@hjmds/design-contracts 1.37.2 → 1.38.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.
Files changed (99) hide show
  1. package/dist/card.d.ts +2 -1
  2. package/dist/card.d.ts.map +1 -1
  3. package/dist/card.js +3 -1
  4. package/dist/card.js.map +1 -1
  5. package/dist/catalog.d.ts +42 -12
  6. package/dist/catalog.d.ts.map +1 -1
  7. package/dist/colors.js +2 -2
  8. package/dist/colors.js.map +1 -1
  9. package/dist/component-recipes.d.ts +34 -6
  10. package/dist/component-recipes.d.ts.map +1 -1
  11. package/dist/component-recipes.js +16 -9
  12. package/dist/component-recipes.js.map +1 -1
  13. package/dist/result.d.ts +1 -1
  14. package/dist/result.d.ts.map +1 -1
  15. package/dist/result.js +2 -1
  16. package/dist/result.js.map +1 -1
  17. package/dist/screen-patterns.d.ts +3 -3
  18. package/dist/screen-patterns.d.ts.map +1 -1
  19. package/dist/screen-patterns.js +5 -4
  20. package/dist/screen-patterns.js.map +1 -1
  21. package/dist/semantic-colors.d.ts +10 -0
  22. package/dist/semantic-colors.d.ts.map +1 -1
  23. package/dist/semantic-colors.js +3 -0
  24. package/dist/semantic-colors.js.map +1 -1
  25. package/dist/steps.d.ts +2 -1
  26. package/dist/steps.d.ts.map +1 -1
  27. package/dist/steps.js +3 -1
  28. package/dist/steps.js.map +1 -1
  29. package/dist/version.d.ts +1 -1
  30. package/dist/version.js +1 -1
  31. package/dist/version.js.map +1 -1
  32. package/docs/collection-rail.md +3 -0
  33. package/docs/generated/component-maturity.md +1 -1
  34. package/docs/generated/renderer-evidence.json +3 -3
  35. package/docs/generated/renderer-evidence.md +1 -1
  36. package/docs/generated/showcase-manifest.json +1 -1
  37. package/docs/theme-palette.md +7 -0
  38. package/docs/usage/README.md +22 -22
  39. package/docs/usage/SELECTION.md +2 -2
  40. package/docs/usage/components/alert-dialog.md +1 -1
  41. package/docs/usage/components/auth-provider-button.md +1 -1
  42. package/docs/usage/components/auth-screen-layout.md +4 -2
  43. package/docs/usage/components/bottom-cta.md +1 -1
  44. package/docs/usage/components/button.md +7 -1
  45. package/docs/usage/components/card.md +2 -1
  46. package/docs/usage/components/chat-message.md +2 -2
  47. package/docs/usage/components/chat-screen.md +2 -2
  48. package/docs/usage/components/comment-thread-row.md +11 -7
  49. package/docs/usage/components/comment-thread-screen.md +3 -3
  50. package/docs/usage/components/composition-layout.md +6 -2
  51. package/docs/usage/components/conversion-funnel.md +3 -3
  52. package/docs/usage/components/design-system-provider.md +1 -1
  53. package/docs/usage/components/dialog.md +2 -2
  54. package/docs/usage/components/editor-screen.md +2 -2
  55. package/docs/usage/components/form.md +1 -1
  56. package/docs/usage/components/icon-button.md +6 -0
  57. package/docs/usage/components/image-choice-group.md +2 -2
  58. package/docs/usage/components/list-detail-screen.md +2 -2
  59. package/docs/usage/components/list.md +1 -0
  60. package/docs/usage/components/media-selection-screen.md +3 -3
  61. package/docs/usage/components/message-composer.md +2 -2
  62. package/docs/usage/components/moderation-screen.md +2 -2
  63. package/docs/usage/components/notice.md +1 -1
  64. package/docs/usage/components/notification-inbox-screen.md +2 -2
  65. package/docs/usage/components/notification-item.md +2 -2
  66. package/docs/usage/components/onboarding-screen.md +2 -2
  67. package/docs/usage/components/overview-screen.md +2 -2
  68. package/docs/usage/components/permission-screen.md +2 -2
  69. package/docs/usage/components/photo-source-sheet.md +1 -1
  70. package/docs/usage/components/profile-screen.md +2 -2
  71. package/docs/usage/components/profile-summary.md +1 -1
  72. package/docs/usage/components/result.md +2 -2
  73. package/docs/usage/components/screen-layout.md +3 -3
  74. package/docs/usage/components/section.md +1 -1
  75. package/docs/usage/components/segmented-control.md +4 -0
  76. package/docs/usage/components/selection-action-bar.md +1 -1
  77. package/docs/usage/components/settings-screen.md +2 -2
  78. package/docs/usage/components/sheet.md +1 -1
  79. package/docs/usage/components/shortcut-recorder.md +1 -1
  80. package/docs/usage/components/side-panel.md +1 -1
  81. package/docs/usage/components/statistic.md +1 -1
  82. package/docs/usage/components/steps.md +4 -2
  83. package/docs/usage/components/streaming-answer.md +1 -1
  84. package/docs/usage/components/table-column-settings.md +1 -1
  85. package/docs/usage/components/tabs.md +4 -0
  86. package/docs/usage/components/top-bar.md +10 -4
  87. package/docs/usage/components/transfer-list.md +1 -1
  88. package/docs/usage/components/transfer-task.md +1 -1
  89. package/docs/usage/compositions/compound-controls.md +1 -1
  90. package/docs/usage/compositions/expo-interactions.md +1 -1
  91. package/docs/usage/compositions/input-sheet.md +1 -1
  92. package/docs/usage/compositions/interaction-flow-apply.md +4 -4
  93. package/docs/usage/compositions/interaction-flow-draft.md +3 -3
  94. package/docs/usage/compositions/paper-surface.md +1 -1
  95. package/docs/usage/screens/flow-media.md +1 -1
  96. package/docs/usage/screens/mockup-studio.md +2 -2
  97. package/docs/usage/tokens/color.md +8 -2
  98. package/docs/usage/tokens/spacing.md +2 -2
  99. package/package.json +1 -1
