@hjmds/design-contracts 1.12.0 → 1.13.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/avatar-fallback.d.ts +11 -0
- package/dist/avatar-fallback.d.ts.map +1 -1
- package/dist/avatar-fallback.js +21 -0
- package/dist/avatar-fallback.js.map +1 -1
- package/dist/base-recipes.d.ts +17 -0
- package/dist/base-recipes.d.ts.map +1 -1
- package/dist/base-recipes.js +17 -0
- package/dist/base-recipes.js.map +1 -1
- package/dist/catalog.d.ts +25 -0
- package/dist/catalog.d.ts.map +1 -1
- package/dist/command-palette.d.ts +14 -9
- package/dist/command-palette.d.ts.map +1 -1
- package/dist/command-palette.js +8 -9
- package/dist/command-palette.js.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 +5 -0
- package/dist/component-recipes.js.map +1 -1
- package/dist/provider-button.d.ts.map +1 -1
- package/dist/provider-button.js +3 -0
- package/dist/provider-button.js.map +1 -1
- package/dist/reactions.d.ts +10 -0
- package/dist/reactions.d.ts.map +1 -1
- package/dist/reactions.js +7 -0
- package/dist/reactions.js.map +1 -1
- package/dist/screen-patterns.d.ts +147 -0
- package/dist/screen-patterns.d.ts.map +1 -0
- package/dist/screen-patterns.js +149 -0
- package/dist/screen-patterns.js.map +1 -0
- package/dist/slider.d.ts +8 -0
- package/dist/slider.d.ts.map +1 -1
- package/dist/slider.js +6 -1
- package/dist/slider.js.map +1 -1
- package/dist/upload-item.d.ts +5 -0
- package/dist/upload-item.d.ts.map +1 -1
- package/dist/upload-item.js +5 -0
- package/dist/upload-item.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 +3 -3
- package/docs/agreement.md +5 -0
- package/docs/avatar-fallback.md +7 -0
- package/docs/bottom-navigation.md +6 -0
- package/docs/brand-boundary.md +1 -1
- package/docs/button-label.md +6 -0
- package/docs/clipboard.md +3 -0
- package/docs/command-palette.md +45 -2
- package/docs/consumer-policy.md +5 -1
- package/docs/data-table.md +6 -4
- package/docs/dialog.md +8 -2
- package/docs/form.md +51 -0
- 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/link.md +8 -0
- package/docs/migration-native-legacy-removal.md +45 -1
- package/docs/optional-adapters.md +1 -1
- package/docs/password-field.md +5 -0
- package/docs/product-composition-adoption.md +40 -0
- package/docs/progress.md +19 -1
- package/docs/provider-button.md +13 -0
- package/docs/result.md +3 -0
- package/docs/screen-chrome.md +10 -0
- package/docs/screen-patterns.md +376 -0
- package/docs/sheet.md +12 -0
- package/docs/splitter.md +8 -2
- package/docs/theming.md +36 -29
- package/docs/toggle-group.md +7 -0
- package/docs/tour.md +7 -1
- package/docs/tree.md +5 -2
- package/docs/upload-item.md +7 -0
- package/docs/usage/README.md +236 -0
- package/docs/usage/STANDARD.md +108 -0
- package/docs/usage/components/accordion.md +107 -0
- package/docs/usage/components/activity-heatmap.md +104 -0
- package/docs/usage/components/affix.md +86 -0
- package/docs/usage/components/agreement.md +129 -0
- package/docs/usage/components/alert-dialog.md +130 -0
- package/docs/usage/components/anchor.md +96 -0
- package/docs/usage/components/aspect-ratio.md +89 -0
- package/docs/usage/components/asset.md +126 -0
- package/docs/usage/components/auth-provider-button.md +116 -0
- package/docs/usage/components/auth-screen-layout.md +129 -0
- package/docs/usage/components/avatar.md +114 -0
- package/docs/usage/components/badge.md +84 -0
- package/docs/usage/components/bottom-cta.md +125 -0
- package/docs/usage/components/bottom-info.md +99 -0
- package/docs/usage/components/bottom-navigation.md +136 -0
- package/docs/usage/components/breadcrumb.md +81 -0
- package/docs/usage/components/button.md +118 -0
- package/docs/usage/components/calendar.md +122 -0
- package/docs/usage/components/card.md +110 -0
- package/docs/usage/components/carousel.md +113 -0
- package/docs/usage/components/celebration.md +96 -0
- package/docs/usage/components/chat-message.md +122 -0
- package/docs/usage/components/chat-screen.md +112 -0
- package/docs/usage/components/checkbox-group.md +104 -0
- package/docs/usage/components/checkbox.md +103 -0
- package/docs/usage/components/chip.md +104 -0
- package/docs/usage/components/code-block.md +111 -0
- package/docs/usage/components/collapsible.md +112 -0
- package/docs/usage/components/color-picker.md +86 -0
- package/docs/usage/components/combobox.md +137 -0
- package/docs/usage/components/command-palette.md +125 -0
- package/docs/usage/components/comment-thread-screen.md +125 -0
- package/docs/usage/components/container.md +98 -0
- package/docs/usage/components/content-transition.md +101 -0
- package/docs/usage/components/context-menu.md +136 -0
- package/docs/usage/components/counter-badge.md +107 -0
- package/docs/usage/components/data-table.md +122 -0
- package/docs/usage/components/date-picker.md +142 -0
- package/docs/usage/components/date-range-picker.md +111 -0
- package/docs/usage/components/description-list.md +103 -0
- package/docs/usage/components/design-system-provider.md +124 -0
- package/docs/usage/components/dialog.md +176 -0
- package/docs/usage/components/divider.md +89 -0
- package/docs/usage/components/editor-screen.md +126 -0
- package/docs/usage/components/effect-surface.md +120 -0
- package/docs/usage/components/empty-state.md +114 -0
- package/docs/usage/components/field.md +129 -0
- package/docs/usage/components/file-picker.md +114 -0
- package/docs/usage/components/floating-action-button.md +138 -0
- package/docs/usage/components/form.md +162 -0
- package/docs/usage/components/grid.md +99 -0
- package/docs/usage/components/heading.md +87 -0
- package/docs/usage/components/icon-button.md +126 -0
- package/docs/usage/components/icon.md +105 -0
- package/docs/usage/components/image.md +122 -0
- package/docs/usage/components/keyboard-avoiding.md +93 -0
- package/docs/usage/components/keyboard-dock.md +110 -0
- package/docs/usage/components/keyboard-form-scroll-view.md +95 -0
- package/docs/usage/components/keyboard-motion-provider.md +86 -0
- package/docs/usage/components/layout.md +117 -0
- package/docs/usage/components/link.md +121 -0
- package/docs/usage/components/list-detail-screen.md +103 -0
- package/docs/usage/components/list-row.md +124 -0
- package/docs/usage/components/list.md +119 -0
- package/docs/usage/components/load-more.md +115 -0
- package/docs/usage/components/masonry.md +109 -0
- package/docs/usage/components/media-selection-screen.md +119 -0
- package/docs/usage/components/mentions.md +119 -0
- package/docs/usage/components/menu.md +129 -0
- package/docs/usage/components/menubar.md +93 -0
- package/docs/usage/components/message-composer.md +124 -0
- package/docs/usage/components/moderation-screen.md +113 -0
- package/docs/usage/components/notice.md +106 -0
- package/docs/usage/components/notification-inbox-screen.md +97 -0
- package/docs/usage/components/notification-item.md +98 -0
- package/docs/usage/components/number-field.md +131 -0
- package/docs/usage/components/onboarding-screen.md +106 -0
- package/docs/usage/components/otp-field.md +101 -0
- package/docs/usage/components/pagination.md +82 -0
- package/docs/usage/components/password-field.md +137 -0
- package/docs/usage/components/permission-screen.md +107 -0
- package/docs/usage/components/photo-source-sheet.md +119 -0
- package/docs/usage/components/popover.md +108 -0
- package/docs/usage/components/profile-screen.md +89 -0
- package/docs/usage/components/progress.md +122 -0
- package/docs/usage/components/qr-code.md +122 -0
- package/docs/usage/components/radio-group.md +124 -0
- package/docs/usage/components/radio.md +104 -0
- package/docs/usage/components/result.md +116 -0
- package/docs/usage/components/saved-items-screen.md +126 -0
- package/docs/usage/components/screen-layout.md +119 -0
- package/docs/usage/components/search-field.md +120 -0
- package/docs/usage/components/search-screen.md +215 -0
- package/docs/usage/components/section.md +111 -0
- package/docs/usage/components/segmented-control.md +138 -0
- package/docs/usage/components/select.md +142 -0
- package/docs/usage/components/settings-screen.md +126 -0
- package/docs/usage/components/shared-transition-element.md +111 -0
- package/docs/usage/components/shared-transition-screen.md +86 -0
- package/docs/usage/components/sheet.md +151 -0
- package/docs/usage/components/side-panel.md +104 -0
- package/docs/usage/components/sidebar.md +107 -0
- package/docs/usage/components/skeleton.md +105 -0
- package/docs/usage/components/skip-nav.md +76 -0
- package/docs/usage/components/slider.md +121 -0
- package/docs/usage/components/sortable-collection.md +127 -0
- package/docs/usage/components/spinner.md +86 -0
- package/docs/usage/components/splitter.md +103 -0
- package/docs/usage/components/stack.md +93 -0
- package/docs/usage/components/statistic.md +123 -0
- package/docs/usage/components/steps.md +110 -0
- package/docs/usage/components/surface.md +91 -0
- package/docs/usage/components/swipe-actions.md +124 -0
- package/docs/usage/components/switch.md +120 -0
- package/docs/usage/components/tabs.md +134 -0
- package/docs/usage/components/tag.md +84 -0
- package/docs/usage/components/tags-input.md +111 -0
- package/docs/usage/components/text-area.md +112 -0
- package/docs/usage/components/text-format.md +75 -0
- package/docs/usage/components/text-transition.md +104 -0
- package/docs/usage/components/text.md +101 -0
- package/docs/usage/components/thinking-orb.md +105 -0
- package/docs/usage/components/timeline.md +105 -0
- package/docs/usage/components/toast.md +145 -0
- package/docs/usage/components/toggle-group.md +95 -0
- package/docs/usage/components/tooltip.md +103 -0
- package/docs/usage/components/top-bar.md +124 -0
- package/docs/usage/components/top.md +89 -0
- package/docs/usage/components/tour.md +118 -0
- package/docs/usage/components/transfer-list.md +115 -0
- package/docs/usage/components/tree.md +91 -0
- package/docs/usage/components/upload-item.md +99 -0
- package/docs/usage/components/virtual-list.md +105 -0
- package/docs/usage/components/visually-hidden.md +72 -0
- package/docs/usage/components/watermark.md +78 -0
- package/docs/usage/compositions/action-recovery-optimistic.md +180 -0
- package/docs/usage/compositions/action-recovery-save.md +235 -0
- package/docs/usage/compositions/action-recovery-undo.md +193 -0
- package/docs/usage/compositions/common-message.md +132 -0
- package/docs/usage/compositions/common-notification.md +101 -0
- package/docs/usage/compositions/compound-controls.md +186 -0
- package/docs/usage/compositions/data-layouts.md +157 -0
- package/docs/usage/compositions/disclosure.md +144 -0
- package/docs/usage/compositions/environment-matrix.md +139 -0
- package/docs/usage/compositions/expo-interactions.md +149 -0
- package/docs/usage/compositions/family-drawer.md +201 -0
- package/docs/usage/compositions/floating-action-button.md +197 -0
- package/docs/usage/compositions/input-sheet.md +148 -0
- package/docs/usage/compositions/interaction-adapters.md +190 -0
- package/docs/usage/compositions/interaction-flow-apply.md +205 -0
- package/docs/usage/compositions/interaction-flow-draft.md +188 -0
- package/docs/usage/compositions/interaction-flow-search.md +171 -0
- package/docs/usage/compositions/native-renderers.md +106 -0
- package/docs/usage/compositions/navigation-bar-collection.md +164 -0
- package/docs/usage/compositions/optional-adapters.md +169 -0
- package/docs/usage/compositions/optional-motion.md +109 -0
- package/docs/usage/compositions/photo-source.md +104 -0
- package/docs/usage/compositions/purpose-input-comment.md +110 -0
- package/docs/usage/compositions/purpose-input-message.md +119 -0
- package/docs/usage/compositions/reference-first.md +96 -0
- package/docs/usage/compositions/reference-review.md +107 -0
- package/docs/usage/compositions/reference-settings.md +107 -0
- package/docs/usage/compositions/selection-scope.md +174 -0
- package/docs/usage/compositions/stea-event-ticket.md +166 -0
- package/docs/usage/compositions/stea-flip-card.md +162 -0
- package/docs/usage/compositions/stea-order-progress.md +184 -0
- package/docs/usage/compositions/stea-otp-verify.md +215 -0
- package/docs/usage/compositions/stea-pixel-empty.md +140 -0
- package/docs/usage/compositions/stea-schedule-card.md +169 -0
- package/docs/usage/compositions/stea-stat-summary.md +154 -0
- package/docs/usage/compositions/time-selection.md +174 -0
- package/docs/usage/compositions/toast-layout.md +128 -0
- package/docs/usage/compositions/visual-foundations.md +185 -0
- package/docs/usage/compositions/web-additions.md +146 -0
- package/docs/usage/compositions/web-navigation.md +143 -0
- package/docs/usage/screens/common-chat.md +127 -0
- package/docs/usage/screens/common-comments.md +108 -0
- package/docs/usage/screens/common-inbox.md +110 -0
- package/docs/usage/screens/common-login.md +98 -0
- package/docs/usage/screens/common-profile.md +221 -0
- package/docs/usage/screens/common-saved.md +127 -0
- package/docs/usage/screens/common-search.md +274 -0
- package/docs/usage/screens/common-settings.md +126 -0
- package/docs/usage/screens/common-shell.md +108 -0
- package/docs/usage/screens/dashboard.md +245 -0
- package/docs/usage/screens/discovery-gallery.md +306 -0
- package/docs/usage/screens/flow-collection.md +96 -0
- package/docs/usage/screens/flow-editor.md +120 -0
- package/docs/usage/screens/flow-media.md +111 -0
- package/docs/usage/screens/flow-moderation.md +120 -0
- package/docs/usage/screens/flow-onboarding.md +193 -0
- package/docs/usage/screens/flow-permission.md +103 -0
- package/docs/usage/screens/landing.md +347 -0
- package/docs/usage/screens/mockup-studio.md +190 -0
- package/docs/usage/screens/notification-settings.md +206 -0
- package/docs/usage/screens/reference-comparison.md +159 -0
- package/docs/usage/templates/component.md +61 -0
- package/docs/usage/templates/composition.md +47 -0
- package/docs/usage/templates/screen.md +56 -0
- package/docs/usage/templates/token.md +32 -0
- package/docs/usage/tokens/color.md +142 -0
- package/docs/usage/tokens/elevation-opacity.md +86 -0
- package/docs/usage/tokens/layers.md +98 -0
- package/docs/usage/tokens/layout.md +114 -0
- package/docs/usage/tokens/motion.md +88 -0
- package/docs/usage/tokens/radius.md +53 -0
- package/docs/usage/tokens/size.md +74 -0
- package/docs/usage/tokens/spacing.md +73 -0
- package/docs/usage/tokens/stroke.md +50 -0
- package/docs/usage/tokens/theme-studio.md +70 -0
- package/docs/usage/tokens/typography-studio.md +70 -0
- package/docs/usage/tokens/typography.md +89 -0
- package/package.json +7 -1
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# 크기
|
|
2
|
+
|
|
3
|
+
- 단계: 토큰
|
|
4
|
+
- 상태: 배포
|
|
5
|
+
- 지원: Web · Native
|
|
6
|
+
- 적용: 1.12.1
|
|
7
|
+
- 검토일: 2026-10-06
|
|
8
|
+
- 근거: `src/foundations.ts`(`glyph`·`control`), `src/component-recipes.ts`(`iconRecipe`·`spinnerRecipe`·`chipRecipe`·`avatarRecipe`·`skeletonRecipe`), `src/base-recipes.ts`(`buttonRecipe`), `src/design-system-provider.ts`(`visibleControlHeight`), `packages/react/src/theme.ts`
|
|
9
|
+
- 스토리북: `배포/토큰/공간과 크기/크기`
|
|
10
|
+
|
|
11
|
+
## 언제 쓰나
|
|
12
|
+
|
|
13
|
+
아이콘·작은 그림(glyph)의 크기와 누를 수 있는 컨트롤의 높이·최소 터치 영역을 정할 때 쓴다. 모든 버튼의 폭이나 화면 요소의
|
|
14
|
+
크기를 뜻하지 않는다. 화면 폭·행 높이는 [화면 여백과 너비](layout.md)에 있다.
|
|
15
|
+
|
|
16
|
+
## 값
|
|
17
|
+
|
|
18
|
+
### glyph(아이콘·작은 그림)
|
|
19
|
+
|
|
20
|
+
| 토큰 | 값 | Web CSS 변수 | Native 경로 | 용도 |
|
|
21
|
+
| --- | --- | --- | --- | --- |
|
|
22
|
+
| `glyph.xs` | 14 | — | `glyph.xs` | Spinner `small` |
|
|
23
|
+
| `glyph.sm` | 20 | — | `glyph.sm` | Spinner `medium`(기본), 작은 아이콘 |
|
|
24
|
+
| `glyph.md` | 24 | — | `glyph.md` | Icon 기본 크기, Steps 표지 |
|
|
25
|
+
| `glyph.lg` | 28 | — | `glyph.lg` | Spinner `large`, EmptyState 아이콘 |
|
|
26
|
+
| `glyph.xl` | 32 | — | `glyph.xl` | 큰 아이콘 |
|
|
27
|
+
| `glyph.xxl` | 44 | — | `glyph.xxl` | Skeleton 원 기본 지름, Calendar `large` 날짜 칸 지름 |
|
|
28
|
+
| `glyph.xxxl` | 48 | — | `glyph.xxxl` | 가장 큰 아이콘 |
|
|
29
|
+
|
|
30
|
+
Icon의 `size` prop은 이 이름(`"md"`)을 받는다. Avatar는 glyph가 아니라 자기 크기(`small` 32 · `medium` 40 · `large` 48 · `xlarge` 64)를 쓴다.
|
|
31
|
+
|
|
32
|
+
### control(컨트롤 높이·터치 영역)
|
|
33
|
+
|
|
34
|
+
| 토큰 | 값 | Web CSS 변수 | Native 경로 | 용도 |
|
|
35
|
+
| --- | --- | --- | --- | --- |
|
|
36
|
+
| `control.minTouchTarget` | 44 | `--hjm-control-min-touch-target` | `control.minTouchTarget` | 누를 수 있는 모든 것의 최소 터치 영역(가로·세로). ListRow `compact` 한 줄, Calendar `medium` 칸 |
|
|
37
|
+
| `control.buttonHeight.small` | 36 | `--hjm-control-button-small` | `control.buttonHeight.small` | Button `size="small"`. `control.buttonHitSlop.small` 4를 더해 터치 영역 44 |
|
|
38
|
+
| `control.buttonHeight.medium` | 44 | `--hjm-control-button-medium` | `control.buttonHeight.medium` | Button `size="medium"`(기본) |
|
|
39
|
+
| `control.buttonHeight.large` | 52 | `--hjm-control-button-large` | `control.buttonHeight.large` | Button `size="large"`, 화면 하단 주 행동 |
|
|
40
|
+
| `control.fieldHeight` | 44 | `--hjm-control-field-height` | `control.fieldHeight` | 한 줄 입력 필드 높이 |
|
|
41
|
+
| `control.chipHeight.small` | 36 | — | `control.chipHeight.small` | Chip `size="small"` |
|
|
42
|
+
| `control.chipHeight.medium` | 44 | — | `control.chipHeight.medium` | Chip `size="medium"` |
|
|
43
|
+
| `control.selectionIndicator` | 24 | — | `control.selectionIndicator` | Checkbox·Radio 표지 상자 |
|
|
44
|
+
|
|
45
|
+
Provider의 `minimumVisualTarget`을 켜면 보이는 버튼 높이가 44보다 작아지지 않는다(`small`도 44). Web은 `--hjm-control-button-*`에 반영된다.
|
|
46
|
+
Native 경로의 `glyph`·`control`은 `@hjmds/design-contracts/foundations` import다.
|
|
47
|
+
|
|
48
|
+
## 쓰는 법
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
// Web
|
|
52
|
+
import { Icon } from "@hjmds/react/display";
|
|
53
|
+
|
|
54
|
+
<Icon name="search" size="sm" />
|
|
55
|
+
// 제품 고유 누름 영역: .product-tile { min-block-size: var(--hjm-control-min-touch-target); }
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
// Native
|
|
60
|
+
import { Pressable } from "react-native";
|
|
61
|
+
import { control, glyph } from "@hjmds/design-contracts/foundations";
|
|
62
|
+
|
|
63
|
+
<Pressable style={{ minHeight: control.minTouchTarget, minWidth: control.minTouchTarget }} onPress={open}>
|
|
64
|
+
<ProductMark width={glyph.md} height={glyph.md} />
|
|
65
|
+
</Pressable>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
아이콘 사용법은 [Icon](../components/icon.md), 버튼 크기 선택은 [Button 배치](../components/button.md#배치)를 본다.
|
|
69
|
+
|
|
70
|
+
## 하지 말 것
|
|
71
|
+
|
|
72
|
+
- 누를 수 있는 영역을 44보다 작게 만들지 않는다. 그림이 작으면 hitSlop·padding으로 터치 영역을 44로 맞춘다.
|
|
73
|
+
- Button·필드 높이를 `style`로 바꾸지 않는다. `size` prop으로만 고른다.
|
|
74
|
+
- 아이콘 크기에 18, 22 같은 새 숫자를 쓰지 않는다.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# 간격
|
|
2
|
+
|
|
3
|
+
- 단계: 토큰
|
|
4
|
+
- 상태: 배포
|
|
5
|
+
- 지원: Web · Native
|
|
6
|
+
- 적용: 1.12.1
|
|
7
|
+
- 검토일: 2026-10-06
|
|
8
|
+
- 근거: `src/foundations.ts`(`spacing`·`layout`), `src/grid.ts`(`gridGaps`), `src/base-recipes.ts`(`buttonRecipe`·`fieldRecipe`), `src/auth-screen.ts`, `packages/react/src/theme.ts`, `packages/react/src/styles.css`
|
|
9
|
+
- 스토리북: `배포/토큰/공간과 크기/간격`
|
|
10
|
+
|
|
11
|
+
## 언제 쓰나
|
|
12
|
+
|
|
13
|
+
요소 사이 간격(gap)과 영역 안쪽 여백(padding)을 정할 때 쓴다. 숫자는 Web에서 CSS px, Native에서 dp(pt)다.
|
|
14
|
+
화면 좌우 여백·최대 폭은 이 값을 묶어 이름을 붙인 [화면 여백과 너비](layout.md)를 먼저 본다.
|
|
15
|
+
|
|
16
|
+
## 값
|
|
17
|
+
|
|
18
|
+
| 토큰 | 값 | Web CSS 변수 | Native 경로 | 용도 |
|
|
19
|
+
| --- | --- | --- | --- | --- |
|
|
20
|
+
| `spacing.xxs` | 4 | `--hjm-space-xxs` | `spacing.xxs` · `theme.tokens.spacing.xxs` | 목록 팝업 안쪽 여백(Select·Menubar) |
|
|
21
|
+
| `spacing.xs` | 8 | `--hjm-space-xs` | `spacing.xs` · `theme.tokens.spacing.xs` | 필드 라벨과 입력 사이, DatePicker 팝업과 입력 사이, EmptyState 안 요소 사이 |
|
|
22
|
+
| `spacing.sm` | 12 | `--hjm-space-sm` | `spacing.sm` · `theme.tokens.spacing.sm` | 나란한 버튼 사이, Toast 사이, small 버튼 좌우·필드 위아래 안쪽 여백 |
|
|
23
|
+
| `spacing.md` | 16 | `--hjm-space-md` | `spacing.md` · `theme.tokens.spacing.md` | Stack·Grid 기본 gap, medium 버튼·필드 좌우 안쪽 여백, `layout.contentGap`, `layout.pagePadding.compact` |
|
|
24
|
+
| `spacing.lg` | 20 | `--hjm-space-lg` | `spacing.lg` · `theme.tokens.spacing.lg` | large 버튼 좌우 안쪽 여백, `layout.pagePadding.regular`, Dialog 하단 여백 |
|
|
25
|
+
| `spacing.xl` | 24 | `--hjm-space-xl` | `spacing.xl` · `theme.tokens.spacing.xl` | `layout.sectionGap`, `layout.pagePadding.spacious`, EmptyState·Result 좌우 여백 |
|
|
26
|
+
| `spacing.xxl` | 32 | `--hjm-space-xxl` | `spacing.xxl` · `theme.tokens.spacing.xxl` | EmptyState 위아래 여백 |
|
|
27
|
+
| `spacing.xxxl` | 40 | `--hjm-space-xxxl` | `spacing.xxxl` · `theme.tokens.spacing.xxxl` | Result 위아래 여백, AuthScreen regular 위아래 여백 |
|
|
28
|
+
|
|
29
|
+
- Native 경로의 `spacing`은 `@hjmds/design-contracts/foundations` import, `theme`은 `useHjmNativeTheme()` 결과다.
|
|
30
|
+
- Stack·Grid·Surface의 `gap`·`padding` prop은 이 토큰 이름(`"md"`)을 받는다. Grid는 `none`(0)을 하나 더 받는다.
|
|
31
|
+
- 두 단계 사이에서 애매하면 작은 쪽을 고른다. 새 숫자(10, 18 등)를 만들지 않는다.
|
|
32
|
+
|
|
33
|
+
## 쓰는 법
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
// Web
|
|
37
|
+
import { Stack, Surface } from "@hjmds/react/layout";
|
|
38
|
+
|
|
39
|
+
<Surface padding="lg">
|
|
40
|
+
<Stack gap="sm">{children}</Stack>
|
|
41
|
+
</Surface>
|
|
42
|
+
|
|
43
|
+
// 제품 CSS가 꼭 필요하면 변수로: .product-toolbar { gap: var(--hjm-space-xs); padding-inline: var(--hjm-space-md); }
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
// Native
|
|
48
|
+
import { StyleSheet } from "react-native";
|
|
49
|
+
import { spacing } from "@hjmds/design-contracts/foundations";
|
|
50
|
+
import { Stack, Surface } from "@hjmds/react-native/primitives";
|
|
51
|
+
|
|
52
|
+
<Surface padding="lg">
|
|
53
|
+
<Stack gap="sm">{children}</Stack>
|
|
54
|
+
</Surface>
|
|
55
|
+
|
|
56
|
+
const styles = StyleSheet.create({ toolbar: { gap: spacing.xs, paddingHorizontal: spacing.md } });
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
간격 배치 규칙은 [Stack](../components/stack.md)·[Grid](../components/grid.md)·[Container](../components/container.md) 지침에 있다.
|
|
60
|
+
|
|
61
|
+
## 하지 말 것
|
|
62
|
+
|
|
63
|
+
- `margin: 13px`, `padding: 10` 같은 숫자를 직접 쓰지 않는다. 토큰에 없는 리듬은 계약 공백이므로 이슈로 올린다.
|
|
64
|
+
- 자식마다 margin을 붙여 간격을 만들지 않는다. 감싸는 Stack·Grid의 `gap`으로 정한다.
|
|
65
|
+
- `--hjm-space-*` 변수를 제품 CSS에서 재정의하지 않는다([브랜드 경계 §3](../../brand-boundary.md)).
|
|
66
|
+
- 화면 좌우 여백을 화면마다 `spacing.lg`로 적지 않는다. [Container](../components/container.md)의 `gutter`를 쓴다.
|
|
67
|
+
|
|
68
|
+
## 플랫폼 차이
|
|
69
|
+
|
|
70
|
+
| 항목 | Web | Native |
|
|
71
|
+
| --- | --- | --- |
|
|
72
|
+
| 단위 | CSS px(`--hjm-space-*`는 `px` 문자열) | dp(pt) 숫자 |
|
|
73
|
+
| Stack `gap` 타입 | 토큰 이름만 | 토큰 이름 또는 숫자 |
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# 테두리
|
|
2
|
+
|
|
3
|
+
- 단계: 토큰
|
|
4
|
+
- 상태: 배포
|
|
5
|
+
- 지원: Web · Native
|
|
6
|
+
- 적용: 1.12.1
|
|
7
|
+
- 검토일: 2026-10-06
|
|
8
|
+
- 근거: `src/foundations.ts`(`stroke`), `src/component-contracts.ts`(`focusIndicatorContract`), `src/base-recipes.ts`(`fieldRecipe`), `src/component-recipes.ts`(`segmentedControlRecipe`·`tabsRecipe`), `packages/react/src/theme.ts`
|
|
9
|
+
- 스토리북: `배포/토큰/표면과 움직임/테두리`
|
|
10
|
+
|
|
11
|
+
## 언제 쓰나
|
|
12
|
+
|
|
13
|
+
테두리·구분선·포커스 링의 두께를 정할 때 쓴다. 색은 [색상](color.md)의 테두리 역할(`border`·`borderControl`·`border.focus`)에서 고른다.
|
|
14
|
+
|
|
15
|
+
## 값
|
|
16
|
+
|
|
17
|
+
| 토큰 | 값 | Web CSS 변수 | Native 경로 | 용도 |
|
|
18
|
+
| --- | --- | --- | --- | --- |
|
|
19
|
+
| `stroke.subtle` | 1 | `--hjm-stroke-subtle` | `stroke.subtle` | 약한 경계(`border.subtle` 색과 함께) |
|
|
20
|
+
| `stroke.default` | 1 | `--hjm-stroke-default` | `stroke.default` | 영역 경계·구분선·필드 테두리(`fieldRecipe.borderWidth` 1) |
|
|
21
|
+
| `stroke.strong` | 2 | `--hjm-stroke-strong` | `stroke.strong` | 선택 표시: SegmentedControl 선택 칸 테두리, Tabs 현재 탭 밑줄 높이 |
|
|
22
|
+
| `stroke.focus` | 2 | `--hjm-stroke-focus` · `--hjm-focus-width` | `stroke.focus` | 키보드 포커스 링. 바깥 간격 2(`--hjm-focus-offset`), 색 `contentBrand`(`--hjm-color-focus`) |
|
|
23
|
+
|
|
24
|
+
Native 경로의 `stroke`는 `@hjmds/design-contracts/foundations` import다.
|
|
25
|
+
|
|
26
|
+
## 쓰는 법
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
// Web
|
|
30
|
+
// 제품 고유 영역: .product-panel { border: var(--hjm-stroke-default) solid var(--hjm-color-border); }
|
|
31
|
+
import { Surface } from "@hjmds/react/layout";
|
|
32
|
+
|
|
33
|
+
<Surface bordered>{children}</Surface>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
// Native
|
|
38
|
+
import { View } from "react-native";
|
|
39
|
+
import { stroke } from "@hjmds/design-contracts/foundations";
|
|
40
|
+
import { useHjmNativeTheme } from "@hjmds/react-native/provider";
|
|
41
|
+
|
|
42
|
+
const theme = useHjmNativeTheme();
|
|
43
|
+
<View style={{ borderWidth: stroke.default, borderColor: theme.colors.border }} />;
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## 하지 말 것
|
|
47
|
+
|
|
48
|
+
- 0.5·1.5 같은 두께를 만들지 않는다. hairline이 필요하면 `stroke.subtle`과 `border.subtle` 색을 쓴다.
|
|
49
|
+
- HJM 컴포넌트의 포커스 링을 지우거나(`outline: none`) 다시 그리지 않는다. 제품 고유 컨트롤만 같은 값(`stroke.focus` 2, 간격 2)으로 그린다.
|
|
50
|
+
- 테두리 두께로 선택 상태를 알리는 경우 색도 함께 바꾼다. 두께만으로는 구분이 약하다.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# 테마 편집
|
|
2
|
+
|
|
3
|
+
- 단계: 토큰
|
|
4
|
+
- 상태: 배포
|
|
5
|
+
- 지원: Web · Native
|
|
6
|
+
- 적용: 1.12.1
|
|
7
|
+
- 검토일: 2026-10-06
|
|
8
|
+
- 근거: [테마 작업실](../../theme-studio.md), [브랜드 경계](../../brand-boundary.md), `src/theme-studio.ts`, `src/palette-contrast.ts`, `showcase/web/src/foundations/ThemeStudio.stories.tsx`, `showcase/native/src/ThemeStudio.stories.tsx`
|
|
9
|
+
- 스토리북: `배포/토큰/편집 도구/테마 편집`
|
|
10
|
+
|
|
11
|
+
## 언제 쓰나
|
|
12
|
+
|
|
13
|
+
제품 브랜드 색을 정할 때, 바꿀 색을 light·dark 양쪽에서 실제 컴포넌트에 입혀 보고 대비를 확인한 뒤
|
|
14
|
+
Provider에 넣을 `brandPalette` 설정을 얻는 작업 도구다. 새 테마 엔진이나 자동 색 생성기가 아니다.
|
|
15
|
+
|
|
16
|
+
도구 흐름(Storybook 화면, Web·Native 같음):
|
|
17
|
+
|
|
18
|
+
1. light·dark 각각 세 역할(주요 버튼 배경 `primary`, 주요 버튼 글자 `onPrimary`, 브랜드 강조 글자 `contentBrand`)에 `#rrggbb`를 넣고 적용한다.
|
|
19
|
+
2. 같은 화면 아래 샘플(버튼·입력·비활성·오류·아이콘·알림·기록 목록)이 그 팔레트로 다시 그려진다.
|
|
20
|
+
3. "색 대비 확인"에서 각 쌍의 대비·기준·통과 여부를 본다. 미달이 하나라도 있으면 색을 고친다.
|
|
21
|
+
4. "설정 내보내기"로 `{ "brandPalette": … }` JSON을 받는다(Web 파일 다운로드, Native OS 공유). 아래 코드 블록에서 복사해도 된다.
|
|
22
|
+
|
|
23
|
+
## 값
|
|
24
|
+
|
|
25
|
+
| 토큰 | 값 | Web CSS 변수 | Native 경로 | 용도 |
|
|
26
|
+
| --- | --- | --- | --- | --- |
|
|
27
|
+
| `StudioColorRole` | `primary` · `onPrimary` · `contentBrand` | `--hjm-color-primary` · `--hjm-color-on-primary` · `--hjm-color-content-brand` | `theme.colors.primary` 등 | 도구에서 바꿀 수 있는 세 역할 |
|
|
28
|
+
| `applyStudioColor(palette, theme, role, color)` | 여섯 자리 HEX만 허용(아니면 `TypeError`), 소문자로 저장, 입력 객체 불변 | — | `@hjmds/design-contracts/theme-studio` | 역할 하나의 색 바꾸기 |
|
|
29
|
+
| `studioReport(palette, theme)` | 각 규칙의 `foreground`·`background`·`ratio`·`minimum`·`pass` | — | `@hjmds/design-contracts/theme-studio` | HJM 기본 팔레트에 바꾼 값을 합쳐 대비 검사. 통과 판정은 반올림 전 값 |
|
|
30
|
+
| `exportStudioPalette(palette)` | `{ "brandPalette": { "light": {…}, "dark": {…} } }` JSON 문자열 | — | `@hjmds/design-contracts/theme-studio` | 산출물. 바꾼 key만 담는다 |
|
|
31
|
+
| 대비 기준 | 글자 4.5 · 형태(`primary`·`borderControl`)와 `textWeak` 3 | — | `paletteContrastRules` | [색상](color.md)의 쌍 표와 같다 |
|
|
32
|
+
|
|
33
|
+
## 쓰는 법
|
|
34
|
+
|
|
35
|
+
산출물은 Provider의 `brandPalette` prop에 그대로 넣고, 같은 값을 제품 테스트에서 `checkBrandPaletteContrast`로 검사한다.
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
// Web
|
|
39
|
+
import { HjmProvider } from "@hjmds/react/provider";
|
|
40
|
+
import { brandPalette } from "./brand-palette"; // 테마 편집에서 내보낸 JSON의 brandPalette
|
|
41
|
+
|
|
42
|
+
<HjmProvider brandPalette={brandPalette}>{app}</HjmProvider>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
// Native
|
|
47
|
+
import { HjmNativeProvider } from "@hjmds/react-native/provider";
|
|
48
|
+
import { checkBrandPaletteContrast } from "@hjmds/design-contracts/palette-contrast";
|
|
49
|
+
import { brandPalette } from "./brand-palette";
|
|
50
|
+
|
|
51
|
+
<HjmNativeProvider brandPalette={brandPalette} safeAreaInsets={insets}>{app}</HjmNativeProvider>
|
|
52
|
+
|
|
53
|
+
// 제품 테스트
|
|
54
|
+
expect(checkBrandPaletteContrast(brandPalette)).toEqual([]);
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## 하지 말 것
|
|
58
|
+
|
|
59
|
+
- 통과 표시를 전체 접근성 인증으로 보고하지 않는다. 지정된 색 쌍의 대비일 뿐이고 hover·focus·실제 배경은 따로 확인한다.
|
|
60
|
+
- 내보낸 JSON을 HJM 중앙 토큰이나 다른 제품 기본값으로 쓰지 않는다. 그 제품의 `brandPalette`에만 쓴다.
|
|
61
|
+
- 도구 밖에서 `--hjm-color-*`를 재정의해 같은 효과를 내지 않는다([브랜드 경계 §3](../../brand-boundary.md)).
|
|
62
|
+
- Showcase 샘플 문구·예시 색을 제품에 복사하지 않는다. 도구의 라벨·오류 문구는 showcase 소유다.
|
|
63
|
+
|
|
64
|
+
## 플랫폼 차이
|
|
65
|
+
|
|
66
|
+
| 항목 | Web | Native |
|
|
67
|
+
| --- | --- | --- |
|
|
68
|
+
| 내보내기 | `hjm-brand-palette.json` 파일 다운로드 | OS 공유 시트(`Share.share`) |
|
|
69
|
+
| 기록 샘플 | DataTable | List |
|
|
70
|
+
| 키보드 | — | 입력이 키보드에 가리지 않게 스크롤이 키보드 높이를 따른다 |
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# 글꼴 편집
|
|
2
|
+
|
|
3
|
+
- 단계: 토큰
|
|
4
|
+
- 상태: 배포
|
|
5
|
+
- 지원: Web · Native
|
|
6
|
+
- 적용: 1.12.1
|
|
7
|
+
- 검토일: 2026-10-06
|
|
8
|
+
- 근거: [테마 작업실](../../theme-studio.md), `src/foundations.ts`(`fontFamily`), `showcase/web/src/foundations/TypographyStudio.stories.tsx`, `showcase/native/src/TypographyStudio.stories.tsx`, `showcase/shared/typography-studio.ts`
|
|
9
|
+
- 스토리북: `배포/토큰/편집 도구/글꼴 편집`
|
|
10
|
+
|
|
11
|
+
## 언제 쓰나
|
|
12
|
+
|
|
13
|
+
제품 서체 후보를 정할 때, 후보 폰트를 기본 서체와 나란히 같은 크기로 그려 한글·영문·숫자·긴 문장을 비교하고
|
|
14
|
+
출처·라이선스를 함께 기록하는 작업 도구다. 공개 API가 없는 Storybook 도구이며 HJM 토큰을 바꾸지 않는다.
|
|
15
|
+
|
|
16
|
+
도구 흐름:
|
|
17
|
+
|
|
18
|
+
1. 후보 폰트를 넣는다. Web은 `.woff`·`.woff2`·`.ttf`·`.otf` 파일 선택, Native는 사용 권한이 있는 OTF·TTF 주소(`https://` 또는 `file://`)를 넣고 "서체 불러오기".
|
|
19
|
+
2. 상태 문구가 비어 있음 → 불러오는 중 → 불러옴 / 실패로 바뀐다. 실패하면 기본 서체로 표시한다.
|
|
20
|
+
3. "기본 서체"와 "비교할 서체" 두 카드에서 `heading` 크기 제목, 본문, 굵은 본문을 비교한다. 한글 글리프가 없는 부분은 기본 서체로 대체될 수 있다.
|
|
21
|
+
4. 서체 출처·라이선스 문서 주소를 적고, 아래 "서체 후보 설정" 코드 블록을 기록으로 가져간다.
|
|
22
|
+
|
|
23
|
+
## 값
|
|
24
|
+
|
|
25
|
+
| 토큰 | 값 | Web CSS 변수 | Native 경로 | 용도 |
|
|
26
|
+
| --- | --- | --- | --- | --- |
|
|
27
|
+
| 비교 기준 서체 | Web `system-ui, sans-serif`, Native OS 기본 | `--hjm-font-family-ui`(HJM 기본 목록은 [타이포그래피](typography.md)) | — | "기본 서체" 카드 |
|
|
28
|
+
| 비교 글자 크기 | `typography.heading` 24 · `typography.body` 14 · body bold | `--hjm-type-heading-*` · `--hjm-type-body-*` | `theme.tokens.typography` | 두 카드가 같은 단계로 그린다 |
|
|
29
|
+
| 산출물(Web) | `{ fileName, source, license, status, fallback: "system-ui, sans-serif" }` JSON | — | — | 후보 기록. 폰트 파일은 포함하지 않는다 |
|
|
30
|
+
| 산출물(Native) | `{ family, status, source, license }` JSON | — | — | 후보 기록 |
|
|
31
|
+
| `status` | `empty` · `loading` · `ready` · `error` | — | — | 불러오기 상태 |
|
|
32
|
+
|
|
33
|
+
## 쓰는 법
|
|
34
|
+
|
|
35
|
+
후보가 정해지면 제품이 폰트 파일과 라이선스를 소유하고 제품 앱에서 등록한다. HJM 컴포넌트는 Web에서 Provider 루트의 서체를,
|
|
36
|
+
`host="contents"`일 때는 제품 루트의 서체를 상속한다.
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
// Web
|
|
40
|
+
import { HjmProvider } from "@hjmds/react/provider";
|
|
41
|
+
|
|
42
|
+
// 제품 CSS: @font-face { font-family: "ProductSans"; src: url("/fonts/product-sans.woff2") format("woff2"); }
|
|
43
|
+
// 제품 CSS: .product-root { font-family: "ProductSans", system-ui, sans-serif; }
|
|
44
|
+
<div className="product-root">
|
|
45
|
+
<HjmProvider host="contents">{app}</HjmProvider>
|
|
46
|
+
</div>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
// Native
|
|
51
|
+
import { useFonts } from "expo-font";
|
|
52
|
+
|
|
53
|
+
const [loaded] = useFonts({ ProductSans: require("./assets/fonts/ProductSans.otf") });
|
|
54
|
+
// HJM Native 컴포넌트는 fontFamily를 지정하지 않는다. 제품 서체 적용 범위는 제품 Text 래퍼가 정한다.
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## 하지 말 것
|
|
58
|
+
|
|
59
|
+
- 라이선스가 확인되지 않은 폰트를 제품에 넣지 않는다. 도구에 적은 출처·라이선스 주소를 제품 문서에 남긴다.
|
|
60
|
+
- 도구에서 불러온 폰트를 저장·배포 경로로 쓰지 않는다. Web 파일은 현재 미리보기에서만 쓰고, Native 등록은 앱 종료까지만 남는다.
|
|
61
|
+
- `--hjm-font-family-ui`를 제품 CSS에서 재정의하지 않는다([브랜드 경계 §3](../../brand-boundary.md)).
|
|
62
|
+
- 서체를 바꾸면서 글자 크기·줄 높이 토큰을 함께 바꾸지 않는다. 같은 크기에서 비교한 결과로 고른다.
|
|
63
|
+
|
|
64
|
+
## 플랫폼 차이
|
|
65
|
+
|
|
66
|
+
| 항목 | Web | Native |
|
|
67
|
+
| --- | --- | --- |
|
|
68
|
+
| 폰트 입력 | 파일 선택, `FontFace`로 메모리에서 등록(업로드 없음) | 주소 입력, `expo-font` `loadAsync` |
|
|
69
|
+
| 초기화 | 등록한 폰트를 문서에서 제거 | 기본 서체로 돌아가지만 등록은 앱 종료까지 유지 |
|
|
70
|
+
| 서체 적용 | 스타일 `fontFamily: "<family>", system-ui, sans-serif` | 등록이 끝난 뒤에만 `fontFamily` 적용 |
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# 타이포그래피
|
|
2
|
+
|
|
3
|
+
- 단계: 토큰
|
|
4
|
+
- 상태: 배포
|
|
5
|
+
- 지원: Web · Native
|
|
6
|
+
- 적용: 1.12.1
|
|
7
|
+
- 검토일: 2026-10-06
|
|
8
|
+
- 근거: `src/foundations.ts`(`typography`·`heading`·`fontFamily`·`fontWeight`·`letterSpacing`·`numeric`·`largeTextThreshold`), `src/component-recipes.ts`(`textRecipe`), `packages/react/src/theme.ts`, `packages/react/src/provider.tsx`, `packages/react-native/src/provider.tsx`
|
|
9
|
+
- 스토리북: `배포/토큰/색과 글자/타이포그래피`
|
|
10
|
+
|
|
11
|
+
## 언제 쓰나
|
|
12
|
+
|
|
13
|
+
글자 크기·줄 높이·굵기를 정할 때 쓴다. 대부분은 [Text](../components/text.md)의 `variant`·`emphasis`와
|
|
14
|
+
[Heading](../components/heading.md)의 `level`로 고르고, 토큰을 직접 읽는 것은 제품 고유 그림(차트 라벨 등)일 때다.
|
|
15
|
+
|
|
16
|
+
## 값
|
|
17
|
+
|
|
18
|
+
### 글자 단계(`typography`, Text `variant`)
|
|
19
|
+
|
|
20
|
+
| 토큰 | 값 | Web CSS 변수 | Native 경로 | 용도 |
|
|
21
|
+
| --- | --- | --- | --- | --- |
|
|
22
|
+
| `typography.caption` | 11 / 줄 16 / 400 | `--hjm-type-caption-size` · `-line-height` · `-weight` | `theme.tokens.typography.caption` | 가장 작은 보조 표기, AuthScreen 정책 링크 |
|
|
23
|
+
| `typography.label` | 12 / 줄 18 / 600 | `--hjm-type-label-*` | `theme.tokens.typography.label` | 라벨·도움말·small 버튼 글자 |
|
|
24
|
+
| `typography.body` | 14 / 줄 20 / 400 | `--hjm-type-body-*` | `theme.tokens.typography.body` | 기본 본문·medium 버튼·필드 글자 |
|
|
25
|
+
| `typography.bodyLarge` | 16 / 줄 24 / 400 | `--hjm-type-body-large-*` | `theme.tokens.typography.bodyLarge` | 읽기용 긴 본문·large 버튼 글자 |
|
|
26
|
+
| `typography.title` | 18 / 줄 26 / 700 | `--hjm-type-title-*` | `theme.tokens.typography.title` | 카드 제목(`heading.level5`) |
|
|
27
|
+
| `typography.titleLarge` | 20 / 줄 28 / 800 | `--hjm-type-title-large-*` | `theme.tokens.typography.titleLarge` | 큰 구획 제목(`heading.level4`) |
|
|
28
|
+
| `typography.heading` | 24 / 줄 32 / 800 | `--hjm-type-heading-*` | `theme.tokens.typography.heading` | 화면의 가장 큰 제목 |
|
|
29
|
+
|
|
30
|
+
### 문서 제목 단계(`heading`, Heading `level`)
|
|
31
|
+
|
|
32
|
+
| 토큰 | 값 | Web CSS 변수 | Native 경로 | 용도 |
|
|
33
|
+
| --- | --- | --- | --- | --- |
|
|
34
|
+
| `heading.level1` | 40 / 줄 48 / 800 | — | `heading.level1` | 랜딩·문서의 대표 제목 |
|
|
35
|
+
| `heading.level2` | 32 / 줄 40 / 800 | — | `heading.level2` | 긴 페이지의 큰 구획 제목 |
|
|
36
|
+
| `heading.level3` | = `typography.heading` 24 | `--hjm-type-heading-*` | `heading.level3` | 화면 제목 |
|
|
37
|
+
| `heading.level4` | = `typography.titleLarge` 20 | `--hjm-type-title-large-*` | `heading.level4` | 구획 제목 |
|
|
38
|
+
| `heading.level5` | = `typography.title` 18 | `--hjm-type-title-*` | `heading.level5` | 카드 제목 |
|
|
39
|
+
|
|
40
|
+
### 서체·굵기·자간·숫자
|
|
41
|
+
|
|
42
|
+
| 토큰 | 값 | Web CSS 변수 | Native 경로 | 용도 |
|
|
43
|
+
| --- | --- | --- | --- | --- |
|
|
44
|
+
| `fontFamily.ui` | Inter, Pretendard, -apple-system, BlinkMacSystemFont, Segoe UI, sans-serif | `--hjm-font-family-ui` | `fontFamily.ui` | 화면 글자. Native는 HJM이 서체를 지정하지 않아 OS 기본 서체로 그린다 |
|
|
45
|
+
| `fontFamily.code` | ui-monospace, SFMono-Regular, Consolas, Liberation Mono, monospace | — (`--hjm-font-family-code` fallback) | `fontFamily.code` | 코드 |
|
|
46
|
+
| `fontWeight.regular` · `medium` · `semibold` · `bold` · `heavy` | 400 · 500 · 600 · 700 · 800 | `--hjm-font-weight-<이름>` | `fontWeight.<이름>` | Text `emphasis`: `regular` 400 · `medium` 600 · `strong` 700 |
|
|
47
|
+
| `letterSpacing.tight` · `normal` · `wide` | -0.2 · 0 · 0.2 | — | `letterSpacing.<이름>` | 자간 조정이 필요한 제품 고유 글자. HJM 컴포넌트는 자간을 지정하지 않는다 |
|
|
48
|
+
| `numeric.tabular` · `proportional` | `tabular-nums` · `proportional-nums` | — | `numeric.<이름>` | 바뀌는 숫자(카운터·통계·날짜 칸)는 `tabular`로 폭을 고정 |
|
|
49
|
+
| `largeTextThreshold` | 1.6 | 루트 `data-large-text="true"` | `largeTextThreshold` | 글자 배율이 이 값 이상이면 큰 글자 배치로 바꾼다 |
|
|
50
|
+
|
|
51
|
+
Native 경로의 `theme`은 `useHjmNativeTheme()`, 나머지 이름은 `@hjmds/design-contracts/foundations` import다.
|
|
52
|
+
Web 크기 변수는 `rem × --hjm-text-scale`이라 Provider의 `textScale`을 따른다.
|
|
53
|
+
|
|
54
|
+
## 쓰는 법
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
// Web
|
|
58
|
+
import { Text } from "@hjmds/react/layout";
|
|
59
|
+
import { Heading } from "@hjmds/react/heading";
|
|
60
|
+
|
|
61
|
+
<Heading level="level3">{t("orders.title")}</Heading>
|
|
62
|
+
<Text as="p" variant="body" tone="muted">{t("orders.hint")}</Text>
|
|
63
|
+
// 제품 고유 그림: .product-axis-label { font-size: var(--hjm-type-caption-size); line-height: var(--hjm-type-caption-line-height); }
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
// Native
|
|
68
|
+
import { Text } from "@hjmds/react-native/primitives";
|
|
69
|
+
import { Heading } from "@hjmds/react-native/heading";
|
|
70
|
+
|
|
71
|
+
<Heading level="level3">{t("orders.title")}</Heading>
|
|
72
|
+
<Text variant="body" tone="muted">{t("orders.hint")}</Text>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## 하지 말 것
|
|
76
|
+
|
|
77
|
+
- `font-size: 15px`, `fontWeight: "900"`처럼 단계 밖 값을 쓰지 않는다.
|
|
78
|
+
- 크기를 맞추려고 Heading의 `semanticLevel`을 바꾸지 않는다. 시각 크기는 `level`, 문서 구조는 `semanticLevel`이다.
|
|
79
|
+
- 글자 크기를 고정해 OS 글자 크기 설정을 막지 않는다(`allowFontScaling={false}`, px 고정 `font-size`).
|
|
80
|
+
- 줄 높이를 지워 글자를 겹치게 하지 않는다. 한국어 본문은 토큰 줄 높이를 그대로 쓴다.
|
|
81
|
+
- 제품 서체는 [글꼴 편집](typography-studio.md)으로 비교·라이선스를 확인한 뒤 제품이 소유한다. `--hjm-font-family-ui`를 재정의하지 않는다.
|
|
82
|
+
|
|
83
|
+
## 플랫폼 차이
|
|
84
|
+
|
|
85
|
+
| 항목 | Web | Native |
|
|
86
|
+
| --- | --- | --- |
|
|
87
|
+
| 단위 | rem(16px 기준) × `--hjm-text-scale` | dp. OS 글자 크기를 따르고, Provider `textScale`을 주면 HJM이 한 번만 곱한다 |
|
|
88
|
+
| 서체 | `--hjm-font-family-ui` 목록 | OS 기본 서체(HJM이 `fontFamily`를 지정하지 않음) |
|
|
89
|
+
| 큰 글자 판정 | 루트 `data-large-text` | `isLargeTextScale(environment.textScale)` |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hjmds/design-contracts",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.0",
|
|
4
4
|
"description": "Renderer-neutral design contracts, tokens, recipes, and behaviors shared by HJM products.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -660,6 +660,12 @@
|
|
|
660
660
|
"react-native": "./dist/action-session.js",
|
|
661
661
|
"import": "./dist/action-session.js",
|
|
662
662
|
"default": "./dist/action-session.js"
|
|
663
|
+
},
|
|
664
|
+
"./screen-patterns": {
|
|
665
|
+
"types": "./dist/screen-patterns.d.ts",
|
|
666
|
+
"react-native": "./dist/screen-patterns.js",
|
|
667
|
+
"import": "./dist/screen-patterns.js",
|
|
668
|
+
"default": "./dist/screen-patterns.js"
|
|
663
669
|
}
|
|
664
670
|
},
|
|
665
671
|
"files": [
|