@hjmds/design-contracts 1.22.0 → 1.24.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/catalog.d.ts +16 -0
- package/dist/catalog.d.ts.map +1 -1
- package/dist/component-recipes.d.ts +16 -0
- package/dist/component-recipes.d.ts.map +1 -1
- package/dist/component-recipes.js +3 -0
- package/dist/component-recipes.js.map +1 -1
- package/dist/conversation-row.d.ts +13 -0
- package/dist/conversation-row.d.ts.map +1 -0
- package/dist/conversation-row.js +14 -0
- package/dist/conversation-row.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- 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/screen-patterns.md +11 -4
- package/docs/usage/README.md +3 -1
- package/docs/usage/SELECTION.md +36 -23
- package/docs/usage/STANDARD.md +5 -0
- package/docs/usage/components/comment-thread-screen.md +4 -1
- package/docs/usage/components/composition-layout.md +93 -0
- package/docs/usage/components/conversation-row.md +93 -0
- package/docs/usage/components/list-row.md +7 -0
- package/docs/usage/components/screen-layout.md +4 -1
- package/docs/usage/components/segmented-control.md +7 -0
- package/docs/usage/components/top-bar.md +1 -0
- package/docs/usage/compositions/action-feedback.md +3 -1
- package/docs/usage/compositions/action-recovery-optimistic.md +4 -2
- package/docs/usage/compositions/action-recovery-save.md +4 -2
- package/docs/usage/compositions/action-recovery-undo.md +4 -2
- package/docs/usage/compositions/activity-status.md +3 -1
- package/docs/usage/compositions/adaptive-content.md +4 -2
- package/docs/usage/compositions/authoring-tools.md +2 -0
- package/docs/usage/compositions/collection-detail.md +3 -1
- package/docs/usage/compositions/collection-editing.md +2 -0
- package/docs/usage/compositions/command-records.md +3 -1
- package/docs/usage/compositions/common-message.md +3 -1
- package/docs/usage/compositions/common-notification.md +3 -1
- package/docs/usage/compositions/communication.md +2 -0
- package/docs/usage/compositions/compound-controls.md +4 -2
- package/docs/usage/compositions/content-transition-comparison.md +3 -1
- package/docs/usage/compositions/context-toolbar.md +4 -2
- package/docs/usage/compositions/data-layouts.md +4 -2
- package/docs/usage/compositions/data-workflows.md +2 -0
- package/docs/usage/compositions/date-entry.md +3 -1
- package/docs/usage/compositions/date-time-selection.md +3 -1
- package/docs/usage/compositions/design-profile-comparison.md +3 -1
- package/docs/usage/compositions/disclosure.md +6 -4
- package/docs/usage/compositions/document-resource.md +3 -1
- package/docs/usage/compositions/environment-matrix.md +3 -1
- package/docs/usage/compositions/expo-interactions.md +4 -2
- package/docs/usage/compositions/family-drawer.md +4 -2
- package/docs/usage/compositions/field-group.md +3 -1
- package/docs/usage/compositions/floating-action-button.md +3 -1
- package/docs/usage/compositions/illustrated-outcome.md +3 -1
- package/docs/usage/compositions/input-sheet.md +3 -1
- package/docs/usage/compositions/interaction-adapters.md +3 -1
- package/docs/usage/compositions/interaction-flow-apply.md +3 -1
- package/docs/usage/compositions/interaction-flow-draft.md +3 -1
- package/docs/usage/compositions/interaction-flow-search.md +3 -1
- package/docs/usage/compositions/live-list.md +3 -1
- package/docs/usage/compositions/media-transport.md +2 -0
- package/docs/usage/compositions/native-renderers.md +3 -1
- package/docs/usage/compositions/navigation-bar-collection.md +3 -1
- package/docs/usage/compositions/optional-adapters.md +3 -1
- package/docs/usage/compositions/optional-motion.md +3 -1
- package/docs/usage/compositions/origin-dialog.md +3 -1
- package/docs/usage/compositions/paper-surface.md +3 -1
- package/docs/usage/compositions/photo-source.md +3 -1
- package/docs/usage/compositions/purpose-input-comment.md +8 -2
- package/docs/usage/compositions/purpose-input-message.md +4 -2
- package/docs/usage/compositions/reference-first.md +3 -1
- package/docs/usage/compositions/reference-review.md +3 -1
- package/docs/usage/compositions/reference-settings.md +3 -1
- package/docs/usage/compositions/selection-motion.md +4 -2
- package/docs/usage/compositions/selection-scope.md +3 -1
- package/docs/usage/compositions/social-compositions.md +2 -0
- package/docs/usage/compositions/stea-event-ticket.md +3 -1
- package/docs/usage/compositions/stea-flip-card.md +4 -2
- package/docs/usage/compositions/stea-order-progress.md +5 -3
- package/docs/usage/compositions/stea-otp-verify.md +5 -3
- package/docs/usage/compositions/stea-pixel-empty.md +5 -3
- package/docs/usage/compositions/stea-schedule-card.md +5 -3
- package/docs/usage/compositions/stea-stat-summary.md +4 -2
- package/docs/usage/compositions/streaming-answer.md +2 -0
- package/docs/usage/compositions/task-controls.md +2 -0
- package/docs/usage/compositions/texture-comparison.md +3 -1
- package/docs/usage/compositions/time-selection.md +5 -3
- package/docs/usage/compositions/toast-layout.md +3 -1
- package/docs/usage/compositions/toggle-feedback.md +2 -0
- package/docs/usage/compositions/transfer-task.md +2 -0
- package/docs/usage/compositions/upload-recovery.md +4 -2
- package/docs/usage/compositions/video-dialog.md +3 -1
- package/docs/usage/compositions/visual-foundations.md +5 -3
- package/docs/usage/compositions/web-additions.md +6 -4
- package/docs/usage/compositions/web-navigation.md +4 -2
- package/docs/usage/screens/common-chat.md +3 -1
- package/docs/usage/screens/common-comments.md +6 -4
- package/docs/usage/screens/common-inbox.md +3 -1
- package/docs/usage/screens/common-login.md +3 -1
- package/docs/usage/screens/common-profile.md +3 -1
- package/docs/usage/screens/common-saved.md +3 -1
- package/docs/usage/screens/common-search.md +3 -1
- package/docs/usage/screens/common-settings.md +3 -1
- package/docs/usage/screens/common-shell.md +3 -1
- package/docs/usage/screens/dashboard.md +3 -1
- package/docs/usage/screens/discovery-gallery.md +3 -1
- package/docs/usage/screens/flow-collection.md +3 -1
- package/docs/usage/screens/flow-editor.md +3 -1
- package/docs/usage/screens/flow-media.md +3 -1
- package/docs/usage/screens/flow-moderation.md +3 -1
- package/docs/usage/screens/flow-onboarding.md +3 -1
- package/docs/usage/screens/flow-permission.md +3 -1
- package/docs/usage/screens/landing.md +4 -2
- package/docs/usage/screens/mockup-studio.md +3 -1
- package/docs/usage/screens/notification-settings.md +32 -138
- package/docs/usage/screens/product-bento.md +3 -1
- package/docs/usage/screens/reference-comparison.md +3 -1
- package/package.json +6 -1
|
@@ -4,10 +4,12 @@
|
|
|
4
4
|
- 상태: 배포
|
|
5
5
|
- 지원: Web · Native
|
|
6
6
|
- 적용: 1.12.1
|
|
7
|
-
- 검토일: 2026-10-
|
|
7
|
+
- 검토일: 2026-10-15
|
|
8
8
|
- 근거: `showcase/web/src/patterns/NotificationSettings.stories.tsx`, `showcase/native/src/NotificationSettings.stories.tsx`, `src/component-recipes.ts`(`topBarRecipe`·`bottomCtaRecipe`·`sectionRecipe`·`switchRecipe`), `src/container.ts`, `src/responsive.ts`(`resolveWindowClass`), `packages/react/src/styles.css`(`.hjm-top-bar`·`.hjm-bottom-cta`)
|
|
9
9
|
- 스토리북: `배포/화면/설정/알림 설정`
|
|
10
10
|
|
|
11
|
+
공통 구조·배치·상태·배지의 소유권은 [화면과 구성 선택](../SELECTION.md#소유권)을 따른다. 앱은 데이터·문구·브랜드·추가 기능을 공개 슬롯과 콜백으로 연결한다. 아래 코드 골격을 앱별 기본 구조 복제의 근거로 사용하지 않는다. 전용 화면 API가 없는 제품 콘텐츠는 `ScreenLayout`의 본문에 HJM 구성을 연결한다.
|
|
12
|
+
|
|
11
13
|
## 목적
|
|
12
14
|
|
|
13
15
|
알림 종류 몇 개를 스위치로 켜고 끈 뒤 하단 버튼 하나로 저장하는 설정 화면이다. 상단 바 · 읽기 폭 본문 · 하단 행동 바의
|
|
@@ -17,61 +19,27 @@
|
|
|
17
19
|
## 영역 구조
|
|
18
20
|
|
|
19
21
|
```text
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
├──────────────────────────────────────────────┤ ↕ spacing.lg 20
|
|
24
|
-
│ ② Container reading (최대 720, │ ─ 스크롤 ─
|
|
25
|
-
│ 좌우 gutter: 폭<600 compact 16 · 이상 20) │
|
|
26
|
-
│ Section │
|
|
27
|
-
│ 필요한 소식만 받아요 ← title │ title-description spacing.xxs 4
|
|
28
|
-
│ 원하는 알림을 골라 주세요… ← description │ 머리-내용 spacing.xs 8
|
|
29
|
-
│ ┌────────────────────────────────────────┐ │
|
|
30
|
-
│ │ 내 활동 알림 (●──) │ │ Switch presentation=row
|
|
31
|
-
│ │ 댓글과 답글이 도착하면… │ │ 라벨 왼쪽, 스위치 끝
|
|
32
|
-
│ │ ↕ spacing.md 16 │ │
|
|
33
|
-
│ │ 주간 모아보기 (──○) │ │
|
|
34
|
-
│ │ 일주일의 소식을 한 번에… │ │
|
|
35
|
-
│ └────────────────────────────────────────┘ │
|
|
36
|
-
│ ┌ Notice success(저장 후) · danger(실패) ┐ │
|
|
37
|
-
│ └────────────────────────────────────────┘ │
|
|
38
|
-
├──────────────────────────────────────────────┤ ↕ 20
|
|
39
|
-
│ ③ BottomCTA (위 테두리 1 + 위쪽 그림자) │ 최소 높이 64 (고정)
|
|
40
|
-
│ 선택한 알림만 보내드릴게요. ← description │ caption, muted
|
|
41
|
-
│ [ 이 설정으로 저장하기 ] │ ← 주 행동, 폭 전체
|
|
42
|
-
└ 하단 안전 영역(BottomCTA safeAreaBottom) ────┘
|
|
22
|
+
ScreenLayout: 제목(고정) → 본문(스크롤) → footer(고정)
|
|
23
|
+
본문: CompositionLayout(설정 제목·설명 → 설정 행 → 저장 안내)
|
|
24
|
+
footer: 저장 행동
|
|
43
25
|
```
|
|
44
26
|
|
|
45
|
-
넓은 폭 Web: TopBar와 BottomCTA는 화면 폭 전체, 본문만 Container `reading`으로 가운데 720 폭에 묶인다.
|
|
46
|
-
|
|
47
27
|
| 영역 | 컴포넌트 | 위치 | 크기·간격 |
|
|
48
28
|
| --- | --- | --- | --- |
|
|
49
|
-
| 바깥 틀 |
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
|
|
|
53
|
-
|
|
54
|
-
gutter는 창 폭으로 고른다: `resolveWindowClass(width) === "compact" ? "compact" : "regular"`([화면 여백과 너비](../tokens/layout.md)).
|
|
55
|
-
상단·스크롤 본문·하단 행동은 별도 영역으로 둔다. 목록이 길어져도 저장 행동이 본문과 함께 밀려나지 않는다.
|
|
56
|
-
|
|
57
|
-
```text
|
|
58
|
-
Native 고정 배치
|
|
59
|
-
┌ TopBar safeAreaTop={insets.top} ─────┐ 고정
|
|
60
|
-
├ ScrollView paddingVertical 20 ───────┤
|
|
61
|
-
│ Container > Section > Switch … │ 스크롤
|
|
62
|
-
├ BottomCTA safeAreaBottom={insets.bottom} ┤ 고정
|
|
63
|
-
└──────────────────────────────────────┘
|
|
64
|
-
```
|
|
29
|
+
| 바깥 틀 | ScreenLayout | host의 남은 높이 | 공통 화면 폭·padding·본문 스크롤 |
|
|
30
|
+
| 설정 묶음 | CompositionLayout | 본문 | 공통 제목·설명·내용 간격 |
|
|
31
|
+
| 설정 값 | Switch | 구성 본문 | 제품 데이터·변경 콜백 |
|
|
32
|
+
| 저장 | footer | 화면 하단 | HJM 고정 영역; 제품 저장 요청과 pending 연결 |
|
|
65
33
|
|
|
66
34
|
## 버튼과 행동 위치
|
|
67
35
|
|
|
68
36
|
| 행동 | 컴포넌트·tone | 위치 | 개수·순서 |
|
|
69
37
|
| --- | --- | --- | --- |
|
|
70
|
-
| 저장(주 행동) |
|
|
71
|
-
| 보조 행동 |
|
|
72
|
-
| 항목 켜기·끄기 | Switch `presentation="row"` 행 전체 | 본문
|
|
38
|
+
| 저장(주 행동) | Button(primary) | 화면 맨 아래 바 | 1. 저장 중 `loading`, 저장 뒤에는 라벨을 `t("settings.saved")`로 바꾸고 `disabled` |
|
|
39
|
+
| 보조 행동 | Button(secondary) | 같은 바, 주 행동 앞(왼쪽) | 스토리에는 없음. 둘 다 있으면 [보조][주] 같은 폭으로 나뉜다 |
|
|
40
|
+
| 항목 켜기·끄기 | Switch `presentation="row"` 행 전체 | 본문 CompositionLayout 안 | 항목 수만큼, 위→아래 |
|
|
73
41
|
| 다시 불러오기 | Notice `action` > Button `tone="secondary" size="small"` | 불러오기 실패 Notice 안 | 스토리에 없음. 1 |
|
|
74
|
-
| 뒤로 |
|
|
42
|
+
| 뒤로 | ScreenLayout `leading` | 상단 바 시작 끝 | 스토리에는 없음. 하위 설정 화면이면 1 |
|
|
75
43
|
| 파괴 행동 | — | — | 없음 |
|
|
76
44
|
|
|
77
45
|
## 상태
|
|
@@ -79,10 +47,10 @@ Native 고정 배치
|
|
|
79
47
|
| 상태 | 화면 모습 | 행동 |
|
|
80
48
|
| --- | --- | --- |
|
|
81
49
|
| 기본 | 스위치가 메모리 예제의 초기 저장값. 변경이 없으면 저장 버튼 비활성 | 스위치를 바꾸면 저장 가능. 저장값으로 되돌리면 다시 비활성 |
|
|
82
|
-
| 로딩 | 스토리에 없음. 첫 값을 불러오는 동안
|
|
83
|
-
| 빈 | 해당 없음(설정 항목은 항상 있다). 항목이 조건부면
|
|
84
|
-
| 오류 | **최초 불러오기 실패**(스토리에는 없음): 스위치 대신 [Notice](../components/notice.md) `tone="danger"` + `action` 다시 시도, 저장 버튼 `disabled`. **저장 실패**(스토리에서 `다음 저장 실패시키기`로 실행):
|
|
85
|
-
| 저장됨 |
|
|
50
|
+
| 로딩 | 스토리에 없음. 첫 값을 불러오는 동안 CompositionLayout 안 스위치 자리에 [Skeleton](../components/skeleton.md) `shape="text"`, 저장 버튼 `disabled`. 저장 중이면 Button에 `loading`(누름을 막고 같은 자리에 스피너) | 기다림 |
|
|
51
|
+
| 빈 | 해당 없음(설정 항목은 항상 있다). 항목이 조건부면 CompositionLayout 아래 안내 Text | — |
|
|
52
|
+
| 오류 | **최초 불러오기 실패**(스토리에는 없음): 스위치 대신 [Notice](../components/notice.md) `tone="danger"` + `action` 다시 시도, 저장 버튼 `disabled`. **저장 실패**(스토리에서 `다음 저장 실패시키기`로 실행): CompositionLayout 끝에 Notice `tone="danger"`(action 없음 — 다시 시도는 저장 버튼이 맡는다), 사용자가 고른 스위치 값을 그대로 두고 `loading`만 푼다. 문구는 네트워크 실패 `settings.error.offline`·서버 실패 `settings.error.server`로 나눈다. 다시 시도가 또 실패하면 같은 Notice가 같은 자리에 남고 문구만 갱신한다. Native는 `announcement="assertive"`(기본 `none`) | 다시 시도 / 다시 저장 |
|
|
53
|
+
| 저장됨 | CompositionLayout 끝에 Notice `tone="success"`(제목 + 켜짐/꺼짐 요약). 버튼은 "저장했어요"로 바뀌고 비활성. Native Notice `announcement="polite"` | 스위치를 다시 바꾸면 저장 상태가 풀린다 |
|
|
86
54
|
|
|
87
55
|
|
|
88
56
|
### 설정 초안의 저장 경계
|
|
@@ -102,115 +70,41 @@ Native 고정 배치
|
|
|
102
70
|
|
|
103
71
|
| 지침 | 쓰는 곳 |
|
|
104
72
|
| --- | --- |
|
|
105
|
-
| [
|
|
106
|
-
| [
|
|
107
|
-
| [Section](../components/section.md) | ② 설정 묶음 제목·설명 |
|
|
73
|
+
| [ScreenLayout](../components/screen-layout.md) | 제목·본문·고정 footer |
|
|
74
|
+
| [CompositionLayout](../components/composition-layout.md) | ② 설정 묶음 제목·설명 |
|
|
108
75
|
| [Switch](../components/switch.md) | ② 항목 행 |
|
|
109
76
|
| [Notice](../components/notice.md) | 저장 결과·오류 |
|
|
110
77
|
| [Skeleton](../components/skeleton.md) | 첫 값 불러오기 |
|
|
111
|
-
| [
|
|
78
|
+
| [Button](../components/button.md) | ③ 하단 저장 |
|
|
112
79
|
| [Stack](../components/stack.md) | 세 층 사이, 스위치 목록 |
|
|
113
80
|
| [화면 여백과 너비](../tokens/layout.md) | `layout.readingMaxWidth`, `layout.pagePadding.compact`·`regular`, `resolveWindowClass` |
|
|
114
81
|
| [간격](../tokens/spacing.md) | `spacing.xxs`·`xs`·`sm`·`md`·`lg` |
|
|
115
82
|
|
|
116
83
|
## 코드 골격
|
|
117
84
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
import { TopBar } from "@hjmds/react/top-bar";
|
|
123
|
-
import { BottomCTA } from "@hjmds/react/bottom-cta";
|
|
124
|
-
import { Container, Stack, Section } from "@hjmds/react/layout";
|
|
125
|
-
import { Switch } from "@hjmds/react/selection";
|
|
126
|
-
import { Notice, Skeleton } from "@hjmds/react/feedback";
|
|
127
|
-
import { Button } from "@hjmds/react/actions";
|
|
128
|
-
import { resolveWindowClass } from "@hjmds/design-contracts/responsive";
|
|
129
|
-
|
|
130
|
-
const failureKey = { offline: "settings.error.offline", server: "settings.error.server" } as const;
|
|
131
|
-
const onOffKey = { on: "settings.on", off: "settings.off" } as const;
|
|
132
|
-
|
|
133
|
-
const gutter = resolveWindowClass(window.innerWidth) === "compact" ? "compact" : "regular";
|
|
134
|
-
const summary = t("settings.saved.summary", {
|
|
135
|
-
activity: t(onOffKey[activity ? "on" : "off"]),
|
|
136
|
-
digest: t(onOffKey[digest ? "on" : "off"]),
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
<main><Stack gap="lg">
|
|
140
|
-
<TopBar title={t("settings.notifications.title")} />
|
|
141
|
-
<Container size="reading" gutter={gutter}>
|
|
142
|
-
<Section title={t("settings.notifications.section")} description={t("settings.notifications.hint")}>
|
|
143
|
-
{status === "loading" ? <Stack gap="md"><Skeleton shape="text" width="60%" /><Skeleton shape="text" width="40%" /></Stack> : null}
|
|
144
|
-
{status === "loadFailed" && failure ? <Notice tone="danger" title={t(failureKey[failure])}
|
|
145
|
-
action={<Button tone="secondary" size="small" onClick={reload}>{t("common.retry")}</Button>} /> : null}
|
|
146
|
-
{status === "ready" ? <Stack gap="md">
|
|
147
|
-
<Switch presentation="row" label={t("settings.activity")} description={t("settings.activity.hint")}
|
|
148
|
-
checked={activity} onCheckedChange={v => { setActivity(v); setSaved(false); }} />
|
|
149
|
-
</Stack> : null}
|
|
150
|
-
{status === "ready" && failure ? <Notice tone="danger" title={t(failureKey[failure])} description={t("settings.error.kept")} /> : null}
|
|
151
|
-
{saved ? <Notice tone="success" title={t("settings.saved.title")} description={summary} /> : null}
|
|
152
|
-
</Section>
|
|
153
|
-
</Container>
|
|
154
|
-
<BottomCTA position="sticky" description={t("settings.cta.hint")}
|
|
155
|
-
primaryAction={{ label: saved ? t("settings.saved") : t("settings.save"), onClick: save, loading: saving, disabled: saved || status !== "ready" }} />
|
|
156
|
-
</Stack></main>
|
|
157
|
-
```
|
|
85
|
+
<!-- usage-example: Web ../../../../../showcase/web/src/patterns/NotificationSettings.stories.tsx -->
|
|
86
|
+
- [Web 실행 예제](../../../../../showcase/web/src/patterns/NotificationSettings.stories.tsx)
|
|
87
|
+
<!-- usage-example: Native ../../../../../showcase/native/src/NotificationSettings.stories.tsx -->
|
|
88
|
+
- [Native 실행 예제](../../../../../showcase/native/src/NotificationSettings.stories.tsx)
|
|
158
89
|
|
|
159
|
-
|
|
160
|
-
// Native — 상단·하단 바를 고정한 형태
|
|
161
|
-
import { ScrollView, View, useWindowDimensions } from "react-native";
|
|
162
|
-
import { useSafeAreaInsets } from "react-native-safe-area-context"; // 제품 의존성
|
|
163
|
-
import { spacing } from "@hjmds/design-contracts/foundations";
|
|
164
|
-
import { resolveWindowClass } from "@hjmds/design-contracts/responsive";
|
|
165
|
-
import { TopBar } from "@hjmds/react-native/top-bar";
|
|
166
|
-
import { BottomCTA } from "@hjmds/react-native/bottom-cta";
|
|
167
|
-
import { Container, Stack, Section } from "@hjmds/react-native/primitives";
|
|
168
|
-
import { Switch } from "@hjmds/react-native/inputs";
|
|
169
|
-
import { Notice } from "@hjmds/react-native/feedback";
|
|
170
|
-
|
|
171
|
-
const failureKey = { offline: "settings.error.offline", server: "settings.error.server" } as const;
|
|
172
|
-
const insets = useSafeAreaInsets();
|
|
173
|
-
const { width } = useWindowDimensions();
|
|
174
|
-
const gutter = resolveWindowClass(width) === "compact" ? "compact" : "regular";
|
|
175
|
-
|
|
176
|
-
<View style={{ flex: 1 }}>
|
|
177
|
-
<TopBar title={t("settings.notifications.title")} safeAreaTop={insets.top} />
|
|
178
|
-
<ScrollView contentContainerStyle={{ paddingVertical: spacing.lg }}>
|
|
179
|
-
<Container size="reading" gutter={gutter}>
|
|
180
|
-
<Section title={t("settings.notifications.section")} description={t("settings.notifications.hint")}>
|
|
181
|
-
<Stack gap="md">
|
|
182
|
-
<Switch presentation="row" label={t("settings.activity")} description={t("settings.activity.hint")}
|
|
183
|
-
checked={activity} onCheckedChange={v => { setActivity(v); setSaved(false); }} />
|
|
184
|
-
</Stack>
|
|
185
|
-
{failure ? <Notice announcement="assertive" tone="danger" title={t(failureKey[failure])} description={t("settings.error.kept")} /> : null}
|
|
186
|
-
{saved ? <Notice announcement="polite" tone="success" title={t("settings.saved.title")} description={summary} /> : null}
|
|
187
|
-
</Section>
|
|
188
|
-
</Container>
|
|
189
|
-
</ScrollView>
|
|
190
|
-
<BottomCTA safeAreaBottom={insets.bottom} description={t("settings.cta.hint")}
|
|
191
|
-
primaryAction={{ label: saved ? t("settings.saved") : t("settings.save"), onPress: save, loading: saving, disabled: saved }} />
|
|
192
|
-
</View>
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
`react-native-safe-area-context`는 HJM 의존성이 아니다. 제품이 쓰는 inset 출처를 넘긴다. Native 로딩·불러오기 실패는 Web과 같은
|
|
196
|
-
자리에 같은 컴포넌트를 둔다(Button은 `onPress`).
|
|
90
|
+
예제는 ScreenLayout·CompositionLayout에 설정 데이터와 저장 콜백을 연결한다. 메모리 저장 fixture를 운영 요청으로 취급하지 않는다.
|
|
197
91
|
|
|
198
92
|
## 큰 글자·다크·좁은 폭
|
|
199
93
|
|
|
200
94
|
| 조건 | 바뀌는 것 |
|
|
201
95
|
| --- | --- |
|
|
202
|
-
|
|
|
203
|
-
|
|
|
204
|
-
|
|
205
|
-
|
|
96
|
+
| 다크 | 공통 semantic token으로 전환 |
|
|
97
|
+
| 좁은 폭 | 공통 화면·구성의 줄바꿈과 간격을 사용 |
|
|
98
|
+
|
|
99
|
+
ScreenLayout이 화면 여백과 스크롤을, CompositionLayout이 묶음 간격을 관리한다. 테마는 공통 semantic token을 사용한다. footer 안에서 BottomCTA를 중첩해 여백과 경계선을 두 번 적용하지 않는다.
|
|
206
100
|
|
|
207
101
|
## 플랫폼 차이
|
|
208
102
|
|
|
209
103
|
| 항목 | Web | Native |
|
|
210
104
|
| --- | --- | --- |
|
|
211
105
|
| Switch 기본 배치 | `inline`(행으로 쓰려면 `presentation="row"` 명시) | `row` |
|
|
212
|
-
| 하단 바 고정 |
|
|
213
|
-
| 안전 영역 |
|
|
106
|
+
| 하단 바 고정 | ScreenLayout footer | ScreenLayout footer |
|
|
107
|
+
| 안전 영역 | 제품 host에서 연결 | 제품 host에서 연결 |
|
|
214
108
|
| 저장·오류 알림 | Notice가 `role="status"` | Notice `announcement` 명시(기본 `none`): 저장됨 `polite`, 오류 `assertive` |
|
|
215
109
|
| 스토리 상태 | 기본·다크·큰 글자, 기본 화면에서 저장 실패와 재시도 실행 | 기본·다크·큰 글자, 동일 메모리 저장 흐름 |
|
|
216
110
|
|
|
@@ -4,12 +4,14 @@
|
|
|
4
4
|
- 상태: 배포
|
|
5
5
|
- 지원: Web · Native
|
|
6
6
|
- 적용: 1.14.0
|
|
7
|
-
- 검토일: 2026-10-
|
|
7
|
+
- 검토일: 2026-10-15
|
|
8
8
|
- 근거: `reference-adoption-previews.tsx`, `reference-adoption.css`
|
|
9
9
|
- 스토리북: `배포/화면/소개/기능 카드와 주 행동`
|
|
10
10
|
|
|
11
11
|
승급: 2026-10-07 사용자 승인, [검토 결과](../../../../../docs/qa/2026-10-07-experiment-promotion-release.md). Storybook 분류이며 제품 적용 증거는 별도다.
|
|
12
12
|
|
|
13
|
+
공통 구조·배치·상태·배지의 소유권은 [화면과 구성 선택](../SELECTION.md#소유권)을 따른다. 앱은 데이터·문구·브랜드·추가 기능을 공개 슬롯과 콜백으로 연결한다. 아래 코드 골격을 앱별 기본 구조 복제의 근거로 사용하지 않는다. 전용 화면 API가 없는 제품 콘텐츠는 `ScreenLayout`의 본문에 HJM 구성을 연결한다.
|
|
14
|
+
|
|
13
15
|
## 목적
|
|
14
16
|
|
|
15
17
|
기능을 실제 미리보기로 보여 주고 첫 행동으로 이어지는 소개 화면이다. 기존 Surface/Stack/Button/ImageComparison을 조합한다.
|
|
@@ -4,10 +4,12 @@
|
|
|
4
4
|
- 상태: 배포
|
|
5
5
|
- 지원: Web · Native
|
|
6
6
|
- 적용: 구성 API 지침 참조
|
|
7
|
-
- 검토일: 2026-10-
|
|
7
|
+
- 검토일: 2026-10-15
|
|
8
8
|
- 근거: [반복 화면 조합](../../screen-patterns.md); 공통 API와 실제 Web·Native 예제의 슬롯·상태를 대조해 중복 조립 방지. 2026-10-06 사용자 승인으로 스토리북 배포(이전 `실험/화면/표현 비교/같은 기록의 세 가지 구성`, [승인 기록](../../../../../docs/STORYBOOK_NAVIGATION.md#21-2026-10-06-전체-승격과-규격-확정))
|
|
9
9
|
- 스토리북: `배포/화면/화면 틀과 도구/기록 표현 비교`
|
|
10
10
|
|
|
11
|
+
공통 구조·배치·상태·배지의 소유권은 [화면과 구성 선택](../SELECTION.md#소유권)을 따른다. 앱은 데이터·문구·브랜드·추가 기능을 공개 슬롯과 콜백으로 연결한다. 아래 코드 골격을 앱별 기본 구조 복제의 근거로 사용하지 않는다. 전용 화면 API가 없는 제품 콘텐츠는 `ScreenLayout`의 본문에 HJM 구성을 연결한다.
|
|
12
|
+
|
|
11
13
|
## 목적
|
|
12
14
|
|
|
13
15
|
ScreenLayout을 사용해 같은 기록의 세 가지 구성 흐름을 구성한다. 제품이 데이터·권한·서버 확정·문구를 공급하며, 예제의 메모리 저장을 운영 저장으로 취급하지 않는다.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hjmds/design-contracts",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.24.0",
|
|
4
4
|
"description": "Renderer-neutral design contracts, tokens, recipes, and behaviors shared by HJM products.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -792,6 +792,11 @@
|
|
|
792
792
|
"react-native": "./dist/streaming-answer.js",
|
|
793
793
|
"import": "./dist/streaming-answer.js",
|
|
794
794
|
"default": "./dist/streaming-answer.js"
|
|
795
|
+
},
|
|
796
|
+
"./conversation-row": {
|
|
797
|
+
"types": "./dist/conversation-row.d.ts",
|
|
798
|
+
"import": "./dist/conversation-row.js",
|
|
799
|
+
"default": "./dist/conversation-row.js"
|
|
795
800
|
}
|
|
796
801
|
},
|
|
797
802
|
"files": [
|