@@ -64,7 +64,7 @@ import { TransferTask } from "@hjmds/react-native/transfer-task";
64
64
  | 항목 | 값 | 근거 |
65
65
  | --- | --- | --- |
66
66
  | 크기 | 버튼은 [Button](button.md) 기본 `medium`(높이 44), 막대는 [Progress](progress.md) 기본 `medium` 두께 8, 부모 폭을 채운다 | `transfer-task.tsx` |
67
- | 간격 | 버튼 줄·막대·상태 사이 `spacing.md` 16, 버튼 사이 `spacing.sm` 12 | `Stack gap="md"`, 버튼 줄 `gap="sm"` |
67
+ | 간격 | 버튼 줄·막대·상태 사이 `spacing.md` 16, 버튼 사이 `spacing.xs` 8 | `Stack gap="md"`, 버튼 줄 `gap="xs"` |
68
68
  | 순서·정렬 | [시작] [취소(진행 중만)] → 진행 막대 → 결과 문구(가운데) | 양 renderer |
69
69
  | 고정·스크롤 | 없음. 놓는 영역이 정한다 | — |
70
70
  | 좁은 폭·큰 글자 | 버튼 줄이 `wrap`으로 줄바꿈 | `Stack axis="inline" wrap` |
@@ -62,7 +62,7 @@
62
62
  | 바깥 틀 | Web 문서 스크롤 > `Container`. Native `ScrollView` > `Container` | 블록을 감싸는 제품 화면. 상단 안전 영역은 내비게이션 헤더(또는 [TopBar](../components/top-bar.md))가 맡는다 | 좌우 `Container gutter`: 폭 600 미만 `compact` 16, 이상 `regular` 20([화면 여백](../tokens/layout.md)). Native 위아래는 `contentContainerStyle` `paddingVertical: spacing.lg` 20 |
63
63
  | 블록 | `Stack gap="xl"` | 바깥 틀 안, 본문 흐름 | 자식 사이 `spacing.xl` 24 |
