@hjmds/design-contracts 1.18.0 โ 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/behaviors.d.ts +7 -6
- package/dist/behaviors.d.ts.map +1 -1
- package/dist/behaviors.js +4 -3
- package/dist/behaviors.js.map +1 -1
- package/dist/bottom-navigation.d.ts +4 -0
- package/dist/bottom-navigation.d.ts.map +1 -1
- package/dist/bottom-navigation.js +11 -0
- package/dist/bottom-navigation.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 +42 -0
- package/dist/catalog.d.ts.map +1 -1
- package/dist/component-recipes.d.ts +42 -0
- package/dist/component-recipes.d.ts.map +1 -1
- package/dist/component-recipes.js +14 -1
- package/dist/component-recipes.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/screen-patterns.d.ts +4 -0
- package/dist/screen-patterns.d.ts.map +1 -1
- package/dist/screen-patterns.js +12 -3
- package/dist/screen-patterns.js.map +1 -1
- package/dist/toast.d.ts +10 -1
- package/dist/toast.d.ts.map +1 -1
- package/dist/toast.js +43 -2
- 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/asset.md +7 -0
- package/docs/bottom-navigation.md +11 -0
- 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 +41 -2
- package/docs/usage/README.md +248 -245
- 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/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 +16 -5
- package/docs/usage/components/button.md +2 -2
- package/docs/usage/components/card.md +1 -1
- package/docs/usage/components/carousel.md +12 -4
- package/docs/usage/components/chat-message.md +6 -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 +2 -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 +3 -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 +11 -49
- 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 +2 -3
- package/docs/usage/components/text.md +85 -4
- package/docs/usage/components/timeline.md +2 -2
- package/docs/usage/components/toast.md +17 -7
- 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 +11 -5
- 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 +1 -1
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
- ์ํ: ๋ฐฐํฌ
|
|
5
5
|
- ์ง์: Web ยท Native
|
|
6
6
|
- ์ ์ฉ: 1.12.1
|
|
7
|
-
- ๊ฒํ ์ผ: 2026-10-
|
|
7
|
+
- ๊ฒํ ์ผ: 2026-10-13
|
|
8
8
|
- ๊ทผ๊ฑฐ: `showcase/web/src/patterns/DiscoveryGallery.stories.tsx`, `showcase/native/src/DiscoveryGallery.stories.tsx`, `showcase/shared/discovery-gallery.ts`, `src/base-recipes.ts`(`buttonRecipe.states.selected`), `src/grid.ts`
|
|
9
9
|
- ์คํ ๋ฆฌ๋ถ: `๋ฐฐํฌ/ํ๋ฉด/๊ฒ์/์ํ ํ์`
|
|
10
10
|
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
โ ์ํ ๊ฒ์ (๋ณด์ด๋ ๋ผ๋ฒจ) โ
|
|
29
29
|
โ [๐ ๋ชจ๋ฐ์ผ, ์์
๊ณต๊ฐ ........... (x)] โ SearchField ์ต์ 44
|
|
30
30
|
โ โ spacing.xl 24 โ
|
|
31
|
-
โ โก [์ ์ฒด] [์น์ฌ์ดํธ] [๋ชจ๋ฐ์ผ] [๋์๋ณด๋] โ
|
|
31
|
+
โ โก [์ ์ฒด] [์น์ฌ์ดํธ] [๋ชจ๋ฐ์ผ] [๋์๋ณด๋] โ SegmentedControl pills, ๋จ์ผ ์ ํ
|
|
32
32
|
โ โข [์ ๋ ฌ: ์ธ๊ธฐ์] [์ ์ฅํ ์ํ 2] โ secondary(์ ๋ ฌ) ยท ghost+selected(์ ์ฅ๋ง ๋ณด๊ธฐ)
|
|
33
33
|
โ โฃ "N๊ฐ์ ์ํ" (์ํ ์๋ฆผ) โ
|
|
34
34
|
โ (์ค๋ฅ๋ฉด ์ฌ๊ธฐ Notice danger + [๋ค์ ์๋]) โ
|
|
@@ -76,9 +76,9 @@
|
|
|
76
76
|
| ํ๋ | ์ปดํฌ๋ํธยทtone | ์์น | ๊ฐ์ยท์์ |
|
|
77
77
|
| --- | --- | --- | --- |
|
|
78
78
|
| ๊ฒ์ | SearchField `onValueChange` | โ ๋งจ ์๋ | 1. ์
๋ ฅ ์ฆ์ ๊ฑฐ๋ฅธ๋ค |
|
|
79
|
-
| ์นดํ
๊ณ ๋ฆฌ |
|
|
79
|
+
| ์นดํ
๊ณ ๋ฆฌ | SegmentedControl `presentation="pills"` | โก | ์นดํ
๊ณ ๋ฆฌ ์, "์ ์ฒด"๊ฐ ๋งจ ์ |
|
|
80
80
|
| ์ ๋ ฌ ์ ํ | Button `secondary`, ๋ผ๋ฒจ์ ํ์ฌ ๊ฐ(`t("gallery.sort", { value: t(sortKey[sort]) })`) | โข ์ฒซ ์๋ฆฌ | 1. ๋๋ฅผ ๋๋ง๋ค ์ธ๊ธฐ์ โ ์ต์ ์ |
|
|
81
|
-
| ์ ์ฅํ ์ํ๋ง |
|
|
81
|
+
| ์ ์ฅํ ์ํ๋ง | Button `ghost` + `selected`, ๋ผ๋ฒจ์ ๊ฐ์ | โข ์ ๋ ฌ ๋ค | 1 |
|
|
82
82
|
| ์์ธ ๋ณด๊ธฐ | Button `ghost` | ์นด๋ ๋งจ ์๋ ๋ฒํผ ์ค ์ฒซ ์๋ฆฌ | ์นด๋๋ง๋ค 1. `aria-label`/`accessibilityLabel`์ ์ํ ์ ๋ชฉ ํฌํจ |
|
|
83
83
|
| ์นด๋ ์ ์ฅ | Button `secondary` + `selected`(ํ ๊ธ) | ์นด๋ ๋ฒํผ ์ค ๋์งธ ์๋ฆฌ | ์นด๋๋ง๋ค 1. ๋ผ๋ฒจ "์ ์ฅ" โ "์ ์ฅ๋จ", ์ ๊ทผ์ฑ ์ด๋ฆ์ ์ ๋ชฉ๊ณผ ์ ์ฅ/์ ์ฅ ์ทจ์ |
|
|
84
84
|
| ์ํธ ์ ์ฅ(์ํธ์ ์ฃผ ํ๋) | Button ๊ธฐ๋ณธ primary + `selected` | โฆ Sheet `footer`(Native ๊ฝ ์ฐฌ ํญ, Web ๋ ์ ๋ ฌ) | 1. ๋ผ๋ฒจ "์ปฌ๋ ์
์ ์ ์ฅ" โ "์ ์ฅ ์ทจ์". ์ํธ๋ฅผ ๋ซ์ง ์๋ ํ ๊ธ์ด๋ค |
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
| ํ๊ดด ํ๋ | โ | โ | ์์(์ ์ฅ ์ทจ์๋ ๊ฐ์ ๋ฒํผ์ ํ ๊ธ) |
|
|
88
88
|
|
|
89
89
|
primary๋ ํ๋ฉด์์ ๋น ๊ฒฐ๊ณผ ๋ณต๊ตฌ ํ๋, ์ํธ ์์์ ์ ์ฅ ํ๋๋ค. ์ํธ ์ ํ๋์ ๊ทธ ํ๋ฉด ์์์ ์ธ๊ณ , `selected`๋ฅผ ์ค ๋ฒํผ์
|
|
90
|
-
tone๊ณผ ๊ด๊ณ์์ด ์ ํ ๋ชจ์(๋ฐฐ๊ฒฝ `bg`,
|
|
90
|
+
tone๊ณผ ๊ด๊ณ์์ด ์ ํ ๋ชจ์(๋ฐฐ๊ฒฝ `bg`, ๊ธ์ `contentBrand`, ๋ณ๋ ์ ํ ํ
๋๋ฆฌ ์์)์ผ๋ก ์น ํด์ ธ ์ธ์ง ์๋๋ค([Button](../components/button.md) "๊ผญ ์งํฌ ๊ฒ").
|
|
91
91
|
์นด๋ ์ ๋ฒํผ์ [๋ณด๊ธฐ][์ ์ฅ] ์์๋ก ์์ ์ ๋ ฌ, `wrap`์ด๋ค. ์นด๋ ์ ์ฒด๋ฅผ ๋๋ฆ ๋์์ผ๋ก ๋ง๋ค์ง ์๋๋ค โ ์นด๋ ์์ ๋ฒํผ์ด ๋์ด๋ผ
|
|
92
92
|
๊ฒน์น ๋๋ฆ ๋์์ด ๋๋ค.
|
|
93
93
|
|
|
@@ -96,9 +96,9 @@ tone๊ณผ ๊ด๊ณ์์ด ์ ํ ๋ชจ์(๋ฐฐ๊ฒฝ `bg`, ๊ธ์ยทํ
๋๋ฆฌ `contentBrand`
|
|
|
96
96
|
| ์ํ | ํ๋ฉด ๋ชจ์ต | ํ๋ |
|
|
97
97
|
| --- | --- | --- |
|
|
98
98
|
| ๊ธฐ๋ณธ | "์ ์ฒด"ยท์ธ๊ธฐ์, ์ ์ฒด ์นด๋, ๊ฒฐ๊ณผ ์ | ๊ฒ์ยทํํฐยท์ ๋ ฌยท์ ์ฅยท๋ณด๊ธฐ |
|
|
99
|
-
| ๋ก๋ฉ | ์คํ ๋ฆฌ์ ์์.
|
|
100
|
-
| ๋น |
|
|
101
|
-
| ์ค๋ฅ | ์คํ ๋ฆฌ์ ์์. โ ~โข์ ๋จ๊ธฐ๊ณ โฃ ์๋ [Notice](../components/notice.md) `tone="danger"`(Native `announcement="assertive"` โ ๊ธฐ๋ณธ `none`). ๋ฌธ๊ตฌ๋ ์์ธ๋ณ ํค(`errorKey`: ๋คํธ์ํฌ `gallery.error.network`, ์๋ฒ `gallery.error.server`). ์ด์ ๊ฒฐ๊ณผ๊ฐ ์์ผ๋ฉด โค๋ฅผ ์ ์งํ๊ณ ,
|
|
99
|
+
| ๋ก๋ฉ | ๋๊ธฐ ์คํ ๋ฆฌ์ ์์. ์ ํ ์ต์ด ์กฐํ๋ ScreenLayout ๋ณธ๋ฌธ ์ค์ spinner, ์ฌ์กฐํ๋ ๊ธฐ์กด ๊ฒฐ๊ณผ์ ๊ฒ์ยทํํฐ๋ฅผ ์ ์งํ๋ค | ๊ฐ์ ์์ฒญ ์ค๋ณต ์คํ ๋ฐฉ์ง |
|
|
100
|
+
| ๋น | ์ฑ๊ณต ์๋ต 0๊ฑด์ผ ๋๋ง ScreenLayout ๋ณธ๋ฌธ ์ค์ ๋น ์ํ(`t("gallery.empty.title")`, ์ค๋ช
) | [ํํฐ ์ด๊ธฐํ] |
|
|
101
|
+
| ์ค๋ฅ | ์คํ ๋ฆฌ์ ์์. โ ~โข์ ๋จ๊ธฐ๊ณ โฃ ์๋ [Notice](../components/notice.md) `tone="danger"`(Native `announcement="assertive"` โ ๊ธฐ๋ณธ `none`). ๋ฌธ๊ตฌ๋ ์์ธ๋ณ ํค(`errorKey`: ๋คํธ์ํฌ `gallery.error.network`, ์๋ฒ `gallery.error.server`). ์ด์ ๊ฒฐ๊ณผ๊ฐ ์์ผ๋ฉด โค๋ฅผ ์ ์งํ๊ณ , ์ฒซ ์กฐํ ์คํจ๋ฉด ScreenLayout ์ค์ ์ค๋ฅ์ ์ฌ์๋๋ฅผ ์ฌ์ฉํ๊ณ EmptyState๋ฅผ ๊ทธ๋ฆฌ์ง ์๋๋ค(๋น ๊ฒฐ๊ณผ์ ์คํจ๋ฅผ ์์ง ์๋๋ค). ๋ค์ ์๋๊ฐ ๋ ์คํจํ๋ฉด ๊ฐ์ Notice๋ฅผ ๊ฐ์ ์๋ฆฌ์ ๋๊ณ ๋ฒํผ `loading`๋ง ํผ๋ค | Notice `action` ๋ค์ ์๋ 1๊ฐ |
|
|
102
102
|
| ์ ์ฅ ํ ๊ธ | ์นด๋ ๋ฒํผ์ด `selected`๋ก ๋ฐ๋๊ณ โข ์ ์ฅ ๊ฐ์๊ฐ ๋์ด๋๋ค. ์ ์ฅ๋ง ๋ณด๊ธฐ ์ค ์ ์ฅ ์ทจ์ํ๋ฉด ์นด๋๊ฐ ์ฌ๋ผ์ง๊ณ ๊ฒฐ๊ณผ ์๊ฐ ์ฝํ๋ค | โ |
|
|
103
103
|
| ์์ธ ์ด๋ฆผ | ์ํธ๊ฐ ์ฌ๋ผ์ค๊ณ ๊ฐ์ ๊ทธ๋ฆผ์ ํฌ๊ฒ ๋ณด์ธ๋ค. ์ํธ์์ ์ ์ฅํ๋ฉด ์นด๋ ์ํ๋ ๊ฐ์ด ๋ฐ๋๋ค | ์ ์ฅยท๋ซ๊ธฐ |
|
|
104
104
|
|
|
@@ -115,7 +115,7 @@ tone๊ณผ ๊ด๊ณ์์ด ์ ํ ๋ชจ์(๋ฐฐ๊ฒฝ `bg`, ๊ธ์ยทํ
๋๋ฆฌ `contentBrand`
|
|
|
115
115
|
| [Grid](../components/grid.md) | โค ์นด๋ ๊ฒฉ์ |
|
|
116
116
|
| [AspectRatio](../components/aspect-ratio.md) ยท [Image](../components/image.md) | ์ ํ์ ์ค์ ์ธ๋ค์ผ, ๋ก๋ฉ Skeleton ํ |
|
|
117
117
|
| [EmptyState](../components/empty-state.md) | ๊ฒฐ๊ณผ ์์ |
|
|
118
|
-
| [Skeleton](../components/skeleton.md) | ๋ก๋ฉ |
|
|
118
|
+
| [Skeleton](../components/skeleton.md) | ๋ก๋ฉ | ๋๊ธฐ ์คํ ๋ฆฌ์ ์์. ์ ํ ์ต์ด ์กฐํ๋ ScreenLayout ๋ณธ๋ฌธ ์ค์ spinner, ์ฌ์กฐํ๋ ๊ธฐ์กด ๊ฒฐ๊ณผ์ ๊ฒ์ยทํํฐ๋ฅผ ์ ์งํ๋ค | ๊ฐ์ ์์ฒญ ์ค๋ณต ์คํ ๋ฐฉ์ง |
|
|
119
119
|
| [Notice](../components/notice.md) | ์ค๋ฅ |
|
|
120
120
|
| [Sheet](../components/sheet.md) | โฆ ์์ธ |
|
|
121
121
|
| [ํ๋ฉด ์ฌ๋ฐฑ๊ณผ ๋๋น](../tokens/layout.md) | gutterยท์ต๋ ํญยทbreakpoint |
|
|
@@ -123,155 +123,61 @@ tone๊ณผ ๊ด๊ณ์์ด ์ ํ ๋ชจ์(๋ฐฐ๊ฒฝ `bg`, ๊ธ์ยทํ
๋๋ฆฌ `contentBrand`
|
|
|
123
123
|
|
|
124
124
|
## ์ฝ๋ ๊ณจ๊ฒฉ
|
|
125
125
|
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
๋๊ธฐ ๊ฒ์ยท์นดํ
๊ณ ๋ฆฌยท๋
๋ฆฝ ์ ์ฅ ํ ๊ธยท์์ธ Sheet์ ์คํ ์๋ณธ์
|
|
127
|
+
`showcase/web/src/patterns/DiscoveryGallery.stories.tsx`์
|
|
128
|
+
`showcase/native/src/DiscoveryGallery.stories.tsx`๋ค. ์ด ์ด๋ฆ์ ๊ณต๊ฐ ํ๋ฉด API๋ ์๋ค.
|
|
129
|
+
์ ํ์ ๋น๋๊ธฐ ๊ฒ์์ [๊ฒ์ ๊ฒฐ๊ณผ์ ํํฐ](common-search.md)์ SearchScreen์ ๋จผ์ ๊ฒํ ํ๋ค.
|
|
130
|
+
๊ฐค๋ฌ๋ฆฌ ๊ฒฉ์๊ฐ ํ์ํ๋ฉด ๊ธฐ์กด GridยทSheet์ ์๋ ScreenLayout ์ํ๋ฅผ ๊ฒฐํฉํ๋ค.
|
|
128
131
|
|
|
129
132
|
```tsx
|
|
130
133
|
// Web
|
|
131
|
-
import {
|
|
132
|
-
import { Heading } from "@hjmds/react/heading";
|
|
134
|
+
import { ScreenLayout } from "@hjmds/react/screens";
|
|
133
135
|
import { Button } from "@hjmds/react/actions";
|
|
134
|
-
import {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
<main><Container size="content" gutter={gutter}><Stack gap="xl">
|
|
151
|
-
<Stack gap="md">
|
|
152
|
-
<Text tone="brand">{t("gallery.eyebrow")}</Text>
|
|
153
|
-
<Heading level="level3" semanticLevel={1}>{t("gallery.title")}</Heading>
|
|
154
|
-
<Text as="p">{t("gallery.intro")}</Text>
|
|
155
|
-
<SearchField label={t("gallery.search")} clearLabel={t("gallery.clear")} loading={loading} value={query} onValueChange={setQuery} />
|
|
156
|
-
</Stack>
|
|
157
|
-
<SegmentedControl label={t("gallery.category")} presentation="pills"
|
|
158
|
-
items={categories.map(id => ({ value: id, label: t(categoryKey[id]) }))} value={category} onValueChange={setCategory} />
|
|
159
|
-
<Stack axis="inline" wrap gap="sm">
|
|
160
|
-
<Button tone="secondary" onClick={toggleSort}>{t("gallery.sort", { value: t(sortKey[sort]) })}</Button>
|
|
161
|
-
<Button tone="ghost" selected={savedOnly} onClick={() => setSavedOnly(v => !v)}>{t("gallery.savedOnly", { count: savedCount })}</Button>
|
|
162
|
-
</Stack>
|
|
163
|
-
<Text role="status">{loading ? "" : t("gallery.count", { count: results.length })}</Text>
|
|
164
|
-
{error ? <Notice tone="danger" title={t(errorKey[error])}
|
|
165
|
-
action={<Button tone="secondary" size="small" loading={retrying} onClick={retry}>{t("common.retry")}</Button>} /> : null}
|
|
166
|
-
{loading && results.length === 0 ? (
|
|
167
|
-
<Grid {...gridProps} aria-busy="true" aria-label={t("gallery.loading")}>
|
|
168
|
-
{[0, 1, 2].map(i => <Stack key={i} gap="sm"><AspectRatio ratio={1.6} aria-hidden="true"><Skeleton shape="block" height="100%" /></AspectRatio><Skeleton shape="text" width="60%" /></Stack>)}
|
|
169
|
-
</Grid>
|
|
170
|
-
) : results.length ? (
|
|
171
|
-
<Grid {...gridProps}>
|
|
172
|
-
{results.map(item => <article key={item.id}><Stack gap="sm">
|
|
173
|
-
<Thumbnail item={item} />
|
|
174
|
-
<Text variant="label">{item.title}</Text>
|
|
175
|
-
<Text tone="muted">{t("gallery.meta", { author: item.author, category: item.categoryLabel })}</Text>
|
|
176
|
-
<Stack axis="inline" wrap gap="sm">
|
|
177
|
-
<Button tone="ghost" aria-label={t("gallery.viewNamed", { title: item.title })} onClick={() => setSelected(item)}>{t("gallery.details")}</Button>
|
|
178
|
-
<Button tone="secondary" selected={isSaved(item)} onClick={() => toggleSaved(item.id)}
|
|
179
|
-
aria-label={t(isSaved(item) ? "gallery.unsaveNamed" : "gallery.saveNamed", { title: item.title })}>
|
|
180
|
-
{t(isSaved(item) ? "gallery.saved" : "gallery.save")}</Button>
|
|
181
|
-
</Stack>
|
|
182
|
-
</Stack></article>)}
|
|
183
|
-
</Grid>
|
|
184
|
-
) : error ? null : <EmptyState title={t("gallery.empty.title")} description={t("gallery.empty.body")}
|
|
185
|
-
action={<Button onClick={reset}>{t("gallery.reset")}</Button>} />}
|
|
186
|
-
<Sheet open={selected !== null} onOpenChange={o => { if (!o) setSelected(null); }}
|
|
187
|
-
title={selected?.title ?? t("gallery.detail")} closeLabel={t("common.close")}
|
|
188
|
-
footer={selected ? <Button selected={isSaved(selected)} onClick={() => toggleSaved(selected.id)}
|
|
189
|
-
aria-label={t(isSaved(selected) ? "gallery.unsaveNamed" : "gallery.saveNamed", { title: selected.title })}>
|
|
190
|
-
{t(isSaved(selected) ? "gallery.unsave" : "gallery.saveToCollection")}</Button> : null}>
|
|
191
|
-
{selected ? <Stack gap="lg">
|
|
192
|
-
<Thumbnail item={selected} />
|
|
193
|
-
<Text>{t("gallery.meta", { author: selected.author, category: selected.categoryLabel })}</Text>
|
|
194
|
-
<Text as="p">{selected.description}</Text>
|
|
195
|
-
</Stack> : null}
|
|
196
|
-
</Sheet>
|
|
197
|
-
</Stack></Container></main>
|
|
136
|
+
import { Notice } from "@hjmds/react/feedback";
|
|
137
|
+
|
|
138
|
+
// hasLoaded๋ ์ฑ๊ณตํ ์กฐํ๊ฐ ์๋์ง๋ค. 0๊ฑด ์ฑ๊ณต๋ true์ด๋ฉฐ ๋ฐฐ์ด ๊ธธ์ด๋ก ๋์ ํ์ง ์๋๋ค.
|
|
139
|
+
<>
|
|
140
|
+
<ScreenLayout title={t("gallery.title")} actions={categoryControls}
|
|
141
|
+
notice={<>{searchAndSort}{hasLoaded && error ? <Notice tone="danger" title={t(errorKey[error])}
|
|
142
|
+
action={<Button tone="secondary" loading={retrying} onClick={retry}>{t("common.retry")}</Button>} /> : null}</>}
|
|
143
|
+
state={!hasLoaded
|
|
144
|
+
? error ? { kind: "error", title: t(errorKey[error]) } : { kind: "loading", title: t("gallery.loading") }
|
|
145
|
+
: results.length === 0 ? { kind: "empty", title: t("gallery.empty.title") } : { kind: "ready" }}
|
|
146
|
+
stateAction={!hasLoaded && error ? <Button loading={retrying} onClick={retry}>{t("common.retry")}</Button>
|
|
147
|
+
: hasLoaded && results.length === 0 ? <Button onClick={reset}>{t("gallery.reset")}</Button> : null}>
|
|
148
|
+
{galleryGrid}
|
|
149
|
+
</ScreenLayout>
|
|
150
|
+
{detailSheet}
|
|
151
|
+
</>
|
|
198
152
|
```
|
|
199
153
|
|
|
200
154
|
```tsx
|
|
201
155
|
// Native
|
|
202
|
-
import {
|
|
203
|
-
import { spacing } from "@hjmds/design-contracts/foundations";
|
|
204
|
-
import { resolveWindowClass } from "@hjmds/design-contracts/responsive";
|
|
205
|
-
import { AspectRatio, Container, Grid, Stack, Text } from "@hjmds/react-native/primitives";
|
|
206
|
-
import { Heading } from "@hjmds/react-native/heading";
|
|
156
|
+
import { ScreenLayout } from "@hjmds/react-native/screens";
|
|
207
157
|
import { Button } from "@hjmds/react-native/actions";
|
|
208
|
-
import {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
<
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
<Heading level="level3" semanticLevel={1}>{t("gallery.title")}</Heading>
|
|
224
|
-
<Text>{t("gallery.intro")}</Text>
|
|
225
|
-
<SearchField label={t("gallery.search")} clearLabel={t("gallery.clear")} busy={loading} busyLabel={t("gallery.searching")}
|
|
226
|
-
value={query} onValueChange={setQuery} />
|
|
227
|
-
</Stack>
|
|
228
|
-
<SegmentedControl label={t("gallery.category")} presentation="pills"
|
|
229
|
-
items={categories.map(id => ({ value: id, label: t(categoryKey[id]) }))} value={category} onValueChange={setCategory} />
|
|
230
|
-
<Stack axis="inline" wrap gap="sm">
|
|
231
|
-
<Button tone="secondary" onPress={toggleSort}>{t("gallery.sort", { value: t(sortKey[sort]) })}</Button>
|
|
232
|
-
<Button tone="ghost" selected={savedOnly} onPress={() => setSavedOnly(v => !v)}>{t("gallery.savedOnly", { count: savedCount })}</Button>
|
|
233
|
-
</Stack>
|
|
234
|
-
<Text accessibilityLiveRegion="polite">{loading ? "" : t("gallery.count", { count: results.length })}</Text>
|
|
235
|
-
{error ? <Notice tone="danger" announcement="assertive" title={t(errorKey[error])}
|
|
236
|
-
action={<Button tone="secondary" size="small" loading={retrying} onPress={retry}>{t("common.retry")}</Button>} /> : null}
|
|
237
|
-
{loading && results.length === 0 ? (
|
|
238
|
-
<Grid {...gridProps}>
|
|
239
|
-
{[0, 1, 2].map(i => <Stack key={i} gap="sm">
|
|
240
|
-
<AspectRatio ratio={1.6}><Skeleton shape="block" layoutStyle={{ flex: 1 }} {...(i === 0 ? { accessibilityLabel: t("gallery.loading") } : {})} /></AspectRatio>
|
|
241
|
-
<Skeleton shape="text" width="60%" />
|
|
242
|
-
</Stack>)}
|
|
243
|
-
</Grid>
|
|
244
|
-
) : results.length ? (
|
|
245
|
-
<Grid {...gridProps}>
|
|
246
|
-
{results.map(item => <Stack key={item.id} gap="sm">
|
|
247
|
-
<Thumbnail item={item} />
|
|
248
|
-
<Text variant="label">{item.title}</Text>
|
|
249
|
-
<Text tone="muted">{t("gallery.meta", { author: item.author, category: item.categoryLabel })}</Text>
|
|
250
|
-
<Stack axis="inline" wrap gap="sm">
|
|
251
|
-
<Button tone="ghost" accessibilityLabel={t("gallery.viewNamed", { title: item.title })} onPress={() => setSelected(item)}>{t("gallery.details")}</Button>
|
|
252
|
-
<Button tone="secondary" selected={isSaved(item)} onPress={() => toggleSaved(item.id)}
|
|
253
|
-
accessibilityLabel={t(isSaved(item) ? "gallery.unsaveNamed" : "gallery.saveNamed", { title: item.title })}>
|
|
254
|
-
{t(isSaved(item) ? "gallery.saved" : "gallery.save")}</Button>
|
|
255
|
-
</Stack>
|
|
256
|
-
</Stack>)}
|
|
257
|
-
</Grid>
|
|
258
|
-
) : error ? null : <EmptyState title={t("gallery.empty.title")} description={t("gallery.empty.body")}
|
|
259
|
-
action={<Button onPress={reset}>{t("gallery.reset")}</Button>} />}
|
|
260
|
-
<Sheet scrollable open={selected !== null} onOpenChange={o => { if (!o) setSelected(null); }}
|
|
261
|
-
title={selected?.title ?? t("gallery.detail")} closeLabel={t("common.close")}
|
|
262
|
-
footer={selected ? <Button fullWidth selected={isSaved(selected)} onPress={() => toggleSaved(selected.id)}
|
|
263
|
-
accessibilityLabel={t(isSaved(selected) ? "gallery.unsaveNamed" : "gallery.saveNamed", { title: selected.title })}>
|
|
264
|
-
{t(isSaved(selected) ? "gallery.unsave" : "gallery.saveToCollection")}</Button> : null}>
|
|
265
|
-
{selected ? <Stack gap="lg">
|
|
266
|
-
<Thumbnail item={selected} />
|
|
267
|
-
<Text>{t("gallery.meta", { author: selected.author, category: selected.categoryLabel })}</Text>
|
|
268
|
-
<Text>{selected.description}</Text>
|
|
269
|
-
</Stack> : null}
|
|
270
|
-
</Sheet>
|
|
271
|
-
</Stack></Container>
|
|
272
|
-
</ScrollView>
|
|
158
|
+
import { Notice } from "@hjmds/react-native/feedback";
|
|
159
|
+
|
|
160
|
+
<>
|
|
161
|
+
<ScreenLayout title={t("gallery.title")} actions={categoryControls}
|
|
162
|
+
notice={<>{searchAndSort}{hasLoaded && error ? <Notice tone="danger" announcement="assertive" title={t(errorKey[error])}
|
|
163
|
+
action={<Button tone="secondary" loading={retrying} onPress={retry}>{t("common.retry")}</Button>} /> : null}</>}
|
|
164
|
+
state={!hasLoaded
|
|
165
|
+
? error ? { kind: "error", title: t(errorKey[error]) } : { kind: "loading", title: t("gallery.loading") }
|
|
166
|
+
: results.length === 0 ? { kind: "empty", title: t("gallery.empty.title") } : { kind: "ready" }}
|
|
167
|
+
stateAction={!hasLoaded && error ? <Button loading={retrying} onPress={retry}>{t("common.retry")}</Button>
|
|
168
|
+
: hasLoaded && results.length === 0 ? <Button onPress={reset}>{t("gallery.reset")}</Button> : null}>
|
|
169
|
+
{galleryGrid}
|
|
170
|
+
</ScreenLayout>
|
|
171
|
+
{detailSheet}
|
|
172
|
+
</>
|
|
273
173
|
```
|
|
274
174
|
|
|
175
|
+
์ ReactNode ์ฌ๋กฏ์ ์ ํ์ด ๊ธฐ์กด SearchFieldยทSegmentedControlยทGridยทSheet๋ก ๊ตฌ์ฑํ๋ค.
|
|
176
|
+
ScreenLayout host๋ ๋จ์ ๋ณธ๋ฌธ ๋์ด๋ฅผ ํ๋ณดํ๊ณ ๋ก๋ฉยท์ค๋ฅยท๋น ์ํ๋ฅผ ๊ทธ ์์ญ ์ค์์ ๋๋ค.
|
|
177
|
+
์ฌ์กฐํ๋ hasLoaded์ ๋ง์ง๋ง ์ฑ๊ณต ๊ฒฐ๊ณผ๋ฅผ ์ ์งํ๋ค. ๊ฒ์์ดยทํํฐยท์ ๋ ฌ์ request key์ ๋ฃ๊ณ ์๋ต key๊ฐ
|
|
178
|
+
ํ์ฌ ์ ํ๊ณผ ๊ฐ์ ๋๋ง ์ ์ฉํ๋ค. ์ด์ ๊ฒ์ ๊ฒฐ๊ณผ๋ฅผ ์ ์งํ๋ ๋์ ๊ทธ ๊ฒฐ๊ณผ์ ํ์ฌ์ฑ์ ์ ํ์ด ํ์ํ๊ณ
|
|
179
|
+
๋ง์ง ์๋ ํญ๋ชฉ์ ํ์ ํ๋์ ๋ง๋๋ค. ์ ์ฅ pendingยท์คํจ๋ ํด๋น ์ํ ID๋ณ๋ก ๊ด๋ฆฌํด ์ ์ฒด ๊ฒฉ์๋ฅผ ๊ต์ฒดํ์ง ์๋๋ค.
|
|
180
|
+
|
|
275
181
|
## ํฐ ๊ธ์ยท๋คํฌยท์ข์ ํญ
|
|
276
182
|
|
|
277
183
|
| ์กฐ๊ฑด | ๋ฐ๋๋ ๊ฒ |
|
|
@@ -287,7 +193,7 @@ const gridProps = { columns: { compact: 1, medium: 2, expanded: 3 }, gap: { comp
|
|
|
287
193
|
| --- | --- | --- |
|
|
288
194
|
| ๊ฒฉ์ | Grid(ํญ์ `ResizeObserver`๋ก ์ฐ๋ค), ์ฌ์ด `spacing.xl` 24 | Grid(ํญ์ `onLayout`์ผ๋ก ์ฐ๋ค), ์ฌ์ด `spacing.xl` 24 |
|
|
289
195
|
| ๊ทธ๋ฆผ ์ ๊ทผ์ฑ | `aria-hidden="true"` | `accessibilityElementsHidden` + `importantForAccessibility="no-hide-descendants"` |
|
|
290
|
-
| ๊ฒฐ๊ณผ ์ ์๋ฆผ | `role="status"` |
|
|
196
|
+
| ๊ฒฐ๊ณผ ์ ์๋ฆผ | `role="status"` | ๊ณต๊ฐ StatusText(Android live region + iOS active ๋ฌธ๊ตฌ ๋ณ๊ฒฝ ์๋ฆผ โ [์ฌ์ฉ๋ฒ](../components/text.md#statustext)) |
|
|
291
197
|
| ๊ฒ์ ์งํ | `loading` | `busy` + `busyLabel`(ํ์) |
|
|
292
198
|
| ์ํธ footer | ์ค๋ฅธ์ชฝ ์ ๋ ฌ ๊ฐ๋ก ์ค | ์ธ๋ก ์ด, `fullWidth` |
|
|
293
199
|
| ์ค๋ฅ Notice ์๋ฆผ | `tone="danger"`๊ฐ ์๋ฆผ ์์ญ | `announcement="assertive"`๋ฅผ ๋ช
์(๊ธฐ๋ณธ `none`) |
|
|
@@ -304,3 +210,6 @@ const gridProps = { columns: { compact: 1, medium: 2, expanded: 3 }, gap: { comp
|
|
|
304
210
|
- ์ํธ ํ์ ํ๋์ footer์ ๋๋ค. Native๋ scrollable ๋ณธ๋ฌธ๊ณผ ๋ถ๋ฆฌํด ํฐ ๊ธ์์์๋ ์ ๊ทผ ๊ฐ๋ฅํ๊ฒ ํ๋ค.
|
|
305
211
|
- ํ์ฌ ์คํ ๋ฆฌ์ ์นด๋ ๋ฉํ๋ "์๊ฐ ยท ์นดํ
๊ณ ๋ฆฌ ยท ์ข์์ N"์ ํ๊ตญ์ด ํ
ํ๋ฆฟ์ผ๋ก ์กฐ๋ฆฝํ๋ค. ์ ํ์ `t("gallery.meta", { author, category })`์ฒ๋ผ
|
|
306
212
|
๋ณด๊ฐ ํค ํ๋๋ก ๋๋ค. ์ข์์ ์๊ฐ ํ์ํ๋ฉด ๊ฐ์ ํค์ ๊ฐ์ ๋ํ๋ค.
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
2026-10-13 ํ๋ ๊ฒ์์์ ์ ๊ฑฐ/๋ณต๊ตฌ ๋ค ํค๋ณด๋ ๋ฌธ๋งฅ ์ ์ค์ ํ์ธํด ๋ณด๊ฐํ๋ค. Web ์ ์ฅ๋ง ๋ณด๊ธฐ์์ ์ ์ฅ ์ทจ์๋ก ์นด๋๊ฐ ์ฌ๋ผ์ง๋ฉด ์ ์ฅ ํํฐ๋ก ์ด์ ์ ๋๋ฆฐ๋ค. ์์ธ๋ฅผ ๋ซ์ ๋๋ ์๋ ์์ธ ๋ฒํผ, ํด๋น ์นด๋๊ฐ ์ ๊ฑฐ๋์ผ๋ฉด ์ ์ฅ ํํฐ๋ฅผ ์ ํ๋ซํผ Sheet returnFocusRef๋ก ์ง์ ํ๋ค. Web ๋น ๊ฒฐ๊ณผ ์ด๊ธฐํ๋ ๊ฒ์ ํ๋๋ก ์ด์ด์ง๋ค. Native ref ์ฐ๊ฒฐ๊ณผ ์ค์ OS ์ ๊ทผ์ฑ ์ด์ ์ด๋ ๊ฒ์ฆ์ ๊ตฌ๋ถํ๋ค.
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
- ๋จ๊ณ: ํ๋ฉด
|
|
4
4
|
- ์ํ: ๋ฐฐํฌ
|
|
5
5
|
- ์ง์: Web ยท Native
|
|
6
|
-
- ์ ์ฉ:
|
|
7
|
-
- ๊ฒํ ์ผ: 2026-10-
|
|
6
|
+
- ์ ์ฉ: ๊ตฌ์ฑ API ์ง์นจ ์ฐธ์กฐ
|
|
7
|
+
- ๊ฒํ ์ผ: 2026-10-13
|
|
8
8
|
- ๊ทผ๊ฑฐ: [๋ฐ๋ณต ํ๋ฉด ์กฐํฉ](../../screen-patterns.md); ๊ณตํต API์ ์ค์ WebยทNative ์์ ์ ์ฌ๋กฏยท์ํ๋ฅผ ๋์กฐํด ์ค๋ณต ์กฐ๋ฆฝ ๋ฐฉ์ง. 2026-10-06 ์ฌ์ฉ์ ์น์ธ์ผ๋ก ์คํ ๋ฆฌ๋ถ ๋ฐฐํฌ(์ด์ `์คํ/ํ๋ฉด/๊ธฐ๋ณธ ํ๋ฆ/๋ชฉ๋ก๊ณผ ์์ธ`, [์น์ธ ๊ธฐ๋ก](../../../../../docs/STORYBOOK_NAVIGATION.md#21-2026-10-06-์ ์ฒด-์น๊ฒฉ๊ณผ-๊ท๊ฒฉ-ํ์ ))
|
|
9
9
|
- ์คํ ๋ฆฌ๋ถ: `๋ฐฐํฌ/ํ๋ฉด/์ฝํ
์ธ /๋ชฉ๋ก๊ณผ ์์ธ`
|
|
10
10
|
|
|
@@ -39,7 +39,24 @@ host: ๋จ์ ๋์ดยทsafe areaยทํค๋ณด๋
|
|
|
39
39
|
| ๊ธฐ๋ณธ | ๋ชฉ๋ก ํค๋ โ ๋ชฉ๋ก โ ๋ ๋ณด๊ธฐ / ์์ธ ํค๋ โ ์์ธ | ๊ฐ ๊ณต๊ฐ ์ฝ๋ฐฑ์ ์ ํ ์ํ์ ์ฐ๊ฒฐ |
|
|
40
40
|
| ๋ก๋ฉ | ์ต์ด ์กฐํ๋ ๋ณธ๋ฌธ ์ํ, ์ ์ฅ์ ํด๋น ํ๋ pending | ์ค๋ณต ์ ์ถ ์ฐจ๋จ; ์ฑ๊ณต์ ๋จผ์ ํ์ํ์ง ์์ |
|
|
41
41
|
| ๋น | ์ค์ ์กฐํ 0๊ฑด ๋๋ ์์ง ์์ฑํ์ง ์์ ์ํ ์๋ด | ์์ยท์กฐ๊ฑด ํด์ ๋ฑ ๋งฅ๋ฝ์ ๋ง๋ ๋์ |
|
|
42
|
-
| ์ค๋ฅ | ๋ชฉ๋ก pane ์ ์ง; ์์ธ ์คํจ๋ detail.
|
|
42
|
+
| ์ค๋ฅ | ๋ชฉ๋ก pane ์ ์ง; ์์ธ ์คํจ๋ detail.stateยทdetail.stateAction์ผ๋ก ๋ณต๊ตฌ | ์คํจ ์์ธ๊ณผ ์ฌ์๋ ๊ฒฝ๋ก ์ ๊ณต |
|
|
43
|
+
|
|
44
|
+
### ๋ชฉ๋ก๊ณผ ์์ธ์ ๋
๋ฆฝ ์ํ
|
|
45
|
+
|
|
46
|
+
`state`๋ ๋ชฉ๋ก์, `detail.state`๋ ์์ธ์๋ง ์ ์ฉํ๋ค. ์ ์์ธ prop์ ๋ฏธ๊ฒ์(1.18.0 ์ดํ)์ด๋ฉฐ
|
|
47
|
+
๊ธฐ์กด `detail: { title, content }` ์ฌ์ฉ๋ฒ์ ๊ทธ๋๋ก ์ ์งํ๋ค. ๋ชฉ๋ก ์
๋ ฅยท์คํฌ๋กค์ ๋ณด์กดํ ์ฑ
|
|
48
|
+
์์ธ์ ์ต์ด ์กฐํยท์ค๋ฅยท์ฌ์๋๋ฅผ ์ค์ ์ํ๋ก ํํํ๋ ค๊ณ ์ถ๊ฐํ๋ค.
|
|
49
|
+
|
|
50
|
+
| ์ํฉ | ๊ณต๊ฐ ์ฌ๋กฏ | ๋จ๊ฒจ์ผ ํ๋ ๊ฒ |
|
|
51
|
+
| --- | --- | --- |
|
|
52
|
+
| ์์ธ ์ต์ด ์กฐํ | detail.state=loading | ์จ๊ฒจ์ง ๋ชฉ๋ก์ ๊ฒ์ยท์ ํยท์คํฌ๋กค |
|
|
53
|
+
| ์์ธ ์กฐํ ์คํจ | detail.state=error + detail.stateAction | ์์ธ ์ ๋ชฉยท๋ชฉ๋ก์ผ๋ก ๋์๊ฐ๊ธฐ |
|
|
54
|
+
| ์ด๋ฏธ ์ฝ์ ์์ธ ์ฌ์กฐํ ์คํจ | detail.state=ready + detail.notice | ๊ธฐ์กด ์์ธ ๋ด์ฉ |
|
|
55
|
+
| ๋ชฉ๋ก ์ถ๊ฐ ์กฐํ ์คํจ | list ์ LoadMore | ์ด๋ฏธ ํ์๋ ํยทํ์ด์ง cursor |
|
|
56
|
+
| ์์ธ ๋ซ๊ธฐ | detail ์๋ต | ์๋ ๋ชฉ๋ก์ผ๋ก ๋ณต๊ท, Web ์๋ ํฌ์ปค์ค ๋ณต์ |
|
|
57
|
+
|
|
58
|
+
์ ํ id๊ฐ ๋ฐ๋๊ฑฐ๋ ์์ธ๋ฅผ ๋ซ์ผ๋ฉด ํด๋น ์์ฒญ์ ์ทจ์ํ๊ฑฐ๋ ๋ฆ์ ์๋ต์ ๋ฌด์ํ๋ค.
|
|
59
|
+
์์ธ ์์ฒญ ์คํจ๋ฅผ ๋ชฉ๋ก `state=error`๋ก ๋๊ธฐ๋ฉด ๋ณต๊ทํ ๋ชฉ๋ก๊น์ง ์ฌ๋ผ์ง๋ค.
|
|
43
60
|
|
|
44
61
|
## ์ฌ์ฉํ๋ ์ง์นจ
|
|
45
62
|
|
|
@@ -59,7 +76,7 @@ import { ListDetailScreen } from "@hjmds/react/screen-flows";
|
|
|
59
76
|
<ListDetailScreen
|
|
60
77
|
title={t("orders.title")}
|
|
61
78
|
list={<List label={t("orders.list")}>{rows}</List>}
|
|
62
|
-
{...(selected ? { detail: { title: selected.name, content: <OrderDetail order={selected}
|
|
79
|
+
{...(selected ? { detail: { title: selected.name, content: <OrderDetail order={selected} />, state: detailState, stateAction: detailRetry, notice: detailNotice } } : {})}
|
|
63
80
|
back={{ label: t("common.back"), onAction: () => setSelected(null) }}
|
|
64
81
|
refresh={{ label: t("common.refresh"), onAction: refetch, pending: isRefetching }}
|
|
65
82
|
/>
|
|
@@ -73,24 +90,36 @@ import { ListDetailScreen } from "@hjmds/react-native/screen-flows";
|
|
|
73
90
|
<ListDetailScreen
|
|
74
91
|
title={t("orders.title")}
|
|
75
92
|
list={<List label={t("orders.list")}>{rows}</List>}
|
|
76
|
-
{...(selected ? { detail: { title: selected.name, content: <OrderDetail order={selected}
|
|
93
|
+
{...(selected ? { detail: { title: selected.name, content: <OrderDetail order={selected} />, state: detailState, stateAction: detailRetry, notice: detailNotice } } : {})}
|
|
77
94
|
back={{ label: t("common.back"), onAction: () => setSelected(null) }}
|
|
78
95
|
refresh={{ label: t("common.refresh"), onAction: refetch, pending: isRefetching }}
|
|
79
96
|
/>
|
|
80
97
|
```
|
|
81
98
|
|
|
99
|
+
`detailState`๋ `{ kind: "ready" }` ๋๋ ์ง์ญํ๋ title์ ๊ฐ์ง loading/error/restricted ์ํ๋ค.
|
|
100
|
+
`detailRetry`๋ ํด๋น id๋ง ๋ค์ ์กฐํํ๋ Button, `detailNotice`๋ ๊ธฐ์กด ์์ธ๋ฅผ ์ ์งํ๋ Notice๋ค.
|
|
101
|
+
|
|
102
|
+
<!-- usage-example: Web ../../../../../showcase/web/src/patterns/list-detail-recovery-preview.tsx -->
|
|
103
|
+
- [Web ์์ธ ๋ณต๊ตฌ ์คํ ์์ ](../../../../../showcase/web/src/patterns/list-detail-recovery-preview.tsx)
|
|
104
|
+
<!-- usage-example: Native ../../../../../showcase/native/src/list-detail-recovery-preview.tsx -->
|
|
105
|
+
- [Native ์์ธ ๋ณต๊ตฌ ์คํ ์์ ](../../../../../showcase/native/src/list-detail-recovery-preview.tsx)
|
|
106
|
+
|
|
107
|
+
์คํ ๋ฆฌ `์์ธ ์กฐํ ์คํจ์ ๋ณต๊ตฌ`: ๋ชฉ๋ก ๋ฉ๋ชจ ์
๋ ฅ โ ๋ค์ ์์ธ ์กฐํ ์คํจ์ํค๊ธฐ โ ํญ๋ชฉ ์ด๊ธฐ โ
|
|
108
|
+
์์ธ๋ง ๋ค์ ๋ถ๋ฌ์ค๊ธฐ โ ๋ชฉ๋ก์ผ๋ก ๋ณต๊ทํด ๋ฉ๋ชจ ์ ์ง ํ์ธ. ์์ ์ ์ง์ฐยท์๋ฒ ์๋ต์ ๋ฉ๋ชจ๋ฆฌ ๋ชจ์๋ค.
|
|
109
|
+
|
|
82
110
|
์ฝ๋ฐฑยท๋ฐ์ดํฐยท์ง์ญํ ํจ์๋ ์ ํ์์ ๊ณต๊ธํ๋ค. WebยทNative import์ ํ์ props๋ ์ API ์ง์นจ์์ ํ์ธํ๋ค.
|
|
83
111
|
|
|
84
|
-
##
|
|
112
|
+
## ๋คํฌยท์ข์ ํญ
|
|
85
113
|
|
|
86
114
|
| ์กฐ๊ฑด | ๋ฐ๋๋ ๊ฒ |
|
|
87
115
|
| --- | --- |
|
|
88
|
-
| ํฐ ๊ธ์ | 2๋ฐฐ ๊ธ์์์ ์ ๋ชฉยทํ์ ๋ด์ฉ ๋์ด๋ก ์ฆ๊ฐ. footerยท๋ซ๊ธฐยท์
๋ ฅ ํ๋๊ฐ ๊ฒน์น์ง ์๋์ง ํ์ธ |
|
|
89
116
|
| ๋คํฌ | semantic ์์ผ๋ก ๋ด์ฉ๊ณผ ํ๋ฉด์ ํจ๊ป ์ ํ; ์์ ๋ธ๋๋ ์์ ์ ํ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ๋ณต์ฌํ์ง ์์ |
|
|
90
117
|
| ์ข์ ํญ | 320px๋ถํฐ ํ ์ด๋ก ์ฝ๊ธฐ ์์ ์ ์ง. ๊ฐ์ํ ๋ณธ๋ฌธ์ scroll=content, ์ค์ฒฉ ์คํฌ๋กค ๊ธ์ง |
|
|
91
118
|
| ํค๋ณด๋ | Native host๊ฐ safe area์ ํค๋ณด๋๋ฅผ ํ ๋ฒ ์ฒ๋ฆฌ; Web์ ํฌ์ปค์ค๋ ์
๋ ฅ๊ณผ footer ๊ฐ๋ฆผ ํ์ธ |
|
|
92
119
|
|
|
93
120
|
## ํจ์
|
|
94
121
|
|
|
95
|
-
- ๋ชฉ๋ก pane ์ ์ง; ์์ธ ์คํจ๋ detail.
|
|
96
|
-
- Storybook์ ์ค์ ์๋ฒยทOS ๊ถํยท๋ผ์ฐํฐ ์ฐ๋ ์ฆ๊ฑฐ๊ฐ ์๋๋ค.
|
|
122
|
+
- ๋ชฉ๋ก pane ์ ์ง; ์์ธ ์คํจ๋ detail.stateยทdetail.stateAction์ผ๋ก ๋ณต๊ตฌ.
|
|
123
|
+
- Storybook์ ์ค์ ์๋ฒยทOS ๊ถํยท๋ผ์ฐํฐ ์ฐ๋ ์ฆ๊ฑฐ๊ฐ ์๋๋ค. ๊ธฐ๋ณธยท๋คํฌ์ ์คํจ/๋ณต๊ตฌ๋ฅผ ๊ฐ๊ฐ ํ์ธํ๋ค.
|
|
124
|
+
|
|
125
|
+
2026-10-13 ์ค์ ์์ ์ฐ๊ฒฐ ๊ฒ์: ์ ๊ธฐ๋ก์ ๋น ์ด์์ผ๋ก ์์ํ๊ณ , ์ฑ๊ณตํ ์ ๋ชฉยท๋ณธ๋ฌธ์ ๊ณ ์ ID์ ๋ชฉ๋ก ํญ๋ชฉ์ ํจ๊ป ๋ณด๊ดํ๋ค. ๋ค๋ฅธ ๊ธฐ๋ก ์์ธ๋ ํ์ฌ ํธ์ง ์ด์์ ์ฝ์ง ์๋๋ค. ์ ์ฅ ์ฑ๊ณต ์ ์ ์ฒด ๋ชฉ๋ก์ผ๋ก ๋์๊ฐ ์ ํญ๋ชฉ์ ๋ณด์ด๋ฉฐ, ๋น ๋ชฉ๋ก์์ ์์ฑํ ๋ค์๋ ready๋ก ์ ํํ๋ค. ํํฐ์ ์ ๊ธฐ๋ก ํ๋์ ํ์ํด๋ ์๋ก๊ณ ์นจ ์คํจ Notice๋ฅผ ๋ฎ์ด์ฐ์ง ์๋๋ค.
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
- ๋จ๊ณ: ํ๋ฉด
|
|
4
4
|
- ์ํ: ๋ฐฐํฌ
|
|
5
5
|
- ์ง์: Web ยท Native
|
|
6
|
-
- ์ ์ฉ:
|
|
7
|
-
- ๊ฒํ ์ผ: 2026-10-
|
|
6
|
+
- ์ ์ฉ: ๊ตฌ์ฑ API ์ง์นจ ์ฐธ์กฐ
|
|
7
|
+
- ๊ฒํ ์ผ: 2026-10-13
|
|
8
8
|
- ๊ทผ๊ฑฐ: [๋ฐ๋ณต ํ๋ฉด ์กฐํฉ](../../screen-patterns.md); ๊ณตํต API์ ์ค์ WebยทNative ์์ ์ ์ฌ๋กฏยท์ํ๋ฅผ ๋์กฐํด ์ค๋ณต ์กฐ๋ฆฝ ๋ฐฉ์ง. 2026-10-06 ์ฌ์ฉ์ ์น์ธ์ผ๋ก ์คํ ๋ฆฌ๋ถ ๋ฐฐํฌ(์ด์ `์คํ/ํ๋ฉด/๊ธฐ๋ณธ ํ๋ฆ/์์ฑ๊ณผ ์์ `, [์น์ธ ๊ธฐ๋ก](../../../../../docs/STORYBOOK_NAVIGATION.md#21-2026-10-06-์ ์ฒด-์น๊ฒฉ๊ณผ-๊ท๊ฒฉ-ํ์ ))
|
|
9
9
|
- ์คํ ๋ฆฌ๋ถ: `๋ฐฐํฌ/ํ๋ฉด/์ฝํ
์ธ /์์ฑ๊ณผ ์์ `
|
|
10
10
|
|
|
@@ -41,6 +41,23 @@ host: ๋จ์ ๋์ดยทsafe areaยทํค๋ณด๋
|
|
|
41
41
|
| ๋น | ์ค์ ์กฐํ 0๊ฑด ๋๋ ์์ง ์์ฑํ์ง ์์ ์ํ ์๋ด | ์์ยท์กฐ๊ฑด ํด์ ๋ฑ ๋งฅ๋ฝ์ ๋ง๋ ๋์ |
|
|
42
42
|
| ์ค๋ฅ | ์ ์ฅ ์คํจ๋ ์
๋ ฅ ์ ์ง; ์ ์ฅ ์ฑ๊ณต ํ์ธ ํ์๋ง dirty ํด์ | ์คํจ ์์ธ๊ณผ ์ฌ์๋ ๊ฒฝ๋ก ์ ๊ณต |
|
|
43
43
|
|
|
44
|
+
|
|
45
|
+
### ์ด์๊ณผ ์๋ฒ ํ์
|
|
46
|
+
|
|
47
|
+
2026-10-13 ์ ์ ์ ๊ฒ์์ ์ต์ด ์กฐํ์ ๋ณ๊ฒฝ ์์ฒญ์ ์ํ๋ฅผ ๊ฐ์ ๊ณจ๊ฒฉ์ผ๋ก ์ค๋ช
ํ๋ ๋ถ๋ถ์ ๊ตฌ์ฒดํํ๋ค.
|
|
48
|
+
|
|
49
|
+
| ์ํฉ | ์ฐ๊ฒฐ | ์ ์งยท๋ณต๊ตฌ |
|
|
50
|
+
| --- | --- | --- |
|
|
51
|
+
| ์ ์์ฑ | ready + ๋น ์
๋ ฅ | ๋น ์ด์์ ํ๋ฉด empty๊ฐ ์๋๋ค. ์
๋ ฅ์ ๋ฐ๋ก ๋ณด์ฌ ์ค๋ค |
|
|
52
|
+
| ์ ์ฅ ์์ | submit.pending + ์ ์ถ snapshot | cancel๊ณผ ์ด๋ฏธ ์ด๋ฆฐ ์ด์ ๋ฒ๋ฆฌ๊ธฐ ํ์ธ์ HJM์ด ์ ๊ทผ๋ค. ํ์ธ์ฐฝ์ ์ข
๋ฃํ๋ฉฐ ์
๋ ฅ ์ ๊ธยท์ถ๊ฐ ์์ฒญ ์ฐจ๋จ์ ์ ํ์ด ์ฐ๊ฒฐํ๋ค |
|
|
53
|
+
| ์ ์ฅ ์คํจ | ready ์ ์ง + notice | dirty๋ฅผ ํด์ ํ๊ฑฐ๋ ์
๋ ฅ์ ๋ค์ mountํ์ง ์๋๋ค |
|
|
54
|
+
| ์ ์ฅ ์ฑ๊ณต | ์ ์ถ snapshot์ saved๋ก ๊ฐฑ์ | ์์ฒญ ํ ์๋ก ์ด ๋ด์ฉ๊น์ง saved๋ก ์ฒ๋ฆฌํ์ง ์๋๋ค. draftStatus๋ ์ค์ ์์ ์ ์ฅ ์ฑ๊ณต ๋๋ง ํ์ํ๋ค |
|
|
55
|
+
| ๋ธ๋ผ์ฐ์ ยทOS ๋ค๋ก | ์ ํ router์ ์ดํ ๊ฐ๋ | EditorScreen cancel์ discard์ ๊ฐ์ ์ ํ ๊ฒฐ์ ์ ๊ณต์ ํ๋ค |
|
|
56
|
+
|
|
57
|
+
๋ณธ๋ฌธ์ด ready๊ฐ ์๋ ์ต์ด ์กฐํยท์ค๋ฅยท์ ํ ์ํ์์๋ ํค๋/ํ๋จ ์ด๋ ์์น์ ์ ์ฅ๋ ๋นํ์ฑ์ด๋ค.
|
|
58
|
+
2026-10-13 ์
๋ ฅ์ ํ์ํ์ง ์๋ ์ํ์์๋ ์ ์ฅํ ์ ์๋ ๊ฒฝ๋ก๋ฅผ ์์ ํ๋ค. ์คํจํ ์ ์ฅ์
|
|
59
|
+
๋ณธ๋ฌธ์ ์ค๋ฅ ํ๋ฉด์ผ๋ก ๊ต์ฒดํ์ง ์๊ณ ์ ํ์ฒ๋ผ ready + notice๋ก ์ ์งํ๋ค.
|
|
60
|
+
|
|
44
61
|
## ์ฌ์ฉํ๋ ์ง์นจ
|
|
45
62
|
|
|
46
63
|
| ์ง์นจ | ์ฐ๋ ๊ณณ |
|
|
@@ -71,7 +88,7 @@ import { TextField } from "@hjmds/react/forms";
|
|
|
71
88
|
tone: "danger",
|
|
72
89
|
fallbackErrorMessage: t("common.error"),
|
|
73
90
|
}}
|
|
74
|
-
draftStatus={<Text variant="caption" tone="muted">{
|
|
91
|
+
draftStatus={draftStatus ? <Text variant="caption" tone="muted">{draftStatus}</Text> : null}
|
|
75
92
|
>
|
|
76
93
|
<TextField label={t("post.edit.body")} value={draft} onValueChange={setDraft} />
|
|
77
94
|
</EditorScreen>
|
|
@@ -97,7 +114,7 @@ import { TextField } from "@hjmds/react-native/inputs";
|
|
|
97
114
|
tone: "danger",
|
|
98
115
|
fallbackErrorMessage: t("common.error"),
|
|
99
116
|
}}
|
|
100
|
-
draftStatus={<Text variant="caption" tone="muted">{
|
|
117
|
+
draftStatus={draftStatus ? <Text variant="caption" tone="muted">{draftStatus}</Text> : null}
|
|
101
118
|
>
|
|
102
119
|
<TextField label={t("post.edit.body")} value={draft} onValueChange={setDraft} />
|
|
103
120
|
</EditorScreen>
|
|
@@ -105,11 +122,10 @@ import { TextField } from "@hjmds/react-native/inputs";
|
|
|
105
122
|
|
|
106
123
|
์ฝ๋ฐฑยท๋ฐ์ดํฐยท์ง์ญํ ํจ์๋ ์ ํ์์ ๊ณต๊ธํ๋ค. WebยทNative import์ ํ์ props๋ ์ API ์ง์นจ์์ ํ์ธํ๋ค.
|
|
107
124
|
|
|
108
|
-
##
|
|
125
|
+
## ๋คํฌยท์ข์ ํญ
|
|
109
126
|
|
|
110
127
|
| ์กฐ๊ฑด | ๋ฐ๋๋ ๊ฒ |
|
|
111
128
|
| --- | --- |
|
|
112
|
-
| ํฐ ๊ธ์ | 2๋ฐฐ ๊ธ์์์ ์ ๋ชฉยทํ์ ๋ด์ฉ ๋์ด๋ก ์ฆ๊ฐ. footerยท๋ซ๊ธฐยท์
๋ ฅ ํ๋๊ฐ ๊ฒน์น์ง ์๋์ง ํ์ธ |
|
|
113
129
|
| ๋คํฌ | semantic ์์ผ๋ก ๋ด์ฉ๊ณผ ํ๋ฉด์ ํจ๊ป ์ ํ; ์์ ๋ธ๋๋ ์์ ์ ํ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ๋ณต์ฌํ์ง ์์ |
|
|
114
130
|
| ์ข์ ํญ | 320px๋ถํฐ ํ ์ด๋ก ์ฝ๊ธฐ ์์ ์ ์ง. ๊ฐ์ํ ๋ณธ๋ฌธ์ scroll=content, ์ค์ฒฉ ์คํฌ๋กค ๊ธ์ง |
|
|
115
131
|
| ํค๋ณด๋ | Native host๊ฐ safe area์ ํค๋ณด๋๋ฅผ ํ ๋ฒ ์ฒ๋ฆฌ; Web์ ํฌ์ปค์ค๋ ์
๋ ฅ๊ณผ footer ๊ฐ๋ฆผ ํ์ธ |
|
|
@@ -117,4 +133,6 @@ import { TextField } from "@hjmds/react-native/inputs";
|
|
|
117
133
|
## ํจ์
|
|
118
134
|
|
|
119
135
|
- ์ ์ฅ ์คํจ๋ ์
๋ ฅ ์ ์ง; ์ ์ฅ ์ฑ๊ณต ํ์ธ ํ์๋ง dirty ํด์ .
|
|
120
|
-
- Storybook์ ์ค์ ์๋ฒยทOS ๊ถํยท๋ผ์ฐํฐ ์ฐ๋ ์ฆ๊ฑฐ๊ฐ ์๋๋ค.
|
|
136
|
+
- Storybook์ ์ค์ ์๋ฒยทOS ๊ถํยท๋ผ์ฐํฐ ์ฐ๋ ์ฆ๊ฑฐ๊ฐ ์๋๋ค. ๊ธฐ๋ณธยท๋คํฌ์ ์คํจ/๋ณต๊ตฌ๋ฅผ ๊ฐ๊ฐ ํ์ธํ๋ค.
|
|
137
|
+
|
|
138
|
+
2026-10-13 ์ค์ ์์ ์ฐ๊ฒฐ ๊ฒ์: ์ ์ฅ ์ค ์
๋ ฅ์ Web readOnlyยทNative disabled๋ก ์ ๊ทธ๊ณ , ๊ฐ์ ๋ ๋ ์ฌ์ด์ ๋ค์ด์จ ์ ์ฅ ์์ฒญ๋ ๋๊ธฐ ์ ๊ธ์ผ๋ก ํ ๋ฒ๋ง ์ฒ๋ฆฌํ๋ค. ์คํจ ์์ฝ์ ์์ฒญ ์์ ๋ ์๋นํ๋ฉฐ ์งํ ์ค ์์ฝ ๋ณ๊ฒฝ์ ๋ฌด์ํ๋ค. ์คํจ ํ ํ์ฌ ์ด์์ผ๋ก ์ฌ์๋ํ๊ณ , ํ๊ธฐํ๋ฉด ๋ง์ง๋ง์ผ๋ก ํ์ ํ snapshot์ผ๋ก ๋์๊ฐ๋ค. ์์ ์ 400ms ์ง์ฐ๊ณผ ๋ฉ๋ชจ๋ฆฌ ์ ์ฅ์ ์๋ฒ ์ ์ฅ ์ฆ๊ฑฐ๊ฐ ์๋๋ค.
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
- ๋จ๊ณ: ํ๋ฉด
|
|
4
4
|
- ์ํ: ๋ฐฐํฌ
|
|
5
5
|
- ์ง์: Web ยท Native
|
|
6
|
-
- ์ ์ฉ:
|
|
7
|
-
- ๊ฒํ ์ผ: 2026-10-
|
|
6
|
+
- ์ ์ฉ: ๊ตฌ์ฑ API ์ง์นจ ์ฐธ์กฐ
|
|
7
|
+
- ๊ฒํ ์ผ: 2026-10-13
|
|
8
8
|
- ๊ทผ๊ฑฐ: [๋ฐ๋ณต ํ๋ฉด ์กฐํฉ](../../screen-patterns.md); ๊ณตํต API์ ์ค์ WebยทNative ์์ ์ ์ฌ๋กฏยท์ํ๋ฅผ ๋์กฐํด ์ค๋ณต ์กฐ๋ฆฝ ๋ฐฉ์ง. 2026-10-06 ์ฌ์ฉ์ ์น์ธ์ผ๋ก ์คํ ๋ฆฌ๋ถ ๋ฐฐํฌ(์ด์ `์คํ/ํ๋ฉด/๊ธฐ๋ณธ ํ๋ฆ/์ฌ์ง ์ ํ๊ณผ ์
๋ก๋`, [์น์ธ ๊ธฐ๋ก](../../../../../docs/STORYBOOK_NAVIGATION.md#21-2026-10-06-์ ์ฒด-์น๊ฒฉ๊ณผ-๊ท๊ฒฉ-ํ์ ))
|
|
9
9
|
- ์คํ ๋ฆฌ๋ถ: `๋ฐฐํฌ/ํ๋ฉด/์ฝํ
์ธ /์ฌ์ง ์ ํ๊ณผ ์
๋ก๋`
|
|
10
10
|
|
|
@@ -41,6 +41,21 @@ host: ๋จ์ ๋์ดยทsafe areaยทํค๋ณด๋
|
|
|
41
41
|
| ๋น | ์ค์ ์กฐํ 0๊ฑด ๋๋ ์์ง ์์ฑํ์ง ์์ ์ํ ์๋ด | ์์ยท์กฐ๊ฑด ํด์ ๋ฑ ๋งฅ๋ฝ์ ๋ง๋ ๋์ |
|
|
42
42
|
| ์ค๋ฅ | ์
๋ก๋ ์คํจ ํญ๋ชฉ๋ง ์ฌ์๋, ์๋ฃ ๋ฒํผ์ ์ ํ ์ ์ฑ
์ผ๋ก ์ ํ | ์คํจ ์์ธ๊ณผ ์ฌ์๋ ๊ฒฝ๋ก ์ ๊ณต |
|
|
43
43
|
|
|
44
|
+
|
|
45
|
+
### ํญ๋ชฉ๋ณ ์
๋ก๋์ ์๋ฃ ์กฐ๊ฑด
|
|
46
|
+
|
|
47
|
+
WebยทNative `media-picker-preview.tsx`๋ ์ต๋ 5์ฅ์ ์์๋๋ก ๊ณ ๋ฅธ ๋ค ๊ณตํต `items` ๊ฒฉ์์์ ๋ฉ๋ชจ๋ฆฌ ์
๋ก๋๋ฅผ ์์ฐํ๋ค. `์คํจ์ ๋ณต๊ตฌ`๋ ์ฒซ ํญ๋ชฉ ํ ๋ฒ๋ง ์คํจํ๋ฉฐ, ํญ๋ชฉ์ ์ฌ์๋๋ก ํด๋น ์ฌ์ง๋ง ๋ค์ ์ฒ๋ฆฌํ๋ค. ์
๋ก๋ยท์คํจยท0์ฅ ์ํ์์๋ ์๋ฃ๋ฅผ ๋ง๊ณ , ์ฌ์ง ์ ๊ฑฐยท์ ํ ํ๋ฉด ๋ณต๊ท ๋ค ๋์ฐฉํ ์ด์ ๊ฒฐ๊ณผ๋ ๋ฌด์ํ๋ค. ๋ชจ๋ ์ฑ๊ณตํ ๋ค ์๋ฃํ๋ฉด ์์๋ฅผ ํฌํจํ ์ฝ๊ธฐ ์ ์ฉ ๊ฒฐ๊ณผ๊ฐ ๋จ๊ณ `์๋ก ์ ํ`์ผ๋ก ์ด๊ธฐํํ๋ค. `showcase/shared/media-picker-example.ts`๋ ์ด ์์ ๋ง์ ๋ฉ๋ชจ๋ฆฌ ์ด๋ํฐ์ด๋ฉฐ ์ค์ OS ์ฌ์ง ์ ๊ทผยท๊ถํ์ด๋ ์๋ฒ ์
๋ก๋๋ฅผ ์ํํ์ง ์๋๋ค.
|
|
48
|
+
|
|
49
|
+
2026-10-13 ์ ์ ์ ๊ฒ์์ ์ต์ด ์กฐํ์ ๋ณ๊ฒฝ ์์ฒญ์ ์ํ๋ฅผ ๊ฐ์ ๊ณจ๊ฒฉ์ผ๋ก ์ค๋ช
ํ๋ ๋ถ๋ถ์ ๊ตฌ์ฒดํํ๋ค.
|
|
50
|
+
|
|
51
|
+
| ์ํฉ | ์ฐ๊ฒฐ | ์ ์งยท๋ณต๊ตฌ |
|
|
52
|
+
| --- | --- | --- |
|
|
53
|
+
| ์ ํ 0๊ฐ | empty + add | ์ ์ฌ์ง ์ ํ์ ๊ณ์ ๊ฐ๋ฅํ๊ณ done์ ์ ํ ์ ์ฑ
์ ๋ฐ๋ผ ์ ๊ทผ๋ค |
|
|
54
|
+
| ์
๋ก๋ ํผ์ฌ | ์ธ๋ค์ผยท์์์ ๊ฐ UploadItem ์ํ ์ ์ง | ์คํจํ ํญ๋ชฉ๋ง ์ฌ์๋ํ๋ค. ์ฑ๊ณตํ ์ฌ์ง์ ๋ค์ ์
๋ก๋ํ์ง ์๋๋ค |
|
|
55
|
+
| ์๋ฃ ๊ฐ๋ฅ | ํ์ ํญ๋ชฉ ๋ชจ๋ ์๋ฒ ํ์ | ์
๋ก๋ ์ค์ด ์๋์ด๋ ์คํจยท์ทจ์ ํญ๋ชฉ์ด ๋จ์ผ๋ฉด done์ ๋ฐ๋ก ํ์ฑํํ์ง ์๋๋ค |
|
|
56
|
+
| ๊ถํ ์ ํ | restricted + ๊ถํ ์๋ด ํ๋ | ๋ก์ปฌ ์ธ๋ค์ผ์ด ์กด์ฌํ๋ค๋ ์ด์ ๋ก OS ์ ๊ทผ ๊ถํ์ ์ป์๋ค๊ณ ํ๋จํ์ง ์๋๋ค |
|
|
57
|
+
| ์ ๊ฑฐยท์ทจ์ | ์ ํ์ด ์์ฒญ ์ทจ์ ๋ฐ id๋ณ ๊ฒฐ๊ณผ ๋ฌด์ | ๋ฆ์ ์๋ต์ด ์ ๊ฑฐํ ์ฌ์ง์ ๋ค์ ์ถ๊ฐํ์ง ์๊ฒ ํ๋ค |
|
|
58
|
+
|
|
44
59
|
## ์ฌ์ฉํ๋ ์ง์นจ
|
|
45
60
|
|
|
46
61
|
| ์ง์นจ | ์ฐ๋ ๊ณณ |
|
|
@@ -60,7 +75,7 @@ import { MediaSelectionScreen } from "@hjmds/react/screen-flows";
|
|
|
60
75
|
items={picked.map((p) => ({ descriptor: { id: p.id, name: p.fileName, state: p.upload },
|
|
61
76
|
preview: <img src={p.uri} alt="" width={p.width} height={p.height} /> }))}
|
|
62
77
|
add={{ label: t("media.add"), onAction: openPicker }}
|
|
63
|
-
done={{ label: t("media.done"), onAction: submit, disabled: uploading }}
|
|
78
|
+
done={{ label: t("media.done"), onAction: submit, disabled: uploading || !canComplete }}
|
|
64
79
|
labels={{ pending: t("upload.pending"), uploading: t("upload.uploading"),
|
|
65
80
|
success: t("upload.success"), cancel: t("upload.cancel"), retry: t("upload.retry") }}
|
|
66
81
|
actionLabels={{ remove: t("media.remove"), moveUp: t("media.moveUp"), moveDown: t("media.moveDown") }}
|
|
@@ -82,7 +97,7 @@ import { Image } from "react-native";
|
|
|
82
97
|
items={picked.map((p) => ({ descriptor: { id: p.id, name: p.fileName, state: p.upload },
|
|
83
98
|
preview: <Image src={p.uri} width={p.width} height={p.height} /> }))}
|
|
84
99
|
add={{ label: t("media.add"), onAction: openPicker }}
|
|
85
|
-
done={{ label: t("media.done"), onAction: submit, disabled: uploading }}
|
|
100
|
+
done={{ label: t("media.done"), onAction: submit, disabled: uploading || !canComplete }}
|
|
86
101
|
labels={{ pending: t("upload.pending"), uploading: t("upload.uploading"),
|
|
87
102
|
success: t("upload.success"), cancel: t("upload.cancel"), retry: t("upload.retry") }}
|
|
88
103
|
actionLabels={{ remove: t("media.remove"), moveUp: t("media.moveUp"), moveDown: t("media.moveDown") }}
|
|
@@ -94,13 +109,14 @@ import { Image } from "react-native";
|
|
|
94
109
|
/>
|
|
95
110
|
```
|
|
96
111
|
|
|
112
|
+
`canComplete`๋ ํ์ ํ์ผ์ ์ฑ๊ณตยท์ ํ ๊ฐ์ ๋ฑ ์ ํ ์๋ฃ ์กฐ๊ฑด์ด๋ค. ๋จ์ํ uploading=false์ธ ์คํจ ์ํ๋ฅผ ์๋ฃ๋ก ์ทจ๊ธํ์ง ์๋๋ค.
|
|
113
|
+
|
|
97
114
|
์ฝ๋ฐฑยท๋ฐ์ดํฐยท์ง์ญํ ํจ์๋ ์ ํ์์ ๊ณต๊ธํ๋ค. WebยทNative import์ ํ์ props๋ ์ API ์ง์นจ์์ ํ์ธํ๋ค. ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์ด๋ฏธ์ง๋ ์ ํ์ด ๊ณต๊ธํ๋ค(Web `img`, Native `Image`).
|
|
98
115
|
|
|
99
|
-
##
|
|
116
|
+
## ๋คํฌยท์ข์ ํญ
|
|
100
117
|
|
|
101
118
|
| ์กฐ๊ฑด | ๋ฐ๋๋ ๊ฒ |
|
|
102
119
|
| --- | --- |
|
|
103
|
-
| ํฐ ๊ธ์ | 2๋ฐฐ ๊ธ์์์ ์ ๋ชฉยทํ์ ๋ด์ฉ ๋์ด๋ก ์ฆ๊ฐ. footerยท๋ซ๊ธฐยท์
๋ ฅ ํ๋๊ฐ ๊ฒน์น์ง ์๋์ง ํ์ธ |
|
|
104
120
|
| ๋คํฌ | semantic ์์ผ๋ก ๋ด์ฉ๊ณผ ํ๋ฉด์ ํจ๊ป ์ ํ; ์์ ๋ธ๋๋ ์์ ์ ํ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ๋ณต์ฌํ์ง ์์ |
|
|
105
121
|
| ์ข์ ํญ | ๊ธฐ๋ณธ ๊ฒฉ์๋ `minColumnWidth` ์์ด `columns={{ compact: 2, expanded: 3 }}`๋ผ 320px์์๋ 2์ด์ด๋ค(ํ ์ด๋ก ์ ์ง ์๋๋ค). 960 ๋ฏธ๋ง 2์ด, ์ด์ 3์ด. ์ด๋ยท์ ๊ฑฐ ๋ฒํผ ํ์ ์ค๋ฐ๊ฟ๋๋ค. ํ ์ด์ด ํ์ํ๋ฉด `library` ์ฌ๋กฏ์ผ๋ก ์ ํ ๊ฒฉ์๋ฅผ ๋๊ธด๋ค |
|
|
106
122
|
| ํค๋ณด๋ | Native host๊ฐ safe area์ ํค๋ณด๋๋ฅผ ํ ๋ฒ ์ฒ๋ฆฌ; Web์ ํฌ์ปค์ค๋ ์
๋ ฅ๊ณผ footer ๊ฐ๋ฆผ ํ์ธ |
|
|
@@ -108,4 +124,4 @@ import { Image } from "react-native";
|
|
|
108
124
|
## ํจ์
|
|
109
125
|
|
|
110
126
|
- ์
๋ก๋ ์คํจ ํญ๋ชฉ๋ง ์ฌ์๋, ์๋ฃ ๋ฒํผ์ ์ ํ ์ ์ฑ
์ผ๋ก ์ ํ.
|
|
111
|
-
- Storybook์ ์ค์ ์๋ฒยทOS ๊ถํยท๋ผ์ฐํฐ ์ฐ๋ ์ฆ๊ฑฐ๊ฐ ์๋๋ค.
|
|
127
|
+
- Storybook์ ์ค์ ์๋ฒยทOS ๊ถํยท๋ผ์ฐํฐ ์ฐ๋ ์ฆ๊ฑฐ๊ฐ ์๋๋ค. ๊ธฐ๋ณธยท๋คํฌ์ ์คํจ/๋ณต๊ตฌ๋ฅผ ํ์ธํ๋ค. ์ต๋ ๊ธ์์ ์ด๋ฅผ ๋ชจ์ฌํ๋ ํ๋ ์กฐ๊ฑด์ ๊ณตํต ์ฌ์ฉ์ ์ง์นจ์ ๋ฐ๋ผ ๊ฒ์ฆยท์ค๊ณ ๊ณ ๋ ค์์ ์ ์ธํ๋ค.
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
- ๋จ๊ณ: ํ๋ฉด
|
|
4
4
|
- ์ํ: ๋ฐฐํฌ
|
|
5
5
|
- ์ง์: Web ยท Native
|
|
6
|
-
- ์ ์ฉ:
|
|
7
|
-
- ๊ฒํ ์ผ: 2026-10-
|
|
6
|
+
- ์ ์ฉ: ๊ตฌ์ฑ API ์ง์นจ ์ฐธ์กฐ
|
|
7
|
+
- ๊ฒํ ์ผ: 2026-10-13
|
|
8
8
|
- ๊ทผ๊ฑฐ: [๋ฐ๋ณต ํ๋ฉด ์กฐํฉ](../../screen-patterns.md); ๊ณตํต API์ ์ค์ WebยทNative ์์ ์ ์ฌ๋กฏยท์ํ๋ฅผ ๋์กฐํด ์ค๋ณต ์กฐ๋ฆฝ ๋ฐฉ์ง. 2026-10-06 ์ฌ์ฉ์ ์น์ธ์ผ๋ก ์คํ ๋ฆฌ๋ถ ๋ฐฐํฌ(์ด์ `์คํ/ํ๋ฉด/๊ธฐ๋ณธ ํ๋ฆ/์ ๊ณ ์ ์ฐจ๋จ`, [์น์ธ ๊ธฐ๋ก](../../../../../docs/STORYBOOK_NAVIGATION.md#21-2026-10-06-์ ์ฒด-์น๊ฒฉ๊ณผ-๊ท๊ฒฉ-ํ์ ))
|
|
9
9
|
- ์คํ ๋ฆฌ๋ถ: `๋ฐฐํฌ/ํ๋ฉด/์ํต/์ ๊ณ ์ ์ฐจ๋จ`
|
|
10
10
|
|
|
@@ -41,6 +41,19 @@ host: ๋จ์ ๋์ดยทsafe areaยทํค๋ณด๋
|
|
|
41
41
|
| ๋น | ์ค์ ์กฐํ 0๊ฑด ๋๋ ์์ง ์์ฑํ์ง ์์ ์ํ ์๋ด | ์์ยท์กฐ๊ฑด ํด์ ๋ฑ ๋งฅ๋ฝ์ ๋ง๋ ๋์ |
|
|
42
42
|
| ์ค๋ฅ | ์ ๊ณ ์คํจ์ ์ ํ ์ฌ์ ยท์ค๋ช
์ ์ง; ์ฐจ๋จ์ ์ฑ๊ณต ํ ํ์ | ์คํจ ์์ธ๊ณผ ์ฌ์๋ ๊ฒฝ๋ก ์ ๊ณต |
|
|
43
43
|
|
|
44
|
+
|
|
45
|
+
### ์ ๊ณ ์ ์ฐจ๋จ์ ์๋ก ๋ค๋ฅธ ๊ฒฐ๊ณผ
|
|
46
|
+
|
|
47
|
+
2026-10-13 ์ ์ ์ ๊ฒ์์ ์ต์ด ์กฐํ์ ๋ณ๊ฒฝ ์์ฒญ์ ์ํ๋ฅผ ๊ฐ์ ๊ณจ๊ฒฉ์ผ๋ก ์ค๋ช
ํ๋ ๋ถ๋ถ์ ๊ตฌ์ฒดํํ๋ค.
|
|
48
|
+
|
|
49
|
+
| ์ํฉ | ์ฐ๊ฒฐ | ์ ์งยท๋ณต๊ตฌ |
|
|
50
|
+
| --- | --- | --- |
|
|
51
|
+
| ์ฌ์ ๋ฏธ์ ํ | submit ๋นํ์ฑ | reason์ ํ์ฌ reasons์ ๊ฐ์ด์ด์ผ ํ๋ค |
|
|
52
|
+
| ์ ๊ณ ์คํจ | ์ ํ ์ฌ์ ยท์ค๋ช
์ ์ง + notice | ๋ค์ ์ ๊ณ ๋ ๊ฐ์ ๋์๊ณผ ํ์ฌ ์ด์์ผ๋ก ํ๋ค |
|
|
53
|
+
| ์ฐจ๋จ ํ์ธ ์ทจ์ | ๊ธฐ์กด ์ฐจ๋จ ์ํ ์ ์ง | ์ ๊ณ ์ด์์ ๋ณ๊ฐ์ด๋ฏ๋ก ์ง์ฐ์ง ์๋๋ค |
|
|
54
|
+
| ์ฐจ๋จ ์คํจ | AlertDialog ์ ์ง | Promise ์คํจ๋ฅผ ์ ๋ฌํ๋ค. ํ์ธ์ฐฝ์ ๋จผ์ ๋ซ๊ณ ์ฑ๊ณต ์ฒ๋ฆฌํ์ง ์๋๋ค |
|
|
55
|
+
| ๋์ ๋ณ๊ฒฝ | ๋์ id์ ์ด์ยท์์ฒญ ๋ฌถ์ ๊ฐฑ์ | ์ด์ ๋์์ ๋ฆ์ ์๋ต์ด ์ ๋์ ์ํ๋ฅผ ๋ฎ์ง ์๊ฒ ํ๋ค |
|
|
56
|
+
|
|
44
57
|
## ์ฌ์ฉํ๋ ์ง์นจ
|
|
45
58
|
|
|
46
59
|
| ์ง์นจ | ์ฐ๋ ๊ณณ |
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
- ๋จ๊ณ: ํ๋ฉด
|
|
4
4
|
- ์ํ: ๋ฐฐํฌ
|
|
5
5
|
- ์ง์: Web ยท Native
|
|
6
|
-
- ์ ์ฉ:
|
|
7
|
-
- ๊ฒํ ์ผ: 2026-10-
|
|
6
|
+
- ์ ์ฉ: ๊ตฌ์ฑ API ์ง์นจ ์ฐธ์กฐ
|
|
7
|
+
- ๊ฒํ ์ผ: 2026-10-13
|
|
8
8
|
- ๊ทผ๊ฑฐ: [๋ฐ๋ณต ํ๋ฉด ์กฐํฉ](../../screen-patterns.md), WebยทNative `src/screen-flows.tsx`(`OnboardingScreen`), ์์ `showcase/*/screen-flow-previews.tsx`(`OnboardingFlowPreview`)ยท`showcase/shared/onboarding-pattern.ts`(์ฃผ์ ยท์์ฝ). 2026-10-06 ์ฌ์ฉ์ ์น์ธ์ผ๋ก ์คํ `๊ธฐ๋ณธ ํ๋ฆ/์จ๋ณด๋ฉ`(OnboardingScreen)์ ๋ฐฐํฌํ๋ฉด์ ๊ฐ์ ์ผ์ ์ง์ ์กฐ๋ฆฝํ๋ ๋ฐฐํฌ `ํ๋ฉด/์จ๋ณด๋ฉ`์ ๋์ฒดํ๋ค(Web id `patterns-onboarding` ๋ณด์กด, [์น์ธ ๊ธฐ๋ก](../../../../../docs/STORYBOOK_NAVIGATION.md#21-2026-10-06-์ ์ฒด-์น๊ฒฉ๊ณผ-๊ท๊ฒฉ-ํ์ ))
|
|
9
9
|
- ์คํ ๋ฆฌ๋ถ: `๋ฐฐํฌ/ํ๋ฉด/์๊ฐ/์จ๋ณด๋ฉ`
|
|
10
10
|
|
|
@@ -188,7 +188,7 @@ const topicPicker = <Stack axis="inline" wrap gap="xs">
|
|
|
188
188
|
## ํจ์
|
|
189
189
|
|
|
190
190
|
- `notice` ์๋ฆฌ๋ ์งํ ๋ฌธ๊ตฌ๊ฐ ์ฐจ์งํ๋ค. ์ ์ฅ ์คํจ๋ฅผ ๋์ฐ๋ ค๊ณ OnboardingScreen์ notice๋ฅผ ๋๊ธธ ์ ์์ผ๋ ๋ง์ง๋ง ๋จ๊ณ `content`์ ๋๋ค.
|
|
191
|
-
- ์๋ฃ `pending`
|
|
191
|
+
- ์๋ฃ ๋๋ ๊ฑด๋๋ฐ๊ธฐ `pending` ๋์ HJM์ ์ด๋ ๋ฒํผ์ ํจ๊ป ์ ๊ทผ๋ค(๋ฏธ๊ฒ์(1.18.0 ์ดํ)). ์ ํ์ ๊ฐ์ ์๋ฃ ์์ฒญ์ pending์ ์ฐ๊ฒฐํ๊ณ , ์คํจํ๋ฉด ํ์ฌ ๋จ๊ณยท์ ํ๊ฐ์ ์ ์งํ ์ฑ ์ ๊ธ์ ํผ๋ค. ๋ผ์ฐํฐ ์ดํ์ ๋ณ๋๋ก ์ฐ๊ฒฐํ๋ค.
|
|
192
192
|
- ํ์ฌ ์คํ ๋ฆฌ์ ์งํ ๋ฌธ๊ตฌ๋ `` `${index} / ${total}` `` ๊ณ ์ ๋ฌธ์์ด์ด๋ค. ์ ํ์ ๋ณด๊ฐ ํค ํ๋(`onboarding.progress`)๋ฅผ ์ด๋ค.
|
|
193
193
|
- Storybook์ ์ค์ ์๋ฒยท๋ผ์ฐํฐ ์ฐ๋ ์ฆ๊ฑฐ๊ฐ ์๋๋ค. ๊ธฐ๋ณธยท์ด๋์ด ํ
๋งยทํฐ ๊ธ์์ ์คํจ์ ๋ณต๊ตฌ๋ฅผ ๊ฐ๊ฐ ํ์ธํ๋ค.
|
|
194
194
|
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
- ๋จ๊ณ: ํ๋ฉด
|
|
4
4
|
- ์ํ: ๋ฐฐํฌ
|
|
5
5
|
- ์ง์: Web ยท Native
|
|
6
|
-
- ์ ์ฉ:
|
|
7
|
-
- ๊ฒํ ์ผ: 2026-10-
|
|
6
|
+
- ์ ์ฉ: ๊ตฌ์ฑ API ์ง์นจ ์ฐธ์กฐ
|
|
7
|
+
- ๊ฒํ ์ผ: 2026-10-13
|
|
8
8
|
- ๊ทผ๊ฑฐ: [๋ฐ๋ณต ํ๋ฉด ์กฐํฉ](../../screen-patterns.md); ๊ณตํต API์ ์ค์ WebยทNative ์์ ์ ์ฌ๋กฏยท์ํ๋ฅผ ๋์กฐํด ์ค๋ณต ์กฐ๋ฆฝ ๋ฐฉ์ง. 2026-10-06 ์ฌ์ฉ์ ์น์ธ์ผ๋ก ์คํ ๋ฆฌ๋ถ ๋ฐฐํฌ(์ด์ `์คํ/ํ๋ฉด/๊ธฐ๋ณธ ํ๋ฆ/๊ถํ ์๋ด`, [์น์ธ ๊ธฐ๋ก](../../../../../docs/STORYBOOK_NAVIGATION.md#21-2026-10-06-์ ์ฒด-์น๊ฒฉ๊ณผ-๊ท๊ฒฉ-ํ์ ))
|
|
9
9
|
- ์คํ ๋ฆฌ๋ถ: `๋ฐฐํฌ/ํ๋ฉด/์๊ฐ/๊ถํ ์๋ด`
|
|
10
10
|
|
|
@@ -38,9 +38,23 @@ host: ๋จ์ ๋์ดยทsafe areaยทํค๋ณด๋
|
|
|
38
38
|
| --- | --- | --- |
|
|
39
39
|
| ๊ธฐ๋ณธ | ์ ํ์ ๊ทธ๋ฆผ โ ๊ถํ ์ด์ โ ์ํ๋ณ ํ๋ | ๊ฐ ๊ณต๊ฐ ์ฝ๋ฐฑ์ ์ ํ ์ํ์ ์ฐ๊ฒฐ |
|
|
40
40
|
| ๋ก๋ฉ | ์ต์ด ์กฐํ๋ ๋ณธ๋ฌธ ์ํ, ์ ์ฅ์ ํด๋น ํ๋ pending | ์ค๋ณต ์ ์ถ ์ฐจ๋จ; ์ฑ๊ณต์ ๋จผ์ ํ์ํ์ง ์์ |
|
|
41
|
-
| ๋น |
|
|
41
|
+
| ๋น | ํด๋น ์์: ๊ถํ์ ๋ชฉ๋ก 0๊ฑด์ด ์๋๋ผ OS ์ํ๋ค | ์ํ์ ๋ง๋ ํ๋์ ์ ๊ณต |
|
|
42
|
+
| ์ฌ์ฉ ๋ถ๊ฐ | status=unavailable, ๊ธฐ๋ฅ ๋ฏธ์ง์ยท๋์ฒด ๊ฒฝ๋ก ์๋ด | skip ๋ฑ ์ ํ ๋์ |
|
|
42
43
|
| ์ค๋ฅ | ๋ ๋ ์ OS ์์ฒญ ๊ธ์ง; ์ค์ ๋ณต๊ท ์ ์ ํ์ด ์ํ ์ฌ์กฐํ | ์คํจ ์์ธ๊ณผ ์ฌ์๋ ๊ฒฝ๋ก ์ ๊ณต |
|
|
43
44
|
|
|
45
|
+
|
|
46
|
+
### OS ์ํ์ ๋ง๋ ๋ค์ ํ๋
|
|
47
|
+
|
|
48
|
+
2026-10-13 ์ ์ ์ ๊ฒ์์ ์ต์ด ์กฐํ์ ๋ณ๊ฒฝ ์์ฒญ์ ์ํ๋ฅผ ๊ฐ์ ๊ณจ๊ฒฉ์ผ๋ก ์ค๋ช
ํ๋ ๋ถ๋ถ์ ๊ตฌ์ฒดํํ๋ค.
|
|
49
|
+
|
|
50
|
+
| ์ํฉ | ์ฐ๊ฒฐ | ์ ์งยท๋ณต๊ตฌ |
|
|
51
|
+
| --- | --- | --- |
|
|
52
|
+
| prompt | request | ์ฌ์ฉ์ ํ๋์์๋ง OS ๊ถํ ์์ฒญ |
|
|
53
|
+
| denied | settings | ์ค์ ์ฑยท๋ธ๋ผ์ฐ์ ๋์์ผ๋ก ์ด๋; ๋ณต๊ท ์ ์ค์ ๊ถํ ์ฌ์กฐํ |
|
|
54
|
+
| granted | continueAction | ์ฌ์ฉํ ๊ธฐ๋ฅ์ผ๋ก ์ด๋ |
|
|
55
|
+
| unavailable | skip ๋๋ ์ ํ ๋์ | ๊ถํ ์ฌ์์ฒญ์ ๋ฐ๋ณตํ์ง ์๋๋ค |
|
|
56
|
+
| ์กฐํยท์์ฒญ ์คํจ | notice + ๊ฐ์ ์์ฒญ ์ฌ์๋ | denied์ ํต์ ยทํธ์คํธ ์ค๋ฅ๋ฅผ ๊ฐ์ ์ํ๋ก ์ ์ฅํ์ง ์๋๋ค |
|
|
57
|
+
|
|
44
58
|
## ์ฌ์ฉํ๋ ์ง์นจ
|
|
45
59
|
|
|
46
60
|
| ์ง์นจ | ์ฐ๋ ๊ณณ |
|