@hjmds/design-contracts 1.29.0 → 1.31.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/behaviors.d.ts +1 -0
- package/dist/behaviors.d.ts.map +1 -1
- package/dist/bottom-navigation.d.ts +24 -0
- package/dist/bottom-navigation.d.ts.map +1 -1
- package/dist/bottom-navigation.js +34 -0
- package/dist/bottom-navigation.js.map +1 -1
- package/dist/carousel.d.ts +30 -0
- package/dist/carousel.d.ts.map +1 -1
- package/dist/carousel.js +32 -0
- package/dist/carousel.js.map +1 -1
- package/dist/catalog.d.ts +382 -64
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +147 -131
- package/dist/catalog.js.map +1 -1
- package/dist/component-definitions.d.ts +21 -131
- package/dist/component-definitions.d.ts.map +1 -1
- package/dist/component-definitions.js +9 -132
- package/dist/component-definitions.js.map +1 -1
- package/dist/component-recipes.d.ts +87 -0
- package/dist/component-recipes.d.ts.map +1 -1
- package/dist/component-recipes.js +44 -1
- package/dist/component-recipes.js.map +1 -1
- package/dist/icon.d.ts +58 -1
- package/dist/icon.d.ts.map +1 -1
- package/dist/icon.js +69 -0
- package/dist/icon.js.map +1 -1
- package/dist/image-choice.d.ts +7 -0
- package/dist/image-choice.d.ts.map +1 -1
- package/dist/image-choice.js +7 -0
- package/dist/image-choice.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/recipes.d.ts +1 -1
- package/dist/recipes.d.ts.map +1 -1
- package/dist/recipes.js.map +1 -1
- package/dist/screen-patterns.d.ts +100 -0
- package/dist/screen-patterns.d.ts.map +1 -1
- package/dist/screen-patterns.js +98 -3
- package/dist/screen-patterns.js.map +1 -1
- package/dist/showcase.d.ts.map +1 -1
- package/dist/showcase.js +10 -0
- package/dist/showcase.js.map +1 -1
- package/dist/steps.d.ts +16 -7
- package/dist/steps.d.ts.map +1 -1
- package/dist/steps.js +6 -1
- package/dist/steps.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/architecture.md +18 -0
- package/docs/bottom-navigation.md +10 -0
- package/docs/carousel.md +8 -0
- package/docs/dialog.md +23 -0
- package/docs/generated/component-maturity.md +32 -29
- package/docs/generated/renderer-evidence.json +1551 -1118
- package/docs/generated/renderer-evidence.md +243 -237
- package/docs/generated/showcase-manifest.json +688 -69
- package/docs/icon.md +9 -0
- package/docs/screen-patterns.md +18 -0
- package/docs/stable-core.md +22 -0
- package/docs/steps.md +4 -3
- package/docs/usage/README.md +28 -25
- package/docs/usage/SELECTION.md +1 -1
- package/docs/usage/components/auth-screen-layout.md +15 -5
- package/docs/usage/components/bottom-navigation.md +65 -2
- package/docs/usage/components/card.md +36 -5
- package/docs/usage/components/carousel.md +1 -0
- package/docs/usage/components/chat-date-separator.md +86 -0
- package/docs/usage/components/chat-message.md +10 -1
- package/docs/usage/components/chat-screen.md +3 -2
- package/docs/usage/components/comment-thread-row.md +11 -3
- package/docs/usage/components/comment-thread-screen.md +1 -1
- package/docs/usage/components/dialog.md +69 -0
- package/docs/usage/components/editor-screen.md +6 -2
- package/docs/usage/components/field.md +13 -0
- package/docs/usage/components/icon-button.md +1 -0
- package/docs/usage/components/icon-tile.md +10 -1
- package/docs/usage/components/icon.md +45 -6
- package/docs/usage/components/image-choice-group.md +3 -1
- package/docs/usage/components/media-selection-screen.md +17 -0
- package/docs/usage/components/message-composer.md +4 -1
- package/docs/usage/components/moderation-screen.md +88 -2
- package/docs/usage/components/page-indicator.md +102 -0
- package/docs/usage/components/profile-screen.md +9 -3
- package/docs/usage/components/profile-summary.md +3 -3
- package/docs/usage/components/screen-layout.md +9 -0
- package/docs/usage/components/steps.md +14 -7
- package/docs/usage/components/tabs.md +21 -1
- package/docs/usage/components/text.md +30 -1
- package/docs/usage/components/typing-indicator.md +89 -0
- package/docs/usage/screens/common-login.md +3 -1
- package/docs/usage/screens/common-profile.md +3 -3
- package/docs/usage/screens/flow-editor.md +13 -2
- package/docs/usage/screens/flow-moderation.md +31 -3
- package/package.json +2 -1
package/docs/icon.md
CHANGED
|
@@ -46,3 +46,12 @@ Lucide 1.49.0 is the verified development/showcase version and optional peer.
|
|
|
46
46
|
The Native factory uses a scalar-only component interface instead of exporting
|
|
47
47
|
one host version's RN StyleProp types, keeping consumers on supported newer RN
|
|
48
48
|
versions structurally compatible. This does not replace provider/brand logos.
|
|
49
|
+
|
|
50
|
+
## 공용 경로 — 2026-10-18 (1.31.0)
|
|
51
|
+
|
|
52
|
+
semantic 이름별 24-unit stroke 경로는 `semanticIconPaths`(`components/icon`)가 소유한다. 이전에는 Web renderer
|
|
53
|
+
내부 레지스트리라 Native 제품이 같은 그림을 adapter에 다시 그렸다(utilverse `arrowUp`·`arrowDown`·`rotate`).
|
|
54
|
+
Web Icon은 이 데이터를 내장 그림으로 쓰고, Native는 optional peer `react-native-svg`를 쓰는 `/icon-svg`의
|
|
55
|
+
`renderSemanticGlyph`로 같은 경로를 그린다. Native core는 계속 SVG 없이 동작하며 `renderGlyph` 계약은 바뀌지 않는다.
|
|
56
|
+
이번에 순서 이동(`arrowUp`·`arrowDown`), 회전(`rotate`, 시계 방향), 차단 해제(`unblock`)를 추가했다. 세 방향 기호는
|
|
57
|
+
물리 방향이라 RTL에서 반전하지 않는다. 눈/가린 눈은 기존 `visibility`·`visibilityOff`다.
|
package/docs/screen-patterns.md
CHANGED
|
@@ -426,3 +426,21 @@ API별 제공 기준과 개발 중 추가분은 [사용 지침](usage/README.md)
|
|
|
426
426
|
|
|
427
427
|
검증: 각 renderer의 `screen-recovery` 테스트. Web은 Chromium 동작 검사, Native는 host 렌더 검사이며
|
|
428
428
|
실기기 성능·운영 서버·npm 게시·소비 앱 반영을 뜻하지 않는다.
|
|
429
|
+
|
|
430
|
+
## 2026-10-18 헤더 식별 표시·채팅 타임라인 조각
|
|
431
|
+
|
|
432
|
+
HJM 1.30.0 채택 감사에서 제품이 공통 구조를 다시 만든 지점(야잘알 팀 상세 헤더, 유틸버스 도구 헤더·런처·채팅,
|
|
433
|
+
번뚝 DM, spint 홈 로딩)을 공개 API로 옮겼다. 모두 추가 API이며 기존 기본값은 그대로다.
|
|
434
|
+
|
|
435
|
+
- `ScreenLayout.titleLeading`: 제목 앞 장식 표시. `titleVisibility="hidden"`이면 표시가 `title`을 이름으로 하는
|
|
436
|
+
heading이 된다. ChatScreen의 비공개 상대 사진 자리를 공개했다(`avatar`는 유지). Native 가운데 헤더의 양쪽 열
|
|
437
|
+
측정 방식은 바꾸지 않았다.
|
|
438
|
+
- `ScreenLayout.loadingIndicator`: CompositionLayout과 같은 브랜드 로딩 계약.
|
|
439
|
+
- `IconTile` `frame`·`shape`·`size`(`iconTileRecipe.shapes`·`fillMinSize`·`fillMaxSize`·`defaults`).
|
|
440
|
+
- `ChatMessage.reactions.summary`(`chatMessageRecipe.reactionSummary`, `resolveChatReactionSummary`)와
|
|
441
|
+
메뉴 행 `tone`(Menu의 `MenuItemTone`).
|
|
442
|
+
- `MessageComposer.error`는 나타날 때 assertive로 알린다(버그 수정).
|
|
443
|
+
- 새 조각 `TypingIndicator`(`typingIndicatorRecipe`)·`ChatDateSeparator`(`chatDateSeparatorRecipe`).
|
|
444
|
+
|
|
445
|
+
검증: Web `screens-additions.browser.test.tsx`(Chromium), Native `screens-additions.test.tsx`(host 렌더),
|
|
446
|
+
contracts `screen-patterns.test.ts`. 실기기·npm 게시·소비 앱 반영을 뜻하지 않는다.
|
package/docs/stable-core.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Stable Core
|
|
2
2
|
|
|
3
|
+
## 2026-10-18 화면·구성 22종 승격
|
|
4
|
+
|
|
5
|
+
ScreenLayout, CompositionLayout, SettingsScreen, SearchScreen, EditorScreen, PermissionScreen,
|
|
6
|
+
OnboardingScreen, ModerationScreen, ChatScreen, NotificationInboxScreen, CommentThreadScreen,
|
|
7
|
+
ListDetailScreen, MediaSelectionScreen, ProfileScreen, ChatMessage, NotificationRow, NotificationItem,
|
|
8
|
+
CommentThreadRow, ProfileSummary, IconTile, MessageComposer, PhotoSourceSheet의 계약과 Web·Native
|
|
9
|
+
surface를 stable로 올렸다. 이름과 기존 id는 유지한다.
|
|
10
|
+
|
|
11
|
+
인계된 default/evidence 통과 결과를 재사용하고, 이번 작업에서 해당 행의 환경 매트릭스를 실행했다.
|
|
12
|
+
함께 확인한 Chart·ImageChoiceGroup을 포함해 Web 118건, Native 109건과 별도 Onboarding·Pagination·DataTable·Chart
|
|
13
|
+
관련 Native 검사 20건이 통과했다. 최대 글자 조건은 사용자 지침에 따라 실행하지 않았다.
|
|
14
|
+
ScreenLayout의 포커스 가능한 본문 이름, ListRow 계열 fixture의 계약상 부모 여백, Native host API 모델과
|
|
15
|
+
DataTable RTL 들여쓰기·정렬을 바로잡았다. contracts component-references 13건과 Web preview 3건·Native registry 1건,
|
|
16
|
+
세 패키지 build와 두 Showcase 타입 검사도 통과했다. 제품 수나 별도 승인 절차를 조건으로 추가하지 않았다.
|
|
17
|
+
|
|
18
|
+
기기 QA·npm 게시·소비 앱 적용은 이번 결과가 아니다. Chart·ImageChoiceGroup과 Native Pagination·DataTable의
|
|
19
|
+
기존 beta 상태는 이번 22종 승격 범위 밖이므로 유지했다.
|
|
20
|
+
|
|
21
|
+
기존 별개 Storybook 정적 문제는 미해결이다: Web `showcase/web/src/patterns/CommonChat.stories.tsx` 및
|
|
22
|
+
Native `showcase/native/src/CommonChat.stories.tsx`의 Group 스토리 순서(S4), Web `showcase/web/src/patterns/ShortcutRecorder.stories.tsx`의
|
|
23
|
+
플랫폼 전용 항목 차이 기록(S6). canonical 등록·S9 누락은 없으며 이 세 건을 전체 Storybook 검사 통과로 보고하지 않는다.
|
|
24
|
+
|
|
3
25
|
## 2026-09-30 선택형 상호작용 어댑터·Liquid Toast 승격
|
|
4
26
|
|
|
5
27
|
`sortable`·`swipe-actions`·`content-transition`·`carousel-motion`·`celebration`(Web·Native)과 Native Liquid Toast를
|
package/docs/steps.md
CHANGED
|
@@ -33,7 +33,7 @@ index > cursor → pending
|
|
|
33
33
|
두 단계 이상 "current"이거나, cursor보다 앞선 단계가 아직 "pending"으로 남거나, cursor
|
|
34
34
|
너머의 단계가 "complete"인 상태는 애초에 표현할 수 없다 — 이 저장소의 다른 계약들
|
|
35
35
|
(`SheetOpenState`, `ComboboxCollectionState`, `LoadMoreState`)과 같은 이유다: 유효하지 않은
|
|
36
|
-
조합을 타입과 유도 규칙으로 만들 수 없게 한다.
|
|
36
|
+
조합을 타입과 유도 규칙으로 만들 수 없게 한다. 누르기는 커서 앞 단계로 돌아가는 것만 열었으므로(아래
|
|
37
37
|
참고) 흐름은 항상 cursor 기준 선형이라 이 유도가 항상 맞다.
|
|
38
38
|
|
|
39
39
|
`"complete"`는 2026-10-02에 추가했다. 그 전에는 마지막 단계에 커서가 있으면 항상 "진행 중"으로
|
|
@@ -100,11 +100,12 @@ index > cursor → pending
|
|
|
100
100
|
| --- | --- |
|
|
101
101
|
| `pending / current / complete / error`(유도) | 공개 |
|
|
102
102
|
| 순서(`position`/`total`) | 공개 |
|
|
103
|
-
|
|
|
103
|
+
| 지난 단계 누르기(`revisitable` + renderer `onStepPress`) | **공개(1.31.0)** — 2026-10-18 spint 작성 화면이 지난 단계를 눌러 돌아가려고 단계 레일을 직접 그렸다. resolver가 커서보다 앞선 단계에 `revisitable: true`를 붙이고, renderer는 제품이 `onStepPress`를 줄 때 그 단계만 버튼으로 만든다(칸 전체, 최소 44 `stepsRecipe.press.minTouchTarget`). 이전 판단("뒤로 가기는 별도 버튼")은 바로 앞 단계 행동에는 그대로 유효하다. |
|
|
104
|
+
| 앞으로 건너뛰기(현재·다음 단계 누르기) | **배제** — 검증 전 단계를 지나치고 단일 커서 유도를 흐린다. 커서 단계는 이미 있는 자리라 누를 이유가 없다. |
|
|
104
105
|
| vertical 방향 | **배제** — 두 사용처 모두 가로 진행바 하나만 필요해 antd 표면을 미리 복제하지 않는다. |
|
|
105
106
|
| dot type(압축 점 표현) | **배제** — 측정된 요구가 없다. numbered + check/error 마크 하나만 공개한다. |
|
|
106
107
|
| custom icon(스텝별 임의 아이콘 교체) | **배제** — 4개 상태 마크로 충분하고, 임의 아이콘 허용은 브랜드 표현의 일관성을 깨뜨린다. |
|
|
107
|
-
| navigation type(`navigation`/`inline` 등 antd variant) | **배제** — 위
|
|
108
|
+
| navigation type(`navigation`/`inline` 등 antd variant) | **배제** — 위 앞으로 건너뛰기·vertical 배제와 같은 이유로 단일 표현만 남긴다. |
|
|
108
109
|
|
|
109
110
|
## 검증 화면
|
|
110
111
|
|
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.30.0의 생성 manifest에서 읽은 정규(canonical) API 기준이다. 동반·선택형 확장은 개별 계약을 확인한다.
|
|
10
10
|
Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품 반영을 의미하지 않는다.
|
|
11
11
|
`분류`는 Storybook 제목 `<배포|실험>/<단계>/<분류>/<항목>`의 셋째 마디이고, 토큰·구성·화면은 Storybook 메뉴와 같은 순서다.
|
|
12
12
|
|
|
@@ -43,7 +43,7 @@ Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품
|
|
|
43
43
|
| [AspectRatio](components/aspect-ratio.md) | 레이아웃 | 이미지·동영상·지도처럼 늦게 로드되는 매체의 자리를 미리 잡아 레이아웃 흔들림을 막을 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
44
44
|
| [Asset](components/asset.md) | 데이터 표시 | 아이콘·이미지·Lottie·비디오를 같은 크기·모서리 규칙의 액자에 넣을 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
45
45
|
| [AuthProviderButton](components/auth-provider-button.md) | 동작 | Google·Kakao·Naver·Apple 소셜 로그인 버튼에 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
46
|
-
| [AuthScreenLayout](components/auth-screen-layout.md) | 레이아웃 | 로그인·가입 진입 화면의 배치에 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
46
|
+
| [AuthScreenLayout](components/auth-screen-layout.md) | 레이아웃 | 로그인·가입 진입 화면의 배치에 쓴다. | 1.12.1 (`safeAreaBottom`·링크 `target`/`rel`/`accessibilityHint` 1.28.1) | Web · Native | Web stable / Native stable | 배포 |
|
|
47
47
|
| [Avatar](components/avatar.md) | 데이터 표시 | 사람·계정을 사진 또는 이니셜로 나타낼 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
48
48
|
| [Badge](components/badge.md) | 데이터 표시 | 항목의 상태나 분류를 짧은 글자 하나로 붙일 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
49
49
|
| [BezierEditor](components/bezier-editor.md) | 구성/직접 조작과 모션 | CSS `cubic-bezier` 이징 네 좌표를 슬라이더로 편집하고 곡선과 움직임 미리 보기를 함께 보여 줄 때 쓴다. | 1.21.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
@@ -57,8 +57,9 @@ Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품
|
|
|
57
57
|
| [Carousel](components/carousel.md) | 데이터 표시 | 한 번에 카드 하나만 보이고 사용자가 순서대로 넘겨 보는 유한한 묶음에 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
58
58
|
| [Celebration](components/celebration.md) | 구성/직접 조작과 모션 | 목표 달성, 첫 완료처럼 드물게 일어나는 성공 순간에 한 번 터지는 색종이 효과에 쓴다. | 1.12.1 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
59
59
|
| [Chart](components/chart.md) | 데이터 표시 | 수치의 흐름·비교·몫·모양·관계를 그림으로 읽게 할 때 쓴다. | 1.21.0 | Web · Native | Web beta / Native beta | 배포 |
|
|
60
|
-
| [
|
|
61
|
-
| [
|
|
60
|
+
| [ChatDateSeparator](components/chat-date-separator.md) | 데이터 표시 | 대화 타임라인에서 날짜(또는 오래 쉰 뒤의 시각)가 바뀌는 자리에 가운데 정렬 구분 줄을 둘 때 쓴다. | 미게시(1.30.0 이후) | Web · Native | Web beta / Native beta | 실험 |
|
|
61
|
+
| [ChatMessage](components/chat-message.md) | 구성/정보 표시 | DM·대화 타임라인의 메시지 한 개에 쓴다. | 1.17.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
62
|
+
| [ChatScreen](components/chat-screen.md) | 화면/소통 | DM·대화방처럼 헤더, 메시지 타임라인, 하단 작성창으로 이루어진 화면 한 장에 쓴다. | 1.17.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
62
63
|
| [Checkbox](components/checkbox.md) | 입력 | 독립된 예/아니오 하나를 고르는 항목에 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
63
64
|
| [CheckboxGroup](components/checkbox-group.md) | 입력 | 한 질문에 대한 여러 선택지 중 0개 이상을 고르게 할 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
64
65
|
| [Chip](components/chip.md) | 입력 | 누를 수 있는 작은 pill이다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
@@ -68,9 +69,9 @@ Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품
|
|
|
68
69
|
| [ColorPicker](components/color-picker.md) | 입력 | 사용자가 콘텐츠 색(라벨 색, 태그 색, 테마 편집기의 사용자 값 등)을 sRGB HEX로 고르는 폼 입력에 쓴다. | 1.12.1 | Web | Web stable / Native unsupported | 배포 |
|
|
69
70
|
| [Combobox](components/combobox.md) | 입력 | 주어진 목록에서 하나를 고르는데 목록이 길어 입력으로 좁혀야 할 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
70
71
|
| [CommandPalette](components/command-palette.md) | 오버레이 | ⌘K 스타일로 앱 전체의 **행동**을 검색해 실행하는 모달에 쓴다. | 1.12.1 | Web | Web stable / Native unsupported | 배포 |
|
|
71
|
-
| [CommentThreadRow](components/comment-thread-row.md) | — | 가상화 목록(FlatList·가상 스크롤러)처럼 제품이 댓글 목록을 직접 그려야 할 때 댓글 한 행을 그린다. | 1.23.0 | Web · Native |
|
|
72
|
-
| [CommentThreadScreen](components/comment-thread-screen.md) | 화면/소통 | 게시물·콘텐츠 아래의 댓글 화면 한 장에 쓴다. | 1.17.1 | Web · Native |
|
|
73
|
-
| [CompositionLayout](components/composition-layout.md) | 화면/설정 | 카드·패널·화면 본문 안의 콘텐츠 묶음에 제목·배지·행동·안내·본문·하단 영역이 필요할 때 쓴다. | 1.23.0 | Web · Native |
|
|
72
|
+
| [CommentThreadRow](components/comment-thread-row.md) | — | 가상화 목록(FlatList·가상 스크롤러)처럼 제품이 댓글 목록을 직접 그려야 할 때 댓글 한 행을 그린다. | 1.23.0 | Web · Native | Web stable / Native stable | 실험 |
|
|
73
|
+
| [CommentThreadScreen](components/comment-thread-screen.md) | 화면/소통 | 게시물·콘텐츠 아래의 댓글 화면 한 장에 쓴다. | 1.17.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
74
|
+
| [CompositionLayout](components/composition-layout.md) | 화면/설정 | 카드·패널·화면 본문 안의 콘텐츠 묶음에 제목·배지·행동·안내·본문·하단 영역이 필요할 때 쓴다. | 1.23.0 | Web · Native | Web stable / Native stable | 배포 |
|
|
74
75
|
| [Container](components/container.md) | 레이아웃 | 화면 본문의 최대 폭과 좌우(논리 방향) 여백을 맞출 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
75
76
|
| [ContentTransition](components/content-transition.md) | 시각 효과 | 같은 자리의 내용이 상태에 따라 바뀔 때(필터 결과 패널, 단계별 본문) 새 내용이 짧게 나타나도록 감싼다. | 1.12.1 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
76
77
|
| [ContextMenu](components/context-menu.md) | 탐색 | Web에서 제품이 소유한 영역(카드·목록 행·캔버스)의 우클릭·길게 누르기·Shift+F10에 명령 목록을 띄울 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native unsupported | 배포 |
|
|
@@ -85,7 +86,7 @@ Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품
|
|
|
85
86
|
| [DesignSystemProvider](components/design-system-provider.md) | 기반 기능 | 앱 루트에 한 번 둔다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
86
87
|
| [Dialog](components/dialog.md) | 오버레이 | 화면 흐름을 잠시 멈추고 사용자의 주의가 필요한 **짧은 작업**에 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
87
88
|
| [Divider](components/divider.md) | 레이아웃 | 서로 다른 내용 묶음 사이에 얇은 구분선이 필요할 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
88
|
-
| [EditorScreen](components/editor-screen.md) | 화면/콘텐츠 | 글쓰기·프로필 수정처럼 한 화면 전체가 편집 흐름일 때 쓴다. | 1.17.1 | Web · Native |
|
|
89
|
+
| [EditorScreen](components/editor-screen.md) | 화면/콘텐츠 | 글쓰기·프로필 수정처럼 한 화면 전체가 편집 흐름일 때 쓴다. | 1.17.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
89
90
|
| [EffectSurface](components/effect-surface.md) | 시각 효과 | 환영·온보딩·빈 히어로처럼 분위기를 주는 배경이 필요할 때 내용 뒤에 장식 레이어(mesh·glow·grain)를 깐다. | 1.12.1 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
90
91
|
| [EmptyState](components/empty-state.md) | 상태와 알림 | 목록이 비었거나 검색 결과가 0건이라 **아직 없음**을 알릴 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
91
92
|
| [EventAttendanceCard](components/event-attendance-card.md) | 구성/선택과 필터 | 행사·모임 카드에서 일정, 참석자 수, 참석자 목록을 보여 주고 참석 응답(참석·미정·불참 등)과 캘린더 추가를 실제 요청으로 처리할 때 쓴다. | 1.21.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
@@ -99,9 +100,9 @@ Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품
|
|
|
99
100
|
| [Grid](components/grid.md) | 레이아웃 | 카드·타일처럼 같은 모양의 자식을 창 크기에 따라 열 수를 바꿔 배치할 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
100
101
|
| [Heading](components/heading.md) | 글자와 아이콘 | 자리를 모르는 제목 글자 하나가 필요할 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
101
102
|
| [HistogramExplorer](components/histogram-explorer.md) | 구성/정보 표시 | 실제 관측값 배열의 분포를 동폭 구간 막대로 보여 주고, 사용자가 구간 수를 바꿔 볼 때 쓴다. | 1.21.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
102
|
-
| [Icon](components/icon.md) | 글자와 아이콘 | HJM semantic 이름(`search`, `back`, `chevronEnd`, `notifications` 등
|
|
103
|
+
| [Icon](components/icon.md) | 글자와 아이콘 | HJM semantic 이름(`search`, `back`, `chevronEnd`, `notifications` 등 47개)으로 고르는 그림 기호에 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
103
104
|
| [IconButton](components/icon-button.md) | 동작 | 보이는 글자 없이 아이콘만으로 표시하는 행동에 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
104
|
-
| [IconTile](components/icon-tile.md) | — | 프로필·런처 격자의 아이콘 위/제목 아래 항목에 쓴다. | 1.26.0 | Web · Native |
|
|
105
|
+
| [IconTile](components/icon-tile.md) | — | 프로필·런처 격자의 아이콘 위/제목 아래 항목에 쓴다. | 1.26.0 | Web · Native | Web stable / Native stable | 실험 |
|
|
105
106
|
| [Image](components/image.md) | 데이터 표시 | 원본 크기를 아는 사진·차트 이미지를 로드 전에 자리를 잡아 두고, 실패해도 의미를 잃지 않게 보여 줄 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
106
107
|
| [ImageChoiceGroup](components/image-choice-group.md) | 화면/계정 | 아바타 얼굴, 프로필 사진, 모음에 넣을 사진처럼 **그림을 보고 고르는** 단일·다중 선택에 쓴다. | 미게시(1.26.1 이후) | Web · Native | Web beta / Native beta | 배포 |
|
|
107
108
|
| [ImageComparison](components/image-comparison.md) | 데이터 표시 | 같은 좌표와 비율의 두 이미지를 겹쳐 변화량을 비교할 때 쓴다. | 1.14.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
@@ -115,34 +116,35 @@ Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품
|
|
|
115
116
|
| [Layout](components/layout.md) | 레이아웃 | 앱의 상시 골격(header · sidebar · main · footer)을 한 번 세울 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
116
117
|
| [Link](components/link.md) | 동작 | 사용자가 복사하거나 새 탭으로 열 수 있는 **목적지**로 이동할 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
117
118
|
| [List](components/list.md) | 데이터 표시 | 이미 다 불러온, 개수가 많지 않은 행들을 이름 있는 목록 하나로 묶을 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
118
|
-
| [ListDetailScreen](components/list-detail-screen.md) | 화면/콘텐츠 | 목록 화면에서 한 항목의 상세를 같은 화면 안에서 열고, 뒤로 오면 목록의 입력·스크롤이 그대로 남아야 할 때 쓴다. | 1.17.1 | Web · Native |
|
|
119
|
+
| [ListDetailScreen](components/list-detail-screen.md) | 화면/콘텐츠 | 목록 화면에서 한 항목의 상세를 같은 화면 안에서 열고, 뒤로 오면 목록의 입력·스크롤이 그대로 남아야 할 때 쓴다. | 1.17.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
119
120
|
| [ListRow](components/list-row.md) | 데이터 표시 | 목록의 한 줄에 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
120
121
|
| [LoadMore](components/load-more.md) | 탐색 | 이미 그린 항목을 그대로 둔 채 목록 끝에서 다음 페이지를 요청하는 footer에 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
121
122
|
| [Masonry](components/masonry.md) | 레이아웃 | 높이가 서로 다른 카드(사진 피드, 핀보드, 갤러리)를 여러 열에 빈틈없이 쌓을 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
122
|
-
| [MediaSelectionScreen](components/media-selection-screen.md) | 화면/콘텐츠 | 고른 사진·영상을 큰 썸네일 격자로 보여 주고, 각 항목의 업로드 상태·재시도·취소·순서 이동·삭제와 "추가"·"완료" 행동을 한 화면에 묶을 때 쓴다. | 1.17.1 | Web · Native |
|
|
123
|
+
| [MediaSelectionScreen](components/media-selection-screen.md) | 화면/콘텐츠 | 고른 사진·영상을 큰 썸네일 격자로 보여 주고, 각 항목의 업로드 상태·재시도·취소·순서 이동·삭제와 "추가"·"완료" 행동을 한 화면에 묶을 때 쓴다. | 1.17.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
123
124
|
| [MediaTransport](components/media-transport.md) | 구성/직접 조작과 모션 | 제품의 실제 오디오·영상 엔진에 재생·일시 정지·유한 길이 탐색 제어를 붙일 때 쓴다. | 1.21.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
124
125
|
| [Mentions](components/mentions.md) | 입력 | 여러 줄 입력 중 `@`(사람)·`#`(해시태그) 같은 트리거를 치면 후보를 띄우고, 고른 후보를 트리거부터 커서까지 자리에 넣고 공백 하나를 붙이는 입력에 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
125
126
|
| [Menu](components/menu.md) | 탐색 | 트리거 버튼을 누르면 뜨는 **항목 목록**에 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
126
127
|
| [Menubar](components/menubar.md) | 탐색 | 데스크톱 Web 앱 상단에 항상 같은 자리에 있는 가로 메뉴 막대(파일·편집·보기)에 쓴다. | 1.12.1 | Web | Web stable / Native unsupported | 배포 |
|
|
127
|
-
| [MessageComposer](components/message-composer.md) | 구성/입력과 작성 | 채팅·DM·댓글 입력창에 쓴다. | 1.17.1 | Web · Native |
|
|
128
|
-
| [ModerationScreen](components/moderation-screen.md) | 화면/소통 | 게시물·댓글·사용자 **신고** 화면에 쓴다. | 1.17.1 | Web · Native |
|
|
128
|
+
| [MessageComposer](components/message-composer.md) | 구성/입력과 작성 | 채팅·DM·댓글 입력창에 쓴다. | 1.17.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
129
|
+
| [ModerationScreen](components/moderation-screen.md) | 화면/소통 | 게시물·댓글·사용자 **신고** 화면에 쓴다. | 1.17.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
129
130
|
| [Notice](components/notice.md) | 상태와 알림 | 화면 흐름 안 **제자리에 남아 있는** 상태 알림에 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
130
|
-
| [NotificationInboxScreen](components/notification-inbox-screen.md) | 화면/소통 | 알림함 화면 전체 틀에 쓴다. | 1.17.1 | Web · Native |
|
|
131
|
-
| [NotificationItem](components/notification-item.md) | 구성/정보 표시 | 알림함의 알림 한 행에 쓴다. | 1.17.1 | Web · Native |
|
|
132
|
-
| [NotificationRow](components/notification-row.md) | — | 알림 목록에서 아바타, 유형 배지, 미리보기, 시간, 읽지 않음 표시, 선택적 썸네일을 나란히 배치한다. | 1.26.0 | Web · Native |
|
|
131
|
+
| [NotificationInboxScreen](components/notification-inbox-screen.md) | 화면/소통 | 알림함 화면 전체 틀에 쓴다. | 1.17.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
132
|
+
| [NotificationItem](components/notification-item.md) | 구성/정보 표시 | 알림함의 알림 한 행에 쓴다. | 1.17.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
133
|
+
| [NotificationRow](components/notification-row.md) | — | 알림 목록에서 아바타, 유형 배지, 미리보기, 시간, 읽지 않음 표시, 선택적 썸네일을 나란히 배치한다. | 1.26.0 | Web · Native | Web stable / Native stable | 실험 |
|
|
133
134
|
| [NumberField](components/number-field.md) | 입력 | 범위가 정해진 **정확한 수 하나**를 입력받을 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
134
|
-
| [OnboardingScreen](components/onboarding-screen.md) | 화면/소개 | 첫 실행 소개·초기 설정처럼 **몇 단계를 차례로 넘기는 화면**에 쓴다. | 1.14.0 | Web · Native |
|
|
135
|
+
| [OnboardingScreen](components/onboarding-screen.md) | 화면/소개 | 첫 실행 소개·초기 설정처럼 **몇 단계를 차례로 넘기는 화면**에 쓴다. | 1.14.0 | Web · Native | Web stable / Native stable | 배포 |
|
|
135
136
|
| [OtpField](components/otp-field.md) | 입력 | 문자·메일로 받은 **숫자 인증번호**를 칸 모양으로 입력받을 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
136
137
|
| [OverviewScreen](components/overview-screen.md) | 레이아웃 | 같은 데이터와 기능을 유지하면서 테마별 행·카드·격자와 도구 배치를 선택하는 목록 화면에 쓴다. | 1.15.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
138
|
+
| [PageIndicator](components/page-indicator.md) | 탐색 | 제품이 직접 만든 가로 페이저(Native 페이징 `FlatList`, Web scroll-snap 줄) 아래에 지금 몇 번째 페이지인지 점으로 보여 주고, 점을 눌러 그 페이지로 옮길 때 쓴다. | 미게시(1.30.0 이후) | Web · Native | Web beta / Native beta | 실험 |
|
|
137
139
|
| [Pagination](components/pagination.md) | 탐색 | 총 개수(또는 총 페이지 수)가 정해진 결과 집합에서 사용자가 **임의의 페이지로 바로 이동**해야 할 때 Web·Native에서 쓴다. | 1.12.1 | Web · Native | Web stable / Native beta | 배포 |
|
|
138
140
|
| [PasswordField](components/password-field.md) | 입력 | 비밀번호를 입력받고, 필요할 때만 값을 눈으로 확인하게 할 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
139
141
|
| [PasswordRulesField](components/password-rules-field.md) | 구성/입력과 작성 | 새 비밀번호 입력 아래에 제품이 정한 규칙의 충족 개수와 규칙별 상태를 함께 보여 줄 때 쓴다. | 1.21.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
140
|
-
| [PermissionScreen](components/permission-screen.md) | 화면/소개 | 카메라·위치·알림 같은 권한이 **왜 필요한지 설명하고 다음 행동을 고르게 하는** 화면에 쓴다. | 1.17.1 | Web · Native |
|
|
141
|
-
| [PhotoSourceSheet](components/photo-source-sheet.md) | 구성/선택과 필터 | 사진 버튼 하나에서 **앨범에서 고르기 / 촬영하기**를 고르게 할 때 쓴다. | 1.17.1 | Web · Native |
|
|
142
|
+
| [PermissionScreen](components/permission-screen.md) | 화면/소개 | 카메라·위치·알림 같은 권한이 **왜 필요한지 설명하고 다음 행동을 고르게 하는** 화면에 쓴다. | 1.17.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
143
|
+
| [PhotoSourceSheet](components/photo-source-sheet.md) | 구성/선택과 필터 | 사진 버튼 하나에서 **앨범에서 고르기 / 촬영하기**를 고르게 할 때 쓴다. | 1.17.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
142
144
|
| [Popover](components/popover.md) | 오버레이 | 트리거에 붙어 뜨는 비모달 표면 안에 **포커스를 받는 임의 콘텐츠**를 둘 때 쓴다. | 1.12.1 | Web | Web stable / Native unsupported | 배포 |
|
|
143
145
|
| [PricingChoice](components/pricing-choice.md) | 구성/선택과 필터 | 요금제·결제 주기 중 하나를 고르고, 선택한 실제 가격과 혜택을 확인한 뒤 [계속]으로 제품 결제 흐름을 시작할 때 쓴다. | 1.21.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
144
|
-
| [ProfileScreen](components/profile-screen.md) | 화면/계정 | 내 프로필(또는 계정) 화면 틀에 쓴다. | 1.17.1 | Web · Native |
|
|
145
|
-
| [ProfileSummary](components/profile-summary.md) | — | 프로필의 아바타·이름·배지·통계 수치·행동을 구성한다. | 1.26.0 | Web · Native |
|
|
146
|
+
| [ProfileScreen](components/profile-screen.md) | 화면/계정 | 내 프로필(또는 계정) 화면 틀에 쓴다. | 1.17.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
147
|
+
| [ProfileSummary](components/profile-summary.md) | — | 프로필의 아바타·이름·배지·통계 수치·행동을 구성한다. | 1.26.0 | Web · Native | Web stable / Native stable | 실험 |
|
|
146
148
|
| [Progress](components/progress.md) | 상태와 알림 | 작업이 얼마나 진행됐는지 보여 줄 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
147
149
|
| [ProgressiveBlur](components/progressive-blur.md) | 시각 효과 | 스크롤 영역의 바깥에 더 내용이 있음을 알리거나 장식 이미지 가장자리를 흐릴 때 쓴다. | 1.14.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
148
150
|
| [QRCode](components/qr-code.md) | 데이터 표시 | 문자열(초대 링크, 연결 코드, 결제·체크인 URL)을 다른 기기의 카메라로 스캔하게 할 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
@@ -154,14 +156,14 @@ Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품
|
|
|
154
156
|
| [ReplyMessage](components/reply-message.md) | 구성/입력과 작성 | 대화 타임라인의 메시지에 실제 메시지 id를 묶은 답장 동작을 붙일 때 쓴다. | 1.21.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
155
157
|
| [Result](components/result.md) | 상태와 알림 | 사용자 행동 뒤 흐름이 **끝난** 화면에 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
156
158
|
| [SavedItemsScreen](components/saved-items-screen.md) | 화면/콘텐츠 | 저장한 이미지·게시물을 컬렉션 표지 → 사진 격자 → 상세 순서로 탐색할 때 쓴다. | 1.17.1 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
157
|
-
| [ScreenLayout](components/screen-layout.md) | 화면/화면 틀과 도구 | 한 라우트 화면의 뼈대가 필요할 때 쓴다. | 1.17.1 | Web · Native |
|
|
159
|
+
| [ScreenLayout](components/screen-layout.md) | 화면/화면 틀과 도구 | 한 라우트 화면의 뼈대가 필요할 때 쓴다. | 1.17.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
158
160
|
| [SearchField](components/search-field.md) | 입력 | 목록·화면 안에서 검색어를 입력받을 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
159
|
-
| [SearchScreen](components/search-screen.md) | 화면/검색 | 검색어 입력, 필터, 최근 검색, 결과 목록을 갖춘 검색 화면 전체에 쓴다. | 1.17.1 | Web · Native |
|
|
161
|
+
| [SearchScreen](components/search-screen.md) | 화면/검색 | 검색어 입력, 필터, 최근 검색, 결과 목록을 갖춘 검색 화면 전체에 쓴다. | 1.17.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
160
162
|
| [Section](components/section.md) | 레이아웃 | 화면 안의 내용 묶음에 제목·설명·머리 행동(“모두 보기”, “편집”)을 붙일 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
161
163
|
| [SegmentedControl](components/segmented-control.md) | 입력 | 2~4개의 짧은 보기 중 **항상 하나가 선택된** 전환에 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
162
164
|
| [Select](components/select.md) | 입력 | 폼 한 칸에서 여러 선택지 중 하나를 고르게 할 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
163
165
|
| [SelectionActionBar](components/selection-action-bar.md) | 구성/선택과 필터 | 목록에서 여러 항목을 고른 뒤 보관·삭제 같은 같은 행동을 한 번에 실행하고, 방금 확정된 작업만 되돌릴 때 쓴다. | 1.21.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
164
|
-
| [SettingsScreen](components/settings-screen.md) | 화면/설정 | 앱의 설정 화면 전체에 쓴다. | 1.17.1 | Web · Native |
|
|
166
|
+
| [SettingsScreen](components/settings-screen.md) | 화면/설정 | 앱의 설정 화면 전체에 쓴다. | 1.17.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
165
167
|
| [SharedTransitionElement](components/shared-transition-element.md) | 구성/직접 조작과 모션 | 목록의 카드(사진·썸네일)를 눌러 상세 화면으로 갈 때, 같은 요소가 두 화면 사이에서 확대·축소되어 이어지는 공유 요소 전환에 쓴다. | 1.12.1 | Native | 개별 API 계약 참조 | 배포 |
|
|
166
168
|
| [SharedTransitionScreen](components/shared-transition-screen.md) | 구성/직접 조작과 모션 | `createHjmTransitionStack()`으로 만든 stack에서 공유 요소 전환을 쓸 때, **각 라우트 본문**을 감싼다. | 1.12.1 | Native | 개별 API 계약 참조 | 배포 |
|
|
167
169
|
| [Sheet](components/sheet.md) | 오버레이 | 현재 화면 위에 모달로 띄우는 보조 작업 패널에 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
@@ -203,6 +205,7 @@ Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품
|
|
|
203
205
|
| [TransferList](components/transfer-list.md) | 입력 | 한 항목 집합을 두 목록으로 나누고 사용자가 항목을 오가게 할 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
204
206
|
| [TransferTask](components/transfer-task.md) | 구성/피드백과 복구 | 업로드·다운로드·동기화처럼 실제 전송 계층이 진행량을 알려 주는 작업에 시작·취소·진행률·결과를 한 묶음으로 붙인다. | 1.21.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
205
207
|
| [Tree](components/tree.md) | 데이터 표시 | 깊이가 정해지지 않은 계층 데이터를 펼치고 접으며 탐색하고, 그 안에서 하나 또는 여럿을 고를 때 쓴다. | 1.12.1 | Web | Web stable / Native unsupported | 배포 |
|
|
208
|
+
| [TypingIndicator](components/typing-indicator.md) | 상태와 알림 | 대화 타임라인에서 상대가 지금 입력 중임을 보여 줄 때 쓴다. | 미게시(1.30.0 이후) | Web · Native | Web beta / Native beta | 실험 |
|
|
206
209
|
| [UploadItem](components/upload-item.md) | 데이터 표시 | 사용자가 고른 파일 **한 개**의 업로드 상태(대기·전송 중·완료·실패)를 한 행으로 보여 줄 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
207
210
|
| [VirtualList](components/virtual-list.md) | 데이터 표시 | 행 높이가 **모두 같은** 긴 목록(수백~수천 행)을 정해진 높이 안에서 스크롤할 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
208
211
|
| [VisuallyHidden](components/visually-hidden.md) | 기반 기능 | Web에서 화면에는 보이지 않지만 스크린 리더는 읽어야 하는 **문맥 문구**를 덧붙일 때 쓴다. | 1.12.1 | Web | Web stable / Native unsupported | 배포 |
|
package/docs/usage/SELECTION.md
CHANGED
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
| 예제 전용 도구(실패 예약 등) | "미리보기 도구" 캡션 아래 `Button size="small" tone="ghost"`로 분리 | 제품 행동과 같은 모양·폭 |
|
|
44
44
|
| 헤더 제목·추가 기능 | 제목은 기본 가운데(`ScreenLayout`·`TopBar`, 왼쪽 정렬은 선택), 추가 기능은 `actions`에 아이콘 버튼 1~2개로 오른쪽 위(`ScreenFlowAction.icon`, 넘치면 Menu) | 왼쪽 정렬 제목, 헤더의 글자 버튼(가운데 제목을 밀어냄), 본문에 흩어진 도구 버튼 |
|
|
45
45
|
| 도구성 행동(새로고침·추가·편집·삭제·공유·검색·필터·더보기) | `IconButton` + 아이콘, 글자는 `label`(보조기술 이름). HJM 화면은 아이콘 슬롯(`ScreenFlowAction.icon` 등) | 헤더·행·도구 막대의 글자 버튼 |
|
|
46
|
-
| 화면 나가기(뒤로·닫기·설정 나가기) | `ScreenLayout`(과 이를 쓰는 화면)
|
|
46
|
+
| 화면 나가기(뒤로·닫기·설정 나가기) | `ScreenLayout`(과 이를 쓰는 화면)·`AuthScreenLayout`의 `exit` — 헤더 시작 쪽 아이콘 버튼, 글자 없음. 단계형 작성의 앞 단계는 `EditorScreen` `stepBack`(1.31.0) | 본문·하단의 "나가기" 글자 버튼, 화면마다 다른 화살표, 로그인·작성 화면 위에 따로 얹은 `TopBar` |
|
|
47
47
|
| 버튼 묶음 간격 | 세로로 쌓으면 `gap="xs"`(8), 가로로 나란하면 `gap="sm"`(12) — `actionGroupRecipe` | 세로 버튼 사이 12 이상 |
|
|
48
48
|
| 간격 | `Stack`·`ScreenLayout`·recipe 간격 | 임의 `margin`·빈 `View` |
|
|
49
49
|
| 화면 진입 시 입력 포커스 | `ScreenLayout`(과 이를 쓰는 화면)·`AuthScreenLayout`·`Sheet`·`Dialog`의 `initialFocus`, 주 입력 지정은 칸의 `initialFocusTarget`([진입 포커스](components/screen-layout.md#진입-포커스)) | 앱별 `autoFocus`·지연 `ref.focus()`·단계 전환·검색 열기 뒤 `ref.focus()`, 대화·댓글 화면의 작성창 자동 포커스 |
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
- 상태: 배포
|
|
5
5
|
- 지원: Web · Native
|
|
6
6
|
- 적용: 1.12.1 (`safeAreaBottom`·링크 `target`/`rel`/`accessibilityHint` 1.28.1)
|
|
7
|
-
- 검토일: 2026-10-
|
|
7
|
+
- 검토일: 2026-10-18
|
|
8
8
|
- 근거: [로그인 화면 골격](../../auth-screen.md), [1.4 제품 채택 가이드](../../product-adoption-1.4.md), recipe `authScreenRecipe`(`src/auth-screen.ts`), 포트폴리오 상위 기준 루트 `docs/LOGIN_SCREEN_STANDARD.md`(LS)
|
|
9
9
|
- 스토리북: `배포/컴포넌트/레이아웃/로그인 화면`
|
|
10
10
|
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
| --- | --- |
|
|
22
22
|
| 제공자 버튼 하나하나 | [AuthProviderButton](auth-provider-button.md) (`main` 슬롯에 넣는다) |
|
|
23
23
|
| 동의 체크 항목 | [Agreement](agreement.md) (`footer`나 가입 단계에 넣는다) |
|
|
24
|
+
| 로그인 위에 "로그인" 제목·뒤로/닫기만 두려고 바깥에 얹는 [TopBar](top-bar.md) | 이 레이아웃의 `title`·`exit`(1.31.0) |
|
|
24
25
|
|
|
25
26
|
## 공개 이름과 import
|
|
26
27
|
|
|
@@ -54,6 +55,8 @@ import { AuthScreenFooter, AuthScreenHero, AuthScreenLayout } from "@hjmds/react
|
|
|
54
55
|
import { AuthScreenFooter, AuthScreenHero, AuthScreenLayout } from "@hjmds/react-native/auth-screen";
|
|
55
56
|
|
|
56
57
|
<AuthScreenLayout
|
|
58
|
+
title={t("auth.title")} // 머리 띠의 route 이름(선택)
|
|
59
|
+
exit={{ kind: "close", label: t("common.close"), disabled: pending, onPress: close }} // 헤더 시작 쪽 닫기(선택)
|
|
57
60
|
mainCard
|
|
58
61
|
{...(pending ? { pendingLabel: t("auth.pending") } : {})}
|
|
59
62
|
hero={<AuthScreenHero mark={<ProductMark />} title={t("auth.tagline")} description={t("auth.description")} />}
|
|
@@ -71,6 +74,8 @@ import { AuthScreenFooter, AuthScreenHero, AuthScreenLayout } from "@hjmds/react
|
|
|
71
74
|
|
|
72
75
|
| prop | 값 | 기본값 | 설명 |
|
|
73
76
|
| --- | --- | --- | --- |
|
|
77
|
+
| `title` | 문자열 | — | 1.31.0. route 이름("로그인")을 [ScreenLayout](screen-layout.md) 가운데 정렬 머리와 같은 띠(최소 높이 52, `Heading` `level5`, 문서 수준 1)에 그린다. 공백만 있으면 `TypeError`. Web은 이때 `AuthScreenHero`의 기본 `headingLevel`이 2가 된다(route 이름이 h1) |
|
|
78
|
+
| `exit` | `ScreenExit`(`{ kind: "back" \| "close", label, onClick/onPress, disabled? }`) | — | 1.31.0. ScreenLayout·TopBar `exit`와 같은 아이콘 뒤로/닫기, 머리 띠 시작 끝. `label`은 보조기술 이름. `title` 없이 `exit`만 줘도 띠를 그린다 |
|
|
74
79
|
| `hero` · `main` | `ReactNode` | 필수 | 제품 마크·제목·설명 / 제공자 버튼 목록(진행 중에도 같은 목록) |
|
|
75
80
|
| `footer` | `ReactNode` | — | 동의 고지·정책 링크 |
|
|
76
81
|
| `density` | `regular` · `compact` | `regular` | 제품이 화면 높이를 보고 고른다. 간격·padding만 바뀐다 |
|
|
@@ -80,7 +85,7 @@ import { AuthScreenFooter, AuthScreenHero, AuthScreenLayout } from "@hjmds/react
|
|
|
80
85
|
| Web `as` | `main` · `section` | `main` | 최대 폭은 416이다 |
|
|
81
86
|
| `layoutStyle` | margin·width·flex·`alignSelf` | — | 바깥 배치 전용(Web·Native 모두) |
|
|
82
87
|
| `initialFocus` | `first-input` · `none` | `none` | 1.28.2. [ScreenLayout 진입 포커스](screen-layout.md#진입-포커스)와 같은 규칙. 로그인은 제공자 버튼이 주 행동이라 기본 `none`, 가입 닉네임 단계처럼 입력이 주 행동인 `main`만 `first-input`. 닉네임 단계가 같은 화면에서 나중에 나타나면 그 칸에 `initialFocusTarget`을 준다 |
|
|
83
|
-
| Native `testID` | `string` | — |
|
|
88
|
+
| Native `testID` | `string` | — | 본문 `ScrollView` 식별(머리 띠가 있어도 같은 `ScrollView`) |
|
|
84
89
|
| Native `safeAreaBottom` | 0 이상의 유한수 | `0` | 화면이 닿는 창 아래 가장자리의 safe area(`useSafeAreaInsets().bottom`, 이미 아래를 들인 host 안이면 0). 아래 여백이 `max(paddingBlock, inset)` — `regular` max(40, inset), `compact` max(20, inset) — 으로 한 번만 들어간다(ScreenLayout과 같은 규칙, 합산 없음). 키보드가 열리면 paddingBlock만. 음수·무한대는 `RangeError` |
|
|
85
90
|
| `AuthScreenHero` `title` · `eyebrow` · `description` · `mark` · `headingLevel` | 문자열 · `ReactNode` · `1`~`3` | `headingLevel` 1 | 제목은 필수이고 빈 문자열이면 `TypeError`. 밀도는 바깥 `AuthScreenLayout`을 따른다 |
|
|
86
91
|
| `AuthScreenFooter` `links` · `notice` · `children` | 링크 배열(1개 이상) · `ReactNode` | — | 빈 링크 목록·빈 라벨은 `TypeError`(LS-04: 약관 링크는 로그인 전 같은 화면에 있어야 한다). `children`은 링크 아래 제품 내용 |
|
|
@@ -95,8 +100,9 @@ import { AuthScreenFooter, AuthScreenHero, AuthScreenLayout } from "@hjmds/react
|
|
|
95
100
|
| 간격 | `regular` / `compact`: 바깥 좌우 `layout.pagePadding.regular` 20 / `.compact` 16, 바깥 위아래 `spacing.xxxl` 40 / `spacing.lg` 20, hero 안 `spacing.md` 16 / `spacing.xs` 8, hero↔main `spacing.xl` 24 / `spacing.md` 16, 위 블록↔footer 최소 `spacing.xl` 24 / `spacing.md` 16. mainCard 안쪽 `spacing.md` 16 | `authScreenRecipe.densities`·`mainCard` |
|
|
96
101
|
| 히어로 문구 | 마크 ↔ 문구 묶음은 hero 간격. eyebrow `label` 12/18·500·브랜드색, 아래 `spacing.xxs` 4 → 태그라인 `regular` `typography.heading` 24/32 · `compact` `titleLarge` 20/28, 굵기는 제목 단계 500, 기본 글자색, 실제 heading 요소(Native `header`) → 설명 `body` 14/20·400·보조색(`muted`), 위 `spacing.xs` 8 | `authScreenRecipe.hero`, `densities.*.titleVariant` |
|
|
97
102
|
| 동의 고지·정책 링크 | 고지 `caption` 11/16 흐린 색, 링크 줄과 `spacing.xxs` 4. 링크 `caption`·브랜드색·밑줄, 링크 사이 `linkGap` 8 + `·` + 8(보이는 글자 간격 약 19). 각 링크 높이 44(배경 없음), 가로 터치 폭은 구분점 앞까지 보이지 않게 넓힘(Web 가상 요소, Native `hitSlop`) | `authScreenRecipe.footer`, `.hjm-auth-screen__link` |
|
|
98
|
-
|
|
|
99
|
-
|
|
|
103
|
+
| 머리 띠(`title`·`exit`) | ScreenLayout 가운데 머리와 같다: 최소 높이 52(`screenHeaderRecipe.minHeight`), 위아래 `spacing.xxs` 4, 좌우 화면 gutter `spacing.md` 16(`screenPatternRecipe.padding`), 시작 끝 `exit`, 가운데 제목 `level5`(양옆 같은 폭 칸). 화면 가장자리까지 닿고(바깥 좌우 여백 밖), 원래 바깥 위 여백(`regular` 40 / `compact` 20)은 띠 아래로 옮겨진다. 스크롤하지 않는다(Native는 `ScrollView` 밖) | `screenHeaderRecipe`, `.hjm-auth-screen__header`, Native `AuthScreenHeader` |
|
|
104
|
+
| 순서·정렬 | 위→아래 (머리 띠) → hero(가운데 정렬 문구) → main(폭 꽉 채움) → footer(동의 고지·정책 링크). 위 블록은 남는 세로 공간에서 가운데, footer는 바닥에 붙는다. 진행 중 로딩은 main 카드 가운데에 겹친다 | `.hjm-auth-screen__block`(`justify-content: center`), `.hjm-auth-screen__pending` |
|
|
105
|
+
| 고정·스크롤 | 머리 띠만 고정이고 나머지는 넘치면 함께 스크롤한다. 위 safe area는 host(SafeAreaView top 등, ScreenLayout과 같다)가, 아래는 레이아웃이 `max(paddingBlock, 하단 inset)`으로 맡는다 — Web `env(safe-area-inset-bottom)`, Native `safeAreaBottom`. Native 키보드 inset은 자동 조정이 처리한다 | `react-native/src/auth-screen.tsx`, `.hjm-auth-screen` |
|
|
100
106
|
| 좁은 폭·큰 글자 | 키 작은 화면·큰 글자에서는 `compact`를 고른다. 그래도 넘치면 스크롤되며 footer는 맨 아래로 밀린다 | `authScreenRecipe.densities` |
|
|
101
107
|
|
|
102
108
|
```text
|
|
@@ -136,7 +142,8 @@ import { AuthScreenFooter, AuthScreenHero, AuthScreenLayout } from "@hjmds/react
|
|
|
136
142
|
|
|
137
143
|
| 항목 | Web | Native |
|
|
138
144
|
| --- | --- | --- |
|
|
139
|
-
| 뿌리 요소 | `<main>` 또는 `as="section"`, ref
|
|
145
|
+
| 뿌리 요소 | `<main>` 또는 `as="section"`, ref 전달. 머리 띠는 그 안의 `<header>` | `ScrollView`. `title`·`exit`가 있으면 `View`(머리 띠 + `ScrollView`)가 뿌리이고 `layoutStyle`은 그 `View`에 간다 |
|
|
146
|
+
| 머리 띠 위 safe area | 다루지 않는다(브라우저·host) | host가 SafeAreaView top으로 준다. TopBar `safeAreaTop`에 해당하는 prop은 없다(ScreenLayout과 같다) |
|
|
140
147
|
| 배치·식별 | `layoutStyle`, `className`, HTML 속성 | `layoutStyle`, `testID` |
|
|
141
148
|
| 진행 중 숨김 | `inert` + `aria-hidden` + `visibility: hidden`, 로딩은 `role="status"` | 터치·접근성 제외 + 불투명도 0, 로딩은 `progressbar` + live region |
|
|
142
149
|
| 키보드 | 브라우저 기본 | 키보드 inset 자동 조정, 탭 유지(`handled`), iOS `interactive`·Android `on-drag` 내리기 |
|
|
@@ -145,6 +152,8 @@ import { AuthScreenFooter, AuthScreenHero, AuthScreenLayout } from "@hjmds/react
|
|
|
145
152
|
|
|
146
153
|
## 함정
|
|
147
154
|
|
|
155
|
+
- `title`·`exit`를 쓰면 바깥에 얹던 TopBar·제품 헤더를 지운다. 둘 다 두면 머리가 두 줄이 된다. Native에서 host TopBar가 맡던 위 safe area(`safeAreaTop`)는 host의 SafeAreaView top으로 옮긴다.
|
|
156
|
+
|
|
148
157
|
- Native에서 아래 홈 인디케이터를 `SafeAreaView edges={['bottom']}`·`paddingBottom: insets.bottom` 래퍼로 들이지 말고 `safeAreaBottom`으로 넘긴다. 둘을 같이 주면 inset + paddingBlock이 다시 더해진다.
|
|
149
158
|
- 1.28.0까지 Native는 iOS `contentInsetAdjustmentBehavior="automatic"`으로 위·아래 safe area를 iOS에서만 더했다. 1.28.1부터 위는 host, 아래는 `safeAreaBottom`이다. 위 safe area를 아무도 들이지 않던 화면은 host에서 TopBar `safeAreaTop`이나 SafeAreaView top으로 들인다.
|
|
150
159
|
- Native는 자체로 키보드 스크롤 여백을 준다. 부모가 다시 keyboard avoidance를 하면 여백이 중복될 수 있으니
|
|
@@ -159,6 +168,7 @@ import { AuthScreenFooter, AuthScreenHero, AuthScreenLayout } from "@hjmds/react
|
|
|
159
168
|
|
|
160
169
|
## 근거
|
|
161
170
|
|
|
171
|
+
- `title`·`exit`(1.31.0): 2026-10-18 앱 감사에서 utilverse·burntok 로그인이 "로그인" 제목과 뒤로/닫기만을 위해 레이아웃 위에 TopBar(burntok은 제품 `AppScreenHeader` 래퍼)를 따로 얹어, 로그인만 다른 머리 높이·제목 단계를 가졌다. 앱마다 띠를 조립하지 않도록 ScreenLayout의 `exit` 버튼과 가운데 머리 recipe를 그대로 쓰는 띠를 이 레이아웃이 소유한다. Native에서 TopBar를 가져오면 `navigation` 그래프 전체가 로그인 subpath에 들어오므로(ScreenLayout이 TopBar를 쓰지 않는 같은 이유) 띠는 `screenHeaderRecipe`로 그린다.
|
|
162
172
|
- `safeAreaBottom`·링크 `target`/`rel`/`accessibilityHint`(1.28.1): 2026-10-17 1.28 채택에서 다에리·utilverse·spint가 레이아웃을 각자 아래 inset 래퍼로 감쌌고(iOS는 자동 content inset이 이미 더해 합산, Android는 아무도 안 들여 spint가 Android만 덧붙임), 다에리 웹은 정책 문서 새 탭 열기(`target="_blank"`)를, spint는 "브라우저에서 열림" 접근성 안내를 링크 슬롯이 없어 잃었다. ScreenLayout의 max 규칙을 그대로 쓰고 링크에 같은 의미의 보조 안내·anchor 속성을 연다.
|
|
163
173
|
- `AuthScreenHero`·`AuthScreenFooter`와 히어로·링크 수치: 2026-10-17 사용자 피드백("굵기랑 크기 줄여", "간격 줄여").
|
|
164
174
|
예제가 히어로에 `Top large`(display 32/40·600)를 넣어 402 폭에서 태그라인이 두 줄이 됐고, 정책 링크는 ghost Button
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
- 상태: 배포
|
|
5
5
|
- 지원: Web · Native
|
|
6
6
|
- 적용: 1.12.1
|
|
7
|
-
- 검토일: 2026-10-
|
|
7
|
+
- 검토일: 2026-10-18
|
|
8
8
|
- 근거: [BottomNavigation](../../bottom-navigation.md), recipe `bottomNavigationRecipe`
|
|
9
9
|
- 스토리북: `배포/컴포넌트/탐색/하단 탐색`
|
|
10
10
|
|
|
@@ -28,6 +28,8 @@
|
|
|
28
28
|
| 이름 | 역할 | Web | Native |
|
|
29
29
|
| --- | --- | --- | --- |
|
|
30
30
|
| `BottomNavigation` | 기본 | `@hjmds/react`, `/navigation` | `@hjmds/react-native`, `/navigation`, `/top-bar` |
|
|
31
|
+
| `BottomNavigationInsetProvider` | 보조(막대가 덮는 높이를 화면에 전달) | `@hjmds/react`, `/navigation` | `@hjmds/react-native`, `/navigation`, `/top-bar` |
|
|
32
|
+
| `useBottomNavigationInset` | 보조(덮인 높이 읽기) | `@hjmds/react`, `/navigation` | `@hjmds/react-native`, `/navigation`, `/top-bar` |
|
|
31
33
|
|
|
32
34
|
## 최소 사용 예
|
|
33
35
|
|
|
@@ -76,6 +78,9 @@ import { BottomNavigation } from "@hjmds/react-native/navigation";
|
|
|
76
78
|
| `configuration.labels` | `visible` · `hidden` | `visible` | `hidden`은 아이콘만 남기고 목적지 이름을 화면에서 뺀다. 이름은 항목의 접근성 이름으로 그대로 읽힌다. 아이콘을 칸 가운데에 둔다. 선택 표시는 아이콘 굵기·확대(와 제품 선택 표시)만 남으므로 의도한 아이콘 전용 막대에만 쓴다 |
|
|
77
79
|
| `configuration.selection` | `emphasis` · `tile` | `emphasis` | `tile`은 선택 목적지 전체를 카드로 채운다. floating·equal·visible labels 전용 |
|
|
78
80
|
| `configuration.surface` | `flat` · `raised` | `flat` | `raised`는 `selection: "tile"` 전용 두께 있는 막대다. surfaceAlt 바탕·borderControl 옆면(4)·선택 카드 옆면(3) |
|
|
81
|
+
| `configuration.iconSize` | `standard` · `large` · `xlarge` | `standard` | 1.31.0 추가. `standard`는 density 글리프(`regular` 24 · `compact` 20). `large` 44 · `xlarge` 52는 앱 아이콘 같은 그림을 `renderIcon`으로 넣는 자리다(`bottomNavigationRecipe.iconSizes`). `renderIcon`이 받은 `size`로 그린다 |
|
|
82
|
+
| 항목 `prominent` | `boolean` | `false` | 1.31.0 추가. 가운데 목적지를 막대 위로 솟은 브랜드 원(지름 56, 글리프 28)으로 그린다. 선택·재선택·router 소유는 다른 항목과 같다. 홀수 개 항목의 정가운데 하나만, `distribution: "equal"`·`bar`/`floating`·`selection: "emphasis"`에서만 허용(위반 시 오류) |
|
|
83
|
+
| Native `placement` | `inline` · `overlay` | `inline` | 1.31.0 추가. `overlay`는 막대를 host 아래쪽에 겹쳐 고정하고(본문이 떠 있는 막대 뒤로 스크롤) 덮는 높이를 `BottomNavigationInsetProvider`에 알린다. `inline`은 자기 높이를 차지하므로 알리지 않는다 |
|
|
79
84
|
| `primaryAction` | `ReactNode`(Button/IconButton) | — | `configuration` 밖의 별도 prop. 생성 같은 비목적지 행동이며 `center-gap` 또는 `capsule`과 짝짓는다 |
|
|
80
85
|
| 항목 `badge` | `{ count, max?, accessibilityLabel }` | `max` 99 | 숫자만. 점 배지는 없다. `count`가 0이면 그리지 않는다 |
|
|
81
86
|
| `onActivate` | `(activation: { key: Key; reason: "navigate" \| "reselect" }) => void` | Web 선택 · Native 필수 | 이동 의도만 알린다. 선택은 바꾸지 않는다. `reselect`는 이미 선택된 항목을 다시 누른 경우 |
|
|
@@ -114,6 +119,58 @@ bar(기본) center-gap + primaryAction
|
|
|
114
119
|
floating·capsule: 바깥 좌우 16 · 위 8 띄운 둥근 표면, 최대 폭 384 · 480
|
|
115
120
|
```
|
|
116
121
|
|
|
122
|
+
### 막대가 덮는 높이 (`BottomNavigationInsetProvider`, 1.31.0)
|
|
123
|
+
|
|
124
|
+
화면 위에 겹치는 막대(Web은 항상 `position: fixed`, Native는 `placement="overlay"`)가 덮는 하단 높이를 화면이 알게 한다.
|
|
125
|
+
화면들과 막대를 함께 감싸는 자리(탭 navigator·앱 셸)에 `BottomNavigationInsetProvider`를 둔다. 막대는 자기 높이(안전 영역
|
|
126
|
+
padding과 `prominent` 원이 막대 위로 솟은 부분 포함)를 측정해 알리고, 키보드 때문에 숨으면 0을 알린다.
|
|
127
|
+
`ScreenLayout`은 이 값을 스스로 읽어 마지막 영역(footer, 없으면 본문)의 아래 여백을 `max(기존 값, 화면 여백 16 + 덮인 높이)`로
|
|
128
|
+
둔다. 그래서 탭 화면마다 손으로 둔 하단 빈칸이 필요 없다. `scroll="content"`로 직접 FlatList를 두는 화면은
|
|
129
|
+
`useBottomNavigationInset()`을 읽어 `contentContainerStyle`의 아래 여백에 더한다. Sheet·Dialog 안에서는 0이다(오버레이가 막대를 덮는다).
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
// Native (Expo Router 탭)
|
|
133
|
+
<BottomNavigationInsetProvider>
|
|
134
|
+
<Tabs tabBar={(props) => <AppTabBar {...props} />} />
|
|
135
|
+
</BottomNavigationInsetProvider>
|
|
136
|
+
// AppTabBar 안: <BottomNavigation placement="overlay" configuration={{ presentation: "floating" }} ... />
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
// Web (앱 셸)
|
|
141
|
+
<BottomNavigationInsetProvider>
|
|
142
|
+
{children /* ScreenLayout 화면 */}
|
|
143
|
+
<BottomNavigation descriptor={descriptor} getHref={href} renderIcon={icon} />
|
|
144
|
+
</BottomNavigationInsetProvider>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Web Provider는 같은 값을 `--hjm-bottom-navigation-inset` CSS 변수로도 내려 준다. ScreenLayout이 아닌 제품 레이아웃은
|
|
148
|
+
`padding-block-end: calc(<여백> + var(--hjm-bottom-navigation-inset, 0px))`로 쓸 수 있다.
|
|
149
|
+
|
|
150
|
+
### 솟은 가운데 목적지 (`prominent`, 1.31.0)
|
|
151
|
+
|
|
152
|
+
가운데 칸이 쓰기·만들기 같은 제품의 주 진입점이면서 **목적지**일 때 쓴다(선택 상태가 있고 다시 누르면 `reselect`).
|
|
153
|
+
행동만 하고 화면이 바뀌지 않으면 `primaryAction`이다. 원은 선택 여부와 관계없이 브랜드 면(`action.brand`)으로 칠하고,
|
|
154
|
+
선택 표시는 다른 항목처럼 라벨 굵기·색이 맡는다. 원은 `지름 − 표시 자리 높이`만큼 위로 올라가 세 라벨이 한 줄에 선다.
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
// Native
|
|
158
|
+
<BottomNavigation
|
|
159
|
+
descriptor={{ accessibilityLabel: t("tab.label"), selectedKey: route, items: [
|
|
160
|
+
{ id: "trail", label: t("tab.sea"), icon: { name: "footprints" } },
|
|
161
|
+
{ id: "echo", label: t("tab.write"), icon: { name: "bird" }, prominent: true },
|
|
162
|
+
{ id: "nest", label: t("tab.beach"), icon: { name: "birdhouse" } },
|
|
163
|
+
] }}
|
|
164
|
+
onActivate={({ key }) => navigation.navigate(key)}
|
|
165
|
+
renderIcon={({ name, color, size, strokeWidth }) => <AppIcon name={name} color={color} size={size} strokeWidth={strokeWidth} />}
|
|
166
|
+
/>
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### 앱 아이콘 자리 (`iconSize`, 1.31.0)
|
|
170
|
+
|
|
171
|
+
`renderIcon`은 원래 어떤 ReactNode든 그릴 수 있다(이미지 포함). `iconSize: "large" | "xlarge"`는 그 자리를 44 · 52로 키워
|
|
172
|
+
런처의 앱 아이콘처럼 큰 그림을 넣게 한다. 그림은 받은 `size`로 그리고 크기를 따로 정하지 않는다.
|
|
173
|
+
|
|
117
174
|
## 꼭 지킬 것
|
|
118
175
|
|
|
119
176
|
- `selectedKey`는 router가 확정한 값으로 넘긴다. `onActivate`는 의도일 뿐이며 컴포넌트가 선택을 바꾸지 않는다.
|
|
@@ -131,13 +188,15 @@ floating·capsule: 바깥 좌우 16 · 위 8 띄운 둥근 표면, 최대 폭 38
|
|
|
131
188
|
| `onActivate` | 선택, 수정키 없는 왼쪽 클릭에만 | 필수, 추가로 `onLongActivate` |
|
|
132
189
|
| 배치 | CSS `position: fixed` 하단 | 제품 레이아웃이 배치 |
|
|
133
190
|
| 하단 inset | `env(safe-area-inset-bottom)` 자동 | `safeAreaBottom`(recipe 최소 padding에 더함) |
|
|
191
|
+
| 화면 위 겹침 | 항상(`position: fixed`). Provider가 덮인 높이를 알림 | `placement="overlay"`일 때만. 기본 `inline`은 자기 높이를 차지 |
|
|
134
192
|
| 키보드 감지 | `visualViewport` 높이 | `Keyboard` 이벤트 |
|
|
135
193
|
| `renderIcon`의 `color` | `"currentColor"` | 해석된 색 문자열 |
|
|
136
194
|
| 그 밖 | `className`·`style`·HTML 속성·`layoutStyle` | `renderBadge`, `getItemTestID`, `layoutStyle`(`style`·`surfaceStyle`·`listStyle`·`primaryActionStyle`은 제거된 속성) |
|
|
137
195
|
|
|
138
196
|
## 함정
|
|
139
197
|
|
|
140
|
-
- Web root가 `position: fixed`라 본문 마지막 내용이 막대 아래로 들어간다.
|
|
198
|
+
- Web root가 `position: fixed`라 본문 마지막 내용이 막대 아래로 들어간다. `BottomNavigationInsetProvider`로 감싸면 ScreenLayout이 여백을 둔다. 직접 만든 레이아웃은 `--hjm-bottom-navigation-inset`을 쓴다.
|
|
199
|
+
- Native 기본 `inline` 막대는 React Navigation `tabBar`처럼 자기 높이를 차지한다. 이때 탭 화면에 하단 빈칸을 또 두면 두 번 비게 된다. 막대 뒤로 본문을 보이게 하려면 `placement="overlay"`와 Provider를 함께 쓴다.
|
|
141
200
|
- `renderLink` 없이 쓰면 일반 `<a>`로 그려 SPA 전환이 일어나지 않는다.
|
|
142
201
|
- Web `onActivate`는 링크 기본 이동을 막지 않는다. `renderLink`의 라우터 Link가 이동하고 `onActivate`는 계측·맨 위로 스크롤 같은 부수 동작에만 쓴다. 수정키·가운데 클릭에는 불리지 않는다.
|
|
143
202
|
- Native 내비게이션 연구 스토리(`showcase/native/src/reference-navigation-bars.tsx`)는 `configuration`과 [Heading](heading.md)을 사용한다. 과거의 `style`·`listStyle` override는 제거되었으며, 선택 타일과 모서리는 공개 configuration 축으로 정한다.
|
|
@@ -168,4 +227,8 @@ floating 그림자는 그리지 않는다. 옆면이 높이를 표현하므로
|
|
|
168
227
|
|
|
169
228
|
## 근거
|
|
170
229
|
|
|
230
|
+
- 덮인 높이 Provider·`placement`: 2026-10-18 Spint가 떠 있는 막대 높이를 몰라 탭 화면마다 `TAB_BAR_SPACE`(112)를 손으로 두었다.
|
|
231
|
+
- `prominent`: 2026-10-18 다에리 가운데 "메아리"(쓰기) 탭을 그리려고 HJM 막대 대신 Expo Router 기본 탭바와 제품 원 아이콘을 썼다.
|
|
232
|
+
- `iconSize`: 2026-10-18 Utilverse 독이 38~54pt 앱 아이콘을 보이려고 Surface·Button으로 막대를 직접 조립했다.
|
|
233
|
+
|
|
171
234
|
- capsule 선택 알약·tile 선택 카드: 2026-10-17 정렬 실측(Web 402·1280, 실험 내비게이션 바 비교). 첫·끝 아이콘의 막대 끝 거리 차이 17~23px은 선택 항목의 `flex: 2` 알약 때문이며 항목 상자 양끝 여백은 5/5로 같았다. 가운데 항목이 14.5px 솟아 보인 값은 tile 선택 카드 상자를 다른 항목의 라벨과 비교한 측정 오차였고 아이콘 244·라벨 268이 모든 항목에서 같았다. 두 renderer에 이미 같은 규칙이 있어 코드는 바꾸지 않고 배치 표에 의도를 적었다.
|
|
@@ -78,7 +78,7 @@ import { Button } from "@hjmds/react-native/actions";
|
|
|
78
78
|
| `selected` | `boolean` | `false` | `true`면 tone이 `accent`로 바뀐다(`cardRecipe.selectedTone`) |
|
|
79
79
|
| `headingLevel`(Web만) | `2` · `3` · `4` | `3` | 제목이 `h3`로 렌더되므로 문서 위계에 맞춰 고른다 |
|
|
80
80
|
| `title` · `description` · `leading` · `media` · `actions` · `children` | `ReactNode` | — | 슬롯. 순서는 HJM이 고정한다 |
|
|
81
|
-
| `onActivate` | `() => void` | — | 카드 전체가 하나의 행동일 때 사용(미게시). Web `aria-label`, Native `accessibilityLabel`
|
|
81
|
+
| `onActivate` | `() => void` | — | 카드 전체가 하나의 행동일 때 사용(미게시). Web `aria-label`, Native `accessibilityLabel` 필수. `actions`와 함께 쓰면 행동은 별도 대상으로 남는다(1.31.0 추가) |
|
|
82
82
|
| `disabled` | `boolean` | `false` | 전체 카드 행동 차단·비활성 피드백(미게시) |
|
|
83
83
|
| `layoutStyle` | margin·width·flex·`alignSelf` | — | 배치 전용. 두 플랫폼 모두 root Surface에 적용된다 |
|
|
84
84
|
|
|
@@ -99,8 +99,39 @@ import { Button } from "@hjmds/react-native/actions";
|
|
|
99
99
|
// Native는 aria-label 대신 accessibilityLabel을 전달한다.
|
|
100
100
|
```
|
|
101
101
|
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
children·media·leading에는 입력/링크/버튼을 넣지 않는다. 카드를 여는 행동과 별도 명령(삭제·더보기)이
|
|
103
|
+
함께 필요하면 명령을 `actions`에 둔다.
|
|
104
|
+
|
|
105
|
+
### 카드 열기와 별도 행동(1.31.0 추가)
|
|
106
|
+
|
|
107
|
+
2026-10-18 unairplane 홈 여정 카드는 카드 전체로 상세를 열고 삭제는 따로 해야 했다. 이전에는 `onActivate`와
|
|
108
|
+
`actions`가 상호 배제라 제품이 카드 안에 Pressable을 다시 조립하고 삭제를 별도 footer로 붙였다.
|
|
109
|
+
이제 둘을 함께 주면 HJM이 버튼 안 버튼 없이 두 대상을 나눈다.
|
|
110
|
+
|
|
111
|
+
```tsx
|
|
112
|
+
// Native
|
|
113
|
+
<Card accessibilityLabel={flightLabel} accessibilityHint={t("journey.openHint")} title={route} description={flightNumber}
|
|
114
|
+
onActivate={openJourney}
|
|
115
|
+
actions={<IconButton label={t("journey.delete", { flight: flightNumber })} tone="ghost" size="small" edge="start" onPress={confirmDelete}>
|
|
116
|
+
<Icon descriptor={{ name: "delete", tone: "danger" }} renderGlyph={renderSemanticGlyph} />
|
|
117
|
+
</IconButton>}>
|
|
118
|
+
{schedule}
|
|
119
|
+
</Card>
|
|
120
|
+
// Web은 accessibilityLabel 대신 aria-label, onPress 대신 onClick을 쓴다.
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
| 항목 | Web | Native |
|
|
124
|
+
| --- | --- | --- |
|
|
125
|
+
| 구조 | root는 `<article>`로 남고, 카드 전체를 덮는 투명 `<button>`(`data-slot="activator"`)이 이름·`aria-pressed`·`disabled`를 가진다. 행동 영역만 그 위에 놓인다 | media+본문이 하나의 `Pressable`(버튼 role·이름·선택/비활성 상태), 행동 줄은 그 형제다 |
|
|
126
|
+
| 누르는 영역 | 행동 버튼을 뺀 카드 전체(행동 줄의 빈 자리 포함) | media+본문. 행동 줄의 빈 자리는 누름 대상이 아니다 |
|
|
127
|
+
| 초점·낭독 순서 | 카드 → 행동 | 카드 → 행동(각각 별도 접근성 요소) |
|
|
128
|
+
| 눌림·비활성 피드백 | media·본문만 흐려진다. 행동은 자기 상태를 쓴다 | 같음 |
|
|
129
|
+
|
|
130
|
+
- `disabled`는 카드 열기만 막는다. 행동을 막으려면 그 버튼의 `disabled`를 따로 준다.
|
|
131
|
+
- 행동은 `actions`에 직접 넣는다. Web은 행동 영역의 직계 자식만 누름을 받으므로, 행동을 넓은 묶음으로 감싸면
|
|
132
|
+
그 묶음의 빈 자리도 카드 열기가 아니라 묶음이 받는다. 행동을 끝 쪽에 두려면 묶음으로 감싸지 말고 첫 행동의
|
|
133
|
+
`layoutStyle`에 Web `{ marginInlineStart: "auto" }`, Native `{ marginStart: "auto" }`를 준다(행동 줄은 시작 쪽부터 놓인다).
|
|
134
|
+
- `actions` 없이 `onActivate`만 주면 기존처럼 root 자체가 버튼(Web `<button>`, Native `Pressable`)이다.
|
|
104
135
|
기존 passive Card는 콜백 없이 동일하게 유지된다. 이 API는 로컬 source/candidate 단계이며
|
|
105
136
|
npm 게시 및 소비 제품의 게시 버전 채택 완료를 뜻하지 않는다.
|
|
106
137
|
|
|
@@ -134,13 +165,13 @@ subtree라 질감을 바꾸거나 host가 실패해도 본문/초안은 유지
|
|
|
134
165
|
- 색·radius·padding은 `tone`·`radius`·`padding` 축으로만 바꾼다. 카드마다 브랜드 색을 칠하지 않는다.
|
|
135
166
|
- 배치는 두 플랫폼 모두 `layoutStyle`로 한다. Native `CardProps`에는 `style`이 없다. Web의 `className`·`style`로 recipe 값을 덮지 않는다.
|
|
136
167
|
카드 목록 사이 간격은 바깥 [Stack](stack.md)·[Grid](grid.md)이 정한다.
|
|
137
|
-
- 카드 전체 행동은 `onActivate`만 사용한다. 카드 안
|
|
168
|
+
- 카드 전체 행동은 `onActivate`만 사용한다. 카드 안 별도 명령은 `actions`에 두고 children에 버튼을 넣지 않는다.
|
|
138
169
|
|
|
139
170
|
## 플랫폼 차이
|
|
140
171
|
|
|
141
172
|
| 항목 | Web | Native |
|
|
142
173
|
| --- | --- | --- |
|
|
143
|
-
| root | 기본 `<article>`, 전체 행동은 `<button type="button">` | 기본 `View`(Surface), 전체 행동은 `Pressable` |
|
|
174
|
+
| root | 기본 `<article>`, 전체 행동은 `<button type="button">`, 전체 행동+`actions`는 `<article>` + 덮개 `<button>` | 기본 `View`(Surface), 전체 행동은 `Pressable`, 전체 행동+`actions`는 media·본문 `Pressable` + 형제 행동 줄 |
|
|
144
175
|
| 제목 | `h{headingLevel}` | `Text` + `accessibilityRole="header"`, 수준 지정 없음 |
|
|
145
176
|
| 배치 | `layoutStyle` | `layoutStyle` |
|
|
146
177
|
| 내용 clip | tone의 `clipsContent`(`raised`는 그림자 때문에 clip 안 함) | 내부 `View`가 항상 clip, 그림자는 바깥에 남는다. frame과 clip이 같은 Provider radius token을 사용 |
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
| 여러 카드의 독립 입력·행동을 함께 유지하는 유한 가로 탐색 | [CollectionRail](list.md#collectionrail-가로-배치) |
|
|
24
24
|
| 항목 수가 많거나 끝이 없음 | [VirtualList](virtual-list.md), [LoadMore](load-more.md) |
|
|
25
25
|
| 같은 자리의 보기 전환 | [Tabs](tabs.md), [SegmentedControl](segmented-control.md) |
|
|
26
|
+
| 페이저와 페이지 내용을 제품이 직접 소유하고 위치 점만 필요 | [PageIndicator](page-indicator.md)(이 컴포넌트의 점 줄과 같은 부품) |
|
|
26
27
|
|
|
27
28
|
## 공개 이름과 import
|
|
28
29
|
|