64
64
  | 소요 시간 | DurationField | 설명 아래 | NumberField 세 칸, 칸 사이 `spacing.md` 16. 세 칸이 모두 들어가면 한 줄(칸 최대 `fieldGroupRecipe.inline.maxWidth`), 아니면 세 칸 모두 세로([FieldGroup](field-group.md)) |
65
- | 확인 | InlineConfirm | 트리거 자리 그대로 | 트리거와 확인 행동이 같은 자리, Button 높이 44, 질문·버튼 줄 사이와 두 버튼 사이 `spacing.sm` 12 |
65
+ | 확인 | InlineConfirm | 트리거 자리 그대로 | 트리거와 확인 행동이 같은 자리, Button 높이 44, 질문·버튼 줄 사이 `spacing.sm` 12, 두 버튼 사이 `spacing.xs` 8 |
66
66
  | 반응 | ReactionPicker | 제목 아래 | `ghost` `pill` Button 묶음, 사이 `spacing.xs` 8, 넘치면 줄바꿈 |
67
67
  | 알림 종 | NotificationBell | 블록 맨 위, 시작 쪽 정렬. TopBar·헤더 끝에 둘 때는 `edge="end"` | IconButton(기본 `medium` 44) + CounterBadge `floating`(끝·위 모서리). `edge`(`start`·`end`·`both`)는 IconButton `edge`와 같은 값(`resolveIconButtonEdgeOverhang`, 44−24)/2 = 10을 벨 루트에 적용해 glyph 칸이 여백 선(TopBar 16)에 오고 배지는 아이콘 모서리를 지킨다 |
68
68
 
@@ -55,7 +55,7 @@
55
55
  | 바깥 틀 | `ScrollView` > `Container size="reading"` | 화면 전체, 스크롤. 상단 안전 영역은 내비게이션 헤더(또는 [TopBar](../components/top-bar.md))가 맡는다. 입력이 없어 키보드 처리는 없다 | 위아래 `contentContainerStyle` `paddingVertical: spacing.lg` 20. 좌우 `Container gutter`: 폭 600 미만 `compact` 16, 이상 `regular` 20([화면 여백](../tokens/layout.md)) |
56
56
  | 머리 | `Heading` + `Text` | Stack 맨 위 | 사이 `spacing.md` 16 |
57
57
  | 설정 토글 | `Switch presentation="row"` | 머리 아래 | 꽉 찬 폭 행, track `medium` 52×32. 큰 글자에서는 track이 라벨 아래로 내려간다 |
58
- | 행동 묶음 | `Stack gap="sm"` + Button ×3 세로 | 토글 아래, 주 행동이 위 | 버튼 사이 `spacing.sm` 12, 각 높이 44 |
58
+ | 행동 묶음 | `Stack gap="xs"` + Button ×3 세로 | 토글 아래, 주 행동이 위 | 버튼 사이 `spacing.xs` 8, 각 높이 44 |
59
59
  | 바뀌는 내용 | `ContentTransition` | 행동 묶음 아래, 함께 스크롤 | `rise` 세로 12 이동, 시간 `motion.normal`, 곡선 `easing.enter`. 래퍼 자체 크기·여백 없음 |
60
60
 
61
61
  - 한 영역(구획 하나) 안이므로 요소 사이는 `layout.contentGap`(`Stack gap="md"` 16)이다([화면 여백](../tokens/layout.md)).
@@ -54,7 +54,7 @@ Native(하단 시트, 키보드 올라옴) Web(하단 시트)
54
54
  | 머리 | 손잡이(+ `showClose`일 때 끝 × IconButton). 보이는 제목 없음, `title`은 접근성 이름(2026-10-17 사용자 결정: 시트는 보이는 제목 없이 `title`을 접근성 이름으로만 쓴다) | 시트 맨 위, 고정 | × 머리 최소 높이 `control.minTouchTarget` 44·좌우 `spacing.lg` 20(+좌우 inset)·위 `spacing.sm` 12(두 플랫폼 같음) |
55
55
  | 실패 알림 | `Notice tone="danger"` | 본문 맨 위(입력 위), 실패했을 때만, 스크롤 | 본문 항목 사이 `spacing.md` 16 |
