@hjmds/design-contracts 1.41.2 → 1.43.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/affix.d.ts +18 -0
- package/dist/affix.d.ts.map +1 -1
- package/dist/affix.js +13 -1
- package/dist/affix.js.map +1 -1
- package/dist/alert-dialog.d.ts +32 -0
- package/dist/alert-dialog.d.ts.map +1 -1
- package/dist/alert-dialog.js +52 -0
- package/dist/alert-dialog.js.map +1 -1
- package/dist/behaviors.d.ts +6 -5
- package/dist/behaviors.d.ts.map +1 -1
- package/dist/behaviors.js +1 -1
- package/dist/behaviors.js.map +1 -1
- package/dist/catalog.d.ts +168 -15
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +4 -4
- package/dist/catalog.js.map +1 -1
- package/dist/character-count.d.ts +103 -0
- package/dist/character-count.d.ts.map +1 -0
- package/dist/character-count.js +68 -0
- package/dist/character-count.js.map +1 -0
- package/dist/chart.d.ts +30 -0
- package/dist/chart.d.ts.map +1 -1
- package/dist/chart.js +18 -0
- package/dist/chart.js.map +1 -1
- package/dist/collection-rail.d.ts +13 -1
- package/dist/collection-rail.d.ts.map +1 -1
- package/dist/collection-rail.js +9 -2
- package/dist/collection-rail.js.map +1 -1
- package/dist/communication.d.ts +25 -0
- package/dist/communication.d.ts.map +1 -1
- package/dist/communication.js +3 -0
- package/dist/communication.js.map +1 -1
- package/dist/component-recipes.d.ts +172 -2
- package/dist/component-recipes.d.ts.map +1 -1
- package/dist/component-recipes.js +122 -8
- package/dist/component-recipes.js.map +1 -1
- package/dist/design-system-provider.d.ts +13 -2
- package/dist/design-system-provider.d.ts.map +1 -1
- package/dist/design-system-provider.js +19 -3
- package/dist/design-system-provider.js.map +1 -1
- package/dist/foundations.d.ts +15 -0
- package/dist/foundations.d.ts.map +1 -1
- package/dist/foundations.js +7 -0
- package/dist/foundations.js.map +1 -1
- package/dist/icon-button-recipe.d.ts +33 -0
- package/dist/icon-button-recipe.d.ts.map +1 -1
- package/dist/icon-button-recipe.js +36 -1
- package/dist/icon-button-recipe.js.map +1 -1
- package/dist/image.d.ts +13 -0
- package/dist/image.d.ts.map +1 -1
- package/dist/image.js +17 -0
- package/dist/image.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- 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 +1 -1
- package/dist/recipes.js.map +1 -1
- package/dist/screen-patterns.d.ts +95 -0
- package/dist/screen-patterns.d.ts.map +1 -1
- package/dist/screen-patterns.js +83 -2
- package/dist/screen-patterns.js.map +1 -1
- package/dist/selection-helpers.d.ts +6 -0
- package/dist/selection-helpers.d.ts.map +1 -1
- package/dist/selection-helpers.js +12 -0
- package/dist/selection-helpers.js.map +1 -1
- package/dist/sidebar.d.ts +17 -2
- package/dist/sidebar.d.ts.map +1 -1
- package/dist/sidebar.js +8 -2
- package/dist/sidebar.js.map +1 -1
- package/dist/steps.d.ts +19 -19
- package/dist/steps.d.ts.map +1 -1
- package/dist/steps.js +21 -9
- package/dist/steps.js.map +1 -1
- package/dist/timeline.d.ts +41 -0
- package/dist/timeline.d.ts.map +1 -1
- package/dist/timeline.js +47 -1
- package/dist/timeline.js.map +1 -1
- package/dist/top.d.ts +21 -2
- package/dist/top.d.ts.map +1 -1
- package/dist/top.js +17 -1
- package/dist/top.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/affix.md +7 -0
- package/docs/avatar-fallback.md +19 -0
- package/docs/brand-boundary.md +24 -2
- package/docs/chart.md +7 -0
- package/docs/collection-rail.md +4 -1
- package/docs/generated/component-maturity.md +1 -1
- package/docs/generated/renderer-evidence.json +10 -6
- package/docs/generated/renderer-evidence.md +1 -1
- package/docs/generated/showcase-manifest.json +12 -5
- package/docs/image.md +5 -0
- package/docs/list-row.md +8 -0
- package/docs/optional-adapters.md +3 -0
- package/docs/overlay-stack.md +27 -0
- package/docs/screen-patterns.md +39 -2
- package/docs/sidebar.md +15 -0
- package/docs/steps.md +23 -19
- package/docs/theme-palette.md +3 -3
- package/docs/theming.md +1 -0
- package/docs/timeline.md +18 -1
- package/docs/top.md +7 -0
- package/docs/usage/README.md +9 -2
- package/docs/usage/components/affix.md +18 -4
- package/docs/usage/components/alert-dialog.md +28 -0
- package/docs/usage/components/avatar.md +30 -9
- package/docs/usage/components/badge.md +20 -5
- package/docs/usage/components/chart.md +19 -1
- package/docs/usage/components/chat-message.md +5 -0
- package/docs/usage/components/chat-room-actions.md +58 -0
- package/docs/usage/components/chat-room-create.md +58 -0
- package/docs/usage/components/chat-room-details.md +58 -0
- package/docs/usage/components/chat-room-invite.md +58 -0
- package/docs/usage/components/chat-room-members.md +58 -0
- package/docs/usage/components/chat-room-profile.md +58 -0
- package/docs/usage/components/checkbox-group.md +24 -1
- package/docs/usage/components/choice-row.md +19 -4
- package/docs/usage/components/composition-layout.md +6 -2
- package/docs/usage/components/counter-badge.md +2 -2
- package/docs/usage/components/design-system-provider.md +2 -1
- package/docs/usage/components/divider.md +12 -1
- package/docs/usage/components/field.md +51 -0
- package/docs/usage/components/icon-button.md +48 -4
- package/docs/usage/components/icon-tile.md +13 -2
- package/docs/usage/components/image.md +25 -0
- package/docs/usage/components/list-row.md +8 -4
- package/docs/usage/components/list.md +1 -1
- package/docs/usage/components/notification-item.md +5 -1
- package/docs/usage/components/permission-screen.md +25 -4
- package/docs/usage/components/screen-layout.md +27 -1
- package/docs/usage/components/segmented-control.md +16 -3
- package/docs/usage/components/select.md +1 -0
- package/docs/usage/components/settings-screen.md +5 -4
- package/docs/usage/components/sheet.md +2 -1
- package/docs/usage/components/sidebar.md +34 -6
- package/docs/usage/components/steps.md +29 -8
- package/docs/usage/components/surface.md +2 -1
- package/docs/usage/components/text-area.md +2 -1
- package/docs/usage/components/timeline.md +25 -4
- package/docs/usage/components/top.md +15 -2
- package/docs/usage/compositions/chat-room.md +110 -0
- package/docs/usage/screens/common-settings.md +3 -2
- package/docs/usage/screens/flow-permission.md +3 -3
- package/docs/usage/tokens/elevation-opacity.md +14 -2
- package/package.json +7 -1
package/docs/steps.md
CHANGED
|
@@ -65,20 +65,14 @@ index > cursor → pending
|
|
|
65
65
|
|
|
66
66
|
- `currentStepStatus` 기본값은 `"current"`(`stepsDefaults.currentStepStatus`). 실패를
|
|
67
67
|
표현하려는 제품만 명시적으로 `"error"`를 넘긴다.
|
|
68
|
-
- `
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
-
|
|
76
|
-
`isStepReached(status)`(`pending`만 false)로 renderer가 인접 segment 색을 고른다.
|
|
77
|
-
- 텍스트(라벨·description)와 마커 글자·아이콘(`indicator.content`), 도달한 connector 색은
|
|
78
|
-
각각 4.5:1 / 3:1을 만족하도록 recipe 색을 선택했다(test로 두 기준을 분리해 검증). `pending`
|
|
79
|
-
마커 테두리와 `connector.unreached`는 Divider·Badge가 이미 쓰는 공용 저대비 `border.default`/
|
|
80
|
-
alpha 톤을 그대로 재사용하는 장식적 tint라 대비 기준 대상이 아니다 — 상태 구분은 마커
|
|
81
|
-
글자·모양(숫자 vs check vs error)과 `statusLabel`이 이미 이중으로 전달한다.
|
|
68
|
+
- `presentation` 기본값은 `"focus"`다. 현재 표지는 `content.primary` 채움 + `canvas` 글자,
|
|
69
|
+
완료는 중립 체크, 예정은 옅은 번호, 오류는 danger 표지를 사용한다. 도달한 연결선도 중립색이다.
|
|
70
|
+
2026-10-23 사용자가 선택한 시안에 따라 이전 success 완료·brand 현재 테두리를 대체한다.
|
|
71
|
+
- 숫자 표지 32, `renderMark` 제품 그림 44, 버튼 최소 높이 44를 분리한다. 그림 표지는 canvas를 유지한다.
|
|
72
|
+
- `compact`는 현재 순서·제목·상태와 분할 막대, 번역된 `overviewLabel` 버튼을 제공한다.
|
|
73
|
+
펼쳐야 지난 단계가 버튼이 된다. `vertical`은 현재 단계의 `renderStepContent(id)`만 펼친다.
|
|
74
|
+
- 콘텐츠·초안·입력 검증·서버 확정은 제품이 소유한다. 표현 변경은 navigationMode의 권한을 바꾸지 않는다.
|
|
75
|
+
- 정확한 props와 배치는 [사용 지침](usage/components/steps.md), 수치는 `stepsRecipe`가 소유한다.
|
|
82
76
|
|
|
83
77
|
## 플랫폼 번역
|
|
84
78
|
|
|
@@ -102,15 +96,15 @@ index > cursor → pending
|
|
|
102
96
|
| 순서(`position`/`total`) | 공개 |
|
|
103
97
|
| 지난 단계 누르기(`revisitable` + renderer `onStepPress`) | **공개(1.31.0)** — 2026-10-18 spint 작성 화면이 지난 단계를 눌러 돌아가려고 단계 레일을 직접 그렸다. resolver가 커서보다 앞선 단계에 `revisitable: true`를 붙이고, renderer는 제품이 `onStepPress`를 줄 때 그 단계만 버튼으로 만든다(칸 전체, 최소 44 `stepsRecipe.press.minTouchTarget`). 이전 판단("뒤로 가기는 별도 버튼")은 바로 앞 단계 행동에는 그대로 유효하다. |
|
|
104
98
|
| 앞으로 건너뛰기(현재·다음 단계 누르기) | **배제** — 검증 전 단계를 지나치고 단일 커서 유도를 흐린다. 커서 단계는 이미 있는 자리라 누를 이유가 없다. |
|
|
105
|
-
|
|
|
99
|
+
| 세로·축약 표현 | **공개(개발)** — 2026-10-23 사용자 선택. `presentation: focus / compact / vertical`, 새 상태 엔진 없이 동일 커서를 표현한다. |
|
|
106
100
|
| dot type(압축 점 표현) | **배제** — 측정된 요구가 없다. numbered + check/error 마크 하나만 공개한다. |
|
|
107
|
-
|
|
|
108
|
-
| navigation type
|
|
101
|
+
| 제품 그림 표지 | **공개** — `renderMark(status, position)` 슬롯. 그림·의미는 제품, 공간·접근성·누름은 HJM 소유다. |
|
|
102
|
+
| 임의 navigation type | 별도 antd 표현을 복제하지 않음. 현재 요구는 공개 presentation 세 가지로 충족한다. |
|
|
109
103
|
|
|
110
104
|
## 검증 화면
|
|
111
105
|
|
|
112
|
-
|
|
113
|
-
|
|
106
|
+
기존 Steps의 등록 상태는 catalog를 따른다. 2026-10-23 추가한 표현은 미게시 개발 소스이며,
|
|
107
|
+
새 표현의 Storybook 화면 확인을 소비 앱 적용·npm 게시로 해석하지 않는다.
|
|
114
108
|
|
|
115
109
|
유력 후보였던 "Yajalal 온보딩(`OnboardingScreen`의 `AppProgress` 대체)"은 검증 결과
|
|
116
110
|
부정확했다 — `OnboardingScreen.tsx`는 지금도 그대로 `AppProgress`(연속 진행바,
|
|
@@ -124,3 +118,13 @@ first-party Web·Native renderer와 상태 파생·환경 matrix 증거는 연
|
|
|
124
118
|
## 읽기 흐름의 자유 이동 — 2026-10-19
|
|
125
119
|
|
|
126
120
|
포트폴리오 설계·운영 설명은 단계 선택으로 해당 본문을 읽는 흐름이므로 `StepsDescriptor.navigationMode: "free"`에서 `onStepPress`가 모든 단계에 동작한다. 기본 `linear`는 기존 검증형 작성 흐름처럼 이전 단계만 허용한다. 이 절이 기존 앞으로 이동 배제 설명의 읽기 흐름 예외다. 단일 currentStepId와 앞/뒤 상태 도출은 유지하며 제품은 상태 문구를 읽기 맥락에 맞춘다.
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
### 2026-10-23 개발 확인
|
|
124
|
+
|
|
125
|
+
- Steps 계약 20개, Web Steps·StepPlayer 4개, Native Steps·StepPlayer 3개 테스트 통과. 세 패키지 빌드와 두 Showcase 타입 검사 통과.
|
|
126
|
+
- Web Storybook: focus·compact·vertical, 오류→수정→완료, 이전 단계와 초안 보존, 390/1000 폭, light/dark, reduced motion과 compact 키보드 펼침을 확인했다.
|
|
127
|
+
- iPhone 17 Pro · iOS 26.5 (`AC433031-1746-46C6-86A9-143A1FC839F8`): 기존 개발 클라이언트에서 세 표현을 표시하고 focus 이동·복귀, compact 펼침, vertical 본문 전환을 확인했다. dark focus도 표시했다. Android 기기와 VoiceOver는 미실행.
|
|
128
|
+
- Native Storybook 탐색 패널의 항목이 Device Hub 접근성 트리에 노출되지 않고 좌표 입력이 반응하지 않아 목록 선택·스크롤은 idb로 수행했다. 실제 결과 화면과 이후 버튼 동작은 Device Hub로 확인했다. 임시 키보드 캡처는 off로 원복했다.
|
|
129
|
+
- 패키지 전체 타입 검사는 기존 선택 UI 테스트의 optional brandPalette/unused import 오류로 실패했다. 변경한 Steps 소스·Showcase 타입 검사는 통과했으며 무관한 테스트 파일은 보존했다.
|
|
130
|
+
- 검증 중 생성된 무관한 컴파일 산출물 변경은 제거했다. 요청한 미리보기를 위해 Web 6006·Native 8084 개발 서버는 유지하며, 미리보기 종료 시 해당 프로세스를 종료하면 된다. 버전 상승·게시·운영 배포는 하지 않았다.
|
package/docs/theme-palette.md
CHANGED
|
@@ -107,11 +107,11 @@ Ant의 원시 색상이나 낮은 테두리 대비까지 복제하지 않고, HJ
|
|
|
107
107
|
|
|
108
108
|
휠의 하늘색과 카테고리 선택색을 비교한 뒤 사용자가 기본 테마의 뉴트럴 안을 승인했다.
|
|
109
109
|
`surfaceSelected`는 light `#f0f1f3`, dark `#30343b`이고 `semanticColors.selection`이 배경·글자·테두리를 묶는다.
|
|
110
|
-
TimePicker, Chip(그룹의 chips 표현 포함)과
|
|
110
|
+
TimePicker, Chip(그룹의 chips 표현 포함)과 `selectionTone="neutral"` SegmentedControl이 같은 선택 배경을 쓴다.
|
|
111
111
|
글자는 기존 `text`, Chip 테두리는 `borderControl`을 쓰며 체크·선택 테두리·포커스 표시를 보존한다.
|
|
112
112
|
이 결정은 위 2026-09-29 기록의 해당 선택 배경을 대체하며 입력 필드 배경은 바꾸지 않는다.
|
|
113
113
|
`surfaceAccent`는 브랜드 보조 배경, `primary`는 주요 동작으로 유지한다.
|
|
114
|
-
|
|
114
|
+
SegmentedControl의 `selectionTone="brand"`와 solid 탭은 브랜드 강조를 쓴다. 같은 날 후속 시각 비교에서 사용자가 강조를 기본으로 선택했으므로 SegmentedControl은 `brand`가 기본이며 `neutral`은 옵션이다(Web·Native 개발 소스, 미게시). 다른 컴포넌트의 중립 선택 역할은 유지한다.
|
|
115
115
|
제품은 `brandPalette`의 `surfaceSelected`로 선택 배경을 지정할 수 있다. 기존 팔레트 대비 검사에 `text`/`surfaceSelected` 4.5:1 쌍을 포함한다.
|
|
116
116
|
|
|
117
117
|
## 선택 상태 색상 기준 (2026-10-23)
|
|
@@ -124,7 +124,7 @@ TimePicker, Chip(그룹의 chips 표현 포함)과 기본 neutral SegmentedContr
|
|
|
124
124
|
| --- | --- | --- |
|
|
125
125
|
| 지속되는 일반 선택 면 | `selection.background`/`selection.content`, 경계가 필요하면 `selection.border` | Chip·칩 그룹, neutral SegmentedControl, TimePicker, filled Tabs, capsule BottomNavigation, ReactionPicker, ToggleGroup, selected Button·IconButton, 선택 Card·ListRow·Select·Combobox·Menu·Tree·TransferList·DataTable 행 |
|
|
126
126
|
| 현재 조작 위치 | 기존 focus/hover/pressed 역할. 확정 선택과 합치지 않음 | CommandPalette·Mentions·TagsInput 제안의 active descendant, Select·Combobox의 active 항목, 포커스 링 |
|
|
127
|
-
|
|
|
127
|
+
| 진한 브랜드 면 | `primary`/`onPrimary` | `Tabs indicator="solid"`, `SegmentedControl` 기본 `selectionTone="brand"`, `BottomNavigation selection="tile"`, prominent destination |
|
|
128
128
|
| 작은 값 표시·현재 위치 표시 | 기존 전용 체크·점·밑줄·테두리 계약 | Checkbox·Radio의 glyph, Switch on, Calendar 날짜 원, underline/text Tabs, 일반 BottomNavigation 아이콘·글자, Pagination·Steps·Anchor·Carousel 위치 표시, 읽기 전용 반응 요약 |
|
|
129
129
|
| 브랜드·장식·업무 강조 | 기존 브랜드/상태 역할 | ChatMessage outgoing, 폴더 그림, liquid toast, 표의 `highlighted` 업무 강조, 브랜드 Surface/Badge, 오류·성공 등 상태 |
|
|
130
130
|
| 미디어 위 선택 증거 | 읽을 수 있는 전용 링·스크림 유지 | ImageChoice·MediaSelection. 회색 면으로 사진을 덮지 않음 |
|
package/docs/theming.md
CHANGED
|
@@ -29,6 +29,7 @@ import { HjmProvider } from "@hjmds/react/provider";
|
|
|
29
29
|
교체되고 나머지는 기본값을 유지하므로 recipe와 대비 규칙이 그대로 적용된다.
|
|
30
30
|
1.5.0부터 Provider가 `brandPalette`를 prop으로 직접 받는다. 이 경로에서 Provider는 계속
|
|
31
31
|
OS theme·글자 크기·reduced motion을 관찰하고, 중첩 Provider는 가장 가까운 상위 `brandPalette`를 물려받는다.
|
|
32
|
+
중첩 Provider가 일부 역할만 바꾸려면 `brandPaletteMode="extend"`를 함께 준다(기본 `replace`는 상위 브랜드를 끊는다, [브랜드 경계 §1.1](./brand-boundary.md#11-하위-범위의-일부-역할만-바꾸기--brandpalettemode-개발-소스미게시)).
|
|
32
33
|
|
|
33
34
|
```tsx
|
|
34
35
|
import { HjmProvider, type HjmBrandPalette } from "@hjmds/react/provider";
|
package/docs/timeline.md
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
각 항목은 stable string `id`와 보이는 `label`을 가진다(Collection 기본 계약의 최소
|
|
33
33
|
부분집합, [[collection]] 참고). `textValue`, `none|single|multiple` selection mode,
|
|
34
34
|
`idle|loading|loadingMore|empty|error` async 상태는 Steps와 같은 이유로 가져오지 않는다 —
|
|
35
|
-
Timeline은 검색/타이핑 탐색 대상이 아니고, 사용자가 고르는 대상도
|
|
35
|
+
Timeline은 검색/타이핑 탐색 대상이 아니고, 기본적으로 사용자가 고르는 대상도 아니다(선택형은 아래 「기록 선택」). 비동기 로딩은
|
|
36
36
|
이 계약이 직접 다루지 않는다 — 항목이 뒤로(과거로) 더 늘어나야 하면 기존 항목을 그대로
|
|
37
37
|
둔 채 다음 페이지만 요청하는 문제이므로, List가 그렇듯 `LoadMore`([[load-more]])와
|
|
38
38
|
합성한다. Timeline 자체가 `idle|loading|empty` 축을 새로 만들지 않는다 — 항목이 하나도
|
|
@@ -143,3 +143,20 @@ Ant Design Timeline의 `mode="alternate"`(항목이 좌우로 번갈아 배치)
|
|
|
143
143
|
connector 시각이 아니라 평평한 `AppListRow` 목록으로 그려져 있어, 시각 recipe 쪽
|
|
144
144
|
vertical slice는 이 조사에서 확인하지 못했다. 구단 상세의 영입·유출 이력도 미확인 후보였다.
|
|
145
145
|
2026-09-29부터 제품 채택은 관측으로 분리하며 [현재 승격 기준](stable-promotion.md)을 따른다.
|
|
146
|
+
|
|
147
|
+
## 기록 선택 (2026-10-23, 개발 소스·미게시)
|
|
148
|
+
|
|
149
|
+
`selectedId`/`onSelectedIdChange`는 기록 하나를 골라 제품의 다른 표시(지도·상세)를 바꾸는 제어형 단일 선택이다.
|
|
150
|
+
위의 "사용자가 고르는 대상이 아니다"는 수동 기록(`selectedId` 없음)의 기본값으로 남는다. 선택은 진행 커서가 아니다 —
|
|
151
|
+
`tone`·connector 색·순서는 선택과 무관하고, 선택된 기록 앞뒤를 지난/남은 단계로 나누지 않는다(그건 Steps).
|
|
152
|
+
|
|
153
|
+
- 계약: `TimelineDescriptor.selectedId`(`Id | null`), 해석 결과의 `selected`, 목록 밖 id는 `RangeError`.
|
|
154
|
+
`validateTimelineSelection`이 `selectedId`와 콜백의 짝, 선택형에서 `renderActions` 금지를 검사한다.
|
|
155
|
+
선택형 기록은 하나의 대상(Web option, Native 선택 버튼)이라 안에 별도 명령을 둘 수 없다.
|
|
156
|
+
- 키보드: `getTimelineSelectionTarget`이 공용 collection 이동 계산(`getCollectionNavigationTarget`, 순환 없음)을 재사용한다.
|
|
157
|
+
기록에는 처음과 끝이 있어 순환하지 않는다. 선택이 포커스를 따르는 이유는 선택이 옆 표시만 바꾸는 가벼운 동작이기 때문이다.
|
|
158
|
+
- 표현: `timelineRecipe.item.selected` — `selection.background` 면 + `selection.border` 1 테두리. ListRow 선택과 같은
|
|
159
|
+
중립 선택 면이며 브랜드 면이 아니다(theme-palette 선택 상태 기준).
|
|
160
|
+
- 기존 API로 표현할 수 없었던 이유: `renderActions`의 Button은 기록과 별도 대상이라 선택 의미가 기록에 붙지 않고,
|
|
161
|
+
[선택 지침](usage/SELECTION.md#조립-규칙필수)이 `selected` Button 나열을 금지한다. RadioGroup·ListRow로 바꾸면
|
|
162
|
+
레일·시각·기록 의미를 제품이 다시 조립해야 한다(다에리 여정 일지 감사).
|
package/docs/top.md
CHANGED
|
@@ -37,3 +37,10 @@
|
|
|
37
37
|
2026-10-07 소비 감사에서 두 renderer의 제목 크기·행간·굵기가 foundation으로 확정된 recipe를 직접 읽어 프로필을 우회했다. `large`는 가까운 프로필의 `heading.level3`, `medium`은 `typography.titleLarge`를 읽고 프로필이 없으면 기존 recipe를 유지한다. 시각 역할은 `headingLevel`과 독립이며 display 서체·제목 의미·보조 행동·초점은 바꾸지 않는다.
|
|
38
38
|
|
|
39
39
|
프로필 연결은 1.15.0 이후 미게시 변경이며, 기본 배포 계약과 실제 Native 기기 검증은 구분한다.
|
|
40
|
+
|
|
41
|
+
## 제목 줄바꿈 (2026-10-23, 개발 소스·미게시)
|
|
42
|
+
|
|
43
|
+
`titleLineBreaks`는 제목 안 `\n`의 의미다. 기본 `collapse`는 공백으로 바꾸고, `preserve`는 제품이 의도한 줄바꿈을 그린다.
|
|
44
|
+
`resolveTopTitle`이 두 renderer의 그릴 글자와 제목 이름을 함께 만든다. 이름은 언제나 줄을 공백 하나로 이은 한 문장이라
|
|
45
|
+
줄바꿈이 보조기기의 제목을 끊지 않는다. 이전에는 같은 `\n`을 Web은 공백으로, Native는 줄바꿈으로 그렸다.
|
|
46
|
+
포트폴리오 사이트 히어로가 `pre-line` span을 Heading에 넣어야 해서 Top을 채택하지 못한 것이 계기다([사용 지침](usage/components/top.md)).
|
package/docs/usage/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
[선택 기준](SELECTION.md)으로 그대로 사용·공개 슬롯 확장·공통 API 보완·제품 고유 기능 연결을 고른다. 설치 버전의 지침을 본다: `node_modules/@hjmds/design-contracts/docs/usage/`.
|
|
8
8
|
이름을 모르면 [쉬운 말로 찾고 비교하기](FINDING.md)에서 일상 표현과 선택 기준·요청 예시로 시작한다.
|
|
9
9
|
제공 기준은 확인한 기본 API 버전이며 최초 출시 버전이 아니다. 구성·화면은 각 API 지침의 제공 버전을 확인한다.
|
|
10
|
-
API 안정성은 1.
|
|
10
|
+
API 안정성은 1.42.1의 생성 manifest에서 읽은 정규(canonical) API 기준이다. 동반·선택형 확장은 개별 계약을 확인한다.
|
|
11
11
|
Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품 반영을 의미하지 않는다.
|
|
12
12
|
`분류`는 Storybook 제목 `<배포|실험>/<단계>/<분류>/<항목>`의 셋째 마디이고, 토큰·구성·화면은 Storybook 메뉴와 같은 순서다.
|
|
13
13
|
|
|
@@ -60,6 +60,12 @@ Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품
|
|
|
60
60
|
| [Chart](components/chart.md) | 데이터 표시 | 수치의 흐름·비교·몫·모양·관계를 그림으로 읽게 할 때 쓴다. | 1.21.0 | Web · Native | Web beta / Native beta | 배포 |
|
|
61
61
|
| [ChatDateSeparator](components/chat-date-separator.md) | 데이터 표시 | 대화 타임라인에서 날짜(또는 오래 쉰 뒤의 시각)가 바뀌는 자리에 가운데 정렬 구분 줄을 둘 때 쓴다. | 1.31.0 | Web · Native | Web beta / Native beta | 배포 |
|
|
62
62
|
| [ChatMessage](components/chat-message.md) | 데이터 표시 | DM·대화 타임라인의 메시지 한 개에 쓴다. | 1.17.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
63
|
+
| [ChatRoomActions](components/chat-room-actions.md) | 구성/입력과 작성 | 나가기·내 기록 삭제·방 삭제를 구분해 확인한다. | 1.43.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
64
|
+
| [ChatRoomCreate](components/chat-room-create.md) | 구성/입력과 작성 | 참여자를 검색·선택하고 사진·이름을 정해 방을 개설한다. | 1.43.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
65
|
+
| [ChatRoomDetails](components/chat-room-details.md) | 구성/입력과 작성 | 방 프로필·도구·참여자·관리 행동을 묶음형 정보 화면으로 보여 준다. | 1.43.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
66
|
+
| [ChatRoomInvite](components/chat-room-invite.md) | 구성/입력과 작성 | 선택한 새 참여자의 실제 초대 결과를 기다린다. | 1.43.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
67
|
+
| [ChatRoomMembers](components/chat-room-members.md) | 구성/입력과 작성 | 참여자를 표시하고 선택 또는 권한별 메뉴를 제공한다. | 1.43.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
68
|
+
| [ChatRoomProfile](components/chat-room-profile.md) | 구성/입력과 작성 | 사진·이름·소개를 편집하고 실제 저장 결과를 기다린다. | 1.43.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
63
69
|
| [ChatScreen](components/chat-screen.md) | 레이아웃 | DM·대화방처럼 헤더, 메시지 타임라인, 하단 작성창으로 이루어진 화면 한 장에 쓴다. | 1.17.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
64
70
|
| [Checkbox](components/checkbox.md) | 입력 | 독립된 예/아니오 하나를 고르는 항목에 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
65
71
|
| [CheckboxGroup](components/checkbox-group.md) | 입력 | 한 질문에 대한 여러 선택지 중 0개 이상을 고르게 할 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
@@ -181,7 +187,7 @@ Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품
|
|
|
181
187
|
| [Splitter](components/splitter.md) | 레이아웃 | 넓은 Web 화면에서 두 영역의 경계를 사용자가 드래그나 키보드로 옮겨 크기를 정할 때 쓴다. | 1.12.1 | Web | Web stable / Native unsupported | 배포 |
|
|
182
188
|
| [Stack](components/stack.md) | 레이아웃 | 자식들을 한 방향으로 늘어놓고 사이 간격을 토큰으로 맞출 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
183
189
|
| [Statistic](components/statistic.md) | 데이터 표시 | 라벨이 붙은 **숫자 지표 하나**(또는 여러 개)를 보여 줄 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
184
|
-
| [Steps](components/steps.md) | 탐색 | 여러 단계로 된 **선형 흐름에서 지금 어디인지** 보여 줄 때 쓴다. | 1.
|
|
190
|
+
| [Steps](components/steps.md) | 탐색 | 여러 단계로 된 **선형 흐름에서 지금 어디인지** 보여 줄 때 쓴다. | 미게시(1.41.2 이후) | Web · Native | Web stable / Native stable | 배포 |
|
|
185
191
|
| [StreamingAnswer](components/streaming-answer.md) | 구성/피드백과 복구 | AI 응답처럼 제공자가 조각(`delta`)으로 보내는 답을 받는 대로 표시하고, 생성·다시 생성·중지를 한 묶음으로 제공한다. | 1.21.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
186
192
|
| [Surface](components/surface.md) | 레이아웃 | 배경·테두리·radius를 가진 **의미 없는 상자**가 필요할 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
187
193
|
| [SwipeActions](components/swipe-actions.md) | 구성/직접 조작과 모션 | 목록 행 하나에 붙은 **삭제·보관 같은 행 단위 행동**을, Native에서는 행을 밀어 드러내고 Web에서는 행 아래 버튼으로 바로 보여 줄 때 쓴다. | 1.12.1 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
@@ -234,6 +240,7 @@ Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품
|
|
|
234
240
|
| [인증번호 확인과 다시 입력](compositions/stea-otp-verify.md) | 입력과 작성 | 문자·메일로 받은 숫자 인증번호를 입력하고 서버 확인을 기다린 뒤, 틀리면 남은 횟수를 보여 주고 다시 받게 하는 흐름에 쓴다. | 1.12.1 | Web · Native | 구성 API별 | 배포 |
|
|
235
241
|
| [입력 시트](compositions/input-sheet.md) | 입력과 작성 | 현재 화면 위에 하단 시트를 띄워 짧은 입력(이름 바꾸기, 메모 한 줄)을 받고, 키보드가 올라와도 본문을 스크롤하며 완료 버튼에 닿게 할 때 쓴다. | 1.12.1 | Web · Native | 구성 API별 | 배포 |
|
|
236
242
|
| [입력을 유지하는 도구](compositions/context-toolbar.md) | 입력과 작성 | 작성 중인 입력을 보존한 채 선택적 도구를 펼쳐야 할 때 쓴다. | 1.14.0 | Web · Native | 구성 API별 | 배포 |
|
|
243
|
+
| [채팅방 관리](compositions/chat-room.md) | 입력과 작성 | `@hjmds/react/communication`, `@hjmds/react-native/communication`에서 제공한다. | 1.43.0 | Web · Native | 구성 API별 | 배포 |
|
|
237
244
|
| [첫 작업을 만들고 이어하기](compositions/reference-first.md) | 입력과 작성 | 첫 기록을 단계별 작성하고 중단한 초안 이어가기 흐름이 필요할 때 쓴다. | 구성 API 지침 참조 | Web · Native | 구성 API별 | 배포 |
|
|
238
245
|
| [날짜 선택과 예정 목록](compositions/stea-schedule-card.md) | 선택과 필터 | 한 주처럼 짧은 날짜 범위에서 날짜 하나를 고르면 같은 카드 안의 일정 목록이 그 날짜로 바뀌는 요약 카드에 쓴다. | 1.12.1 | Web · Native | 구성 API별 | 배포 |
|
|
239
246
|
| [날짜와 시각 선택](compositions/date-time-selection.md) | 선택과 필터 | 기록·알림의 날짜 하나와 하루 안의 시각을 함께 고를 때 쓴다. | 1.16.0 | Web · Native | 구성 API별 | 배포 |
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
- 상태: 배포
|
|
5
5
|
- 지원: Web
|
|
6
6
|
- 적용: 1.12.1
|
|
7
|
-
- 검토일: 2026-10-
|
|
7
|
+
- 검토일: 2026-10-23
|
|
8
8
|
- 근거: [Affix — Web 상단 고정](../../affix.md), `affixRecipe`(`src/affix.ts`)
|
|
9
9
|
- 스토리북: `배포/컴포넌트/기반 기능/고정 배치`
|
|
10
10
|
|
|
@@ -50,16 +50,18 @@ Native 사용 예는 없다(renderer 없음).
|
|
|
50
50
|
| `offset` | 유한한 0 이상의 CSS px | `0` | 스크롤 조상 상단에서 띄울 거리. 아니면 `TypeError` |
|
|
51
51
|
| `disabled` | `boolean` | `false` | 고정을 끄고 일반 흐름으로 둔다. 자식은 재마운트되지 않는다 |
|
|
52
52
|
| `onChange` | `(affixed: boolean) => void` | — | 최초 측정 결과와 이후 붙음↔풀림 전환 때만 호출된다(스크롤마다 호출하지 않는다) |
|
|
53
|
-
| `
|
|
53
|
+
| `layer` | `sticky` · `base` | `sticky` | 쌓임 단계. `sticky`는 공통 `layer.sticky`(100, `--hjm-layer-sticky`)로 뒤에 오는 position 지정 콘텐츠 위에 그린다. `base`(0)는 자체 쌓임을 가진 표면(대화상자·측면 패널 본문) 안에서만 쓴다(개발 소스, 미게시) |
|
|
54
|
+
| `fill` | `canvas` · `none` | `canvas` | 상자 뒤 바탕. `canvas`는 화면 배경(`--hjm-color-bg`)을 깔아 지나가는 콘텐츠가 비치지 않게 한다. `none`은 자식이 자기 표면(Card·채운 도구 막대)을 가질 때 쓴다(개발 소스, 미게시) |
|
|
55
|
+
| `layoutStyle` | margin·width·flex·`alignSelf` | — | sticky 상자의 배치 전용. `position`·`top`·`zIndex`는 Affix가 소유한다 |
|
|
54
56
|
| `children` | `ReactNode` | 필수 | 고정할 영역 |
|
|
55
57
|
|
|
56
58
|
## 배치
|
|
57
59
|
|
|
58
60
|
| 항목 | 값 | 근거 |
|
|
59
61
|
| --- | --- | --- |
|
|
60
|
-
| 크기 | 자식이 정한다. Affix는 여백·높이를 더하지 않고 화면 배경(`--hjm-color-bg`)만 깔아 아래 내용을 가린다 | `.hjm-affix` |
|
|
62
|
+
| 크기 | 자식이 정한다. Affix는 여백·높이를 더하지 않고 `fill="canvas"`(기본)면 화면 배경(`--hjm-color-bg`)만 깔아 아래 내용을 가린다 | `.hjm-affix` |
|
|
61
63
|
| 간격 | 스크롤 조상 상단에서 `offset`만큼 띄운다. 상단 바가 있는 화면은 그 높이를 준다(스토리는 `offset={8}`) | `react/src/affix.tsx`, `showcase/web/src/patterns/WebAdditions.stories.tsx` |
|
|
62
|
-
| 순서·정렬 | 고정하려는 영역이 원래 있던 자리(DOM 순서)에 그대로 둔다.
|
|
64
|
+
| 순서·정렬 | 고정하려는 영역이 원래 있던 자리(DOM 순서)에 그대로 둔다. 쌓임은 `layer`가 정한다: 기본 `sticky`(100)라 뒤에 오는 position 지정 카드·이미지가 고정된 막대 위로 그려지지 않는다. 제품이 바깥 wrapper에 z-index를 따로 주지 않는다 | `affixRecipe.defaults`, `foundations.ts` `layer`, `.hjm-affix[data-layer]` |
|
|
63
65
|
| 고정·스크롤 | 상단 sticky만 된다. 고정 구간은 부모 높이 안에서만 생기고 부모가 끝나면 함께 밀려 올라간다. 한 스크롤 영역에 Affix를 여러 개 두지 않는다 | `affixRecipe`(`edge: "top"`, `position: "sticky"`) |
|
|
64
66
|
| 좁은 폭·큰 글자 | 자식이 스크롤 영역 높이 − `offset`보다 크면 고정하지 않는다(`data-oversize`). 좁은 폭·큰 글자에서는 자식을 한 줄 요약으로 줄인다 | `affixRecipe.oversize: "flow"` |
|
|
65
67
|
|
|
@@ -84,3 +86,15 @@ Native 사용 예는 없다(renderer 없음).
|
|
|
84
86
|
|
|
85
87
|
- 콘텐츠가 스크롤 영역 높이에서 `offset`을 뺀 값보다 크면 고정이 풀리고 일반 흐름으로 돌아간다
|
|
86
88
|
(`data-oversize`). 고정이 안 된다고 보이면 콘텐츠 높이부터 확인한다.
|
|
89
|
+
|
|
90
|
+
## 근거
|
|
91
|
+
|
|
92
|
+
- `layer`·`fill`(2026-10-23 소비 감사): Affix가 z-index를 두지 않아 뒤에 오는 position 지정 내용이 고정된 탭 막대 위로 그려질 수 있었고,
|
|
93
|
+
`layoutStyle`로도 줄 수 없었다. 그래서 포트폴리오 사이트가 `.tabs-bar { position: sticky; z-index: 2; background: var(--hjm-color-bg) }`를
|
|
94
|
+
따로 유지했다. 숫자 z-index 대신 공통 `layer` 단계 이름으로 받고 기본을 BottomCTA·FAB와 같은 `sticky`로 둔다. 바탕 칠은 기존 동작(`canvas`)을
|
|
95
|
+
기본값으로 이름 붙이고 자식이 표면을 가질 때만 `none`을 고른다.
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
// 포트폴리오 사이트 탭 막대 이관 예: sticky·z-index·배경 CSS를 지운다
|
|
99
|
+
<Affix><Container size="content" gutter="regular"><Tabs … /></Container></Affix>
|
|
100
|
+
```
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
| --- | --- | --- | --- |
|
|
30
30
|
| `AlertDialog` | 기본 | `@hjmds/react`, `/overlays` | `@hjmds/react-native`, `/overlays` |
|
|
31
31
|
| `AlertDialogRequest` 타입 | 보조(문구·행동 descriptor) | `@hjmds/design-contracts/components/alert-dialog` | 같음 |
|
|
32
|
+
| `AlertDialogQueueProvider`·`useAlertDialogQueue` | 동반(명령형 확인과 대기열, 개발 소스·미게시) | `@hjmds/react/alert-dialog-queue` | `@hjmds/react-native/alert-dialog-queue` |
|
|
32
33
|
|
|
33
34
|
## 최소 사용 예
|
|
34
35
|
|
|
@@ -151,6 +152,33 @@ import { AlertDialog } from "@hjmds/react-native/overlays";
|
|
|
151
152
|
- Native에서 매우 긴 확인 문구는 본문이 스크롤되도록 바뀌었지만 큰 글자 실기기 검증은 끝나지 않았다([Dialog](../../dialog.md)).
|
|
152
153
|
문구를 자르거나 글자 크기 상한으로 피하지 않는다.
|
|
153
154
|
|
|
155
|
+
### 명령형 확인과 대기열 — `useAlertDialogQueue` (개발 소스·미게시)
|
|
156
|
+
|
|
157
|
+
화면 곳곳에서 "지울까요?"를 묻고 결과를 기다려야 하면 대화상자 상태를 화면마다 두지 않고 앱 루트(라우터 안)에 공급자를 한 번 둔다.
|
|
158
|
+
제품의 AppDialog 대기열·결과 Promise·route scope 구현을 이것으로 바꾼다(2026-10-23 번뚝 웹·앱).
|
|
159
|
+
|
|
160
|
+
```tsx
|
|
161
|
+
// 루트: route가 바뀌면 이전 화면의 질문은 interrupted로 끝난다.
|
|
162
|
+
<AlertDialogQueueProvider scope={pathname}>{children}</AlertDialogQueueProvider>
|
|
163
|
+
|
|
164
|
+
// 화면
|
|
165
|
+
const { open } = useAlertDialogQueue();
|
|
166
|
+
const result = await open({ mode: "confirm", tone: "danger", title: t("delete.title"), description: t("delete.body"),
|
|
167
|
+
confirmLabel: t("delete"), cancelLabel: t("cancel"), onConfirm: () => remove(id), fallbackErrorMessage: t("delete.failed") });
|
|
168
|
+
if (result.outcome === "confirmed") showDone();
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
| 항목 | 값 | 설명 |
|
|
172
|
+
| --- | --- | --- |
|
|
173
|
+
| `open(request, options?)` | `Promise<AlertDialogResult>` | 앞선 질문이 끝난 뒤 순서대로 뜬다. `{ outcome: "confirmed" }` 또는 `{ outcome: "cancelled", reason }`(`cancel-action`·`escape`·`back`·`programmatic`·`interrupted`) |
|
|
174
|
+
| `options` | Web `{ icon?, size? }`, Native `{ size?, returnFocusRef? }` | 요청별 표현. 문구·행동은 `request` |
|
|
175
|
+
| 공급자 `scope` | string | 질문의 주인(보통 route). 바뀌면 다른 scope 질문이 화면에서 내려가고 `interrupted` |
|
|
176
|
+
| 공급자 `modalPriority`·`portalContainer`(Web) | number · HTMLElement | 대기열 대화상자의 층(기본 0)과 portal. 필수 gate는 더 높은 우선순위 모달로 둔다 |
|
|
177
|
+
|
|
178
|
+
- `request.onConfirm`이 Promise면 처리 중에는 닫히지 않고, 실패하면 열린 채 `fallbackErrorMessage`를 보이며 `open`은 성공하거나 취소될 때까지 기다린다.
|
|
179
|
+
- 대화상자가 떠 있는 동안 trigger를 disabled로 두지 않는다. 배경은 이미 inert이고, disabled trigger로는 닫힌 뒤 초점이 돌아가지 못한다.
|
|
180
|
+
- 공급자 밖의 `useAlertDialogQueue`는 throw한다. 한 번에 하나의 Dialog·Sheet를 여는 `useDialog`/`useSheet`(`/overlay-stack`, Web)와는 별개다([계약](../../overlay-stack.md#결과를-돌려주는-확인-대기열--alertdialogqueueprovider-2026-10-23-개발-소스미게시)).
|
|
181
|
+
|
|
154
182
|
### 외부 확인 잠금 (checkout, 미게시)
|
|
155
183
|
|
|
156
184
|
`confirmDisabled`(기본 false)는 요청 제한 시간 등 제품이 판단한 확인 불가 조건이다. Web·Native 모두 확인 행동만 차단하며 취소는 유지한다. 비동기 처리 중 중복 실행·닫힘·실패 상태는 기존 세션이 계속 소유한다. 잠금을 해제해도 열린 세션과 실패 안내를 초기화하지 않는다. Spint의 내 글 내리기 재시도 제한을 공통 확인창에서도 보존하기 위해 추가했다.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
- 상태: 배포
|
|
5
5
|
- 지원: Web · Native
|
|
6
6
|
- 적용: 1.12.1
|
|
7
|
-
- 검토일: 2026-10-
|
|
7
|
+
- 검토일: 2026-10-23
|
|
8
8
|
- 근거: [Avatar fallback and Blobatar](../../avatar-fallback.md), recipe `avatarRecipe`(`src/component-recipes.ts`)
|
|
9
9
|
- 스토리북: `배포/컴포넌트/데이터 표시/아바타` · `배포/컴포넌트/데이터 표시/블로바타 캐릭터` · `배포/컴포넌트/데이터 표시/움직이는 블로바타 캐릭터`
|
|
10
10
|
|
|
@@ -67,14 +67,17 @@ import { Avatar } from "@hjmds/react-native/data-display";
|
|
|
67
67
|
|
|
68
68
|
| prop | 값 | 기본값 | 설명 |
|
|
69
69
|
| --- | --- | --- | --- |
|
|
70
|
-
| `name` | `string` | 필수 | 이니셜과 기본 접근성 이름의 원천. 공백뿐이면 `TypeError` |
|
|
70
|
+
| `name` | `string` | 의미 있는 아바타는 필수 | 이니셜과 기본 접근성 이름의 원천. 공백뿐이면 `TypeError`. `decorative`이면 생략할 수 있다(이니셜 없이 액자·대체 그림만) |
|
|
71
|
+
| `decorative` | `boolean` | `false` | 옆에 이름이 보이는 작성자 표시나 사람 없는 장식. Web은 루트 `aria-hidden`·`img alt=""`이고 `alt`를 함께 줄 수 없다. Native는 `accessibilityLabel`을 함께 줄 수 없다 |
|
|
71
72
|
| Web `src` · Native `source` | `string` · `ImageSourcePropType` | — | 사진이 없으면 prop을 뺀다. 주소(Native는 source 내용)가 바뀌면 실패 상태를 지우고 다시 시도한다 |
|
|
72
|
-
|
|
|
73
|
-
|
|
|
74
|
-
|
|
|
73
|
+
| `size` | `xxsmall`(22) · `xsmall`(28) · `small`(32) · `medium`(40) · `touch`(44) · `large`(48) · `xlarge`(64). Native는 기존 숫자(pt)도 받는다 | Web `medium` · Native 44(`touch`) | `avatarRecipe.sizes`. Native 숫자가 22 미만이면 `RangeError`(2026-10-23 전에는 24). 새 코드는 단계 이름을 쓴다 |
|
|
74
|
+
| `shape` | `circle` · `rounded` | `circle` | `rounded`는 `radius.md`(가장 가까운 디자인 프로필) |
|
|
75
|
+
| `frame` | `outlined` · `surface` · `none` | `outlined` | `avatarRecipe.frames`. `outlined`=canvas 바탕+1px 테두리(기존), `surface`=바탕만, `none`=바탕·테두리 없음(제품 그림이 액자를 채울 때) |
|
|
76
|
+
| `accessory` · `accessoryPlacement` | `ReactNode` · `bottom-end` · `top-end` | — · `bottom-end` | 팀 배지·상태 점 같은 모서리 표식. 아바타 상자 모서리(`avatarRecipe.accessory.offset` 0, Asset·IconTile처럼 바깥으로 나가는 거리)에 붙고 액자에 잘리지 않는다. 누르는 요소를 넣지 않는다 |
|
|
75
77
|
| `renderFallback` | `(context: { size: number; decorative: true }) => ReactNode` | — | 사진이 없거나 실패했을 때만 불린다. `size`는 px/pt 값. null·undefined를 돌려주면 기본 대체 표시(Web `fallback`→이니셜, Native 이니셜)를 쓴다 |
|
|
76
78
|
| Web `alt` | `string` | `name` | `""`이면 보조기기에서 숨긴다 |
|
|
77
|
-
| Web `imageProps` | `img` 속성(`alt`·`src` 제외) | — | `onError`는 `(event: SyntheticEvent<HTMLImageElement>) => void`이며 대체 표시로 바꾼 뒤
|
|
79
|
+
| Web `imageProps` | `img` 속성(`alt`·`src` 제외) | — | `onError`는 `(event: SyntheticEvent<HTMLImageElement>) => void`이며 대체 표시로 바꾼 뒤 불린다. `renderImage`와 함께 주면 `TypeError` |
|
|
80
|
+
| Web `renderImage` | `(props: AvatarImageRenderProps) => ReactNode` | 기본 `img` | `src`, `alt`(장식이면 `""`), `size`(px), `className`(`hjm-avatar__image`, 그대로 붙인다), 세대가 보호된 `onError`. `next/image` 등 제품 이미지 호스트를 연결한다(2026-10-23) |
|
|
78
81
|
| Native `accessibilityLabel` · `decorative` | `{ accessibilityLabel: string }` 또는 `{ decorative: true }` | — | 둘 중 하나가 타입으로 강제된다 |
|
|
79
82
|
| Native `renderImage` | `(context: AvatarImageRenderProps) => ReactNode` | 기본 Native Image | 제품의 이미지 캐시·표시 호스트를 연결한다(1.14.0 추가). `source`, `size`, HJM `fallback`, 세대가 보호된 `onError` 제공 |
|
|
80
83
|
| Native `initials` | `string` | 이름에서 계산 | 앞뒤 공백을 지우고 최대 3자, 대문자 |
|
|
@@ -85,7 +88,7 @@ import { Avatar } from "@hjmds/react-native/data-display";
|
|
|
85
88
|
|
|
86
89
|
| 항목 | 값 | 근거 |
|
|
87
90
|
| --- | --- | --- |
|
|
88
|
-
| 크기 |
|
|
91
|
+
| 크기 | `xxsmall` 22 · `xsmall` 28 · `small` 32 · `medium` 40 · `touch` 44 · `large` 48 · `xlarge` 64. 댓글·칩 안 작은 작성자 표시는 `xxsmall`/`xsmall`, 목록 행에는 Web `medium`/Native 기본, 프로필 머리에는 `xlarge`. 감싼 요소 크기(`h-8` 등)로 맞추지 말고 단계를 고른다. Avatar 자체는 터치 대상이 아니므로 누르는 프로필은 감싸는 행·버튼이 최소 44를 확보한다 | `.hjm-avatar[data-size]`, `react-native/src/data-display.tsx` |
|
|
89
92
|
| 간격 | 자체 바깥 여백이 없다. `AvatarGroup`은 크기의 30%만큼 겹치고 각 아바타에 `bg` 색 2px 테두리를 둘러 경계를 만든다 | `.hjm-avatar-group` |
|
|
90
93
|
| 순서·정렬 | 행·카드·댓글 머리의 시작 쪽에 두고 이름·본문이 끝 쪽으로 이어진다. `AvatarGroup`의 넘친 수 표시는 맨 끝에 온다 | `.hjm-avatar-group__overflow` |
|
|
91
94
|
| 고정·스크롤 | 고정 영역이 없다 | — |
|
|
@@ -93,6 +96,9 @@ import { Avatar } from "@hjmds/react-native/data-display";
|
|
|
93
96
|
|
|
94
97
|
## 꼭 지킬 것
|
|
95
98
|
|
|
99
|
+
- 장식인지 먼저 정한다. 같은 줄에 이름이 보이면 `decorative`로 숨기고, 아바타만 사람을 나타내면 `name`(Web)·`accessibilityLabel`(Native)을 준다.
|
|
100
|
+
- 크기·모양·테두리·모서리 표식을 감싸는 요소의 className·절대 좌표로 다시 만들지 않는다. `size`·`shape`·`frame`·`accessory`를 쓴다.
|
|
101
|
+
|
|
96
102
|
- `name`은 빈 문자열이면 `TypeError`다. 접근성 이름은 Avatar가 소유하고, 대체 그림은 장식으로만 그린다(버튼 등 상호작용 금지).
|
|
97
103
|
- Blobatar `seed`에는 공개 제품 식별자를 쓴다. 이름·이메일·자격증명은 seed로 쓰지 않는다.
|
|
98
104
|
- 사진·표시 이름·남은 인원 문구는 제품 소유다. `overflow`는 i18n 키로 만든다. `overflow`는 보조기기에서 숨겨지므로 전체 인원은 `label` 문구에 넣는다.
|
|
@@ -103,9 +109,10 @@ import { Avatar } from "@hjmds/react-native/data-display";
|
|
|
103
109
|
| 항목 | Web | Native |
|
|
104
110
|
| --- | --- | --- |
|
|
105
111
|
| 사진 | `src`(문자열), `imageProps`로 `img` 속성·`onError` 전달 | `source`(`ImageSourcePropType`). `imageStyle`은 제거된 속성 — layoutStyle 또는 `size` |
|
|
106
|
-
| 접근성 이름 | `alt`(기본 `name`), `alt=""`이면 숨김 | `accessibilityLabel` 필수, 또는 `decorative` |
|
|
112
|
+
| 접근성 이름 | `alt`(기본 `name`), `alt=""`이면 숨김, `decorative`면 루트까지 숨김 | `accessibilityLabel` 필수, 또는 `decorative` |
|
|
107
113
|
| 대체 표시 | `fallback` 노드 또는 이니셜 | `initials`(최대 3자) 또는 이니셜 |
|
|
108
|
-
| 크기·모양 축 |
|
|
114
|
+
| 크기·모양 축 | 단계 이름 · `circle`/`rounded` | 단계 이름 또는 숫자 · `circle`/`rounded` |
|
|
115
|
+
| 이미지 호스트 | `renderImage`(img 대신) 또는 `imageProps` | `renderImage`(HJM `fallback`도 전달) |
|
|
109
116
|
| 묶음 | `AvatarGroup` | 없음 |
|
|
110
117
|
|
|
111
118
|
2026-10-07 실제 Showcase 비교에서 `AvatarGroup`을 `ListRow.leading`에 넣으면 단일 이미지용
|
|
@@ -146,3 +153,17 @@ A→B→A로 되돌아와도 무시한다. source를 같은 값으로 재생성
|
|
|
146
153
|
기본 Native Image 경로는 그대로다. Web은 img/imageProps 경로를 사용하며 src가 바뀌면 요청 img 노드를 교체해 이전 DOM 오류가 새 사진의 대체 표시를 켜지 않도록 한다.
|
|
147
154
|
|
|
148
155
|
Web animated Blobatar는 IntersectionObserver를 사용할 수 없으면 같은 seed·표정의 정적 그림을 유지한다. 장식의 관찰 기능 미지원 때문에 Avatar 본문을 실패시키지 않는다.
|
|
156
|
+
|
|
157
|
+
### 작은 장식 아바타와 모서리 표식 (2026-10-23)
|
|
158
|
+
|
|
159
|
+
번뚝 `UserAvatar`(22·28·32·44, 투명 원 안의 생성 SVG)와 야잘알 `PlayerAvatar`(둥근 사각형, 모서리 팀 배지)가
|
|
160
|
+
Avatar를 쓰지 못한 이유(이름 필수, Web 이미지 호스트 없음, 4단 크기, Native 24 하한, 강제 테두리·바탕)를 공개 축으로 옮겼다.
|
|
161
|
+
|
|
162
|
+
```tsx
|
|
163
|
+
// Web: 작성자 이름 옆의 장식 아바타, 제품 SVG가 액자를 채운다
|
|
164
|
+
<Avatar decorative size="xsmall" frame="none" {...(svgUrl ? { src: svgUrl } : {})} fallback={emoji} />
|
|
165
|
+
|
|
166
|
+
// Native: 둥근 사각형 선수 사진 + 모서리 팀 배지
|
|
167
|
+
<Avatar name={player.name} accessibilityLabel={player.name} size="large" shape="rounded"
|
|
168
|
+
{...(uri ? { source: { uri } } : {})} accessory={<TeamBadge team={team} />} />
|
|
169
|
+
```
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
- 상태: 배포
|
|
5
5
|
- 지원: Web · Native
|
|
6
6
|
- 적용: 1.12.1
|
|
7
|
-
- 검토일: 2026-10-
|
|
7
|
+
- 검토일: 2026-10-23
|
|
8
8
|
- 근거: recipe `badgeRecipe`(`src/component-recipes.ts`)
|
|
9
9
|
- 스토리북: `배포/컴포넌트/데이터 표시/배지`
|
|
10
10
|
|
|
@@ -43,11 +43,25 @@ import { Badge } from "@hjmds/react-native/data-display";
|
|
|
43
43
|
<Badge tone="success" size="small" label={t("order.status.done")} />
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
왼쪽 → 라벨 → 오른쪽 순서로 배치한다. 아이콘 콜백은 배지 글자와 같은 `color
|
|
46
|
+
왼쪽 → 라벨 → 오른쪽 순서로 배치한다. 아이콘 콜백은 배지 글자와 같은 `color`, `glyph.xs`(14) `size`, Icon `regular`와 같은 선 굵기 `strokeWidth`(2, `badgeRecipe.iconStrokeWidth`)를 받는다. 제품 글리프 렌더러(Lucide 등)에 셋을 그대로 넘기고 Icon 노드를 따로 만들지 않는다(strokeWidth는 개발 소스, 미게시). Native는 실제 테마 색을, Web은 `currentColor`를 전달한다. 이 콜백 API는 미게시다. 아이콘은 장식이며 별도 누르기 동작을 넣지 않는다.
|
|
47
47
|
|
|
48
48
|
```tsx
|
|
49
49
|
// Web
|
|
50
|
-
<Badge tone="success" leading={({ color, size }) => <Trophy size={size} color={color} />} trailing={({ color, size }) => <Check size={size} color={color} />}>완료</Badge>
|
|
50
|
+
<Badge tone="success" leading={({ color, size, strokeWidth }) => <Trophy size={size} color={color} strokeWidth={strokeWidth} />} trailing={({ color, size }) => <Check size={size} color={color} />}>완료</Badge>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 제품 분류 색 — 개발 소스, 미게시
|
|
54
|
+
|
|
55
|
+
경기 시리즈·FA 등급처럼 **상태도 브랜드도 아닌 제품 분류**는 `tone` 대신 `categoryColor`에 테마별 색을 넣는다.
|
|
56
|
+
제품이 색을 정하고, HJM이 틀·글자 굵기·간격과 글자색을 정한다. `filled`는 `onStatusFill`(흰색)과 어두운 글자
|
|
57
|
+
(`badgeRecipe.category.darkInk`, 기본 light `text`) 중 대비가 높은 쪽을 고르고, `outline`은 그 색을 글자·테두리로 쓴다.
|
|
58
|
+
어느 쪽도 WCAG AA 4.5:1에 못 미치면(outline은 `bg`·`surface` 모두) `RangeError`를 던진다. 어두운 테마에서 읽히지 않는 색은
|
|
59
|
+
`dark` 값을 따로 준다. `tone`과 함께 주면 `TypeError`다.
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
// Native
|
|
63
|
+
const seriesColor = { light: "#216BA8", dark: "#216BA8" } as const; // 제품 분류 정의
|
|
64
|
+
<Badge size="small" label={t("series.regular")} categoryColor={seriesColor} />
|
|
51
65
|
```
|
|
52
66
|
|
|
53
67
|
## 축과 기본값
|
|
@@ -55,6 +69,7 @@ import { Badge } from "@hjmds/react-native/data-display";
|
|
|
55
69
|
| prop | 값 | 기본값 | 설명 |
|
|
56
70
|
| --- | --- | --- | --- |
|
|
57
71
|
| `tone` | `neutral` · `strong` · `brand` · `info` · `success` · `warning` · `attention` · `danger` | `neutral` | 단색 배경과 흰색 굵은 글자를 사용한다. `neutral`은 회색, `strong`은 더 진한 회색, 나머지는 각 의미의 solid fill이다. `outline`은 투명 배경과 의미색 글자다 |
|
|
72
|
+
| `categoryColor` | `{ light: string; dark: string }`(6자리 hex) | — | `tone` 대신 쓰는 제품 분류 색. 글자색은 HJM이 고르고 AA를 검사한다(위 절). 개발 소스, 미게시 |
|
|
58
73
|
| `variant` | `filled` · `outline` | `filled` | — |
|
|
59
74
|
| `size` | `small` · `medium` | `medium` | — |
|
|
60
75
|
| `leading` · `trailing` | `ReactNode \| (context: BadgeAdornmentContext) => ReactNode` | — | 라벨 왼쪽·오른쪽 아이콘. 양쪽 동시 사용 가능하며 보조기기에서 숨겨진다 |
|
|
@@ -62,7 +77,7 @@ import { Badge } from "@hjmds/react-native/data-display";
|
|
|
62
77
|
| Native `accessibilityLabel` | `string` | `String(label)` | 숫자 라벨에 단위를 붙여 읽힐 때 쓴다 |
|
|
63
78
|
| `layoutStyle` | margin·width·flex·`alignSelf` | — | 배치 전용. Native `style`·`labelStyle`은 제거된 속성 — layoutStyle 또는 tone/토큰 |
|
|
64
79
|
|
|
65
|
-
행동 콜백은 없다. 아이콘 렌더 콜백은
|
|
80
|
+
행동 콜백은 없다. 아이콘 렌더 콜백은 색·크기·선 굵기만 받으며 배지는 누를 수 없는 표시다.
|
|
66
81
|
|
|
67
82
|
상태 채움의 글자·아이콘은 `onStatusFill`, 브랜드 채움은 `onPrimary`, 위험 채움은 `onDanger`를 쓴다. 브랜드의 전경색이 어두워도 상태 배지의 대비를 독립적으로 유지하기 위한 역할 분리다(미게시).
|
|
68
83
|
|
|
@@ -81,7 +96,7 @@ Web·Native 모두 `radius.sm`(8)의 둥근 사각형을 사용한다. 2026-10-1
|
|
|
81
96
|
## 꼭 지킬 것
|
|
82
97
|
|
|
83
98
|
- 라벨은 i18n 키로 넣고 짧게 둔다. 상태 뜻을 색에만 싣지 않는다(글자가 뜻을 말해야 한다).
|
|
84
|
-
- 색은 `tone
|
|
99
|
+
- 색은 `tone`으로 고르고, 제품 분류 색만 `categoryColor`로 넣는다. 브랜드 색을 `style`·`className`·`labelStyle`로 덮거나 배지 하나를 `brandPalette` Provider로 감싸지 않는다(2026-10-23 야잘알 GameSeriesBadge·FA 등급 감사: Provider 중첩은 그 범위의 모든 토큰을 바꾼다).
|
|
85
100
|
- 배치는 Web·Native 모두 `layoutStyle`로만 한다. Native `style`·`labelStyle`은 제거된 속성이다.
|
|
86
101
|
|
|
87
102
|
## 플랫폼 차이
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
- 상태: 배포
|
|
5
5
|
- 지원: Web · Native
|
|
6
6
|
- 적용: 1.21.0
|
|
7
|
-
- 검토일: 2026-10-
|
|
7
|
+
- 검토일: 2026-10-23
|
|
8
8
|
- 근거: [Chart](../../chart.md), `src/chart.ts`(`chartRecipe`, `describeChart`, `resolveLineGeometry`), `src/dataviz.ts`(`resolveDatavizSeriesColor`, `datavizChromeTokens`)
|
|
9
9
|
- 스토리북: `배포/컴포넌트/데이터 표시/차트`
|
|
10
10
|
|
|
@@ -181,6 +181,7 @@ import { BarChart, Sparkline } from "@hjmds/react-native/chart";
|
|
|
181
181
|
| `width`·`height`(`Sparkline`) | `number` | 72 · 28 | `chartRecipe.sparkline` |
|
|
182
182
|
| `accessibilityLabel`(`Sparkline`) | `string` | — | 없으면 장식(보조 기술에서 숨김) |
|
|
183
183
|
| `items`(`ChartLegend`) | `{ id, label, color, value?: string }[]` | — (필수) | `value`는 서식이 끝난 문자열 |
|
|
184
|
+
| `layout`(`ChartLegend`) | `stack` · `inline` | Web: `onSelect` 없으면 `inline`, 있으면 `stack` · Native: `stack` | `stack`은 계열마다 한 행(Native 최소 높이 `chartRecipe.legend.layouts.stack.rowMinHeight` 32, 값은 끝 정렬). `inline`은 항목을 한 줄로 흘리고 넘치면 다음 줄로 감는다(항목 사이 `spacing.md` 16, 줄 사이 `spacing.xxs` 4, 견본·이름·값 사이 `spacing.xs` 8). 지도·차트 아래 짧은 범례에 쓴다(개발 소스, 미게시) |
|
|
184
185
|
|
|
185
186
|
## 배치
|
|
186
187
|
|
|
@@ -284,3 +285,20 @@ Native centerContent에는 Text 등 Native 노드를 쓴다. 모두 제외하거
|
|
|
284
285
|
2026-10-21 포트폴리오의 성긴 일별 관측이 끊겨 읽기 어렵다는 사용자 요청으로 `bridge`를 추가했다. 실제 관측선과 결측 연결 안내선을 구분하며 0 채움·수치 보간은 수행하지 않는다.
|
|
285
286
|
|
|
286
287
|
2026-10-23 오늘야구 선수 최근 7시즌 화면에서 앞쪽 결측의 경계 점선이 빠진 문제를 수정했다(개발 소스, 미게시). 앞·뒤 결측도 실제 관측값 위치에서 하단까지 표시하며, 관측값이 전혀 없으면 점선을 만들지 않는다.
|
|
288
|
+
|
|
289
|
+
2026-10-23 소비 감사: 선택의창 지도 하단의 한 줄 범례(`RouteMapScreen`의 PlaceDot + caption 묶음)는 Native ChartLegend가
|
|
290
|
+
행을 세로로만 쌓아 채택하지 못했다. `layout="inline"`으로 항목을 가로로 흘려 감고, 견본·간격·흐린 정도는
|
|
291
|
+
`chartRecipe.legend`가 소유한다. 알약 모양 바탕은 범례가 아니라 지도 위에 띄우는 제품 구성이므로 `Surface radius="full"`로
|
|
292
|
+
감싼다. Web의 기본값(선택 버튼이 없으면 가로)은 1.41 동작 그대로이며, Native 기본값은 기존 소비 화면(야잘알 StockChart)을
|
|
293
|
+
바꾸지 않도록 `stack`으로 둔다. 두 플랫폼 기본값의 차이는 기존 동작이며 통일은 별도 결정이다.
|
|
294
|
+
|
|
295
|
+
```tsx
|
|
296
|
+
// Native: 선택의창 지도 범례
|
|
297
|
+
<Surface tone="raised" radius="full" padding="xs">
|
|
298
|
+
<ChartLegend layout="inline" items={[
|
|
299
|
+
{ id: "left", label: t("mapLegendLeft"), color: mapColors.leftExposure },
|
|
300
|
+
{ id: "right", label: t("mapLegendRight"), color: mapColors.rightExposure },
|
|
301
|
+
{ id: "neutral", label: t("mapLegendNeutral"), color: mapColors.neutralExposure },
|
|
302
|
+
]} />
|
|
303
|
+
</Surface>
|
|
304
|
+
```
|
|
@@ -70,6 +70,11 @@ import { Text } from "@hjmds/react-native/primitives";
|
|
|
70
70
|
2026-10-16 사용자 결정으로 대화 타임라인의 공통 기준을 카카오톡 iOS 채팅방 실측(@3x 캡처)으로 바꿨다.
|
|
71
71
|
묶음 단위 표시·촘촘한 말풍선·시각 위치를 흡수했고 노란 말풍선 같은 브랜드 색은 가져오지 않았다(색은 semantic token).
|
|
72
72
|
|
|
73
|
+
수신 말풍선 본체·꼬리와 입력 중 표시는 `surfaceAlt`, 발신은 `primary`와 `onPrimary`를 사용한다. 발신 내부 HJM Text의 중립 tone은 밝은 글자를 상속하고 명시적 색·브랜드·위험 tone은 보존한다.
|
|
74
|
+
답글 원문은 3px 세로 강조선과 8px 안쪽 간격으로 구분한다(수신 `contentBrand`, 발신 `onPrimary`).
|
|
75
|
+
아이메시지의 수신/발신 표면 대비와 텔레그램의 인용 강조를 참고했다: https://support.apple.com/guide/iphone/about-imessage-iph4e9799206/ios · https://telegram.org/blog/reply-revolution
|
|
76
|
+
2026-10-23 밝은 기본 테마에서 `surface`와 채팅 배경이 모두 흰색이라 수신 말풍선이 사라진 문제를 수정했다.
|
|
77
|
+
|
|
73
78
|
## 축과 기본값
|
|
74
79
|
|
|
75
80
|
| prop | 값 | 기본값 | 설명 |
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# ChatRoomActions
|
|
2
|
+
|
|
3
|
+
- 단계: 컴포넌트
|
|
4
|
+
- 상태: 배포
|
|
5
|
+
- 지원: Web · Native
|
|
6
|
+
- 적용: 1.43.0
|
|
7
|
+
- 검토일: 2026-10-23
|
|
8
|
+
- 근거: 양 renderer `src/communication.tsx`와 [채팅방 비교·구성 지침](../compositions/chat-room.md)
|
|
9
|
+
- 스토리북: `배포/구성/입력과 작성/채팅방 관리`
|
|
10
|
+
|
|
11
|
+
## 언제 쓰나
|
|
12
|
+
|
|
13
|
+
나가기·내 기록 삭제·방 삭제를 구분해 확인한다.
|
|
14
|
+
|
|
15
|
+
## 쓰지 않을 때
|
|
16
|
+
|
|
17
|
+
| 상황 | 대신 쓸 것 |
|
|
18
|
+
| --- | --- |
|
|
19
|
+
| 메시지 기록과 작성창만 필요한 화면 | [ChatScreen](chat-screen.md) |
|
|
20
|
+
| 제품의 서버·권한·저장 규칙 구현 | 제품 데이터 계층 |
|
|
21
|
+
|
|
22
|
+
## 공개 이름과 import
|
|
23
|
+
|
|
24
|
+
| 이름 | 역할 | Web | Native |
|
|
25
|
+
| --- | --- | --- | --- |
|
|
26
|
+
| `ChatRoomActions` | 나가기·내 기록 삭제·방 삭제를 구분해 확인한다. | `@hjmds/react/communication` | `@hjmds/react-native/communication` |
|
|
27
|
+
|
|
28
|
+
## 최소 사용 예
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
// Web
|
|
32
|
+
import { ChatRoomActions } from "@hjmds/react/communication";
|
|
33
|
+
<ChatRoomActions leave={leaveConfirmation} deleteHistory={historyConfirmation} />
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
// Native
|
|
38
|
+
import { ChatRoomActions } from "@hjmds/react-native/communication";
|
|
39
|
+
<ChatRoomActions leave={leaveConfirmation} deleteHistory={historyConfirmation} />
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Native는 동일 prop 계약으로 `@hjmds/react-native/communication`에서 가져온다. 전체 실행 예제와 연결 props는 [채팅방 관리](../compositions/chat-room.md)의 양 플랫폼 예제를 따른다.
|
|
43
|
+
|
|
44
|
+
## 배치
|
|
45
|
+
|
|
46
|
+
| 항목 | 값 | 근거 |
|
|
47
|
+
| --- | --- | --- |
|
|
48
|
+
| 크기 | 부모 본문 폭, 프로필 Avatar 64·참여자 40 | 기존 Avatar·ListRow recipe |
|
|
49
|
+
| 간격 | 내부 sm·입력 md·그룹 lg | 양 renderer 공통 구성 |
|
|
50
|
+
| 순서·정렬 | 상단 탐색·확인 → 작업 본문 → 오류 | 구성 소스 |
|
|
51
|
+
| 고정·스크롤 | 스크롤·키보드 처리는 host 소유 | 웹·Native의 화면 host 계약 |
|
|
52
|
+
| 좁은 폭 | 도구 동폭, 이름·설명 줄바꿈 | 공통 레이아웃 |
|
|
53
|
+
|
|
54
|
+
## 꼭 지킬 것
|
|
55
|
+
|
|
56
|
+
leave·deleteHistory·deleteRoom은 독립 선택 prop이다. label·title·description·confirmLabel·cancelLabel·errorLabel·onConfirm을 전달한다.
|
|
57
|
+
|
|
58
|
+
데이터·문구·권한은 제품이 소유한다. 저장·개설·초대·삭제는 실제 성공 뒤 Promise를 resolve하고 실패는 reject한다. 입력과 선택은 실패 시 유지한다. Storybook의 메모리 예제를 운영 저장으로 사용하지 않는다. 방 전환 시 `key={roomId}`로 작업 수명을 구분한다.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# ChatRoomCreate
|
|
2
|
+
|
|
3
|
+
- 단계: 컴포넌트
|
|
4
|
+
- 상태: 배포
|
|
5
|
+
- 지원: Web · Native
|
|
6
|
+
- 적용: 1.43.0
|
|
7
|
+
- 검토일: 2026-10-23
|
|
8
|
+
- 근거: 양 renderer `src/communication.tsx`와 [채팅방 비교·구성 지침](../compositions/chat-room.md)
|
|
9
|
+
- 스토리북: `배포/구성/입력과 작성/채팅방 관리`
|
|
10
|
+
|
|
11
|
+
## 언제 쓰나
|
|
12
|
+
|
|
13
|
+
참여자를 검색·선택하고 사진·이름을 정해 방을 개설한다.
|
|
14
|
+
|
|
15
|
+
## 쓰지 않을 때
|
|
16
|
+
|
|
17
|
+
| 상황 | 대신 쓸 것 |
|
|
18
|
+
| --- | --- |
|
|
19
|
+
| 메시지 기록과 작성창만 필요한 화면 | [ChatScreen](chat-screen.md) |
|
|
20
|
+
| 제품의 서버·권한·저장 규칙 구현 | 제품 데이터 계층 |
|
|
21
|
+
|
|
22
|
+
## 공개 이름과 import
|
|
23
|
+
|
|
24
|
+
| 이름 | 역할 | Web | Native |
|
|
25
|
+
| --- | --- | --- | --- |
|
|
26
|
+
| `ChatRoomCreate` | 참여자를 검색·선택하고 사진·이름을 정해 방을 개설한다. | `@hjmds/react/communication` | `@hjmds/react-native/communication` |
|
|
27
|
+
|
|
28
|
+
## 최소 사용 예
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
// Web
|
|
32
|
+
import { ChatRoomCreate } from "@hjmds/react/communication";
|
|
33
|
+
<ChatRoomCreate {...roomDraftProps} {...memberSelectionProps} {...navigationLabels} onCreate={createRoom} />
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
// Native
|
|
38
|
+
import { ChatRoomCreate } from "@hjmds/react-native/communication";
|
|
39
|
+
<ChatRoomCreate {...roomDraftProps} {...memberSelectionProps} {...navigationLabels} onCreate={createRoom} />
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Native는 동일 prop 계약으로 `@hjmds/react-native/communication`에서 가져온다. 전체 실행 예제와 연결 props는 [채팅방 관리](../compositions/chat-room.md)의 양 플랫폼 예제를 따른다.
|
|
43
|
+
|
|
44
|
+
## 배치
|
|
45
|
+
|
|
46
|
+
| 항목 | 값 | 근거 |
|
|
47
|
+
| --- | --- | --- |
|
|
48
|
+
| 크기 | 부모 본문 폭, 프로필 Avatar 64·참여자 40 | 기존 Avatar·ListRow recipe |
|
|
49
|
+
| 간격 | 내부 sm·입력 md·그룹 lg | 양 renderer 공통 구성 |
|
|
50
|
+
| 순서·정렬 | 상단 탐색·확인 → 작업 본문 → 오류 | 구성 소스 |
|
|
51
|
+
| 고정·스크롤 | 스크롤·키보드 처리는 host 소유 | 웹·Native의 화면 host 계약 |
|
|
52
|
+
| 좁은 폭 | 도구 동폭, 이름·설명 줄바꿈 | 공통 레이아웃 |
|
|
53
|
+
|
|
54
|
+
## 꼭 지킬 것
|
|
55
|
+
|
|
56
|
+
선택 없이 다음으로 갈 수 없고 빈 이름으로 개설할 수 없다. onCreate는 실제 구성원 ID와 프로필을 받는다.
|
|
57
|
+
|
|
58
|
+
데이터·문구·권한은 제품이 소유한다. 저장·개설·초대·삭제는 실제 성공 뒤 Promise를 resolve하고 실패는 reject한다. 입력과 선택은 실패 시 유지한다. Storybook의 메모리 예제를 운영 저장으로 사용하지 않는다. 방 전환 시 `key={roomId}`로 작업 수명을 구분한다.
|