@hjmds/design-contracts 1.36.1 → 1.37.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 +27 -0
- package/dist/catalog.d.ts.map +1 -1
- package/dist/chart.d.ts +10 -0
- package/dist/chart.d.ts.map +1 -1
- package/dist/component-recipes.d.ts +17 -0
- package/dist/component-recipes.d.ts.map +1 -1
- package/dist/component-recipes.js +9 -2
- package/dist/component-recipes.js.map +1 -1
- package/dist/dataviz.d.ts +10 -0
- package/dist/dataviz.d.ts.map +1 -1
- package/dist/dataviz.js +3 -0
- package/dist/dataviz.js.map +1 -1
- package/dist/design-system-provider.d.ts +3 -0
- package/dist/design-system-provider.d.ts.map +1 -1
- package/dist/design-system-provider.js +7 -0
- package/dist/design-system-provider.js.map +1 -1
- package/dist/palette-contrast.d.ts +4 -2
- package/dist/palette-contrast.d.ts.map +1 -1
- package/dist/palette-contrast.js +9 -2
- package/dist/palette-contrast.js.map +1 -1
- package/dist/semantic-colors.d.ts.map +1 -1
- package/dist/semantic-colors.js +21 -19
- package/dist/semantic-colors.js.map +1 -1
- package/dist/theme-studio.d.ts +1 -1
- package/dist/theme-studio.js +2 -2
- package/dist/theme-studio.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/brand-boundary.md +6 -3
- package/docs/design-profile.md +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/usage/README.md +5 -4
- package/docs/usage/components/bottom-cta.md +2 -0
- package/docs/usage/components/card.md +1 -1
- package/docs/usage/components/chart.md +4 -0
- package/docs/usage/components/combobox.md +7 -5
- package/docs/usage/components/composition-layout.md +2 -1
- package/docs/usage/components/design-system-provider.md +2 -2
- package/docs/usage/components/empty-state.md +2 -0
- package/docs/usage/components/notice.md +4 -0
- package/docs/usage/components/segmented-control.md +2 -0
- package/docs/usage/components/select.md +9 -7
- package/docs/usage/components/sheet.md +5 -1
- package/docs/usage/components/time-picker.md +1 -1
- package/docs/usage/components/toast.md +3 -0
- package/docs/usage/compositions/save-feedback.md +93 -0
- package/docs/usage/tokens/color.md +11 -5
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Renderer evidence coverage
|
|
2
2
|
|
|
3
|
-
> Generated for HJM 1.
|
|
3
|
+
> Generated for HJM 1.37.0. Do not edit directly; run `pnpm evidence:sync`.
|
|
4
4
|
|
|
5
5
|
This projection joins the canonical surface maturity manifest with first-party renderer claims. Missing scenarios are explicit beta promotion debt; stable surfaces are blocked by CI until none remain.
|
|
6
6
|
|
package/docs/usage/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
버튼 위치에서 시작해 구성·컴포넌트 지침으로 내려가고, 값은 토큰 지침에서 고른다.
|
|
7
7
|
[선택 기준](SELECTION.md)으로 그대로 사용·공개 슬롯 확장·공통 API 보완·제품 고유 기능 연결을 고른다. 설치 버전의 지침을 본다: `node_modules/@hjmds/design-contracts/docs/usage/`.
|
|
8
8
|
제공 기준은 확인한 기본 API 버전이며 최초 출시 버전이 아니다. 구성·화면은 각 API 지침의 제공 버전을 확인한다.
|
|
9
|
-
API 안정성은 1.
|
|
9
|
+
API 안정성은 1.36.1의 생성 manifest에서 읽은 정규(canonical) API 기준이다. 동반·선택형 확장은 개별 계약을 확인한다.
|
|
10
10
|
Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품 반영을 의미하지 않는다.
|
|
11
11
|
`분류`는 Storybook 제목 `<배포|실험>/<단계>/<분류>/<항목>`의 셋째 마디이고, 토큰·구성·화면은 Storybook 메뉴와 같은 순서다.
|
|
12
12
|
|
|
@@ -127,7 +127,7 @@ Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품
|
|
|
127
127
|
| [Menubar](components/menubar.md) | 탐색 | 데스크톱 Web 앱 상단에 항상 같은 자리에 있는 가로 메뉴 막대(파일·편집·보기)에 쓴다. | 1.12.1 | Web | Web stable / Native unsupported | 배포 |
|
|
128
128
|
| [MessageComposer](components/message-composer.md) | 구성/입력과 작성 | 채팅·DM·댓글 입력창에 쓴다. | 1.17.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
129
129
|
| [ModerationScreen](components/moderation-screen.md) | 화면/소통 | 게시물·댓글·사용자 **신고** 화면에 쓴다. | 1.17.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
130
|
-
| [Notice](components/notice.md) | 상태와 알림 |
|
|
130
|
+
| [Notice](components/notice.md) | 상태와 알림 | 저장된 항목·폼 안의 작은 성공 상태는 `appearance="status"`(1.37.0)를 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
131
131
|
| [NotificationInboxScreen](components/notification-inbox-screen.md) | 화면/소통 | 알림함 화면 전체 틀에 쓴다. | 1.17.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
132
132
|
| [NotificationItem](components/notification-item.md) | 구성/정보 표시 | 알림함의 알림 한 행에 쓴다. | 1.17.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
133
133
|
| [NotificationRow](components/notification-row.md) | 데이터 표시 | 알림 목록에서 아바타, 유형 배지, 미리보기, 시간, 읽지 않음 표시, 선택적 썸네일을 나란히 배치한다. | 1.26.0 | Web · Native | Web stable / Native stable | 배포 |
|
|
@@ -196,7 +196,7 @@ Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품
|
|
|
196
196
|
| [ThinkingOrb](components/thinking-orb.md) | 상태와 알림 | AI 에이전트가 실제로 검색·생성·듣기 같은 작업을 하는 동안 그 단계를 보여 줄 때만 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
197
197
|
| [Timeline](components/timeline.md) | 데이터 표시 | 이미 일어난 일을 시간 순서대로 보여 줄 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
198
198
|
| [TimePicker](components/time-picker.md) | 입력 | 하루 중 시각 하나를 시·분 두 열에서 고를 때 쓴다. | 미게시(1.34.0 이후) | Web · Native | Web stable / Native stable | 배포 |
|
|
199
|
-
| [Toast](components/toast.md) | 상태와 알림 |
|
|
199
|
+
| [Toast](components/toast.md) | 상태와 알림 | 저장 완료의 한 줄형·대상 요약형과 화면 안 상태 표시의 선택은 저장 결과 구성을 따른다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
200
200
|
| [ToggleFeedbackButton](components/toggle-feedback-button.md) | 구성/직접 조작과 모션 | 좋아요·저장·알림 받기처럼 켜고 끄는 선택에 반응 모션과 개수를 붙인다. | 1.21.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
201
201
|
| [ToggleGroup](components/toggle-group.md) | 입력 | 여러 개를 동시에 켜고 끄는 짧은 버튼 묶음에 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
202
202
|
| [Tooltip](components/tooltip.md) | 오버레이 | Web에서 이미 이름과 focus를 가진 컨트롤(대개 IconButton)에 **짧은 보충 설명 한 문장**을 붙일 때 쓴다. | 1.12.1 | Web | Web stable / Native unsupported | 배포 |
|
|
@@ -242,6 +242,7 @@ Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품
|
|
|
242
242
|
| [펼치는 검색과 실제 메시지 답장](compositions/communication.md) | 선택과 필터 | 검색 아이콘 버튼에서 검색 영역을 펼치거나 채팅의 실제 메시지를 선택해 답장을 전송할 때 쓴다. | 1.21.0 | Web · Native | 구성 API별 | 배포 |
|
|
243
243
|
| [보관함과 페이지 이동](compositions/web-navigation.md) | 탐색과 이동 | Web에서 상위 보관함 → 하위 모음으로 들어가고, 그 모음의 긴 목록을 페이지 단위로 넘겨 보는 탐색에 쓴다. | 1.12.1 | Web | 구성 API별 | 배포 |
|
|
244
244
|
| [펼침과 메뉴](compositions/disclosure.md) | 탐색과 이동 | 내용을 숨겼다 펼치거나(Collapsible), Web에서 대상에 붙은 작업 메뉴를 우클릭·키보드로 열거나(ContextMenu), 데스크톱 앱처럼 상단 메뉴 막대를 두는(Menubar) 세 방식을 각각 보여 주는 모음이다. | 1.12.1 | Web · Native | 구성 API별 | 배포 |
|
|
245
|
+
| [ShortcutRail](compositions/shortcut-rail.md) | 탐색과 이동 | 최근 장소·최근 도구처럼 누르면 바로 열리는 유한 목록이다. | 1.36.1 | Web · Native | 구성 API별 | 배포 |
|
|
245
246
|
| [대화 메시지](compositions/common-message.md) | 정보 표시 | 말풍선 하나하나에 반응·답장·원문 이동·전송 실패 후 다시 보내기를 붙일 때 쓴다. | 구성 API 지침 참조 | Web · Native | 구성 API별 | 배포 |
|
|
246
247
|
| [명령 기록 표시](compositions/command-records.md) | 정보 표시 | 명령 원문과 출력 기록을 선택·읽기·복사할 때 쓴다. | 1.16.0 | Web · Native | 구성 API별 | 배포 |
|
|
247
248
|
| [문서와 파일](compositions/document-resource.md) | 정보 표시 | 이름·형식·크기와 미리보기·내보내기·별도 메뉴를 함께 제공하는 문서에 쓴다. | 1.14.0 | Web · Native | 구성 API별 | 배포 |
|
|
@@ -261,6 +262,7 @@ Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품
|
|
|
261
262
|
| [보관과 실행 취소](compositions/action-recovery-undo.md) | 피드백과 복구 | 보관·숨기기·목록에서 빼기처럼 제품이 역연산을 제공하는 작업 뒤에, 같은 자리에서 실행 취소를 주고 그 복구 요청이 성공해야 화면을 되돌릴 때 쓴다. | 1.12.1 | Web · Native | 구성 API별 | 배포 |
|
|
262
263
|
| [선택과 오류 복구](compositions/upload-recovery.md) | 피드백과 복구 | 파일 선택과 전송 상태의 취소·재시도를 연결할 때 쓴다. | 1.14.0 | Web · Native | 구성 API별 | 배포 |
|
|
263
264
|
| [스트림 응답과 중지](compositions/streaming-answer.md) | 피드백과 복구 | 실제 provider가 보내는 응답 delta를 표시하고 중지·재생성·오류를 같은 영역에서 제공할 때 쓴다. | 1.21.0 | Web · Native | 구성 API별 | 배포 |
|
|
265
|
+
| [저장 결과](compositions/save-feedback.md) | 피드백과 복구 | 사용자 저장 요청의 성공이 확인된 뒤, 대상과 현재 화면에 맞는 피드백을 선택할 때 쓴다. | 1.37.0 | Web · Native | 구성 API별 | 실험 |
|
|
264
266
|
| [저장과 재시도](compositions/action-recovery-save.md) | 피드백과 복구 | 입력한 내용을 서버에 저장하는 폼 한 덩어리에서 저장 중 중복 실행을 막고, 실패하면 입력을 지우지 않은 채 제출했던 값 그대로 다시 보낼 때 쓴다. | 1.12.1 | Web · Native | 구성 API별 | 배포 |
|
|
265
267
|
| [전송 진행과 취소](compositions/transfer-task.md) | 피드백과 복구 | 실제 다운로드·업로드·작업의 시작/대기/진행·취소·실패 복구를 한 구성으로 제공할 때 쓴다. | 1.21.0 | Web · Native | 구성 API별 | 배포 |
|
|
266
268
|
| [중단해도 남는 현재 상태](compositions/expo-interactions.md) | 피드백과 복구 | 버튼으로 상태를 빠르게 바꾸거나 전환 도중 내용을 닫아도 현재 상태가 바로 보이고 남아야 하는 영역에 쓴다. | 1.12.1 | Native | 구성 API별 | 배포 |
|
|
@@ -286,7 +288,6 @@ Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품
|
|
|
286
288
|
| [테마 조합](compositions/design-profile-comparison.md) | 비교와 검증 | 같은 기능에 10가지 표현을 적용하고, 앱 소유 테마 설정을 넣었을 때 네 단계의 전파와 상태 유지를 검토할 때 쓴다. | 1.16.0 | Web · Native | 구성 API별 | 배포 |
|
|
287
289
|
| [토스트 배치 비교](compositions/toast-layout.md) | 비교와 검증 | Toast 카드 한 장의 내부 배치(톤 배지·제목·설명·닫기·실행 버튼)와 화면 위 위치를 좁은 폭·큰 글자·긴 문구·톤별로 확인하는 비교 스토리다. | 1.12.1 | Web · Native | 구성 API별 | 배포 |
|
|
288
290
|
| [환경 조합 검증](compositions/environment-matrix.md) | 비교와 검증 | 제품 화면이 테마·쓰기 방향·글자 크기·모션 설정이 달라져도 같은 의미를 유지하는지 확인할 때, 어떤 환경 조합과 검증 항목을 골라 볼지 정하는 기준표로 쓴다. | 1.12.1 | Web | 구성 API별 | 배포 |
|
|
289
|
-
| [ShortcutRail](compositions/shortcut-rail.md) | 콘텐츠 | 최근 장소·최근 도구처럼 누르면 바로 열리는 유한 목록이다. | 미게시(1.34.0 이후) | Web · Native | 구성 API별 | 실험 |
|
|
290
291
|
|
|
291
292
|
## 화면
|
|
292
293
|
|
|
@@ -75,6 +75,8 @@ const insets = useSafeAreaInsets();
|
|
|
75
75
|
|
|
76
76
|
## 배치
|
|
77
77
|
|
|
78
|
+
2026-10-20 선택의창 사용자 지적: 버튼의 보이는 면과 터치 영역은 홈 인디케이터·하단 제스처 안전 영역 위에 배치한다. 바탕만 화면 끝까지 이어진다. Native Sheet footer는 앱이 `HjmNativeProvider safeAreaInsets`로 공급한 실제 창 inset을 사용한다. 시트 크기를 줄여도 이 여백은 보존하며, inset 미전달을 제품별 고정 padding으로 덮지 않는다.
|
|
79
|
+
|
|
78
80
|
2026-10-20 번뚝 작성 화면은 BottomCTA에 HTML 제출 연결이 없어 버튼 묶음을 직접 유지했다.
|
|
79
81
|
Web은 기존 form의 onSubmit/IME·검증을 유지하고 아래처럼 footer의 버튼을 form ID로 연결한다.
|
|
80
82
|
onClick에서 requestSubmit을 흉내 내거나 빈 콜백을 넣을 필요가 없다. 여러 편집기가 함께 있으면 React useId로 ID를 만든다.
|
|
@@ -79,7 +79,7 @@ Web·Native 모두 기존 `raised` Surface의 테두리·그림자를 재사용
|
|
|
79
79
|
|
|
80
80
|
| prop | 값 | 기본값 | 설명 |
|
|
81
81
|
| --- | --- | --- | --- |
|
|
82
|
-
| `tone` | `default` · `raised` · `accent` · `sunken` · `subtle`(Surface tone) | `raised` | 테두리와 공통
|
|
82
|
+
| `tone` | `default` · `raised` · `accent` · `sunken` · `subtle`(Surface tone) | `raised` | 테두리와 공통 raised shadow로 입체감 표시. 평면 카드는 `tone="default"` 지정 |
|
|
83
83
|
| `bordered` | `boolean` | `true` | Surface 기본 `false`와 다르다 |
|
|
84
84
|
| `padding` | spacing 이름 | `md`(16) | — |
|
|
85
85
|
| `radius` | radius 이름 | `lg`(foundation 16) | 선택한 designProfile의 같은 radius 역할로 frame과 media clip을 함께 변경 |
|
|
@@ -276,3 +276,7 @@ Native centerContent에는 Text 등 Native 노드를 쓴다. 모두 제외하거
|
|
|
276
276
|
accessibilityLabel={t("comparison")} formatValue={formatValue} missingLabel={t("missing")}
|
|
277
277
|
animateChanges showAxis />
|
|
278
278
|
```
|
|
279
|
+
|
|
280
|
+
### 테마와 글자
|
|
281
|
+
|
|
282
|
+
원형 차트의 비율 라벨은 `chartRecipe.chrome.labelSurface`(`bg`) 판 위에 `labelContent`(`text`)로 표시한다. 제품이 계열색을 바꾸거나 선택하지 않은 조각을 흐리게 해도 라벨 대비가 유지된다. Native SVG 라벨은 프로필의 `caption` 크기와 `ui` 글꼴, Provider의 글자 배율을 따르며 범례 값과 커서 안내도 공통 Text를 사용한다.
|
|
@@ -92,13 +92,15 @@ import { Combobox } from "@hjmds/react-native/forms";
|
|
|
92
92
|
|
|
93
93
|
## 배치
|
|
94
94
|
|
|
95
|
+
2026-10-20 언어 선택 화면에서 자체 모달에 옛 ×·여백이 남은 문제를 해결하기 위해 Native는 공통 Sheet를 직접 사용한다. 닫기 제스처·안전 영역·높이·키보드 대응·teardown은 Sheet가 소유하고, 선택 목록과 확정 콜백은 입력 컴포넌트가 소유한다.
|
|
96
|
+
|
|
95
97
|
Native는 제품 프로필의 `tokens.fontFamily.ui`를 실제 텍스트/입력 host에 연결한다. 기본 UI stack은 OS 서체를 유지하고, 제품이 지정한 첫 named font의 등록·글리프 확인은 제품이 맡는다.
|
|
96
98
|
|
|
97
99
|
| 항목 | 값 | 근거 |
|
|
98
100
|
| --- | --- | --- |
|
|
99
|
-
| 크기 | 입력 높이 `medium` 44(`fieldFrameContract`) · `large` 52(`control.buttonHeight.large`), 폭은 폼 열을 채운다. Web 목록 최대 높이 22.5rem(360, recipe `popover.maxHeight`), 선택지 최소 높이 `compact` 44 · `comfortable` 56(3.5rem). Native
|
|
100
|
-
| 간격 | 라벨·설명·오류는 [Field](field.md) 규칙(`formSupportContract.gap` `spacing.xs` 8). Web 목록 안쪽 `spacing.xs` 8(`comboboxRecipe.popover.padding` = Select와 같은 표면. 2026-10-06까지 4, 1.13.0 변경), 선택지 안쪽 위아래 `spacing.xs` 8 · 좌우 `spacing.sm` 12. Native 시트
|
|
101
|
-
| 순서·정렬 | 폼 안에서 다른 입력과 같은 열에 둔다. Web은 입력 바로 아래(공간이 없으면 위, `data-placement`)에 목록이 붙는다. Native는
|
|
101
|
+
| 크기 | 입력 높이 `medium` 44(`fieldFrameContract`) · `large` 52(`control.buttonHeight.large`), 폭은 폼 열을 채운다. Web 목록 최대 높이 22.5rem(360, recipe `popover.maxHeight`), 선택지 최소 높이 `compact` 44 · `comfortable` 56(3.5rem). Native는 공통 Sheet의 `auto` 높이·가용 영역 상한을 따른다 | `selectRecipe.sizes`·`popover`, `.hjm-combobox__listbox`·`__option`, `react-native/src/forms.tsx` |
|
|
102
|
+
| 간격 | 라벨·설명·오류는 [Field](field.md) 규칙(`formSupportContract.gap` `spacing.xs` 8). Web 목록 안쪽 `spacing.xs` 8(`comboboxRecipe.popover.padding` = Select와 같은 표면. 2026-10-06까지 4, 1.13.0 변경), 선택지 안쪽 위아래 `spacing.xs` 8 · 좌우 `spacing.sm` 12. Native 시트 여백·안전 영역·손잡이와 본문 간격은 [Sheet](sheet.md)의 공통 recipe를 따른다 | `.hjm-combobox__option`, `react-native/src/forms.tsx` |
|
|
103
|
+
| 순서·정렬 | 폼 안에서 다른 입력과 같은 열에 둔다. Web은 입력 바로 아래(공간이 없으면 위, `data-placement`)에 목록이 붙는다. Native는 공통 Sheet의 손잡이 → 상태 문구 또는 선택지 목록 순서다. 제목은 접근성 이름으로만 남기고 ×는 기본으로 숨긴다 | `react/src/advanced-forms.tsx`(`AnchoredPortal`), Native `Sheet` |
|
|
102
104
|
| 고정·스크롤 | 목록은 그 안에서 스크롤한다. Web 목록은 `position: fixed`(z-index `layer.dropdown` 400)로 떠서 화면 스크롤과 무관하다. Native 시트는 배경막(`backdrop.modal`)과 함께 모달로 뜬다 | `.hjm-combobox__listbox`, `react-native/src/forms.tsx` |
|
|
103
105
|
| 좁은 폭·큰 글자 | 선택지 문구는 줄바꿈되고(`overflow-wrap: anywhere`) 높이가 늘어난다. 좁은 폭에서도 Web 목록은 입력에 붙는다 | `.hjm-combobox__option` |
|
|
104
106
|
|
|
@@ -109,8 +111,8 @@ Web Native
|
|
|
109
111
|
│ [ 입력어 _____________ ▾ ]│ │ [ 입력어 _____________ ▾ ]│
|
|
110
112
|
│ ┌──────────────────────┐ │ │ ▒▒▒▒ 배경막 ▒▒▒▒▒▒▒▒▒▒▒▒ │
|
|
111
113
|
│ │ 선택지 1 (44/56) │ │ ← fixed │ ┌──────────────────────┐ │
|
|
112
|
-
│ │ 선택지 2 │ │ 스크롤 │ │
|
|
113
|
-
│ └──────────────────────┘ │ │ │ 선택지 목록(스크롤) │ │ ←
|
|
114
|
+
│ │ 선택지 2 │ │ 스크롤 │ │ ━━━ │ │
|
|
115
|
+
│ └──────────────────────┘ │ │ │ 선택지 목록(스크롤) │ │ ← Sheet 가용 높이
|
|
114
116
|
│ 설명·오류 │ │ │ ░ 하단 안전 영역 ░ │ │
|
|
115
117
|
└──────────────────────────┘ └─┴──────────────────────┴─┘
|
|
116
118
|
```
|
|
@@ -51,6 +51,7 @@ import { CompositionLayout } from "@hjmds/react-native/screens";
|
|
|
51
51
|
|
|
52
52
|
| prop | 값 | 기본값 | 설명 |
|
|
53
53
|
| --- | --- | --- | --- |
|
|
54
|
+
| titleSize | default · compact | default | 1.37.0. compact는 body(14)·500으로 표시하고 제목 의미를 유지한다. 2026-10-20 Spint 시트의 TOP 제목 축소 요청 |
|
|
54
55
|
| title / description | string | 없음 | 제품 지역화 문구 |
|
|
55
56
|
| leading / badge / actions | ReactNode | 없음 | 앞 콘텐츠·제목 옆 배지·끝 행동. 자리와 간격은 HJM |
|
|
56
57
|
| notice | ReactNode | 없음 | 초안을 유지하는 비차단 안내 |
|
|
@@ -93,7 +94,7 @@ footer
|
|
|
93
94
|
| 의미 | Heading·alert/status | header·accessibilityLiveRegion |
|
|
94
95
|
| 환경 | 부모 화면의 높이 | 부모 화면의 safe area·키보드 |
|
|
95
96
|
|
|
96
|
-
제목과 설명 묶음은 자연 너비를 기준으로 늘어나며 부모 너비를 넘지 않는다. 제목과 actions가 한 줄에 들어가지 않으면 actions가 다음 줄로 이동한다. Spint 셀에서 제목이 정렬 버튼 옆의 남은 폭으로 압축되던 문제를 양 renderer에서 수정했다(
|
|
97
|
+
제목과 설명 묶음은 자연 너비를 기준으로 늘어나며 부모 너비를 넘지 않는다. 제목과 actions가 한 줄에 들어가지 않으면 actions가 다음 줄로 이동한다. Spint 셀에서 제목이 정렬 버튼 옆의 남은 폭으로 압축되던 문제를 양 renderer에서 수정했다(1.37.0).
|
|
97
98
|
|
|
98
99
|
2026-10-19 사용자 지시: 앱·모바일 웹뷰의 큰 글씨를 지양하므로 구획 제목은 두 renderer 모두 18(level5)을 기본으로 쓴다.
|
|
99
100
|
headingLevel은 문서 구조만 결정한다. 기존 24는 상한이며 일반 카드·선택 영역 제목의 기본값이 아니다.
|
|
@@ -85,7 +85,7 @@ expect(checkBrandPaletteContrast(PRODUCT_BRAND_PALETTE)).toEqual({ light: [], da
|
|
|
85
85
|
| `textScale` | 연속값 | `1` | — |
|
|
86
86
|
| `reducedMotion` | `true` · `false` | `false` | — |
|
|
87
87
|
| `minimumVisualTarget` | `true` · `false` | `false` | — |
|
|
88
|
-
| `brandPalette` | `{ light?, dark? }` | — | 각각 `ThemeColors`
|
|
88
|
+
| `brandPalette` | `{ light?, dark? }` | — | 각각 `ThemeColors` 20개 key 중 필요한 것만 넘긴다(부분 병합). 상태 강조색은 덮을 수 없다. 중첩 Provider는 가장 가까운 상위의 값을 물려받는다 |
|
|
89
89
|
| `designProfile` | `HjmDesignProfile` | 가장 가까운 상위 프로필 또는 없음 | 기본 프로필·표면 질감은 1.15.0 추가. `hjmDesignPresets` 또는 `defineHjmDesignProfile` 결과만 넣는다. 글자 역할·관련 구성 개선은 1.16.0 변경. [프로필 계약](../../design-profile.md)의 토큰·질감·전환·구성·화면 기본값을 상속한다 |
|
|
90
90
|
| `value` | `DesignSystemProviderValue`(`resolveDesignSystemProviderValue` 결과) | — | 테스트·스토리·임베딩용. 환경 prop·`brandPalette`·`designProfile`과 함께 쓸 수 없고(타입이 막는다), 주면 OS theme·모션 관찰과 상위 `brandPalette` 상속이 멈춘다 |
|
|
91
91
|
| `surfaceEffects`(Native) | `{ renderBackdrop?, insetShadows? }` | 상위 host 또는 없음 | 1.15.0 실험 API. 실제 blur host·inset capability를 한 번 등록하며 `{}`로 하위 영역을 해제. [Surface 질감 계약](../../design-profile.md#surfacecard의-유리클레이-질감) |
|
|
@@ -120,7 +120,7 @@ expect(checkBrandPaletteContrast(PRODUCT_BRAND_PALETTE)).toEqual({ light: [], da
|
|
|
120
120
|
|
|
121
121
|
| 항목 | Web | Native |
|
|
122
122
|
| --- | --- | --- |
|
|
123
|
-
| `density`(`comfortable` 기본 · `compact`) | 있음 |
|
|
123
|
+
| `density`(`comfortable` 기본 · `compact`) | 있음 | 있음. ListRow·Menu·DataTable의 생략된 density에 적용 |
|
|
124
124
|
| `host`(`surface` 기본 · `contents`) | 있음. 문서 루트가 이미 표면을 칠하면 `contents` | 없음 |
|
|
125
125
|
| `systemTheme` 고정(SSR·테스트) | 있음 | 없음(`useColorScheme`) |
|
|
126
126
|
| `safeAreaInsets` | 없음 | 있음. Sheet·DatePicker·Select·Combobox가 기본 여백으로 쓴다 |
|
|
@@ -122,3 +122,5 @@ EmptyState 자체에는 콜백 prop이 없다. 2026-10-07 기존 예제의 생
|
|
|
122
122
|
| 배치 | `layoutStyle`(그 밖에 `className`과 div 속성) | `layoutStyle`(슬롯 style 다섯 개는 제거된 속성) |
|
|
123
123
|
|
|
124
124
|
2026-10-18 사용자 결정: 제목과 보조 설명 모두 `body`(기본 14, 줄 높이 20)를 사용한다. 화면·부분 영역의 크기나 Web 부모의 큰 글자 스타일에 따라 빈 상태 문구를 키우지 않는다. 공통 화면·구성의 `empty` 상태도 같은 기준이다. Spint의 부분 빈 상태가 제목 크기로 커진 문제와 Web의 부모 글자 상속·Native 설명 12의 차이를 함께 정리했다.
|
|
125
|
+
|
|
126
|
+
2026-10-20 Native 행동 영역은 본문 폭을 확보하고 일반 버튼은 가운데에 둔다. `action`에 세로 버튼 묶음을 넣으면 묶음과 버튼에 `width: "100%"`/`fullWidth`를 사용한다. 비행중 빈 화면에서 내용 기반 부모와 백분율 자식의 순환 폭 계산으로 버튼 폭과 중앙 정렬이 달라진 문제를 수정했다(개발 소스, 미게시).
|
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
|
|
11
11
|
## 언제 쓰나
|
|
12
12
|
|
|
13
|
+
저장된 항목·폼 안의 작은 성공 상태는 `appearance="status"`(1.37.0)를 쓴다. 기존 Badge에 제목을 표시하고,
|
|
14
|
+
바깥 배경·테두리·padding을 없앤다. 설명·행동·낭독은 그대로 유지한다. 기본 `appearance="panel"`은 변경하지 않는다.
|
|
15
|
+
세 가지 저장 결과 선택은 [저장 결과 구성](../compositions/save-feedback.md)을 따른다.
|
|
16
|
+
|
|
13
17
|
화면 흐름 안 **제자리에 남아 있는** 상태 알림에 쓴다. 저장 실패, 오프라인, 권한 제한,
|
|
14
18
|
결제 수단 만료처럼 사용자가 읽고 필요하면 행동(`action`)할 때까지 사라지면 안 되는 내용이 여기에 속한다.
|
|
15
19
|
|
|
@@ -184,3 +184,5 @@ Spint 스팟 필터가 제품 ScrollView와 고정 추가 행을 재조립하던
|
|
|
184
184
|
|
|
185
185
|
<!-- usage-example: Web ../../../../../showcase/web/src/components/SegmentedControl.stories.tsx -->
|
|
186
186
|
<!-- usage-example: Native ../../../../../showcase/native/src/components/SegmentedControl.stories.tsx -->
|
|
187
|
+
|
|
188
|
+
2026-10-20 개발 소스·미게시: Spint 카테고리 재검토에서 사용자가 여백은 이전처럼 유지하고 글씨를 줄이도록 요청했다. pills 좌우 여백은 small 12, medium 16으로 복원하고 글씨는 label(12/18)로 통일한다. 높이와 터치 영역은 유지한다.
|
|
@@ -104,12 +104,14 @@ import { NativeSelect } from "@hjmds/react/forms";
|
|
|
104
104
|
|
|
105
105
|
## 배치
|
|
106
106
|
|
|
107
|
+
2026-10-20 언어 선택 화면에서 자체 모달에 옛 ×·여백이 남은 문제를 해결하기 위해 Native는 공통 Sheet를 직접 사용한다. 닫기 제스처·안전 영역·높이·키보드 대응·teardown은 Sheet가 소유하고, 선택 목록과 확정 콜백은 입력 컴포넌트가 소유한다.
|
|
108
|
+
|
|
107
109
|
| 항목 | 값 | 근거 |
|
|
108
110
|
| --- | --- | --- |
|
|
109
|
-
| 크기 | 트리거 최소 높이 `medium` 44 · `large` 52, 폼 열 폭을 채운다(Web `inline-size: 100%`). 선택지 행 `comfortable` 56 · `compact` 44. Web 목록 최대 폭 420(`min(26.25rem, 100vw − 2×spacing.md)`)·최대 높이 360. Native
|
|
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
|
|
111
|
-
| 순서·정렬 | 트리거: 앞 아이콘 → 값(넘치면 말줄임) → 펼침 표시. Web 목록은 트리거 아래·트리거와 같은 폭, 공간이 없으면 위로 뒤집힌다. Native
|
|
112
|
-
| 고정·스크롤 | Web 목록은 `position: fixed` popover(z-index `layer.dropdown` 400), 넘치면 목록 안에서 스크롤. Native는 화면 아래에서 올라오는 modal sheet로 목록만 스크롤되고, 아래 여백에 안전 영역(`safeArea.bottom`)을 더한다. 배경(scrim)을 누르면 닫힌다 | `.hjm-select__listbox`, Native `Select`(
|
|
111
|
+
| 크기 | 트리거 최소 높이 `medium` 44 · `large` 52, 폼 열 폭을 채운다(Web `inline-size: 100%`). 선택지 행 `comfortable` 56 · `compact` 44. Web 목록 최대 폭 420(`min(26.25rem, 100vw − 2×spacing.md)`)·최대 높이 360. Native는 공통 Sheet의 `auto` 높이·가용 영역 상한을 따른다 | `fieldFrameContract.minHeight`, `control.buttonHeight.large`, `selectRecipe.density`·`popover`, `.hjm-select__listbox`, Native `forms.tsx` |
|
|
112
|
+
| 간격 | 트리거 좌우 `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](sheet.md)의 공통 recipe를 따른다 | `selectRecipe.sizes`·`value.gap`, `formSupportContract.gap`, `selectRecipe.popover`(sideOffset 8, collisionPadding 8, padding 8), Native `forms.tsx` |
|
|
113
|
+
| 순서·정렬 | 트리거: 앞 아이콘 → 값(넘치면 말줄임) → 펼침 표시. Web 목록은 트리거 아래·트리거와 같은 폭, 공간이 없으면 위로 뒤집힌다. Native는 공통 Sheet의 상단 손잡이를 쓰며 제목은 접근성 이름으로만 남기고 ×는 기본으로 숨긴다. 확인 버튼은 없고 항목을 누르면 선택하고 닫힌다 | `.hjm-select__trigger`, `select.tsx`(`matchAnchorWidth`), Native `Sheet` |
|
|
114
|
+
| 고정·스크롤 | Web 목록은 `position: fixed` popover(z-index `layer.dropdown` 400), 넘치면 목록 안에서 스크롤. Native는 화면 아래에서 올라오는 modal sheet로 목록만 스크롤되고, 아래 여백에 안전 영역(`safeArea.bottom`)을 더한다. 배경(scrim)을 누르면 닫힌다 | `.hjm-select__listbox`, Native `Select`(Sheet·ScrollView) |
|
|
113
115
|
| 좁은 폭·큰 글자 | 트리거 높이는 최소값이라 큰 글자에서 늘어나고 값은 한 줄 말줄임이다. Web 목록 폭은 화면 폭 − 32를 넘지 않는다 | `.hjm-select__value`, `.hjm-select__listbox` |
|
|
114
116
|
|
|
115
117
|
```text
|
|
@@ -117,13 +119,13 @@ Web popover Native sheet
|
|
|
117
119
|
라벨 ┌──────── scrim (누르면 닫힘) ────────┐
|
|
118
120
|
┌──────────────────────┐ │ │
|
|
119
121
|
│ 선택된 값 ⌄ │ 44 ├─────────────────────────────────────┤ radius.lg 16
|
|
120
|
-
└──────────────────────┘ │
|
|
121
|
-
↓ 8 │ gap
|
|
122
|
+
└──────────────────────┘ │ ━━━ │ ← 손잡이
|
|
123
|
+
↓ 8 │ gap sheetRecipe.body.gap │
|
|
122
124
|
┌──────────────────────┐ │ ┌─────────────────────────────────┐ │
|
|
123
125
|
│ 최신순 ✓ │ 56 │ │ 최신순 ✓ │ │ 56 ↕ 스크롤
|
|
124
126
|
│ 인기순 │ │ │ 인기순 │ │
|
|
125
127
|
└──────────────────────┘ max 360 │ └─────────────────────────────────┘ │
|
|
126
|
-
트리거 폭, max 420 │
|
|
128
|
+
트리거 폭, max 420 │ Sheet 공통 여백 + 안전 영역 │ auto
|
|
127
129
|
└─────────────────────────────────────┘
|
|
128
130
|
```
|
|
129
131
|
|
|
@@ -81,7 +81,7 @@ import { Sheet } from "@hjmds/react-native/overlays";
|
|
|
81
81
|
| --- | --- | --- | --- |
|
|
82
82
|
| `initialFocus` | `single-input` · `first-input` · `none` | 하단: 자동 포커스 없음 / 측면: `single-input` | 1.33.0 정책 변경. 하단 시트는 이 prop·`initialFocusRef`·중첩 화면·`initialFocusTarget`으로 입력 자동 포커스를 켤 수 없다. Web은 모달 컨테이너로 초점을 옮겨 focus trap을 유지하고 Native는 키보드를 열지 않는다. 측면 시트는 기존 Dialog 계약을 따른다. 사용자가 직접 입력칸을 누르는 동작은 유지한다 |
|
|
83
83
|
| `placement` | `bottom` · `start` · `end` | `bottom` | 나오는 가장자리 |
|
|
84
|
-
| `size` | `auto` · `medium`(60%) · `large`(85%) · `full`(100%) | `auto` | `auto`는 내용 높이. 비율은 화면 높이 기준(Web `dvh`), 두 플랫폼 모두 위 safe area(Native는 키보드도)를 뺀 남은 높이를 넘지 않는다. `maxHeightRatio` 0.9 상한은 `auto`에만 걸린다 |
|
|
84
|
+
| `size` | `auto` · `small`(40%, 1.37.0) · `medium`(60%) · `large`(85%) · `full`(100%) | `auto` | `auto`는 내용 높이. 비율은 화면 높이 기준(Web `dvh`), 두 플랫폼 모두 위 safe area(Native는 키보드도)를 뺀 남은 높이를 넘지 않는다. `maxHeightRatio` 0.9 상한은 `auto`에만 걸린다 |
|
|
85
85
|
| `open` · `defaultOpen` | `boolean` | 비제어 `false` | Web은 제어하면 `onOpenChange` 필수, 비제어면 `trigger` 필수 |
|
|
86
86
|
| `onOpenChange` | `(open: boolean, detail: { reason }) => void` | — | reason: `trigger` · `close-action` · `escape` · `back` · `outside` · `swipe` · `programmatic`. Android 하드웨어 back은 Native에서만 `back` |
|
|
87
87
|
| `onDismissComplete` | `(detail: { reason }) => void` | — | 표면이 실제로 사라진 뒤 한 번. 다음 modal·화면 이동은 여기서 |
|
|
@@ -107,6 +107,10 @@ import { Sheet } from "@hjmds/react-native/overlays";
|
|
|
107
107
|
|
|
108
108
|
## 배치
|
|
109
109
|
|
|
110
|
+
2026-10-20 선택의창 위치 안내 사용자 지적: 버튼은 홈 인디케이터·하단 제스처 안전 영역 **위쪽**에 둔다. Native 앱은 `SafeAreaProvider` 아래에서 읽은 `useSafeAreaInsets()`를 `HjmNativeProvider safeAreaInsets`에 전달해야 한다. Provider 기본값은 실제 기기 inset의 자동 조회가 아니므로 누락 시 0이 된다. 시트는 이 값을 사용해 하단 여백을 확보하고 footer의 BottomCTA와 중복 적용하지 않는다. 시트 높이 축소로 안전 여백을 없애지 않는다.
|
|
111
|
+
|
|
112
|
+
개발 소스·미게시: `size="small"`은 가용 높이의 40%로, `medium`(60%) 높이의 2/3이다. 짧은 안내에 내용 높이만 쓰면 지나치게 작고 medium은 빈 공간이 큰 경우 선택한다. Web·Native 공통 recipe가 크기를 소유한다.
|
|
113
|
+
|
|
110
114
|
Native 스크롤 본문은 viewport 높이만큼 content를 채운다(미게시). 고정 크기 시트의 빈/오류/로딩 상태는 `CompositionLayout layoutStyle={{ flex: 1 }}`로 연결해 손잡이·머리·footer를 제외한 본문 중앙에 둔다. 목록이 길면 같은 본문에서 스크롤한다.
|
|
111
115
|
|
|
112
116
|
선택형 Native `GestureSheetInput`의 실제 keyboard-tracking host에도 제품 `tokens.fontFamily.ui`가 이어진다. optional library·폰트 설치와 실제 기기 검증은 제품이 맡는다.
|
|
@@ -73,7 +73,7 @@ import { TimePicker } from '@hjmds/react/time-picker';
|
|
|
73
73
|
| 간격 | 열 사이 spacing.sm(12), 영역 사이 spacing.md(16) | timePickerRecipe |
|
|
74
74
|
| 고정·스크롤 | 제목·확인은 공통 overlay 영역, 시·분 목록만 세로 스크롤 | Popover / Sheet / TimePicker |
|
|
75
75
|
| 좁은 폭·큰 글자 | 좁은 폭은 두 열을 같은 폭으로 유지. 최대 글자 조건은 사용자 지침으로 범위 제외 | 포트폴리오 AGENTS.md |
|
|
76
|
-
| 선택 표시 | radius.md, surfaceAccent 배경·
|
|
76
|
+
| 선택 표시 | radius.md, surfaceAccent 배경·text 글자·500 굵기 | 시간 값은 주요 글자로 강조하고, 제품 선택 배경과 확정 버튼 대표색을 구분(2026-10-20 토스 공개 팔레트 참고 요청) |
|
|
77
77
|
| 설명·오류 | 입력 아래 description/error. 오류는 보조기술에도 알림 | 양 renderer |
|
|
78
78
|
|
|
79
79
|
|
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
|
|
11
11
|
## 언제 쓰나
|
|
12
12
|
|
|
13
|
+
저장 완료의 한 줄형·대상 요약형과 화면 안 상태 표시의 선택은 [저장 결과 구성](../compositions/save-feedback.md)을 따른다.
|
|
14
|
+
한 줄형은 `description`, 요약형은 기존 `title` + `description`을 사용한다. 저장된 카드가 보이면 같은 성공 토스트를 겹치지 않는다.
|
|
15
|
+
|
|
13
16
|
방금 한 행동의 결과처럼 **무시해도 안전한 짧은 알림**에 쓴다. 저장 완료, 복사 완료, 백그라운드 작업 완료
|
|
14
17
|
알림이 여기에 속한다. 화면 흐름 밖에 떠서 3초 뒤 스스로 닫히고, 큐에 쌓인 다음 알림이 이어서 뜬다.
|
|
15
18
|
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# 저장 결과
|
|
2
|
+
|
|
3
|
+
- 단계: 구성
|
|
4
|
+
- 상태: 실험
|
|
5
|
+
- 지원: Web · Native
|
|
6
|
+
- 적용: 1.37.0
|
|
7
|
+
- 검토일: 2026-10-20
|
|
8
|
+
- 근거: 사용자 요청으로 저장 결과 세 유형을 보존하고 모든 제품의 저장 피드백을 같은 선택 기준으로 연결했다.
|
|
9
|
+
- 스토리북: `실험/구성/피드백과 복구/저장 결과`
|
|
10
|
+
|
|
11
|
+
## 언제 쓰나
|
|
12
|
+
|
|
13
|
+
사용자 저장 요청의 성공이 확인된 뒤, 대상과 현재 화면에 맞는 피드백을 선택할 때 쓴다.
|
|
14
|
+
|
|
15
|
+
## 구성 요소
|
|
16
|
+
|
|
17
|
+
| 컴포넌트 | 역할 | 지침 |
|
|
18
|
+
| --- | --- | --- |
|
|
19
|
+
| Toast + Provider/Region | 컴팩트·대상 요약 알림 | [Toast](../components/toast.md) |
|
|
20
|
+
| Notice status | 항목 안의 작은 저장 상태 | [Notice](../components/notice.md) |
|
|
21
|
+
| Card·CompositionLayout·ListRow | 저장된 대상과 설명의 배치 | [구성 골격](../components/composition-layout.md) |
|
|
22
|
+
|
|
23
|
+
| 유형 | 쓰는 상황 | 기존 공개 API |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| 컴팩트 토스트 | 현재 화면에서 저장 결과를 직접 볼 수 없고 짧은 완료 확인이면 충분함 | Toast `description`, `tone="success"`; 앱 루트의 ToastProvider/ToastRegion 사용 |
|
|
26
|
+
| 대상 요약 토스트 | 저장한 대상이나 변경 내용을 함께 확인해야 함 | 같은 Toast의 `title` + `description`; 필요 시 기존 `media` 사용 |
|
|
27
|
+
| 저장 카드에 바로 반영 | 저장된 카드·목록·폼이 보임 | Card/ListRow/CompositionLayout 슬롯의 Notice `appearance="status"`; 기존 저장 버튼의 체크·저장됨 표시도 이 유형 |
|
|
28
|
+
|
|
29
|
+
1·2는 별도 알림 엔진이나 토스트 변형 prop이 아니다. 기존 Toast의 내용 구성이다.
|
|
30
|
+
3은 기존 Notice의 작은 상태 표현이며 별도 타이머·큐가 없다. 같은 성공을 토스트와 카드에서 중복 알리지 않는다.
|
|
31
|
+
오류·경고·필수 안내는 기존 Notice 패널을 유지한다. 자동 저장의 처리 중·실패·미저장 상태를 성공으로 바꾸지 않는다.
|
|
32
|
+
|
|
33
|
+
## 배치
|
|
34
|
+
|
|
35
|
+
| 영역 | 컴포넌트 | 위치 | 크기·간격 |
|
|
36
|
+
| --- | --- | --- | --- |
|
|
37
|
+
| 바깥 틀 | ToastProvider/ToastRegion 또는 기존 Card·폼 | 화면 위 알림 층 또는 저장한 항목 안 | 토스트 가장자리 `spacing.md` 16 + 안전 영역 |
|
|
38
|
+
| 상태 | Toast 또는 Notice status | 토스트 내용 / CompositionLayout `badge` | 토스트 최소 높이 56, status 바깥 padding 0 |
|
|
39
|
+
| 보조 설명 | Toast description / CompositionLayout footer | 상태 아래 | 기본 구성의 `spacing.sm` 12 간격 |
|
|
40
|
+
|
|
41
|
+
```text
|
|
42
|
+
컴팩트: [ ✓ KE123 저장했어요 × ]
|
|
43
|
+
요약: [ ✓ 항공편을 저장했어요 × ]
|
|
44
|
+
[ KE123 · 인천 → 도쿄 ]
|
|
45
|
+
카드: [ KE123 (저장됨) ]
|
|
46
|
+
[ 인천 → 도쿄 ]
|
|
47
|
+
[ 내 항공편에 추가했어요 ]
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
- 토스트는 기존 최대 폭 420, 최소 높이 56, 가장자리 `spacing.md` 16 + 안전 영역을 따른다. 기본 3초이며 요약이 길면 제품이 읽을 시간을 늘린다. 광고 footer가 있는 제품은 상단에 둔다.
|
|
51
|
+
- 카드는 기존 Card와 CompositionLayout이 배치한다. `badge`에 상태 Notice, `footer`에 보조 설명을 넣는다. Notice status는 바깥 padding·border가 0이고 배지는 기존 Badge `size="small"`을 쓴다. 색·높이·정렬을 제품에서 다시 만들지 않는다.
|
|
52
|
+
- 목록은 상태를 기존 행 슬롯에 둔다. 방금 저장한 항목이 현재 정렬에서 안 보이면 해당 결과를 보여 주되 기존 현재 항목의 우선순위를 바꾸지 않는다.
|
|
53
|
+
- 상태 문구와 보조 설명은 제품이 지역화한다. 짧은 상태는 `저장됨`, 대상 요약은 실제 저장한 식별자를 쓴다. 실제 저장 응답/영속 저장 완료 전에는 성공 표시를 만들지 않는다.
|
|
54
|
+
|
|
55
|
+
## 흐름과 상태
|
|
56
|
+
|
|
57
|
+
1. 수정하면 현재 초안의 저장 상태를 해제한다.
|
|
58
|
+
2. 저장 중에는 기존 제출 상태를 유지한다.
|
|
59
|
+
3. 성공한 스냅샷을 확인한 뒤 대상에 맞는 상태를 표시한다. 실패하면 초안을 유지하고 기존 오류 패널을 쓴다.
|
|
60
|
+
성공 후 다시 편집하면 현재 초안의 저장 표시를 해제한다. 목록의 저장된 사본은 그대로 보존한다.
|
|
61
|
+
|
|
62
|
+
| 상태 | 모습 | 포커스·알림 |
|
|
63
|
+
| --- | --- | --- |
|
|
64
|
+
| 기본 | 초안 또는 이전 저장 사본 | 새 성공 알림 없음 |
|
|
65
|
+
| 진행 중 | 기존 저장 버튼의 busy 상태 | 포커스 유지 |
|
|
66
|
+
| 완료 | 토스트 한 장 또는 해당 항목의 status | polite 낭독 한 번 |
|
|
67
|
+
| 실패 | 기존 오류 패널, 초안 유지 | 기존 오류 낭독·재시도 유지 |
|
|
68
|
+
|
|
69
|
+
## 코드 골격
|
|
70
|
+
|
|
71
|
+
실행 예제는 [Web](../../../../../showcase/web/src/components/save-feedback-preview.tsx), [Native](../../../../../showcase/native/src/save-feedback-preview.tsx), 공통 문구 fixture는 [shared](../../../../../showcase/shared/save-feedback.ts)를 참조한다. 예제의 `durationMs: null`은 비교용이며 제품 기본 타이머를 바꾸는 규칙이 아니다.
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
// Web (Native는 같은 슬롯에 announcement="polite"를 연결한다)
|
|
75
|
+
<CompositionLayout title={subject} description={detail}
|
|
76
|
+
badge={saved ? <Notice appearance="status" tone="success" title={savedLabel} /> : undefined}
|
|
77
|
+
footer={saved ? <Text tone="muted">{savedDescription}</Text> : undefined} />
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
// Native
|
|
82
|
+
<CompositionLayout title={subject} description={detail}
|
|
83
|
+
badge={saved ? <Notice appearance="status" tone="success" announcement="polite" title={savedLabel} /> : undefined}
|
|
84
|
+
footer={saved ? <Text tone="muted">{savedDescription}</Text> : undefined} />
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Native에서는 새 성공에만 `announcement="polite"`를 연결한다. 이미 저장된 목록을 다시 그릴 때는 `none`이다.
|
|
88
|
+
Web은 Notice의 `role="status"`와 `aria-live="polite"`를 유지한다. 저장 결과를 없애려고 포커스를 이동하지 않는다.
|
|
89
|
+
현재 초안의 저장 판정은 기존 `resolveSaveFeedback` 계약을 따른다. 이전 초안 저장이 늦게 끝났다고 최신 초안을 저장됨으로 표시하지 않는다.
|
|
90
|
+
|
|
91
|
+
## 배포 경계
|
|
92
|
+
|
|
93
|
+
개발 소스 연결과 설치 패키지는 별개다. status prop은 1.37.0부터 제공한다. 앱·웹의 소스 채택을 각 제품의 운영 배포 완료로 판단하지 않는다.
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
1. 컴포넌트에 `tone`이 있으면 그것으로 고른다([Text](../components/text.md), [Icon](../components/icon.md),
|
|
20
20
|
[Badge](../components/badge.md), [Notice](../components/notice.md), [Button](../components/button.md)).
|
|
21
21
|
2. 없으면 아래 표에서 **칠할 대상**(용도 열)으로 역할을 찾는다. 같은 대상에 후보가 둘이면 위쪽(더 강한) 것을 먼저 본다.
|
|
22
|
-
3. 채운 바탕 위의 글자는 반드시 짝(`onPrimary`·`onDanger`·`
|
|
22
|
+
3. 채운 바탕 위의 글자는 반드시 짝(`onPrimary`·`onDanger`·`onStatusFill`)을 쓴다.
|
|
23
23
|
|
|
24
24
|
## 값
|
|
25
25
|
|
|
@@ -65,8 +65,14 @@
|
|
|
65
65
|
| `feedback.warning.foreground` | `#92400e` / `#fbbf24` | `--hjm-accent-warning` | `theme.palette.statusAccents.warning` | 주의가 필요한 상태 |
|
|
66
66
|
| `feedback.attention.foreground` | `#9a3412` / `#fb923c` | `--hjm-accent-attention` | `theme.palette.statusAccents.attention` | 눈길을 끌 새 소식 |
|
|
67
67
|
| `feedback.<tone>.background` · `.border` | 위 색 alpha 0.1 · 0.3 | — (`color-mix`) | `resolveColorReference(…, theme.palette)` | 피드백 영역의 옅은 바탕·테두리(Notice·Badge가 그린다) |
|
|
68
|
-
| `accentFill.<tone>` | info `#6d28d9` · success `#065f46` · warning `#92400e` · attention `#9a3412`(두 테마 공통) | `--hjm-accent-fill-<tone>` | `theme.palette.statusAccentFills.<tone>` | 꽉 찬 상태 표지 바탕. 글자는 `
|
|
69
|
-
| `
|
|
68
|
+
| `accentFill.<tone>` | info `#6d28d9` · success `#065f46` · warning `#92400e` · attention `#9a3412`(두 테마 공통) | `--hjm-accent-fill-<tone>` | `theme.palette.statusAccentFills.<tone>` | 꽉 찬 상태 표지 바탕. 글자는 팔레트의 `onStatusFill`(기본 `#ffffff`) |
|
|
69
|
+
| `onStatusFill` | `#ffffff`(두 테마 공통) | `--hjm-color-on-status-fill` | `theme.colors.onStatusFill` | 채운 상태 표지의 글자. 모든 상태 fill과 4.5:1 이상 |
|
|
70
|
+
| `neutralFill` | `#4e5968`(두 테마 공통) | `--hjm-color-neutral-fill` | `theme.colors.neutralFill` | 중립 상태 표지 바탕 |
|
|
71
|
+
| `strongFill` | `#333d4b`(두 테마 공통) | `--hjm-color-strong-fill` | `theme.colors.strongFill` | 강한 상태 표지 바탕 |
|
|
72
|
+
| `accentTint` | `weak` 0.1 · `base` 0.15 · `strong` 0.2 · `border` 0.3 | — | `onStatusFill` | `#ffffff`(두 테마 공통) | `--hjm-color-on-status-fill` | `theme.colors.onStatusFill` | 채운 상태 표지의 글자. 모든 상태 fill과 4.5:1 이상 |
|
|
73
|
+
| `neutralFill` | `#4e5968`(두 테마 공통) | `--hjm-color-neutral-fill` | `theme.colors.neutralFill` | 중립 상태 표지 바탕 |
|
|
74
|
+
| `strongFill` | `#333d4b`(두 테마 공통) | `--hjm-color-strong-fill` | `theme.colors.strongFill` | 강한 상태 표지 바탕 |
|
|
75
|
+
| `accentTint` | 피드백 색을 옅게 깔 때 쓰는 alpha |
|
|
70
76
|
|
|
71
77
|
도메인 상태(예: "배송 지연")는 제품 어댑터에서 `info`·`success`·`warning`·`attention`·`danger` 중 하나로 매핑한다.
|
|
72
78
|
`info`·`success`·`warning`·`attention`의 accent 색은 `brandPalette` 변경 대상이 아니다.
|
|
@@ -114,7 +120,7 @@ const theme = useHjmNativeTheme();
|
|
|
114
120
|
const tint = resolveColorReference(semanticColors.feedback.warning.background, theme.palette);
|
|
115
121
|
```
|
|
116
122
|
|
|
117
|
-
제품 브랜드는 Provider의 `brandPalette`로
|
|
123
|
+
제품 브랜드는 Provider의 `brandPalette`로 20개 key 중 필요한 것만 바꾼다. 값은 [테마 편집](theme-studio.md)으로 고르고 대비를 확인한다.
|
|
118
124
|
|
|
119
125
|
```tsx
|
|
120
126
|
// Web
|
|
@@ -131,7 +137,7 @@ import { HjmProvider } from "@hjmds/react/provider";
|
|
|
131
137
|
- 제품 브랜드를 `--hjm-color-*` 재정의나 `.hjm-*` 덮어쓰기로 넣지 않는다. 색만 바꾸면 `brandPalette`, 여러 표현 축을 함께 선택하면 검증한 `designProfile`을 쓴다([브랜드 경계](../../brand-boundary.md)).
|
|
132
138
|
- 성공·오류 색을 브랜드 색으로, 브랜드 색을 상태 색으로 쓰지 않는다.
|
|
133
139
|
- `textWeak`로 읽혀야 하는 문구를 쓰지 않는다. 보조 문구는 `textMuted`·`textSub`다.
|
|
134
|
-
- 채운 `primary`·`dangerFill`·`accentFill` 위에 `text`를 올리지 않는다. 짝(`onPrimary`·`onDanger`·`
|
|
140
|
+
- 채운 `primary`·`dangerFill`·`accentFill` 위에 `text`를 올리지 않는다. 짝(`onPrimary`·`onDanger`·`onStatusFill`)을 쓴다.
|
|
135
141
|
- Showcase의 예시 색을 제품 기본값으로 복사하지 않는다.
|
|
136
142
|
|
|
137
143
|
## 플랫폼 차이
|