56
56
  | 본문 | `TextField` + 설명 | 머리 아래, **스크롤** | 항목 사이 `sheetRecipe.body.gap` `spacing.md` 16. Web body padding `spacing.lg` 20 |
57
- | 완료 | footer `Button`(primary) | 본문 아래, **고정**(스크롤 밖) | 높이 `medium` 44. Native 위 `spacing.sm` 12, footer 세로 열이라 꽉 찬 폭(`fullWidth` 불필요). Web 오른쪽 정렬, 버튼 사이 `spacing.sm` 12, padding 0 `spacing.lg` 20 `spacing.lg` 20 |
57
+ | 완료 | footer `Button`(primary) | 본문 아래, **고정**(스크롤 밖) | 높이 `medium` 44. Native 위 `spacing.sm` 12, footer 세로 열이라 꽉 찬 폭(`fullWidth` 불필요). Web 오른쪽 정렬, 버튼 사이 `spacing.xs` 8, padding 0 `spacing.lg` 20 `spacing.lg` 20 |
58
58
  | 하단 안전 영역 | Sheet가 처리 | 시트 맨 아래 | Native 아래 `spacing.sm` 12 + bottom inset(키보드가 붙어 있으면 inset 0, 대신 키보드 높이만큼 올라감). Web footer 아래 `spacing.lg` 20 + `env(safe-area-inset-bottom)` |
59
59
 
