@hjmds/design-contracts 1.17.2 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/action-session.d.ts +16 -0
- package/dist/action-session.d.ts.map +1 -1
- package/dist/action-session.js +18 -0
- package/dist/action-session.js.map +1 -1
- package/dist/activity-chip.d.ts +127 -0
- package/dist/activity-chip.d.ts.map +1 -0
- package/dist/activity-chip.js +65 -0
- package/dist/activity-chip.js.map +1 -0
- package/dist/base-recipes.d.ts +1 -1
- package/dist/base-recipes.d.ts.map +1 -1
- package/dist/base-recipes.js +2 -1
- package/dist/base-recipes.js.map +1 -1
- package/dist/behaviors.d.ts +9 -6
- package/dist/behaviors.d.ts.map +1 -1
- package/dist/behaviors.js +5 -3
- package/dist/behaviors.js.map +1 -1
- package/dist/bottom-navigation.d.ts +16 -0
- package/dist/bottom-navigation.d.ts.map +1 -1
- package/dist/bottom-navigation.js +18 -0
- package/dist/bottom-navigation.js.map +1 -1
- package/dist/card.d.ts +4 -0
- package/dist/card.d.ts.map +1 -1
- package/dist/card.js +4 -1
- package/dist/card.js.map +1 -1
- package/dist/carousel.d.ts +3 -0
- package/dist/carousel.d.ts.map +1 -1
- package/dist/carousel.js.map +1 -1
- package/dist/catalog.d.ts +80 -9
- package/dist/catalog.d.ts.map +1 -1
- package/dist/component-recipes.d.ts +74 -3
- package/dist/component-recipes.d.ts.map +1 -1
- package/dist/component-recipes.js +38 -6
- package/dist/component-recipes.js.map +1 -1
- package/dist/content-transition.d.ts +1 -1
- package/dist/content-transition.d.ts.map +1 -1
- package/dist/content-transition.js +2 -2
- package/dist/content-transition.js.map +1 -1
- package/dist/field-group.d.ts +14 -0
- package/dist/field-group.d.ts.map +1 -1
- package/dist/field-group.js +9 -0
- package/dist/field-group.js.map +1 -1
- package/dist/form.d.ts.map +1 -1
- package/dist/form.js +10 -3
- package/dist/form.js.map +1 -1
- package/dist/icon-button-recipe.d.ts +1 -5
- package/dist/icon-button-recipe.d.ts.map +1 -1
- package/dist/icon-button-recipe.js +2 -1
- package/dist/icon-button-recipe.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/screen-patterns.d.ts +10 -0
- package/dist/screen-patterns.d.ts.map +1 -1
- package/dist/screen-patterns.js +17 -3
- package/dist/screen-patterns.js.map +1 -1
- package/dist/toast-liquid.d.ts +1 -1
- package/dist/toast-liquid.d.ts.map +1 -1
- package/dist/toast-liquid.js +3 -2
- package/dist/toast-liquid.js.map +1 -1
- package/dist/toast.d.ts +29 -2
- package/dist/toast.d.ts.map +1 -1
- package/dist/toast.js +59 -3
- package/dist/toast.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/docs/action-session.md +2 -0
- package/docs/activity-chip.md +34 -0
- package/docs/asset.md +7 -0
- package/docs/bottom-navigation.md +16 -1
- package/docs/brand-boundary.md +3 -3
- package/docs/collection-rail.md +4 -0
- package/docs/compound-controls.md +8 -3
- package/docs/consumer-policy.md +39 -120
- package/docs/generated/component-maturity.md +1 -1
- package/docs/generated/renderer-evidence.json +3 -3
- package/docs/generated/renderer-evidence.md +1 -1
- package/docs/generated/showcase-manifest.json +1 -1
- package/docs/gravity-letters.md +2 -0
- package/docs/grid-reveal.md +2 -0
- package/docs/layout.md +2 -2
- package/docs/load-more.md +5 -0
- package/docs/migration-native-legacy-removal.md +30 -17
- package/docs/optional-adapters.md +4 -0
- package/docs/screen-patterns.md +23 -1
- package/docs/toast.md +64 -2
- package/docs/usage/README.md +248 -243
- package/docs/usage/SELECTION.md +43 -0
- package/docs/usage/STANDARD.md +22 -10
- package/docs/usage/components/accordion.md +5 -3
- package/docs/usage/components/activity-chip.md +109 -0
- package/docs/usage/components/agreement.md +6 -9
- package/docs/usage/components/alert-dialog.md +12 -6
- package/docs/usage/components/asset.md +10 -4
- package/docs/usage/components/auth-provider-button.md +2 -2
- package/docs/usage/components/avatar.md +8 -6
- package/docs/usage/components/badge.md +4 -4
- package/docs/usage/components/bottom-cta.md +4 -4
- package/docs/usage/components/bottom-info.md +2 -2
- package/docs/usage/components/bottom-navigation.md +18 -6
- package/docs/usage/components/button.md +6 -3
- package/docs/usage/components/card.md +28 -7
- package/docs/usage/components/carousel.md +12 -4
- package/docs/usage/components/chat-message.md +10 -2
- package/docs/usage/components/chat-screen.md +5 -5
- package/docs/usage/components/checkbox-group.md +1 -1
- package/docs/usage/components/checkbox.md +2 -2
- package/docs/usage/components/chip.md +2 -2
- package/docs/usage/components/code-block.md +3 -4
- package/docs/usage/components/collapsible.md +6 -4
- package/docs/usage/components/combobox.md +2 -2
- package/docs/usage/components/command-palette.md +1 -1
- package/docs/usage/components/comment-thread-screen.md +7 -4
- package/docs/usage/components/container.md +1 -1
- package/docs/usage/components/content-transition.md +3 -2
- package/docs/usage/components/context-menu.md +2 -2
- package/docs/usage/components/counter-badge.md +3 -3
- package/docs/usage/components/data-table.md +1 -1
- package/docs/usage/components/date-picker.md +4 -4
- package/docs/usage/components/description-list.md +3 -3
- package/docs/usage/components/design-system-provider.md +2 -2
- package/docs/usage/components/dialog.md +14 -3
- package/docs/usage/components/divider.md +2 -2
- package/docs/usage/components/editor-screen.md +5 -3
- package/docs/usage/components/effect-surface.md +1 -1
- package/docs/usage/components/empty-state.md +6 -6
- package/docs/usage/components/field.md +5 -3
- package/docs/usage/components/file-picker.md +6 -3
- package/docs/usage/components/form.md +1 -1
- package/docs/usage/components/heading.md +3 -3
- package/docs/usage/components/icon-button.md +6 -3
- package/docs/usage/components/icon.md +1 -1
- package/docs/usage/components/image.md +5 -4
- package/docs/usage/components/keyboard-dock.md +1 -1
- package/docs/usage/components/layout.md +1 -1
- package/docs/usage/components/link.md +2 -2
- package/docs/usage/components/list-detail-screen.md +6 -6
- package/docs/usage/components/list-row.md +13 -4
- package/docs/usage/components/list.md +5 -4
- package/docs/usage/components/masonry.md +2 -1
- package/docs/usage/components/media-selection-screen.md +11 -5
- package/docs/usage/components/mentions.md +2 -2
- package/docs/usage/components/menu.md +3 -2
- package/docs/usage/components/menubar.md +2 -2
- package/docs/usage/components/message-composer.md +3 -3
- package/docs/usage/components/moderation-screen.md +3 -2
- package/docs/usage/components/notice.md +2 -2
- package/docs/usage/components/notification-inbox-screen.md +1 -1
- package/docs/usage/components/notification-item.md +2 -2
- package/docs/usage/components/number-field.md +3 -3
- package/docs/usage/components/otp-field.md +1 -1
- package/docs/usage/components/overview-screen.md +1 -1
- package/docs/usage/components/permission-screen.md +1 -1
- package/docs/usage/components/photo-source-sheet.md +1 -1
- package/docs/usage/components/popover.md +2 -2
- package/docs/usage/components/profile-screen.md +1 -1
- package/docs/usage/components/progress.md +2 -2
- package/docs/usage/components/qr-code.md +2 -2
- package/docs/usage/components/radio-group.md +1 -2
- package/docs/usage/components/radio.md +1 -2
- package/docs/usage/components/result.md +1 -1
- package/docs/usage/components/saved-items-screen.md +4 -2
- package/docs/usage/components/screen-layout.md +4 -3
- package/docs/usage/components/search-field.md +1 -1
- package/docs/usage/components/search-screen.md +4 -4
- package/docs/usage/components/section.md +3 -3
- package/docs/usage/components/segmented-control.md +4 -4
- package/docs/usage/components/select.md +2 -3
- package/docs/usage/components/settings-screen.md +18 -56
- package/docs/usage/components/sheet.md +10 -5
- package/docs/usage/components/sidebar.md +1 -1
- package/docs/usage/components/skeleton.md +1 -1
- package/docs/usage/components/skip-nav.md +1 -1
- package/docs/usage/components/slider.md +2 -2
- package/docs/usage/components/spinner.md +2 -2
- package/docs/usage/components/splitter.md +1 -1
- package/docs/usage/components/statistic.md +5 -4
- package/docs/usage/components/steps.md +2 -2
- package/docs/usage/components/surface.md +2 -3
- package/docs/usage/components/switch.md +1 -1
- package/docs/usage/components/tabs.md +4 -4
- package/docs/usage/components/tag.md +2 -2
- package/docs/usage/components/tags-input.md +4 -4
- package/docs/usage/components/text-area.md +5 -3
- package/docs/usage/components/text.md +85 -4
- package/docs/usage/components/timeline.md +2 -2
- package/docs/usage/components/toast.md +41 -13
- package/docs/usage/components/toggle-group.md +3 -3
- package/docs/usage/components/tooltip.md +1 -1
- package/docs/usage/components/top-bar.md +5 -4
- package/docs/usage/components/top.md +3 -3
- package/docs/usage/components/transfer-list.md +5 -4
- package/docs/usage/components/upload-item.md +3 -3
- package/docs/usage/components/virtual-list.md +1 -0
- package/docs/usage/compositions/action-feedback.md +42 -6
- package/docs/usage/compositions/action-recovery-optimistic.md +6 -1
- package/docs/usage/compositions/action-recovery-save.md +19 -23
- package/docs/usage/compositions/action-recovery-undo.md +6 -1
- package/docs/usage/compositions/activity-status.md +168 -0
- package/docs/usage/compositions/collection-detail.md +2 -0
- package/docs/usage/compositions/command-records.md +15 -5
- package/docs/usage/compositions/common-message.md +4 -2
- package/docs/usage/compositions/common-notification.md +5 -3
- package/docs/usage/compositions/compound-controls.md +13 -5
- package/docs/usage/compositions/content-transition-comparison.md +2 -2
- package/docs/usage/compositions/date-entry.md +10 -5
- package/docs/usage/compositions/date-time-selection.md +3 -3
- package/docs/usage/compositions/design-profile-comparison.md +7 -5
- package/docs/usage/compositions/disclosure.md +1 -1
- package/docs/usage/compositions/document-resource.md +10 -3
- package/docs/usage/compositions/expo-interactions.md +3 -2
- package/docs/usage/compositions/family-drawer.md +9 -4
- package/docs/usage/compositions/field-group.md +7 -1
- package/docs/usage/compositions/floating-action-button.md +18 -18
- package/docs/usage/compositions/illustrated-outcome.md +3 -2
- package/docs/usage/compositions/input-sheet.md +6 -2
- package/docs/usage/compositions/interaction-adapters.md +1 -1
- package/docs/usage/compositions/interaction-flow-apply.md +6 -3
- package/docs/usage/compositions/interaction-flow-draft.md +5 -2
- package/docs/usage/compositions/interaction-flow-search.md +5 -2
- package/docs/usage/compositions/live-list.md +7 -5
- package/docs/usage/compositions/navigation-bar-collection.md +8 -7
- package/docs/usage/compositions/optional-adapters.md +1 -1
- package/docs/usage/compositions/origin-dialog.md +5 -5
- package/docs/usage/compositions/paper-surface.md +1 -1
- package/docs/usage/compositions/photo-source.md +1 -1
- package/docs/usage/compositions/purpose-input-comment.md +5 -3
- package/docs/usage/compositions/purpose-input-message.md +5 -3
- package/docs/usage/compositions/reference-first.md +63 -42
- package/docs/usage/compositions/reference-review.md +60 -50
- package/docs/usage/compositions/reference-settings.md +60 -50
- package/docs/usage/compositions/selection-scope.md +48 -35
- package/docs/usage/compositions/stea-order-progress.md +1 -0
- package/docs/usage/compositions/stea-otp-verify.md +5 -3
- package/docs/usage/compositions/stea-pixel-empty.md +3 -3
- package/docs/usage/compositions/time-selection.md +6 -5
- package/docs/usage/compositions/upload-recovery.md +10 -1
- package/docs/usage/compositions/video-dialog.md +10 -3
- package/docs/usage/compositions/web-additions.md +5 -5
- package/docs/usage/compositions/web-navigation.md +1 -1
- package/docs/usage/screens/common-chat.md +21 -8
- package/docs/usage/screens/common-comments.md +13 -1
- package/docs/usage/screens/common-inbox.md +19 -6
- package/docs/usage/screens/common-login.md +19 -7
- package/docs/usage/screens/common-profile.md +22 -9
- package/docs/usage/screens/common-saved.md +16 -2
- package/docs/usage/screens/common-search.md +24 -4
- package/docs/usage/screens/common-settings.md +22 -50
- package/docs/usage/screens/common-shell.md +14 -2
- package/docs/usage/screens/dashboard.md +52 -109
- package/docs/usage/screens/discovery-gallery.md +57 -148
- package/docs/usage/screens/flow-collection.md +38 -9
- package/docs/usage/screens/flow-editor.md +25 -7
- package/docs/usage/screens/flow-media.md +23 -7
- package/docs/usage/screens/flow-moderation.md +15 -2
- package/docs/usage/screens/flow-onboarding.md +3 -3
- package/docs/usage/screens/flow-permission.md +17 -3
- package/docs/usage/screens/landing.md +37 -20
- package/docs/usage/screens/mockup-studio.md +22 -7
- package/docs/usage/screens/notification-settings.md +18 -4
- package/docs/usage/screens/product-bento.md +18 -9
- package/docs/usage/screens/reference-comparison.md +29 -10
- package/docs/usage/tokens/color.md +6 -3
- package/docs/usage/tokens/elevation-opacity.md +4 -2
- package/docs/usage/tokens/font-roles.md +2 -2
- package/docs/usage/tokens/layers.md +3 -3
- package/docs/usage/tokens/motion.md +2 -2
- package/docs/usage/tokens/radius.md +4 -2
- package/docs/usage/tokens/spacing.md +3 -3
- package/docs/usage/tokens/theme-studio.md +2 -2
- package/docs/usage/tokens/typography-studio.md +14 -8
- package/docs/usage/tokens/typography.md +15 -5
- package/package.json +7 -1
|
@@ -88,6 +88,7 @@ import { Masonry } from "@hjmds/react-native/masonry";
|
|
|
88
88
|
- `width`가 0 이하이거나 열 폭이 0 이하, `getItemHeight`가 양의 유한수가 아니면 `TypeError`가 난다. 항목이 비어
|
|
89
89
|
`empty`만 그릴 때도 기하 검사를 먼저 하므로 같다. 측정 전(폭 0)에는 Masonry를 렌더하지 않는다.
|
|
90
90
|
- 화면 폭이 바뀌면 `width`를 다시 넘긴다.
|
|
91
|
+
- 빈 목록도 `width`를 유지하며, `layoutStyle`로 할당한 영역 안에서 안내를 가로·세로 중앙에 놓는다. 높이를 지정하지 않은 본문에서는 안내의 내용 높이를 사용한다.
|
|
91
92
|
|
|
92
93
|
## 플랫폼 차이
|
|
93
94
|
|
|
@@ -100,7 +101,7 @@ import { Masonry } from "@hjmds/react-native/masonry";
|
|
|
100
101
|
## 함정
|
|
101
102
|
|
|
102
103
|
- 모든 항목을 한 번에 그린다. 항목이 많은 무한 피드에서는 렌더 비용이 쌓인다.
|
|
103
|
-
- 항목이 없으면 `empty`만 그리고 목록 role이 붙지 않는다. Web 빈 분기는 `role="group"` + `label` 이름이다(
|
|
104
|
+
- 항목이 없으면 `empty`만 그리고 목록 role이 붙지 않는다. Web 빈 분기는 `role="group"` + `label` 이름이다(1.13.0 변경.
|
|
104
105
|
1.12.1은 role 없는 `<div aria-label>`이라 이름이 노출되지 않았다). 빈 상태 문구는 `empty` 안에 보이는 글로 둔다.
|
|
105
106
|
- 다음 페이지는 목록 다음 형제로 [LoadMore](load-more.md)를 둔다. Native에서 FlatList 밖(ScrollView 안 Masonry)이면
|
|
106
107
|
`onEndReached`가 없으므로 `mode="manual"`로 둔다. Web `automatic`은 sentinel로 동작하지만 비가상화라 항목이
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
- 단계: 컴포넌트
|
|
4
4
|
- 상태: 배포
|
|
5
5
|
- 지원: Web · Native
|
|
6
|
-
- 적용:
|
|
7
|
-
- 검토일: 2026-10-
|
|
6
|
+
- 적용: 1.17.1
|
|
7
|
+
- 검토일: 2026-10-13
|
|
8
8
|
- 근거: [반복 화면 조합](../../screen-patterns.md), Web·Native `src/screens.tsx`·`src/screen-flows.tsx`; 기존 개별 지침을 새 규격으로 통합. 예제 스토리는 2026-10-06 사용자 승인으로 스토리북 배포([승인 기록](../../../../../docs/STORYBOOK_NAVIGATION.md#21-2026-10-06-전체-승격과-규격-확정)). 스토리북 배포는 API 게시가 아니다(`적용` 참고)
|
|
9
9
|
- 스토리북: `배포/화면/콘텐츠/사진 선택과 업로드`
|
|
10
10
|
|
|
@@ -44,7 +44,7 @@ import { MediaSelectionScreen } from "@hjmds/react/screen-flows";
|
|
|
44
44
|
items={picked.map((p) => ({ descriptor: { id: p.id, name: p.fileName, state: p.upload },
|
|
45
45
|
preview: <img src={p.uri} alt="" width={p.width} height={p.height} /> }))}
|
|
46
46
|
add={{ label: t("media.add"), onAction: openPicker }}
|
|
47
|
-
done={{ label: t("media.done"), onAction: submit, disabled: uploading }}
|
|
47
|
+
done={{ label: t("media.done"), onAction: submit, disabled: uploading || !canComplete }}
|
|
48
48
|
labels={{ pending: t("upload.pending"), uploading: t("upload.uploading"),
|
|
49
49
|
success: t("upload.success"), cancel: t("upload.cancel"), retry: t("upload.retry") }}
|
|
50
50
|
actionLabels={{ remove: t("media.remove"), moveUp: t("media.moveUp"), moveDown: t("media.moveDown") }}
|
|
@@ -66,7 +66,7 @@ import { Image } from "react-native";
|
|
|
66
66
|
items={picked.map((p) => ({ descriptor: { id: p.id, name: p.fileName, state: p.upload },
|
|
67
67
|
preview: <Image src={p.uri} width={p.width} height={p.height} /> }))}
|
|
68
68
|
add={{ label: t("media.add"), onAction: openPicker }}
|
|
69
|
-
done={{ label: t("media.done"), onAction: submit, disabled: uploading }}
|
|
69
|
+
done={{ label: t("media.done"), onAction: submit, disabled: uploading || !canComplete }}
|
|
70
70
|
labels={{ pending: t("upload.pending"), uploading: t("upload.uploading"),
|
|
71
71
|
success: t("upload.success"), cancel: t("upload.cancel"), retry: t("upload.retry") }}
|
|
72
72
|
actionLabels={{ remove: t("media.remove"), moveUp: t("media.moveUp"), moveDown: t("media.moveDown") }}
|
|
@@ -104,7 +104,7 @@ Web의 `<img alt="">`는 장식용 미리보기다. 사진 이름은 `removeLabe
|
|
|
104
104
|
| 간격 | 화면 padding `spacing.md` 16; 격자 간격 `spacing.md` 16; 항목 안 미리보기–UploadItem–버튼 줄 `spacing.xs` 8; 버튼 사이 `spacing.xxs` 4; footer 요약–완료 `spacing.sm` 12 | Web·Native `MediaSelectionScreen` |
|
|
105
105
|
| 순서·정렬 | 헤더(제목 → 추가) → 격자(항목마다 미리보기 → UploadItem → 위로·아래로·삭제) → footer(`selectionSummary` → 완료) | 렌더 순서 |
|
|
106
106
|
| 고정·스크롤 | 헤더·footer 고정, 격자는 본문 스크롤(`scroll` 기본 `"screen"`) | `ScreenLayout` |
|
|
107
|
-
| 좁은
|
|
107
|
+
| 좁은 폭 | 좁은 폭에서도 2열 유지; 항목 버튼 줄은 줄바꿈(`flexWrap: "wrap"`)해 버튼을 자르지 않는다 | `screen-flows.tsx` |
|
|
108
108
|
|
|
109
109
|
## 꼭 지킬 것
|
|
110
110
|
|
|
@@ -117,3 +117,9 @@ Web의 `<img alt="">`는 장식용 미리보기다. 사진 이름은 `removeLabe
|
|
|
117
117
|
|
|
118
118
|
- `actions`를 넘겨도 `add` 버튼이 그 자리를 덮는다. 다른 상단 행동은 `leading`이나 `notice`로 둔다.
|
|
119
119
|
- `library`를 주면 `items` 격자와 업로드 상태 표시는 그려지지 않는다. 선택 결과는 `selectionSummary`로 보여 준다.
|
|
120
|
+
|
|
121
|
+
## 삭제·순서 변경 후 Web 키보드 초점
|
|
122
|
+
|
|
123
|
+
기본 격자는 제품이 `items` 변경을 반영한 뒤 초점을 복구한다. 현재 사진을 제거하면 같은 위치의 다음 사진 제거 버튼, 마지막이면 이전 사진 제거 버튼으로 이어진다. 모두 제거하면 활성 `add`로 이동하고, 추가도 잠겼으면 본문에 남는다. 마지막 제거와 동시에 `state.kind="empty"`로 바꿔도 같은 규칙이다. 이동 후 첫·마지막 위치의 버튼이 비활성화되면 같은 사진의 사용 가능한 행동으로 이어진다. 살아 있는 미리보기 입력과 값은 key인 `descriptor.id`를 따라 유지한다. 이동된 초점이 본문 밖으로 가려지면 `scroll="screen"`의 본문만 필요한 만큼 스크롤한다.
|
|
124
|
+
|
|
125
|
+
2026-10-13 실행 검수에서 삭제·경계 이동 후 키보드 문맥이 끊겨 추가한 동작이다. 외부 컨트롤로 이동하거나 명시적으로 blur한 초점은 가져오지 않는다. `library`의 초점·선택과 Native OS 접근성 초점은 이 Web DOM 복구 범위에 포함되지 않는다. `done` 허용 조건과 요청 취소·늦은 응답 처리는 계속 제품이 소유한다.
|
|
@@ -79,7 +79,7 @@ Native 후보 목록의 모서리는 `comboboxRecipe.popover.radius` 역할을 P
|
|
|
79
79
|
| 항목 | 값 | 근거 |
|
|
80
80
|
| --- | --- | --- |
|
|
81
81
|
| 크기 | 후보 한 줄 최소 높이 44(`control.minTouchTarget`). Web 목록 최대 높이 `14rem`, 입력 폭에 맞춤 | `.hjm-mentions__option`·`__list`, Native `minHeight: 44` |
|
|
82
|
-
| 간격 | 라벨·입력·설명·오류 사이 `spacing.xs` 8. Web 목록은 입력과 8, 화면 가장자리 8, 안쪽 8, radius `radius.md` 12 — 모두 Combobox 목록과 같은 `comboboxRecipe.popover`(sideOffset·collisionPadding·padding `spacing.xs`). Native 목록 안쪽 8(같은 recipe)·항목 사이 4, radius `radius.md` 12. 후보 좌우 여백 8. 2026-10-06까지 Web 가장자리 16·안쪽 4, Native 안쪽 4였다(1.
|
|
82
|
+
| 간격 | 라벨·입력·설명·오류 사이 `spacing.xs` 8. Web 목록은 입력과 8, 화면 가장자리 8, 안쪽 8, radius `radius.md` 12 — 모두 Combobox 목록과 같은 `comboboxRecipe.popover`(sideOffset·collisionPadding·padding `spacing.xs`). Native 목록 안쪽 8(같은 recipe)·항목 사이 4, radius `radius.md` 12. 후보 좌우 여백 8. 2026-10-06까지 Web 가장자리 16·안쪽 4, Native 안쪽 4였다(1.13.0 변경) | `comboboxRecipe.popover`, `.hjm-mentions__*`, `react-native/src/mentions.tsx` |
|
|
83
83
|
| 순서·정렬 | 후보 목록은 입력 **바로 아래**. Web은 아래 공간이 모자라면 위로 뒤집는다. Web 후보는 `label` 옆에 `description`, 좁으면 줄바꿈 | `useAnchoredPopup`, `.hjm-mentions__option` |
|
|
84
84
|
| 고정·스크롤 | Web 목록은 떠 있는 portal(z-index `layer.dropdown` 400)이고 넘치면 목록 안 스크롤. Native 목록은 문서 흐름 안에 끼어들어 아래 내용을 민다 | `src/mentions.tsx`(Web·Native) |
|
|
85
85
|
| 좁은 폭·큰 글자 | 키보드 위 입력이면 Native 목록이 가려질 수 있으니 [KeyboardFormScrollView](keyboard-form-scroll-view.md) 안에 둔다 | — |
|
|
@@ -112,7 +112,7 @@ Web Native
|
|
|
112
112
|
| 후보 표시 | 입력 아래 떠 있는 listbox(portal) | 입력 아래 문서 흐름 안 목록 |
|
|
113
113
|
| 키보드 | ↑↓ 이동, Enter 확정, Esc 닫기(입력은 유지) | 해당 없음(누름으로 확정) |
|
|
114
114
|
| 기본 후보 렌더 | `label` + `description` | `label`만 |
|
|
115
|
-
| 추가 prop | `className`, ref(`HTMLTextAreaElement`). `style`은 안쪽 textarea에 붙는다 | `listStyle`은
|
|
115
|
+
| 추가 prop | `className`, ref(`HTMLTextAreaElement`). `style`은 안쪽 textarea에 붙는다 | `listStyle`은 제거된 속성(후보 목록의 외형은 recipe가 소유한다) |
|
|
116
116
|
|
|
117
117
|
## 함정
|
|
118
118
|
|
|
@@ -89,7 +89,7 @@ Native popover와 항목 모서리는 Provider token에서 recipe 역할을 해
|
|
|
89
89
|
| 항목 | 값 | 근거 |
|
|
90
90
|
| --- | --- | --- |
|
|
91
91
|
| 크기 | 항목 높이 `comfortable` 56(`layout.rowHeight.singleLine`) · `compact` 44(`control.minTouchTarget`). Web 표면 폭 `13.75rem`~`min(24rem, 90vw)`, 높이 최대 `100dvh − 2 × spacing.md`. Native 표면 폭 100%·최대 520, 높이 최대 75% | `menuRecipe.density`, `.hjm-menu__content`, `react-native/src/navigation.tsx` |
|
|
92
|
-
| 간격 | 항목 좌우 `spacing.sm` 12, leading·문구·단축키 사이 12. 섹션 제목 좌우 12 · 위아래 `spacing.xs` 8. Web: 트리거와 8(`menuRecipe.sideOffset`), 화면 가장자리 8(`collisionPadding`), 안쪽 `spacing.xs` 8(`menuRecipe.surface.padding`; 2026-10-06까지 4, 1.
|
|
92
|
+
| 간격 | 항목 좌우 `spacing.sm` 12, leading·문구·단축키 사이 12. 섹션 제목 좌우 12 · 위아래 `spacing.xs` 8. Web: 트리거와 8(`menuRecipe.sideOffset`), 화면 가장자리 8(`collisionPadding`), 안쪽 `spacing.xs` 8(`menuRecipe.surface.padding`; 2026-10-06까지 4, 1.13.0 변경), 표면·항목 radius `radius.md` 12, 구분선 위아래 4 · 좌우 8. Native: 바깥 여백·안쪽 `spacing.md` 16, 제목·목록·닫기 사이 12, radius `radius.lg` 16 | `collectionItemContract`, `menuRecipe.sectionLabel`·`surface`, `.hjm-menu__*`, `useAnchoredPopup` |
|
|
93
93
|
| 순서·정렬 | 일반 행동을 위에, `danger` 행동은 맨 아래. Web `align="start"`(기본)는 트리거 시작 끝, `end`는 끝 끝에 맞춘다(행 끝 ⋯은 `end`). Native는 위→아래 제목 → 항목 → 닫기 버튼(`secondary`) | `menuRecipe`, `src/overlays.tsx` |
|
|
94
94
|
| 고정·스크롤 | Web: 트리거에 붙는 portal(z-index `layer.dropdown` 400), 아래가 모자라면 위로 뒤집고 가로는 화면 안으로 민다. 넘치면 표면 안 스크롤. Native: `Modal`로 화면 **가운데**, scrim을 누르면 닫히고 항목 목록만 스크롤 | `useAnchoredPopup`, `react-native/src/navigation.tsx`(`Menu`) |
|
|
95
95
|
| 좁은 폭·큰 글자 | Web 폭 상한 `90vw`, 항목 문구는 줄바꿈된다. Native 높이 상한 75%를 넘으면 목록이 스크롤된다 | `.hjm-menu__content`, `maxHeight: "75%"` |
|
|
@@ -114,6 +114,7 @@ Web (트리거 아래, 앵커) Native (Modal, 화면 가운데)
|
|
|
114
114
|
- 항목 id는 비어 있지 않고 유일해야 하며, 활성 항목이 하나 이상 있어야 한다. 어기면 렌더 중 던진다.
|
|
115
115
|
- Web에서 `label`이 문자열이 아닌 항목은 typeahead용 `textValue`를 준다. 없으면 던진다.
|
|
116
116
|
- 다른 모달·시트·화면 이동을 여는 action은 `onActionAfterDismiss`로 실행한다. 이 콜백은 메뉴가 실제로 닫힌 뒤(Native는 Modal teardown 뒤)에만 실행되므로 두 표면이 겹치지 않는다.
|
|
117
|
+
- Native에서 teardown 완료 전에 재열거나 owner를 교체하면 이전에 대기하던 after-dismiss action은 폐기된다. 비동기 action의 요청 오류는 제품 콜백 안에서 처리하고 제품 오류 UI에 연결한다. 메뉴는 Promise 실패에 따른 오류 화면이나 자동 재시도를 만들지 않는다.
|
|
117
118
|
- 항목 문구·아이콘(제품 소유)은 i18n 키와 제품 아이콘으로 넣고, 색은 `tone`으로만 바꾼다.
|
|
118
119
|
- `MorphingMenu`는 action 전용이다. 선택·async가 필요하면 `Menu`를 쓴다. reduce-motion·RTL에서는 스스로 `Menu`로 돌아간다.
|
|
119
120
|
|
|
@@ -128,4 +129,4 @@ Web (트리거 아래, 앵커) Native (Modal, 화면 가운데)
|
|
|
128
129
|
| 상태 | `disabled` | `disabled`, `readOnly`(+`readOnlyLabel`), `busy`, `onRetry`/`retryLabel` |
|
|
129
130
|
| 표면 | 트리거에 붙는 portal(`portalContainer`) | `Modal` |
|
|
130
131
|
| 항목 label | `ReactNode`(+`textValue`) | `string` |
|
|
131
|
-
| 배치 | `className`, `layoutStyle` | `layoutStyle`(`style`은
|
|
132
|
+
| 배치 | `className`, `layoutStyle` | `layoutStyle`(`style`은 제거된 속성) |
|
|
@@ -93,7 +93,7 @@ Native 예는 없다(renderer 없음).
|
|
|
93
93
|
- `className`·`layoutStyle`은 배치에만 쓴다. 색·높이를 덮지 않는다.
|
|
94
94
|
|
|
95
95
|
2026-10-07 Web 전체 회귀 중 키보드로 옮긴 항목이 첫 항목으로 돌아가는 문제를 재현했다.
|
|
96
|
-
|
|
96
|
+
1.15.0 변경 수정은 패널의 늦은 mouseenter가 키보드 선택을 덮지 않고 실제 마우스 이동에
|
|
97
97
|
맞춰 활성 항목을 바꾼다. 메뉴 막대 라벨의 hover 전환·클릭·비활성 건너뛰기는 유지한다.
|
|
98
98
|
고정 지연이나 키보드 검사 재시도로 가리는 대신 입력 의도를 구분했다.
|
|
99
99
|
[검증 기록](../../../../../docs/qa/2026-10-07-command-records.md).
|
|
@@ -102,4 +102,4 @@ Native 예는 없다(renderer 없음).
|
|
|
102
102
|
|
|
103
103
|
2026-10-07 소비 감사에서 Web 라벨의 숫자 recipe 모서리가 프로필을 우회했다. 기존 `radius.sm` 역할을 가까운 Provider의 CSS 변수로 읽고 변수 없는 독립 사용은 recipe 8을 유지한다. 열린 메뉴·roving focus·비활성 건너뛰기·행동과 Web 전용 범위는 바꾸지 않는다.
|
|
104
104
|
|
|
105
|
-
프로필 연결은 1.
|
|
105
|
+
프로필 연결은 1.16.0 변경이며, 기본 배포 계약과 실제 Native 기기 검증은 구분한다.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
- 단계: 컴포넌트
|
|
4
4
|
- 상태: 배포
|
|
5
5
|
- 지원: Web · Native
|
|
6
|
-
- 적용:
|
|
6
|
+
- 적용: 1.17.1
|
|
7
7
|
- 검토일: 2026-10-07
|
|
8
8
|
- 근거: [반복 화면 조합](../../screen-patterns.md), Web·Native `src/screens.tsx`·`src/screen-flows.tsx`; 기존 개별 지침을 새 규격으로 통합. 예제 스토리는 2026-10-06 사용자 승인으로 스토리북 배포([승인 기록](../../../../../docs/STORYBOOK_NAVIGATION.md#21-2026-10-06-전체-승격과-규격-확정)). 스토리북 배포는 API 게시가 아니다(`적용` 참고)
|
|
9
9
|
- 스토리북: `배포/구성/입력과 작성/메시지 작성`, `배포/구성/입력과 작성/댓글 작성`, `배포/화면/소통/채팅`
|
|
@@ -95,7 +95,7 @@ import { Image } from "react-native";
|
|
|
95
95
|
| `attachmentAction` | `{ label, icon, onPress(), disabled? }` | 없음 | 첨부 버튼(ghost `IconButton`) |
|
|
96
96
|
| `attachments` | `readonly { id, removeLabel, preview, disabled? }[]` | `[]` | 첨부 미리보기. 있으면 `onRemoveAttachment` 필수 |
|
|
97
97
|
| `onRemoveAttachment` | `(id: string) => void` | 없음 | 첨부 제거 |
|
|
98
|
-
| Web `layoutStyle` | `HjmCompositionStyleProp` | 없음 | 작성창 루트 배치(margin·width·flex 등).
|
|
98
|
+
| Web `layoutStyle` | `HjmCompositionStyleProp` | 없음 | 작성창 루트 배치(margin·width·flex 등). 1.13.0 변경 |
|
|
99
99
|
|
|
100
100
|
전송 가능 조건: `disabled`·`pending`·`sendDisabled`가 아니고, 글(공백 제외)·첨부·`additionalContent` 중 하나가 있을 때(`canSubmitMessage`).
|
|
101
101
|
|
|
@@ -104,7 +104,7 @@ import { Image } from "react-native";
|
|
|
104
104
|
| 항목 | 값 | 근거 |
|
|
105
105
|
| --- | --- | --- |
|
|
106
106
|
| 크기 | 입력 `composerMinLines` 1 ~ `composerMaxLines` 5줄(넘으면 입력 안에서 스크롤), `shape="large"`; 첨부 썸네일 `attachmentSize` 80(radius `radius.md`); 제거 버튼은 `IconButton size="small"` 36 + 사방 hit 4(실제 타깃 44), 그 안 보이는 원 `attachmentRemoveSize` 24; circle 전송은 `IconButton size="small"` 36 | `screen-patterns.ts`, `icon-button-recipe.ts` `sizes.small`, Web `styles.css`, Native `MessageComposer` |
|
|
107
|
-
| 간격 | 세로 묶음(context·답장 대상·첨부·입력 줄) 사이와 입력–텍스트 전송 버튼 사이 `screenPatternRecipe.itemGap`(`spacing.sm` 12, 두 플랫폼. 2026-10-06까지 Web은 8, 1.
|
|
107
|
+
| 간격 | 세로 묶음(context·답장 대상·첨부·입력 줄) 사이와 입력–텍스트 전송 버튼 사이 `screenPatternRecipe.itemGap`(`spacing.sm` 12, 두 플랫폼. 2026-10-06까지 Web은 8, 1.13.0 변경); 답장 대상 줄·첨부 사이 `spacing.sm` 12; circle 전송은 입력 글자와 `spacing.sm` 12, 오른쪽 끝 8 | `screenPatternRecipe.itemGap`, Web `.hjm-message-composer`·`__row`(`--hjm-message-composer-gap`), Native `Stack gap="sm"`·`itemGap` |
|
|
108
108
|
| 순서·정렬 | `context` → 답장 대상(작성자·발췌 → 취소) → 첨부 썸네일(→ 첨부 버튼) → 입력·전송 한 줄, 전송은 입력 아래쪽(`flex-end`)에 맞춘다. 입력 줄 안은 `leadingAction` → 글자 → (아이콘 모드) 전송/첨부 | 렌더 순서, Web `forms.tsx` `hjm-field__leading` |
|
|
109
109
|
| 고정·스크롤 | 자체 고정 없음: 화면 composer 슬롯(footer)에 넣는다; 첨부는 가로 스크롤; 키보드 adapter는 host 하나만 | ChatScreen·CommentThreadScreen `composer` |
|
|
110
110
|
| 좁은 폭·큰 글자 | 입력이 남은 폭을 채우고(`flex: 1`, 최소 폭 0) 전송 버튼은 줄지 않는다; 큰 글자에서도 5줄 상한 뒤 입력 안 스크롤로 기록을 가리지 않는다 | Web `.hjm-message-composer__row`, Native `layoutStyle={{ flex: 1 }}` |
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
- 단계: 컴포넌트
|
|
4
4
|
- 상태: 배포
|
|
5
5
|
- 지원: Web · Native
|
|
6
|
-
- 적용:
|
|
7
|
-
- 검토일: 2026-10-
|
|
6
|
+
- 적용: 1.17.1
|
|
7
|
+
- 검토일: 2026-10-13
|
|
8
8
|
- 근거: [반복 화면 조합](../../screen-patterns.md), Web·Native `src/screens.tsx`·`src/screen-flows.tsx`; 기존 개별 지침을 새 규격으로 통합. 예제 스토리는 2026-10-06 사용자 승인으로 스토리북 배포([승인 기록](../../../../../docs/STORYBOOK_NAVIGATION.md#21-2026-10-06-전체-승격과-규격-확정)). 스토리북 배포는 API 게시가 아니다(`적용` 참고)
|
|
9
9
|
- 스토리북: `배포/화면/소통/신고와 차단`
|
|
10
10
|
|
|
@@ -111,3 +111,4 @@ import { ModerationScreen } from "@hjmds/react-native/screen-flows";
|
|
|
111
111
|
- 차단 버튼의 `block.action.onAction`은 호출되지 않는다. 버튼은 확인 대화상자만 열고, 실제 차단은 `confirmation.onConfirm`에서 한다.
|
|
112
112
|
- 서버 신고·권한·차단 mutation, 완료 후 이동은 제품 소유다. 사유 목록과 정책 문구도 제품이 정한다.
|
|
113
113
|
- 확인 대화상자의 성공 후 닫힘·실패 문구는 [AlertDialog](alert-dialog.md) 계약을 따른다.
|
|
114
|
+
- `block`을 제거하면 열린 확인 세션도 종료한다. 나중에 차단 행동을 다시 공급해도 사용자가 버튼을 새로 눌러야 확인창이 열린다. 2026-10-13 사라진 행동의 확인 상태가 부활하던 경로를 수정했다. 대상이 바뀌는 제품은 대상 id를 화면 key/초안·요청 수명에 함께 연결한다.
|
|
@@ -95,7 +95,7 @@ import { Notice } from "@hjmds/react-native/feedback";
|
|
|
95
95
|
## 꼭 지킬 것
|
|
96
96
|
|
|
97
97
|
- 제목·설명·행동 문구는 i18n 키로 넣는다. 아이콘은 제품 소유 자산이고 색은 tone이 정한다.
|
|
98
|
-
- 배치는 `layoutStyle`로만 한다. 색·padding·radius를 `style`/`className`으로 덮지 않는다. Native `style`은
|
|
98
|
+
- 배치는 `layoutStyle`로만 한다. 색·padding·radius를 `style`/`className`으로 덮지 않는다. Native `style`은 제거된 속성이다.
|
|
99
99
|
- 같은 화면에 같은 내용의 Notice와 Toast를 동시에 띄우지 않는다.
|
|
100
100
|
|
|
101
101
|
## 플랫폼 차이
|
|
@@ -105,7 +105,7 @@ import { Notice } from "@hjmds/react-native/feedback";
|
|
|
105
105
|
| 발표 | 항상 live region. `danger`는 `role="alert"`+assertive, 나머지는 `role="status"`+polite | `announcement`: `none`(기본) · `polite` · `assertive`. 지정해야 발표한다 |
|
|
106
106
|
| title/description 타입 | `ReactNode` | `string` |
|
|
107
107
|
| 아이콘 렌더 함수 | 없음 | `renderIcon` |
|
|
108
|
-
| 배치 | `className`, `layoutStyle`(HTML `style`도 받음) | `layoutStyle`(`style`은
|
|
108
|
+
| 배치 | `className`, `layoutStyle`(HTML `style`도 받음) | `layoutStyle`(`style`은 제거된 속성) |
|
|
109
109
|
|
|
110
110
|
## 함정
|
|
111
111
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
- 단계: 컴포넌트
|
|
4
4
|
- 상태: 배포
|
|
5
5
|
- 지원: Web · Native
|
|
6
|
-
- 적용:
|
|
6
|
+
- 적용: 1.17.1
|
|
7
7
|
- 검토일: 2026-10-06
|
|
8
8
|
- 근거: [반복 화면 조합](../../screen-patterns.md), Web·Native `src/screens.tsx`·`src/screen-flows.tsx`; 기존 개별 지침을 새 규격으로 통합. 예제 스토리는 2026-10-06 사용자 승인으로 스토리북 배포([승인 기록](../../../../../docs/STORYBOOK_NAVIGATION.md#21-2026-10-06-전체-승격과-규격-확정)). 스토리북 배포는 API 게시가 아니다(`적용` 참고)
|
|
9
9
|
- 스토리북: `배포/화면/소통/알림함`
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
- 단계: 컴포넌트
|
|
4
4
|
- 상태: 배포
|
|
5
5
|
- 지원: Web · Native
|
|
6
|
-
- 적용:
|
|
6
|
+
- 적용: 1.17.1
|
|
7
7
|
- 검토일: 2026-10-06
|
|
8
8
|
- 근거: [반복 화면 조합](../../screen-patterns.md), Web·Native `src/screens.tsx`·`src/screen-flows.tsx`; 기존 개별 지침을 새 규격으로 통합. 예제 스토리는 2026-10-06 사용자 승인으로 스토리북 배포([승인 기록](../../../../../docs/STORYBOOK_NAVIGATION.md#21-2026-10-06-전체-승격과-규격-확정)). 스토리북 배포는 API 게시가 아니다(`적용` 참고)
|
|
9
9
|
- 스토리북: `배포/구성/정보 표시/알림 항목`, `배포/화면/소통/알림함`
|
|
@@ -95,4 +95,4 @@ import { NotificationItem } from "@hjmds/react-native/screens";
|
|
|
95
95
|
| 상태·시각 줄 | 설명 아래 caption `Text` | `description`과 줄바꿈(`\n`)으로 합친 한 문자열 |
|
|
96
96
|
| 이동 | `href`, `onClick` | `onPress` |
|
|
97
97
|
| 추가 슬롯 | `className`, `layoutStyle` | `titleMetadata`, `trailingAction`, `trailingText`, `layoutStyle` |
|
|
98
|
-
| 제목 굵기 조정 | `Text emphasis` | 렌더러 비공개 입력(`hjmTitleEmphasis`)으로 안 읽음 700(`fontWeight.bold`)·읽음 400(`fontWeight.regular`).
|
|
98
|
+
| 제목 굵기 조정 | `Text emphasis` | 렌더러 비공개 입력(`hjmTitleEmphasis`)으로 안 읽음 700(`fontWeight.bold`)·읽음 400(`fontWeight.regular`). 제거된 `ListRow.titleStyle`을 사용하지 않는다. `NotificationItemProps`에는 `titleStyle`이 없다(1.13.0 변경) |
|
|
@@ -120,7 +120,7 @@ Native는 제품 프로필의 `tokens.fontFamily.ui`를 실제 텍스트/입력
|
|
|
120
120
|
- 단위·통화·소수 자릿수 표시는 만들지 않는다. 보조기기용 문구가 필요하면 `getValueText`로 제품이 포맷한다.
|
|
121
121
|
- 제어형과 비제어형을 렌더 사이에 바꾸지 않는다(`value`를 넣었다 뺐다 하면 던진다).
|
|
122
122
|
- `min ≥ max`, `step ≤ 0`, 범위 밖 `value`는 던진다. DurationField도 범위 밖·정수 아닌 초를 던진다.
|
|
123
|
-
- 색·높이를 덮지 않는다. 배치는 `layoutStyle`로 한다. Native `inputStyle`·`containerStyle`은
|
|
123
|
+
- 색·높이를 덮지 않는다. 배치는 `layoutStyle`로 한다. Native `inputStyle`·`containerStyle`은 제거된 속성 — 높이·글꼴은 `size`, 배치는 `layoutStyle`.
|
|
124
124
|
|
|
125
125
|
## 플랫폼 차이
|
|
126
126
|
|
|
@@ -129,5 +129,5 @@ Native는 제품 프로필의 `tokens.fontFamily.ui`를 실제 텍스트/입력
|
|
|
129
129
|
| 역할 | `spinbutton`, `type="text"` | 입력 + 증감 button, accessibility action |
|
|
130
130
|
| label·description·error 타입 | `ReactNode` | `string` |
|
|
131
131
|
| 추가 이름 | 없음 | `accessibilityLabel`, `accessibilityHint` |
|
|
132
|
-
| 클래스·스타일 | `className`, `inputClassName`, `layoutStyle`(필드 전체). `style`은 안쪽 input | `layoutStyle`(필드 전체). `inputStyle`·`containerStyle`은
|
|
133
|
-
| DurationField 배치 | `className`, `layoutStyle`(fieldset) | `layoutStyle`(
|
|
132
|
+
| 클래스·스타일 | `className`, `inputClassName`, `layoutStyle`(필드 전체). `style`은 안쪽 input | `layoutStyle`(필드 전체). `inputStyle`·`containerStyle`은 제거된 속성 |
|
|
133
|
+
| DurationField 배치 | `className`, `layoutStyle`(fieldset) | `layoutStyle`(1.13.0 변경, 1.12.1은 감싸는 View) |
|
|
@@ -97,5 +97,5 @@ import { OtpField } from "@hjmds/react-native/otp-field";
|
|
|
97
97
|
| 항목 | Web | Native |
|
|
98
98
|
| --- | --- | --- |
|
|
99
99
|
| 이름 | `label` | `label` 또는 `accessibilityLabel`만 |
|
|
100
|
-
| 칸 스타일 통로 | 없음 | `slotStyle`, `slotTextStyle`은
|
|
100
|
+
| 칸 스타일 통로 | 없음 | `slotStyle`, `slotTextStyle`은 제거된 속성. 외형은 `size`·`presentation` |
|
|
101
101
|
| busy 표현 | read-only + `aria-busy` | `editable={false}` + `accessibilityState.busy` |
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
같은 데이터와 기능을 유지하면서 테마별 행·카드·격자와 도구 배치를 선택하는 목록 화면에 쓴다.
|
|
14
14
|
|
|
15
|
-
기본 공개 API는 npm 1.15.0에 있다.
|
|
15
|
+
기본 공개 API는 npm 1.15.0에 있다. 글자 역할·종이 줄 간격·토큰 소비 개선은 1.16.0 변경이다. 실제 설치 버전과 기기 검증은 별도로 확인한다.
|
|
16
16
|
|
|
17
17
|
## 쓰지 않을 때
|
|
18
18
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
- 단계: 컴포넌트
|
|
4
4
|
- 상태: 배포
|
|
5
5
|
- 지원: Web · Native
|
|
6
|
-
- 적용:
|
|
6
|
+
- 적용: 1.17.1
|
|
7
7
|
- 검토일: 2026-10-06
|
|
8
8
|
- 근거: [반복 화면 조합](../../screen-patterns.md), Web·Native `src/screens.tsx`·`src/screen-flows.tsx`; 기존 개별 지침을 새 규격으로 통합. 예제 스토리는 2026-10-06 사용자 승인으로 스토리북 배포([승인 기록](../../../../../docs/STORYBOOK_NAVIGATION.md#21-2026-10-06-전체-승격과-규격-확정)). 스토리북 배포는 API 게시가 아니다(`적용` 참고)
|
|
9
9
|
- 스토리북: `배포/화면/소개/권한 안내`
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
- 단계: 컴포넌트
|
|
4
4
|
- 상태: 배포
|
|
5
5
|
- 지원: Web · Native
|
|
6
|
-
- 적용:
|
|
6
|
+
- 적용: 1.17.1
|
|
7
7
|
- 검토일: 2026-10-06
|
|
8
8
|
- 근거: [반복 화면 조합](../../screen-patterns.md), Web·Native `src/screens.tsx`·`src/screen-flows.tsx`; 기존 개별 지침을 새 규격으로 통합. 예제 스토리는 2026-10-06 사용자 승인으로 스토리북 배포([승인 기록](../../../../../docs/STORYBOOK_NAVIGATION.md#21-2026-10-06-전체-승격과-규격-확정)). 스토리북 배포는 API 게시가 아니다(`적용` 참고)
|
|
9
9
|
- 스토리북: `배포/구성/선택과 필터/사진 촬영과 앨범 선택`
|
|
@@ -63,7 +63,7 @@ Native 예는 없다(renderer 없음).
|
|
|
63
63
|
| `dismissPolicy`(부분 지정) | `{ dismissible?, outsideDismiss?, escapeDismiss?, focusOutDismiss? }`(`boolean`) | 모두 `true` | |
|
|
64
64
|
| `open` · `defaultOpen` | `boolean` | 비제어 `false` | 제어하면 `onOpenChange` 필수 |
|
|
65
65
|
| `onOpenChange` | `(open: boolean, details: { reason }) => void` | — | `reason`: `trigger` · `close-action` · `outside-pointer` · `outside-focus` · `escape` · `programmatic` |
|
|
66
|
-
| `motionOrigin` | `TransitionRect` | — |
|
|
66
|
+
| `motionOrigin` | `TransitionRect` | — | 1.14.0 추가: 열기 직전 viewport 좌표. 위치 확정 뒤 공간 전환하며 기존 비모달 초점·닫기 정책 유지 |
|
|
67
67
|
| `initialFocusRef` | `RefObject<HTMLElement \| null>` | 첫 포커스 가능 요소 | 열릴 때 처음 포커스 |
|
|
68
68
|
| `portalContainer` | `HTMLElement` | `document.body` | 표면을 붙일 곳 |
|
|
69
69
|
| `className` | 문자열 | — | `layoutStyle`은 받지 않는다(아래 함정) |
|
|
@@ -113,7 +113,7 @@ Native 예는 없다(renderer 없음).
|
|
|
113
113
|
- 초안은 Popover 위의 제품 상태에 둔다. 종료 후 portal이 제거되므로 내부 비제어 입력에만 두면 사라진다.
|
|
114
114
|
- 공간 전환 실험은 [버튼에서 이어지는 편집](../compositions/origin-dialog.md)의 Web 전용 변형이다.
|
|
115
115
|
|
|
116
|
-
|
|
116
|
+
1.15.0 변경: 가장 가까운 프로필의 `shadow.floating`을 열린 portal에도 상속한다. 프로필이 없으면 기존 recipe 그림자를 유지한다. 초안과 비모달 초점/닫기 계약은 그대로이며 Native는 기존 Sheet 경로를 쓴다.
|
|
117
117
|
|
|
118
118
|
[Motion 세 편집 예제 검토](../../../../../docs/qa/2026-10-07-motion-reference-page-review.md)에서
|
|
119
119
|
aria-modal 표시와 실제 초점 경계가 다르고, 닫기 후 defaultValue 편집이 초기화되는 것을 확인했다.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
- 단계: 컴포넌트
|
|
4
4
|
- 상태: 배포
|
|
5
5
|
- 지원: Web · Native
|
|
6
|
-
- 적용:
|
|
6
|
+
- 적용: 1.17.1
|
|
7
7
|
- 검토일: 2026-10-06
|
|
8
8
|
- 근거: [반복 화면 조합](../../screen-patterns.md), Web·Native `src/screens.tsx`·`src/screen-flows.tsx`; 기존 개별 지침을 새 규격으로 통합. 예제 스토리는 2026-10-06 사용자 승인으로 스토리북 배포([승인 기록](../../../../../docs/STORYBOOK_NAVIGATION.md#21-2026-10-06-전체-승격과-규격-확정)). 스토리북 배포는 API 게시가 아니다(`적용` 참고)
|
|
9
9
|
- 스토리북: `배포/화면/계정/프로필`
|
|
@@ -104,7 +104,7 @@ linear circular (Web) circular (Native)
|
|
|
104
104
|
`max ≤ 0`, 범위 밖 `value`는 던진다.
|
|
105
105
|
- 이름은 지역화한 `label`로 준다. Native는 보이는 label 없이 `accessibilityLabel`만 줄 수도 있다(`ScrollProgress`는 `label` 필수).
|
|
106
106
|
- 색은 `tone`, 두께는 `size`로만 바꾸고 배치는 `layoutStyle`로 한다. Native의 `style`·`labelStyle`·`valueStyle`·`trackStyle`·`indicatorStyle`은
|
|
107
|
-
|
|
107
|
+
제거된 속성이다.
|
|
108
108
|
- `ScrollProgress`는 window에 자동으로 붙지 않는다. Web은 스크롤 host를, Native는 측정값을 반드시 넘긴다.
|
|
109
109
|
- 작업 완료율에는 `ScrollProgress`가 아니라 `Progress`를 쓴다.
|
|
110
110
|
|
|
@@ -125,7 +125,7 @@ linear circular (Web) circular (Native)
|
|
|
125
125
|
|
|
126
126
|
2026-10-07 레퍼런스 조사에서 끝까지 스크롤한 마지막 행도 블러에 가려지는 문제를 확인했다.
|
|
127
127
|
새 `resolveScrollEdges`는 같은 `ScrollMetrics`에서 논리적 이전/다음 콘텐츠 존재 여부를 계산한다.
|
|
128
|
-
|
|
128
|
+
1.14.0부터 `/scroll-progress` subpath에서 제공한다. 블러 renderer 자체를 제공한다는 뜻은 아니다.
|
|
129
129
|
|
|
130
130
|
```ts
|
|
131
131
|
import { resolveScrollEdges } from "@hjmds/design-contracts/scroll-progress";
|
|
@@ -76,7 +76,7 @@ import { spacing } from "@hjmds/design-contracts/foundations";
|
|
|
76
76
|
| `fallback` | `ReactNode` | 필수 | QR 아래에 그려지는 대체 행동(`null`·`false`면 `TypeError`) |
|
|
77
77
|
| `size` | 숫자(px) | `192` | 실제 크기는 모듈 수의 정수배로 내림된다. 모듈당 2px 미만이면 `TypeError` |
|
|
78
78
|
| `level` | `L` · `M` · `Q` · `H` | `M` | 오류 정정 수준 |
|
|
79
|
-
| `layoutStyle` | 배치 전용 style 객체 | — | 루트 배치만(Native는
|
|
79
|
+
| `layoutStyle` | 배치 전용 style 객체 | — | 루트 배치만(Native는 1.13.0 변경) |
|
|
80
80
|
|
|
81
81
|
콜백은 없다. `style`·`className`은 두 renderer 모두 없다. 1.12.1 Native는 `layoutStyle`이 없어 감싸는 레이아웃에서 배치한다.
|
|
82
82
|
|
|
@@ -117,6 +117,6 @@ import { spacing } from "@hjmds/design-contracts/foundations";
|
|
|
117
117
|
| --- | --- | --- |
|
|
118
118
|
| 그리기 | 인라인 `<svg role="img">` | `react-native-svg`, 감싼 `View`가 `accessibilityRole="image"` |
|
|
119
119
|
| 필요한 peer | `qrcode-generator` | `qrcode-generator`, `react-native-svg` |
|
|
120
|
-
| 배치 | `layoutStyle` | `layoutStyle`(
|
|
120
|
+
| 배치 | `layoutStyle` | `layoutStyle`(1.13.0 변경, 1.12.1은 감싸는 View) |
|
|
121
121
|
|
|
122
122
|
- 2026-10-06 독립 재구현에서 QRCode 바깥 Stack의 gap으로 내부 QR–fallback 간격을 바꿀 수 없음을 확인해 슬롯 안 여백 예제로 수정했다.
|
|
@@ -108,8 +108,7 @@ card(vertical) grouped(vertical)
|
|
|
108
108
|
`value`/`defaultValue`가 items에 없으면 `RangeError`를 던진다. 서버 목록은 정리한 뒤 넘긴다.
|
|
109
109
|
- 옛 Native `options` prop은 1.11에서 제거됐다. 넘기면 `TypeError`다([이관표](../../migration-native-legacy-removal.md)).
|
|
110
110
|
- 오류 문구는 `error`로 넘긴다. 그룹 아래에 별도 Text로 직접 그리지 않는다.
|
|
111
|
-
- 배치는 `layoutStyle`로 한다. Native의 `style`과 slot style(`controlStyle`·`indicatorStyle`·`labelStyle` 등)은
|
|
112
|
-
(개발 모드 경고, 다음 major 제거)다([소비 정책 §3.1](../../consumer-policy.md)). 외형은 `presentation`·`size`·`renderIndicator`로 바꾼다.
|
|
111
|
+
- 배치는 `layoutStyle`로 한다. Native의 `style`과 slot style(`controlStyle`·`indicatorStyle`·`labelStyle` 등)은 제거된 속성이다([소비 정책 §3.1](../../consumer-policy.md)). 외형은 `presentation`·`size`·`renderIndicator`로 바꾼다.
|
|
113
112
|
|
|
114
113
|
## 플랫폼 차이
|
|
115
114
|
|
|
@@ -88,8 +88,7 @@ import { Radio } from "@hjmds/react-native/inputs";
|
|
|
88
88
|
- 묶음의 접근성 이름(fieldset/radiogroup)은 Radio가 만들지 않는다. 단독 Radio 여러 개로 묶음을
|
|
89
89
|
흉내 내지 말고 RadioGroup을 쓴다.
|
|
90
90
|
- 선택 표시는 indicator(dot)가 맡는다. 색만으로 선택을 알리도록 바꾸지 않는다.
|
|
91
|
-
- 배치는 `layoutStyle`로 한다. Native의 `style`·`controlStyle`·`labelStyle` 등 slot style은
|
|
92
|
-
다음 major 제거)다. 색·글자·radius·높이를 덮지 않는다([소비 정책 §3.1](../../consumer-policy.md)).
|
|
91
|
+
- 배치는 `layoutStyle`로 한다. Native의 `style`·`controlStyle`·`labelStyle` 등 slot style은 제거된 속성이다. 색·글자·radius·높이를 덮지 않는다([소비 정책 §3.1](../../consumer-policy.md)).
|
|
93
92
|
|
|
94
93
|
## 플랫폼 차이
|
|
95
94
|
|
|
@@ -113,4 +113,4 @@ import { Result } from "@hjmds/react-native/feedback";
|
|
|
113
113
|
| 아이콘 | `icon`(ReactNode) | `renderIcon({ status, color, backgroundColor })` |
|
|
114
114
|
| 제목 heading 수준 | `headingLevel` | `accessibilityRole="header"` 고정 |
|
|
115
115
|
| 실패 알림 | `role="alert"`(그 외 `status`) | assertive live region, iOS는 `announceForAccessibility` |
|
|
116
|
-
| 바깥 배치 | `className`, `layoutStyle`(HTML `style`도 받음) | `layoutStyle`(`style`은
|
|
116
|
+
| 바깥 배치 | `className`, `layoutStyle`(HTML `style`도 받음) | `layoutStyle`(`style`은 제거된 속성) |
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
- 단계: 컴포넌트
|
|
4
4
|
- 상태: 배포
|
|
5
5
|
- 지원: Web · Native
|
|
6
|
-
- 적용:
|
|
6
|
+
- 적용: 1.17.1
|
|
7
7
|
- 검토일: 2026-10-07
|
|
8
8
|
- 근거: [반복 화면 계약](../../screen-patterns.md); 저장한 항목을 Instagram의 컬렉션 탐색 방식으로 바꾸라는 사용자 요청. 기존 ListDetailScreen·Grid를 합성하며 별도 저장 엔진은 만들지 않는다. 예제 스토리는 2026-10-06 사용자 승인으로 스토리북 배포([승인 기록](../../../../../docs/STORYBOOK_NAVIGATION.md#21-2026-10-06-전체-승격과-규격-확정)). 스토리북 배포는 API 게시가 아니다(`적용` 참고)
|
|
9
9
|
- 스토리북: `배포/화면/콘텐츠/저장한 항목`
|
|
@@ -87,7 +87,7 @@ import { SavedItemsScreen } from "@hjmds/react-native/saved-items";
|
|
|
87
87
|
| actions · leading | ScreenLayout 상속 | 없음 | 홈에서는 제품 `actions` 대신 컬렉션 만들기 버튼이 그 자리를 쓰고 제품 `leading`은 유지된다. 컬렉션·상세에서는 `leading`이 뒤로 버튼이 되고 제품 `actions`가 보인다 |
|
|
88
88
|
| renderThumbnail · renderDetail | `(item) => ReactNode`, 필수 | — | 사진·상세 슬롯, API·자산은 제품 소유 |
|
|
89
89
|
| state · notice | ScreenLayout 상속 | ready · 없음 | 조회 상태, 저장 해제/복구 안내 |
|
|
90
|
-
| layoutStyle | `HjmCompositionStyleProp` | 없음 | Web·Native 모두 목록·상세를 담는 ListDetailScreen 바깥 틀에 적용한다(컬렉션·격자·상세 전환과 상관없이 같은 루트).
|
|
90
|
+
| layoutStyle | `HjmCompositionStyleProp` | 없음 | Web·Native 모두 목록·상세를 담는 ListDetailScreen 바깥 틀에 적용한다(컬렉션·격자·상세 전환과 상관없이 같은 루트). 1.13.0 변경 |
|
|
91
91
|
| className(Web) | `string` | 없음 | 안쪽 목록 ScreenLayout에 붙는다 |
|
|
92
92
|
|
|
93
93
|
## 배치
|
|
@@ -126,3 +126,5 @@ Native collection cover의 모서리는 Provider의 `tokens.radius.md`다. 저
|
|
|
126
126
|
|
|
127
127
|
- 비공개 안내는 권한 구현이 아니다. 서버에서 소유자 접근을 검사한다.
|
|
128
128
|
- HTML/WebView나 Instagram 자산을 복사하는 구현이 아니다. 제품 사진·테마·문구를 슬롯으로 전달한다.
|
|
129
|
+
|
|
130
|
+
미게시(1.18.0 이후): 선택한 컬렉션의 항목이 0개면 별도 Text 행 대신 ListDetailScreen의 empty 상태를 사용해 남은 본문 중앙에 안내한다. 명시한 loading/error/restricted가 우선하고 컬렉션 개요는 ready를 유지한다. 커버는 그룹별로 한 번 계산하며 기존 items 순서의 첫 네 항목을 사용한다.
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
- 단계: 컴포넌트
|
|
4
4
|
- 상태: 배포
|
|
5
5
|
- 지원: Web · Native
|
|
6
|
-
- 적용:
|
|
7
|
-
- 검토일: 2026-10-
|
|
6
|
+
- 적용: 1.17.1
|
|
7
|
+
- 검토일: 2026-10-13
|
|
8
8
|
- 근거: [반복 화면 조합](../../screen-patterns.md), Web·Native `src/screens.tsx`·`src/screen-flows.tsx`; 기존 개별 지침을 새 규격으로 통합. 예제 스토리는 2026-10-06 사용자 승인으로 스토리북 배포([승인 기록](../../../../../docs/STORYBOOK_NAVIGATION.md#21-2026-10-06-전체-승격과-규격-확정)). 스토리북 배포는 API 게시가 아니다(`적용` 참고)
|
|
9
9
|
- 스토리북: `배포/화면/화면 틀과 도구/화면 골격과 상태`
|
|
10
10
|
|
|
@@ -79,7 +79,7 @@ import { ScreenLayout } from "@hjmds/react-native/screens";
|
|
|
79
79
|
| `stateAction` | `ReactNode` | 없음 | 상태 안내 아래 행동(재시도 등) |
|
|
80
80
|
| `scroll` | `"screen"` · `"content"` | `"screen"` | `content`는 본문 자식(가상화 목록)이 스크롤을 소유한다. 상태 교체 중에는 `screen`으로 돌아간다 |
|
|
81
81
|
| `contentInset` | `"default"` · `"none"` | `"default"` | `none`은 헤더·notice·본문·footer padding을 0으로(Native는 footer 위 테두리도 뺀다) |
|
|
82
|
-
| `presentation` | `"dashboard"` · `"editorial"` · `"landscape"` | 가장 가까운 profile.screens.overview / 없으면 기존 골격 |
|
|
82
|
+
| `presentation` | `"dashboard"` · `"editorial"` · `"landscape"` | 가장 가까운 profile.screens.overview / 없으면 기존 골격 | [디자인 프로필](../../design-profile.md)의 제공 범위를 따른다. 명시값이 프로필을 이긴다. 헤더 배치·읽기 폭만 바꾸고 상태·입력·행동 슬롯은 유지한다 |
|
|
83
83
|
| `as` (Web) | `"main"` · `"section"` | `"main"` | 제품 셸에 이미 `<main>`이 있으면 `section` |
|
|
84
84
|
| `layoutStyle` | `HjmCompositionStyleProp` | 없음 | 화면 루트 배치 전용(예: 분할 화면의 `flex`·`width`). ScreenLayout 위에 만든 화면은 모두 이 prop을 루트까지 넘긴다 |
|
|
85
85
|
| `className` (Web) | `string` | 없음 | 식별·배치 보조. 색·여백을 덮지 않는다 |
|
|
@@ -98,6 +98,7 @@ import { ScreenLayout } from "@hjmds/react-native/screens";
|
|
|
98
98
|
## 꼭 지킬 것
|
|
99
99
|
|
|
100
100
|
- Web의 화면 스크롤 본문은 Tab으로 진입할 수 있다. `scroll="content"`의 정상 본문은 자식이 키보드 스크롤을 소유하지만, 오류·빈 상태 등 대체 안내는 화면 스크롤로 바뀌며 Tab 진입도 함께 복원된다.
|
|
101
|
+
- Web에서 본문에 초점을 가진 입력·재시도 버튼이 상태 전환으로 제거되면 같은 본문으로 초점을 복구한다. `scroll="content"`의 본문은 이 복구만을 위한 `tabIndex=-1`을 가지며 일반 Tab 순서에는 추가되지 않는다. 사용자가 다른 컨트롤이나 바깥 영역으로 초점을 옮긴 경우에는 이동시키지 않는다. 2026-10-13 재시도·권한 제한 전환에서 초점이 body로 유실된 경로를 수정했다.
|
|
101
102
|
- 가상화 목록(FlatList, VirtualList)을 넣으면 `scroll="content"`로 둔다. 스크롤을 이중으로 중첩하지 않는다.
|
|
102
103
|
- 새로고침 실패·저장 오류는 `state`를 바꾸지 말고 `ready` + `notice`로 알린다. `loading`으로 바꾸면 본문이
|
|
103
104
|
unmount되어 입력 초안이 사라진다.
|
|
@@ -117,7 +117,7 @@ Native는 제품 프로필의 `tokens.fontFamily.ui`를 실제 텍스트/입력
|
|
|
117
117
|
| --- | --- | --- |
|
|
118
118
|
| 진행 상태 prop | `loading`(+`renderLoadingIndicator`) | `busy`(+`renderBusyIndicator`, `busyLabel` 필수) |
|
|
119
119
|
| 검색 아이콘 | `renderSearchIcon`, 또는 `leading` | `renderLeading`, 또는 `leading` |
|
|
120
|
-
| 진행 중 입력 | 입력 가능(`aria-busy`) | 입력 가능(`accessibilityState.busy`). 2026-10-06까지 Native는 `busy`인 동안 입력을 무시했다(1.
|
|
120
|
+
| 진행 중 입력 | 입력 가능(`aria-busy`) | 입력 가능(`accessibilityState.busy`). 2026-10-06까지 Native는 `busy`인 동안 입력을 무시했다(1.13.0 변경) |
|
|
121
121
|
| 입력 요소 | `<input type="search">`, 원시 `onChange`도 전달 | `TextInput` |
|
|
122
122
|
| 배치 | `layoutStyle`·`fieldClassName`(필드 틀), `style`은 안쪽 input | `layoutStyle` |
|
|
123
123
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
- 단계: 컴포넌트
|
|
4
4
|
- 상태: 배포
|
|
5
5
|
- 지원: Web · Native
|
|
6
|
-
- 적용:
|
|
6
|
+
- 적용: 1.17.1
|
|
7
7
|
- 검토일: 2026-10-06
|
|
8
8
|
- 근거: [반복 화면 조합](../../screen-patterns.md), Web·Native `src/screens.tsx`·`src/screen-flows.tsx`; 기존 개별 지침을 새 규격으로 통합. `onSubmit`·`filtersOverflow`는 2026-10-06 사용자 요청("검색과 필터 있는 앱 서비스 따라해")의 검색 화면 개편에서 추가. 같은 날 사용자 위임 결정(권장안)으로 미리보기에만 있던 두 단계 검색 로직(`committedQuery`·`recentQueries`·`suggestedQueries`·`suggestions`·`resultSummary`·`appliedFilters`·`filterSheet`)과 `queryLabelVisibility`를, utilverse 적용 조사로 `searching`·`searchingLabel`을 추가([계약 결정 표](../../screen-patterns.md#searchscreen-두-단계-검색)). 1.13.0 utilverse 적용에서 드러난 결함으로 `hostGutter`와 확정 시 키보드 닫기(Web 결과 영역 포커스)를 추가(1.13.1 patch). 예제 스토리는 2026-10-06 사용자 승인으로 스토리북 배포([승인 기록](../../../../../docs/STORYBOOK_NAVIGATION.md#21-2026-10-06-전체-승격과-규격-확정)). 스토리북 배포는 API 게시가 아니다(`적용` 참고)
|
|
9
9
|
- 스토리북: `배포/화면/검색/검색 결과와 필터`
|
|
@@ -144,9 +144,9 @@ import { SearchScreen } from "@hjmds/react-native/screen-flows";
|
|
|
144
144
|
| `onSearch` | `(query: string, context: { signal: AbortSignal }) => void` | 필수 | `debounceMs` 뒤 호출. 값이 바뀌면 이전 타이머를 지우고 이전 신호를 abort한다 |
|
|
145
145
|
| `queryClearLabel` | `string` | `queryField`가 없으면 필수 | 기본 입력의 지우기 버튼 이름. 비어 있으면 `TypeError` |
|
|
146
146
|
| `queryField` | `ReactNode` | 없음 | 기본 `SearchField` 대신 그릴 입력. 지우기 동작을 직접 제공한다 |
|
|
147
|
-
| `debounceMs` | `number` | `300` | 0 미만은 0 |
|
|
147
|
+
| `debounceMs` | `number` | `searchScreenRecipe.debounceMs` (`300`) | 유한값을 받으며 0 미만은 0. `NaN`·±`Infinity`는 `RangeError`. 두 renderer가 `resolveSearchDebounceMs`를 공유한다 |
|
|
148
148
|
| `filters` | `ReactNode` | 없음 | 검색 입력 아래, 상단에 고정. 두 단계 검색에서는 결과 단계에만, 검색어 때문인 0건에는 숨긴다 |
|
|
149
|
-
| `onSubmit` | `(query: string) => void` | 없음 | 확정 신호. 모든 확정에서 키보드를 닫는다(Native `Keyboard.dismiss()`, Web은 고른 항목이면 결과 영역으로 포커스,
|
|
149
|
+
| `onSubmit` | `(query: string) => void` | 없음 | 확정 신호. 모든 확정에서 키보드를 닫는다(Native `Keyboard.dismiss()`, Web은 고른 항목이면 결과 영역으로 포커스, 1.13.1 변경) — 아래 플랫폼 차이. 기본 입력의 Web Enter(`enterKeyHint="search"`, IME 조합 중 Enter는 무시)·Native 키보드 검색 키(`returnKeyType="search"`, `onSubmitEditing`)와 SearchScreen이 그린 확정 행·제안·최근·추천 검색어가 모두 여기로 온다. 앞뒤 공백을 지운 값이고 공백만이면 부르지 않는다. 고른 값이 입력과 다르면 먼저 `onQueryChange`. 대기 중인 `onSearch` debounce는 그대로 둔다. `queryField`를 주면 그 입력의 키는 연결하지 않는다 |
|
|
150
150
|
| `committedQuery` | `string` | 없음 | 결과를 보여 줄 확정 검색어. 주면 두 단계 검색(`onSubmit` 필수, 타입). 단계: 검색어 공백 = 검색 전, 확정값과 다름 = 입력 중, 같음 = 결과(앞뒤 공백 무시). `children`은 결과 단계에만 그린다 |
|
|
151
151
|
| `queryLabelVisibility` | `visible` · `hidden` | `visible` | `hidden`이면 보이는 label 없이 `queryLabel`을 접근성 이름(Web `aria-label`, Native `accessibilityLabel`)과 placeholder로 쓴다 |
|
|
152
152
|
| `searching` · `searchingLabel` | `boolean` · `string` | 없음 | 기본 입력의 진행 표시(Web `loading`, Native `busy`+`busyLabel`). 함께 주거나 함께 생략(타입). 켜져 있으면 `searchingLabel`을 낭독한다 |
|
|
@@ -158,7 +158,7 @@ import { SearchScreen } from "@hjmds/react-native/screen-flows";
|
|
|
158
158
|
| `appliedFilters` | `{ items: { key, label }[], removeLabel(label), onRemove(key), clearAllLabel, onClearAll(), removeIcon? }` | 없음 | 결과 머리 아래 × 칩 + `모두 해제`. 개수는 trigger 이름과 0건 원인 판정에도 쓴다 |
|
|
159
159
|
| `filterSheet` | `{ open, onOpenChange(open), title, value, onApply(next), count(draft): number \| null, reset(draft), isDefault(draft), renderContent(draft, setDraft), labels: { close, reset, apply(count) }, size?, trigger? }` | 없음 | 열 때 `value`를 초안으로 복사, 닫히면 초안을 버림, 주 행동에서만 `onApply`. `count = 0`이면 주 행동 비활성, `isDefault`면 초기화 비활성. `trigger`를 주면 칩 줄 맨 앞에 `label(적용 개수)` Chip |
|
|
160
160
|
| `filtersOverflow` | `wrap` · `scroll` | `wrap` | `scroll`이면 `filters`를 한 줄 가로 스크롤 영역에 넣고 화면 좌우 여백(`spacing.md` 16, `contentInset="none"`이면 0)에 `hostGutter`를 더한 만큼 가장자리까지 넓힌다. 첫 칩은 검색 입력과 같은 시작선에 놓인다 |
|
|
161
|
-
| `hostGutter` | `none` · `compact` · `regular` · `spacious` | `none` |
|
|
161
|
+
| `hostGutter` | `none` · `compact` · `regular` · `spacious` | `none` | 1.13.1 변경. 이 화면을 감싼 host가 이미 준 좌우 여백 이름(`containerRecipe.gutters`: 0 · `spacing.md` 16 · `spacing.lg` 20 · `spacing.xl` 24). Container 안이면 그 `gutter`, Sheet 본문 안이면 `regular`(`sheetRecipe.content.paddingHorizontal`과 같은 `spacing.lg`). `scroll` 줄만 이 값을 쓴다 |
|
|
162
162
|
| `recentSearches` | `ReactNode` | 없음 | `query`가 공백일 때만 본문 맨 위에 보인다 |
|
|
163
163
|
| `children` | `ReactNode` | 필수 | 결과 |
|
|
164
164
|
| 나머지 | `ScreenLayout`과 같음(`children`·`footer` 제외) | — | `notice`는 필터 아래에 붙는다 |
|
|
@@ -78,7 +78,7 @@ import { Section } from "@hjmds/react-native/primitives";
|
|
|
78
78
|
| 항목 | 값 | 근거 |
|
|
79
79
|
| --- | --- | --- |
|
|
80
80
|
| 크기 | 자체 배경·테두리·여백이 없다. 폭은 부모를 따른다 | `.hjm-section` |
|
|
81
|
-
| 글자 | 제목 `title` 18/26 bold, 설명 `caption` 11/16(두 플랫폼). 2026-10-06까지 Web은 둘 다 본문 14를 물려받았다(1.
|
|
81
|
+
| 글자 | 제목 `title` 18/26 bold, 설명 `caption` 11/16(두 플랫폼). 2026-10-06까지 Web은 둘 다 본문 14를 물려받았다(1.13.0 변경) | `sectionRecipe.title`·`description`, `.hjm-section__title`·`__description` |
|
|
82
82
|
| 간격 | 머리와 본문 사이 `spacing.xs` 8, 글자 묶음과 행동 사이 `spacing.sm` 12, 제목과 설명 사이 `spacing.xxs` 4. Section끼리의 간격은 Section이 주지 않는다. 감싸는 [Stack](stack.md)이나 `layoutStyle`로 `layout.sectionGap`(`spacing.xl` 24)을 둔다 | `sectionRecipe.gap`·`headerGap`·`copyGap`, `layout.sectionGap` |
|
|
83
83
|
| 순서·정렬 | 머리 행동은 끝(LTR 오른쪽)에 하나, 글자 묶음과 세로 가운데 정렬. 보통 [Link](link.md) 또는 `tone="link"` [Button](button.md) | `.hjm-section__header`, Native `Section` |
|
|
84
84
|
| 고정·스크롤 | 고정되지 않는다. 화면 본문 스크롤 안에 둔다 | — |
|
|
@@ -98,7 +98,7 @@ import { Section } from "@hjmds/react-native/primitives";
|
|
|
98
98
|
|
|
99
99
|
- 제목·설명은 i18n 문구로 넣는다. Native는 `string`만 받는다.
|
|
100
100
|
- 배치는 `layoutStyle`로 한다. Native slot 배치는 `headerStyle`·`copyStyle`·`actionStyle`·`contentStyle`(모두 배치 전용 타입)이다.
|
|
101
|
-
Native `style`은
|
|
101
|
+
Native `style`은 제거된 속성이다.
|
|
102
102
|
- 머리 행동은 하나로 둔다. 여러 행동은 본문 안이나 [Menu](menu.md)로 옮긴다.
|
|
103
103
|
|
|
104
104
|
## 플랫폼 차이
|
|
@@ -108,4 +108,4 @@ import { Section } from "@hjmds/react-native/primitives";
|
|
|
108
108
|
| `title`·`description` 타입 | `ReactNode` | `string` |
|
|
109
109
|
| heading 수준 | `headingLevel` | 없음(header role 고정) |
|
|
110
110
|
| 루트 | `<section>` | `View` |
|
|
111
|
-
| 배치 | `className`, `layoutStyle`(HTML `style`도 받음) | `layoutStyle`, slot `*Style`(`style`은
|
|
111
|
+
| 배치 | `className`, `layoutStyle`(HTML `style`도 받음) | `layoutStyle`, slot `*Style`(`style`은 제거된 속성) |
|
|
@@ -66,7 +66,7 @@ import { SegmentedControl } from "@hjmds/react-native/inputs";
|
|
|
66
66
|
| prop | 값 | 기본값 | 설명 |
|
|
67
67
|
| --- | --- | --- | --- |
|
|
68
68
|
| `items` | Web `readonly { value: string; label: ReactNode; disabled? }[]` · Native `readonly { value: Value; label: string; disabled?; leading?; renderLeading? }[]` | 필수 | 값이 비거나 중복이면 던진다 |
|
|
69
|
-
| `presentation` | `connected` · `pills` | `connected` | 연결된 보기 전환 / 독립된 카테고리 필터. `pills`는
|
|
69
|
+
| `presentation` | `connected` · `pills` | `connected` | 연결된 보기 전환 / 독립된 카테고리 필터. `pills`는 1.13.0 변경 |
|
|
70
70
|
| `size` | `small` · `medium` | `medium` | 항목 최소 높이 36(+hitSlop 4) · 44 |
|
|
71
71
|
| `value` · `defaultValue` | 항목 값 | 첫 번째 활성 항목 | 선택 해제 상태는 없다 |
|
|
72
72
|
| `onValueChange` | Web `(value: string) => void` · Native `(value: Value) => void` | — | 다른 항목을 고를 때. `null`은 오지 않는다 |
|
|
@@ -74,7 +74,7 @@ import { SegmentedControl } from "@hjmds/react-native/inputs";
|
|
|
74
74
|
| `disabled` | `boolean` | `false` | 전체 비활성(Web은 fieldset 속성) |
|
|
75
75
|
| `layoutStyle` | 배치 전용 style 객체 | — | 바깥 배치 |
|
|
76
76
|
|
|
77
|
-
`connected`는 글자 크기 160% 이상(`stackAtFontScale`)에서 항목을 세로로 쌓는다. `pills`는 쌓지 않는다(`pills.largeTextLayout` `wrap`,
|
|
77
|
+
`connected`는 글자 크기 160% 이상(`stackAtFontScale`)에서 항목을 세로로 쌓는다. `pills`는 쌓지 않는다(`pills.largeTextLayout` `wrap`, 1.13.1 변경).
|
|
78
78
|
|
|
79
79
|
## 배치
|
|
80
80
|
|
|
@@ -103,7 +103,7 @@ import { SegmentedControl } from "@hjmds/react-native/inputs";
|
|
|
103
103
|
`value`가 비활성 항목이어도 `RangeError`다.
|
|
104
104
|
- 옛 Native `options` prop은 제거됐다. 넘기면 `TypeError`다([이관표](../../migration-native-legacy-removal.md)).
|
|
105
105
|
- 연결형의 선택 표시는 focus 색 테두리(ring), `pills`는 본문색 채움과 반전 글자다. 제품에서 선택 배경을 직접 덮지 않는다. 배치는 `layoutStyle`로 하고, Native `style`은
|
|
106
|
-
|
|
106
|
+
제거된 속성이다.
|
|
107
107
|
|
|
108
108
|
## 플랫폼 차이
|
|
109
109
|
|
|
@@ -134,7 +134,7 @@ import { SegmentedControl } from "@hjmds/react/selection";
|
|
|
134
134
|
items={categories} value={category} onValueChange={setCategory} />
|
|
135
135
|
```
|
|
136
136
|
|
|
137
|
-
Native는 `@hjmds/react-native/inputs`에서 같은 prop을 사용한다. `presentation`은
|
|
137
|
+
Native는 `@hjmds/react-native/inputs`에서 같은 prop을 사용한다. `presentation`은 1.13.0 추가 API다. 연결형과 pills는 같은 단일 선택 계약을 따른다.
|
|
138
138
|
스토리는 `버튼형 선택`의 `알약 모양`·`비활성`·`알약 모양 · 큰 글자`다. 2026-10-06 사용자 승인으로 실험 `입력/카테고리 필터` 항목을 배포하면서 별도 공개 API가 아니라 이 표현이라 그 스토리로 합쳤다([승인 기록](../../../../../docs/STORYBOOK_NAVIGATION.md#21-2026-10-06-전체-승격과-규격-확정)). Storybook 배포는 npm 게시가 아니다.
|
|
139
139
|
|
|
140
140
|
## 함정
|
|
@@ -107,7 +107,7 @@ import { NativeSelect } from "@hjmds/react/forms";
|
|
|
107
107
|
| 항목 | 값 | 근거 |
|
|
108
108
|
| --- | --- | --- |
|
|
109
109
|
| 크기 | 트리거 최소 높이 `medium` 44 · `large` 52, 폼 열 폭을 채운다(Web `inline-size: 100%`). 선택지 행 `comfortable` 56 · `compact` 44. Web 목록 최대 폭 420(`min(26.25rem, 100vw − 2×spacing.md)`)·최대 높이 360. Native sheet 최대 높이 75% | `fieldFrameContract.minHeight`, `control.buttonHeight.large`, `selectRecipe.density`·`popover`, `.hjm-select__listbox`, Native `forms.tsx` |
|
|
110
|
-
| 간격 | 트리거 좌우 `medium` `spacing.md` 16 · `large` `spacing.lg` 20(recipe), 안쪽 요소 사이 `spacing.sm` 12. 라벨·설명·오류와 `spacing.xs` 8. Web 목록은 트리거에서 8 떨어지고 안쪽 여백 `spacing.xs` 8(`selectRecipe.popover.padding`; 2026-10-06까지 4, 1.
|
|
110
|
+
| 간격 | 트리거 좌우 `medium` `spacing.md` 16 · `large` `spacing.lg` 20(recipe), 안쪽 요소 사이 `spacing.sm` 12. 라벨·설명·오류와 `spacing.xs` 8. Web 목록은 트리거에서 8 떨어지고 안쪽 여백 `spacing.xs` 8(`selectRecipe.popover.padding`; 2026-10-06까지 4, 1.13.0 변경), 화면 가장자리에서 8(`selectRecipe.popover.collisionPadding`). Native sheet 안쪽 `spacing.md` 16, 머리와 목록 사이 `spacing.sm` 12 | `selectRecipe.sizes`·`value.gap`, `formSupportContract.gap`, `selectRecipe.popover`(sideOffset 8, collisionPadding 8, padding 8), Native `forms.tsx` |
|
|
111
111
|
| 순서·정렬 | 트리거: 앞 아이콘 → 값(넘치면 말줄임) → 펼침 표시. Web 목록은 트리거 아래·트리거와 같은 폭, 공간이 없으면 위로 뒤집힌다. Native sheet 머리는 제목 + 끝쪽 닫기 ×(44). 확인 버튼은 없고 항목을 누르면 선택하고 닫힌다 | `.hjm-select__trigger`, `select.tsx`(`matchAnchorWidth`), `CollectionSheetHeader` |
|
|
112
112
|
| 고정·스크롤 | Web 목록은 `position: fixed` popover(z-index `layer.dropdown` 400), 넘치면 목록 안에서 스크롤. Native는 화면 아래에서 올라오는 modal sheet로 목록만 스크롤되고, 아래 여백에 안전 영역(`safeArea.bottom`)을 더한다. 배경(scrim)을 누르면 닫힌다 | `.hjm-select__listbox`, Native `Select`(Modal·ScrollView) |
|
|
113
113
|
| 좁은 폭·큰 글자 | 트리거 높이는 최소값이라 큰 글자에서 늘어나고 값은 한 줄 말줄임이다. Web 목록 폭은 화면 폭 − 32를 넘지 않는다 | `.hjm-select__value`, `.hjm-select__listbox` |
|
|
@@ -135,8 +135,7 @@ Web popover Native sheet
|
|
|
135
135
|
- 옛 Native `options`·`value`·`onValueChange`는 1.11에서 제거됐다. `items`/`selectedKey`/`onSelectionChange`를 쓴다.
|
|
136
136
|
- Native 선택 후 화면 이동·다른 modal 열기는 `onSelectionAfterDismiss`에서 한다. sheet가 닫히기 전에
|
|
137
137
|
다음 modal을 띄우지 않는다.
|
|
138
|
-
- 배치는 `layoutStyle`로 한다. Web `className`·`style`은 트리거 버튼에 붙는다. Native `style`은
|
|
139
|
-
다음 major 제거)다.
|
|
138
|
+
- 배치는 `layoutStyle`로 한다. Web `className`·`style`은 트리거 버튼에 붙는다. Native `style`은 제거된 속성이다.
|
|
140
139
|
|
|
141
140
|
## 플랫폼 차이
|
|
142
141
|
|