60
60
  - 주 행동(완료)은 footer 하나다. 취소는 머리의 닫기 버튼이 맡는다. 버튼을 둘 두면 [Sheet 배치](../components/sheet.md#배치)에 따라 Web 가로 footer는 보조 → 주, Native 세로 footer는 주 → 보조 순서다.
@@ -52,7 +52,7 @@
52
52
  │ ( ) 크게 보기 │ │
53
53
  │ 안내: 적용해야 바뀐다 │ ↓
54
54
  ├──────────────────────────────────────┤
55
- │ Web: [선택 취소] [선택 적용] │ ← footer 고정, 오른쪽 정렬, gap 12
55
+ │ Web: [선택 취소] [선택 적용] │ ← footer 고정, 오른쪽 정렬, gap 8
56
56
  │ Native: [ 선택 적용 ] / [ 선택 취소 ] │ ← 세로, 주 행동 먼저
57
57
  │ ░░ 하단 안전 영역(시트가 더함) ░░ │
58
58
  └──────────────────────────────────────┘
@@ -66,11 +66,11 @@
66
66
  | 트리거 | `Button`(primary) | 현재 값 아래 | `medium` 44(`control.buttonHeight`) |
67
67
  | 시트 머리 | `Sheet` 손잡이(+ `showClose`일 때 끝 ×) | 시트 위 고정 | 보이는 제목 없음, `title`은 접근성 이름(2026-10-17 사용자 결정: 시트는 보이는 제목 없이 `title`을 접근성 이름으로만 쓴다). × 머리 최소 높이 `control.minTouchTarget` 44 |
68
68
  | 선택지 | `RadioGroup`(`presentation="card"`, `accessibilityLabel` = 시트 `title`) | 시트 body, 스크롤 | 행 최소 높이 56(`layout.rowHeight.singleLine`), 항목 사이 `spacing.xs` 8(`selectionGroupRecipe`). 안내 문구와는 `Stack gap="md"` 16. 설치한 버전의 Sheet body gap과 중첩 여부를 확인하며 checkout 상태를 npm 게시 증거로 삼지 않는다 |
69
- | 행동 | `Button` 적용·취소 | 시트 footer, 스크롤 밖 고정 | 간격 `spacing.sm` 12(`sheetRecipe.footer.gap`), Native 위 여백 `spacing.sm` 12 |
69
+ | 행동 | `Button` 적용·취소 | 시트 footer, 스크롤 밖 고정 | 간격 `spacing.xs` 8(`sheetRecipe.footer.gap`), Native 위 여백 `spacing.sm` 12 |
70
70
  | 시트 틀 | `Sheet` | 하단, 모달 | Web 최대 폭 640(`sheetRecipe.web.maxWidth`)·최대 높이 90%, Native 가로 여백 `spacing.lg` 20·최대 높이 90%(`maxHeightRatio` 0.9), 하단 안전 영역 추가 |
71
71
 
72
72
  - footer 순서는 [Sheet](../components/sheet.md) 배치 규칙을 따른다. Web footer는 오른쪽 정렬 가로 줄 **[취소][적용]**(보조 → 주 행동), Native footer는 세로 열이라
73
- **적용(primary) 먼저, 취소(secondary) 아래**다. 두 renderer의 footer가 이미 `gap` 12를 주므로 버튼을 `Stack`으로 다시 감싸지 않는다.
73
+ **적용(primary) 먼저, 취소(secondary) 아래**다. 두 renderer의 footer가 이미 `gap` 8를 주므로 버튼을 `Stack`으로 다시 감싸지 않는다.
74
74
  - primary 개수: 화면에서는 트리거 하나, 시트 안에서는 적용 하나를 센다. 선택지는 RadioGroup이라 버튼으로 세지 않는다.
75
75
  - 선택지를 `selected` Button 나열로 만들지 않는다. 2026-10-16 사용자 지적으로 선택 버튼 줄이 테두리 없는 글자처럼 보였다. 하나 고르기는 [선택 조립 규칙](../SELECTION.md#조립-규칙필수)대로 RadioGroup(선택지가 짧은 2~4개면 SegmentedControl)을 쓴다. 의미(임시 선택 → 적용)는 같다.
76
76
 
@@ -189,7 +189,7 @@ Web `gutter`는 [화면 여백과 너비](../tokens/layout.md)처럼 폭 구간
189
189
 
190
190
  - 시트 안에서 바뀌는 값(임시 선택·초안)은 **시트 밖**, 시트를 여는 화면의 state에 둔다.
191
191
  - 확정은 footer의 주 행동 하나만 한다. 닫기·바깥 누름·back은 확정하지 않는다.
192
- - footer 버튼은 Web [보조][주], Native 주 → 보조 순서로 바로 넘긴다. renderer footer가 간격 12를 준다.
192
+ - footer 버튼은 Web [보조][주], Native 주 → 보조 순서로 바로 넘긴다. renderer footer가 간격 8를 준다.
193
193
  - `returnFocusRef`로 닫힌 뒤 포커스를 트리거에 돌려준다. Native는 Button을 `View ref collapsable={false}`로 감싸 ref를 넘긴다.
194
194
  - 서버에 저장하는 확정이면 저장 중 Sheet `busy`로 닫기를 막고, 실패하면 시트와 시트 밖 값(임시 선택·초안)을 그대로 둔다.
195
195
  - 시트가 닫힌 뒤 다른 모달을 열거나 화면을 옮기면 `onDismissComplete`에서 한다.
@@ -51,7 +51,7 @@
51
51
  │ [ 입력 ] │ │ TextField 높이 44
52
52
  │ 안내 문구 / 저장 실패 문구 │ ↓ 간격 spacing.md 16
53
53
  ├──────────────────────────────────────┤
54
- │ Web: [초안 버리기] [메모 저장] │ ← footer 고정, 오른쪽 정렬, gap 12
54
+ │ Web: [초안 버리기] [메모 저장] │ ← footer 고정, 오른쪽 정렬, gap 8
55
55
  │ Native: [ 메모 저장 ] / [ 초안 버리기 ]│ ← 세로, 주 행동 먼저
56
56
  │ ░░ 하단 안전 영역 / 키보드 위 ░░ │
57
57
  └──────────────────────────────────────┘
@@ -64,11 +64,11 @@
64
64
  | 트리거·상태 | `Button`, `Text` | 제목 아래 | 버튼 `medium` 44, `spacing.md` 16 |
65
65
  | 시트 머리 | `Sheet` header | 시트 위 고정 | Native 최소 높이 `control.minTouchTarget` 44 |
66
66
  | 입력 | `TextField` | 시트 body, 스크롤 | 높이 `control.fieldHeight` 44, 간격 `spacing.md` 16(Native `sheetRecipe.body.gap`, Web은 `Stack gap="md"`) |
67
- | 행동 | `Button` 저장·버리기 | 시트 footer, 스크롤 밖 고정 | 간격 `spacing.sm` 12(`sheetRecipe.footer.gap`) |
67
+ | 행동 | `Button` 저장·버리기 | 시트 footer, 스크롤 밖 고정 | 간격 `spacing.xs` 8(`sheetRecipe.footer.gap`) |
68
68
  | 키보드 | `Sheet keyboardAvoidance`(Native) | 시트 전체가 키보드 위로 | 제품 키보드 listener·maxHeight를 두지 않는다 |
69
69
 
70
70
  - footer 순서는 [Sheet](../components/sheet.md) 배치 규칙을 따른다. Web은 가로 줄 **[버리기][저장]**, Native는 세로 열 **저장(primary) 먼저, 버리기(secondary) 아래**다.
71
- renderer footer가 간격 12를 주므로 `Stack`으로 다시 감싸지 않는다.
71
+ renderer footer가 간격 8를 주므로 `Stack`으로 다시 감싸지 않는다.
72
72
  - 버리기가 되돌릴 수 없는 손실이면 `tone="danger"`와 [InlineConfirm](../components/button.md)으로 한 번 더 확인하는 것을 검토한다.
73
73
 
74
74
  근거: `src/component-recipes.ts`(`sheetRecipe`), `src/foundations.ts`(`control`, `layout`, `heading`), `packages/react/src/styles.css`(`.hjm-sheet__footer`), [Sheet 지침](../components/sheet.md)
@@ -45,7 +45,7 @@
45
45
  | 바깥 틀 | Stack, 스토리 `Container size="reading"` | 화면 앞쪽 비교 도구부터 세로 | gap lg20, 최대 폭 720; Native는 바깥 ScrollView와 기존 테마 비교와 같은 640host-unit 화면 viewport |
46
46
  | 기록 항목 | OverviewScreen·Stack | items 본문 | gap sm12; rows/grid/cards와 화면은 profile 기본값 |
47
47
  | 줄무늬 | EffectSurface | 화면 canvas 뒤 SVG | 한 선 1host unit, spacing 기본24, 명시 비교40; userSpaceOnUse |
48
- | footer | Stack·Button | 기존 OverviewScreen footer | gap sm12, primary 확인 다음 secondary 상세 |
48
+ | footer | Stack·Button | 기존 OverviewScreen footer | gap xs8, primary 확인 다음 secondary 상세 |
49
49
  | 상세 | Dialog·Text | 기존 modal | 현재 초안 읽기, close/Escape·초점 복귀는 기존 계약 |
50
50
 
51
51
  ## 흐름과 상태
@@ -24,7 +24,7 @@ host: 남은 높이·safe area·키보드
24
24
  | 영역 | 컴포넌트 | 위치 | 크기·간격 |
25
25
  | --- | --- | --- | --- |
26
26
  | 바깥 틀 | MediaSelectionScreen | route 본문 | [API 배치 규칙](../components/media-selection-screen.md#배치), host 남은 높이 |
27
- | 내용 | 공개 슬롯(`library`를 주면 기본 격자 대신 그것을 그린다) | 추가(헤더) → 썸네일 격자 → 선택 요약 → 완료(footer) | 기본 격자는 `Grid` 2열, `breakpoint.expanded` 960 이상 3열, 칸 사이 `spacing.md` 16. 칸 안은 미리보기 → UploadItem → 이동·제거 행(`spacing.xs` 8 세로, 버튼 사이 `spacing.xxs` 4) |
27
+ | 내용 | 공개 슬롯(`library`를 주면 기본 격자 대신 그것을 그린다) | 추가(헤더) → 썸네일 격자 → 선택 요약 → 완료(footer) | 기본 격자는 `Grid` 2열, `breakpoint.expanded` 960 이상 3열, 칸 사이 `spacing.md` 16. 칸 안은 미리보기 → UploadItem → 이동·제거 행(`spacing.xs` 8 세로, 버튼 사이 `spacing.xs` 8) |
28
28
  | 상태 | state 또는 해당 API 상태 | 본문 자리·비차단 notice | 입력 중 실패는 본문 높이와 초안을 유지 |
29
29
 
30
30
  ## 버튼과 행동 위치
@@ -56,10 +56,10 @@ Grid columns {compact 1 · expanded 2}(창 폭 960 이상 두 열) gap xl 24
56
56
  | ② 미리보기 | Stack `gap="sm"` > Surface `padding="md"` > `canvas`(`role="img"`, `aria-label`=제목 + 프레임) + ③ | 왼쪽 열(한 열이면 맨 위) | 안쪽 `spacing.md` 16, 폭 100%, 최대 높이 70vh |
57
57
  | ④⑤ 파일·상태 | FilePicker ×2(화면 캡처: PNG·JPEG·WebP·20MB / 장면 설정: JSON·64KB) · Text `role="status"` | 오른쪽 열 맨 위 | 사이 24 |
58
58
  | 실패 | ScreenLayout `notice` > Notice `tone="danger"`(내보내기 실패면 `action` 다시 내보내기) | 헤더 아래 고정, 실패 동안 상태 문구 대신 | 거부된 파일도 읽기 실패와 같은 Notice. 본문 밖이라 재시도 버튼이 사라져도 본문 초점 복구가 PNG 행동 복귀를 가로채지 않는다 |
59
- | ⑥ 타임라인 | Stack `gap="md"` > Heading `level="level5"` `semanticLevel={2}` · 재생 줄(IconButton ×2 + Slider) · 설정 선택 · Button 줄 | 상태 아래 | 사이 `spacing.md` 16, 재생 줄 `Stack axis="inline" gap="sm" align="end"` 12(Slider가 남은 폭), 버튼 줄 `wrap gap="sm"` 12 |
59
+ | ⑥ 타임라인 | Stack `gap="md"` > Heading `level="level5"` `semanticLevel={2}` · 재생 줄(IconButton ×2 + Slider) · 설정 선택 · Button 줄 | 상태 아래 | 사이 `spacing.md` 16, 재생 줄 `Stack axis="inline" gap="xs" align="end"` 8(Slider가 남은 폭), 버튼 줄 `wrap gap="xs"` 8 |
60
60
  | ⑦⑨ 텍스트 입력 | TextField ×4 | 타임라인 아래·선택 묶음 아래 | 높이 44(`control.fieldHeight`) |
61
61
  | ⑧ 선택 묶음 | Stack `gap="xs"` > Text `emphasis="strong"`(보이는 제목) + SegmentedControl(`label` = 같은 제목), 그림자는 Switch `presentation="row"` | 텍스트 입력 사이 | 제목과 컨트롤 사이 `spacing.xs` 8, 묶음 사이 24. SegmentedControl 항목 최소 44 |
62
- | ⑩ 내보내기 줄 | ScreenLayout `footer` > Stack `axis="inline" wrap gap="sm"` > Button ×3 | 화면 아래 고정 | 사이 12 |
62
+ | ⑩ 내보내기 줄 | ScreenLayout `footer` > Stack `axis="inline" wrap gap="xs"` > Button ×3 | 화면 아래 고정 | 사이 8 |
63
63
 
64
64
  ## 버튼과 행동 위치
65
65
 
@@ -30,8 +30,8 @@
30
30
  | 토큰 | 값 | Web CSS 변수 | Native 경로 | 용도 |
31
31
  | --- | --- | --- | --- | --- |
32
32
  | `canvas` = `bg` | `#ffffff` / `#0d1116` | `--hjm-color-bg` | `theme.colors.bg` | 화면 바탕. 카드·패널(Surface·Card)도 모든 tone이 `bg`를 칠하고 층은 테두리·그림자로 나눈다 |
33
- | `surface.default` = `surface` | `#f2f4f6` / `#161b22` | `--hjm-color-surface` | `theme.colors.surface` | 바탕과 구분되는 옅은 면 |
34
- | `surface.sunken` = `surfaceAlt` | `#e5e8eb` / `#1e232a` | `--hjm-color-surface-alt` | `theme.colors.surfaceAlt` | 한 단계 더 들어간 면(CodeBlock 바탕) |
33
+ | `surface.default` = `surface` | `#ffffff` / `#161b22` | `--hjm-color-surface` | `theme.colors.surface` | 바탕과 구분되는 옅은 면 |
34
+ | `surface.sunken` = `surfaceAlt` | `#ebeef2` / `#1e232a` | `--hjm-color-surface-alt` | `theme.colors.surfaceAlt` | 한 단계 더 들어간 면(CodeBlock 바탕) |
35
35
  | `surface.brand` = `surfaceAccent` | `#c9e2ff` / `#224159` | `--hjm-color-surface-accent` | `theme.colors.surfaceAccent` | 브랜드가 드러나는 옅은 면 |
36
36
 
37
37
  ### 글자
@@ -156,3 +156,9 @@ import { HjmProvider } from "@hjmds/react/provider";
156
156
  컴포넌트는 Web CSS 변수 또는 Native `theme.tokens`/semantic palette를 읽는다.
157
157
  직접 foundations를 import한 값은 기본 상수이므로 프로필 변경을 따라가지 않는다. 현재 연결 API의 범위는
158
158
  프로필 계약에서 확인하고 앱 CSS로 내부 값을 덮지 않는다.
159
+
160
+ ### 밝은 테마 표면 기본값 (2026-10-21)
161
+
162
+ 표·표면의 회색 면을 줄이려는 사용자 결정으로 `surface`는 흰색 `#ffffff`,
163
+ `surfaceAlt`는 보조 회색 `#ebeef2`를 사용한다. 페이지 바탕 `bg`는 흰색이며,
164
+ 표 본문은 `surface`, `raised` 카드는 `bg`를 소비한다. 근거는 [팔레트 결정 기록](../../theme-palette.md)을 따른다.
@@ -18,8 +18,8 @@
18
18
  | 토큰 | 값 | Web CSS 변수 | Native 경로 | 용도 |
19
19
  | --- | --- | --- | --- | --- |
20
20
  | `spacing.xxs` | 4 | `--hjm-space-xxs` | `spacing.xxs` · `theme.tokens.spacing.xxs` | SegmentedControl 트랙 안쪽 여백·항목 간격 |
21
- | `spacing.xs` | 8 | `--hjm-space-xs` | `spacing.xs` · `theme.tokens.spacing.xs` | 필드 라벨과 입력 사이, 목록 팝업 안쪽 여백(Select·Menu), DatePicker 팝업과 입력 사이, EmptyState 안 요소 사이 |
22
- | `spacing.sm` | 12 | `--hjm-space-sm` | `spacing.sm` · `theme.tokens.spacing.sm` | 나란한 버튼 사이, Toast 사이, small 버튼 좌우·필드 위아래 안쪽 여백 |
21
+ | `spacing.xs` | 8 | `--hjm-space-xs` | `spacing.xs` · `theme.tokens.spacing.xs` | 가로·세로 버튼 묶음 사이, 필드 라벨과 입력 사이, 목록 팝업 안쪽 여백(Select·Menu), DatePicker 팝업과 입력 사이, EmptyState 안 요소 사이 |
22
+ | `spacing.sm` | 12 | `--hjm-space-sm` | `spacing.sm` · `theme.tokens.spacing.sm` | Toast 사이, small 버튼 좌우·필드 위아래 안쪽 여백 |
23
23
  | `spacing.md` | 16 | `--hjm-space-md` | `spacing.md` · `theme.tokens.spacing.md` | Stack·Grid 기본 gap, medium 버튼·필드 좌우 안쪽 여백, `layout.contentGap`, `layout.pagePadding.compact` |
24
24
  | `spacing.lg` | 20 | `--hjm-space-lg` | `spacing.lg` · `theme.tokens.spacing.lg` | large 버튼 좌우 안쪽 여백, `layout.pagePadding.regular`, Dialog 하단 여백 |
25
25
  | `spacing.xl` | 24 | `--hjm-space-xl` | `spacing.xl` · `theme.tokens.spacing.xl` | `layout.sectionGap`, `layout.pagePadding.spacious`, EmptyState·Result 좌우 여백 |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hjmds/design-contracts",
3
- "version": "1.37.2",
3
+ "version": "1.38.0",
4
4
  "description": "Renderer-neutral design contracts, tokens, recipes, and behaviors shared by HJM products.",
5
5
  "license": "MIT",
6
6
  "repository": {