@hjmds/design-contracts 1.46.0 → 1.47.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 +2 -1
- package/dist/behaviors.d.ts.map +1 -1
- package/dist/bottom-navigation.d.ts +4 -0
- package/dist/bottom-navigation.d.ts.map +1 -1
- package/dist/bottom-navigation.js +12 -0
- package/dist/bottom-navigation.js.map +1 -1
- package/dist/card.d.ts +2 -2
- package/dist/card.d.ts.map +1 -1
- package/dist/card.js +3 -2
- package/dist/card.js.map +1 -1
- package/dist/carousel.d.ts +1 -0
- package/dist/carousel.d.ts.map +1 -1
- package/dist/carousel.js +1 -0
- package/dist/carousel.js.map +1 -1
- package/dist/catalog.d.ts +130 -14
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +4 -3
- package/dist/catalog.js.map +1 -1
- package/dist/color-picker.d.ts +51 -1
- package/dist/color-picker.d.ts.map +1 -1
- package/dist/color-picker.js +56 -2
- package/dist/color-picker.js.map +1 -1
- package/dist/component-recipes.d.ts +23 -9
- package/dist/component-recipes.d.ts.map +1 -1
- package/dist/component-recipes.js +24 -18
- package/dist/component-recipes.js.map +1 -1
- package/dist/conversation-row.d.ts +1 -1
- package/dist/conversation-row.d.ts.map +1 -1
- package/dist/conversation-row.js +2 -1
- package/dist/conversation-row.js.map +1 -1
- package/dist/date-range.d.ts +122 -3
- package/dist/date-range.d.ts.map +1 -1
- package/dist/date-range.js +139 -5
- package/dist/date-range.js.map +1 -1
- package/dist/icon.d.ts +2 -1
- package/dist/icon.d.ts.map +1 -1
- package/dist/icon.js +2 -0
- package/dist/icon.js.map +1 -1
- package/dist/recipes.d.ts +1 -0
- package/dist/recipes.d.ts.map +1 -1
- package/dist/recipes.js +1 -0
- package/dist/recipes.js.map +1 -1
- package/dist/screen-patterns.d.ts +33 -2
- package/dist/screen-patterns.d.ts.map +1 -1
- package/dist/screen-patterns.js +27 -2
- package/dist/screen-patterns.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/bottom-navigation.md +16 -0
- package/docs/color-picker.md +24 -19
- package/docs/generated/component-maturity.md +3 -3
- package/docs/generated/renderer-evidence.json +59 -7
- package/docs/generated/renderer-evidence.md +3 -2
- package/docs/generated/showcase-manifest.json +18 -4
- package/docs/usage/README.md +5 -2
- package/docs/usage/SELECTION.md +109 -0
- package/docs/usage/components/avatar.md +31 -6
- package/docs/usage/components/bottom-navigation.md +16 -0
- package/docs/usage/components/button.md +11 -0
- package/docs/usage/components/card.md +6 -0
- package/docs/usage/components/chat-message.md +10 -2
- package/docs/usage/components/chat-room-members.md +4 -0
- package/docs/usage/components/chat-screen.md +10 -1
- package/docs/usage/components/color-picker.md +65 -28
- package/docs/usage/components/comment-thread-screen.md +16 -1
- package/docs/usage/components/conversation-list-screen.md +81 -0
- package/docs/usage/components/conversation-row.md +5 -1
- package/docs/usage/components/date-range-picker.md +15 -5
- package/docs/usage/components/event-attendance-card.md +4 -0
- package/docs/usage/components/follow-list-screen.md +109 -0
- package/docs/usage/components/follow-profile-card.md +4 -0
- package/docs/usage/components/list-row.md +6 -0
- package/docs/usage/components/menu.md +12 -0
- package/docs/usage/components/notice.md +8 -3
- package/docs/usage/components/notification-inbox-screen.md +10 -0
- package/docs/usage/components/notification-row.md +4 -0
- package/docs/usage/components/page-indicator.md +1 -0
- package/docs/usage/components/profile-summary.md +32 -3
- package/docs/usage/components/section.md +2 -2
- package/docs/usage/components/settings-screen.md +1 -1
- package/docs/usage/components/sheet.md +1 -0
- package/docs/usage/components/statistic.md +1 -1
- package/docs/usage/compositions/web-additions.md +5 -5
- package/docs/usage/screens/common-comments.md +1 -0
- package/docs/usage/screens/common-conversation-list.md +22 -1
- package/docs/usage/screens/common-follow-list.md +87 -0
- package/docs/usage/screens/common-settings.md +23 -0
- package/package.json +1 -1
package/dist/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,MAAM,CAAC,MAAM,mBAAmB,GAAG,QAAiB,CAAC","sourcesContent":["/** Package release shown by documentation surfaces. Kept in sync by a test. */\nexport const designSystemVersion = \"1.
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,MAAM,CAAC,MAAM,mBAAmB,GAAG,QAAiB,CAAC","sourcesContent":["/** Package release shown by documentation surfaces. Kept in sync by a test. */\nexport const designSystemVersion = \"1.47.0\" as const;\n"]}
|
|
@@ -208,3 +208,19 @@ Utilverse는 1.31.0 채택 뒤에도 셸마다 다른 막대 틀(둥근 독·알
|
|
|
208
208
|
라벨 외의 비색상 선택 근거가 된다. 배지와 `prominent` 원은 흐리지 않는다.
|
|
209
209
|
- 막대 바탕색은 기존 팔레트 역할(canvas)이고 테마별 색은 `brandPalette`로 바꾼다. 높이는 `density`와 `iconSize`가 정한다.
|
|
210
210
|
같은 의미의 값을 새 축으로 중복하지 않았다.
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
## 타일 바탕과 선택 강조 분리 (2026-10-25)
|
|
214
|
+
|
|
215
|
+
오늘야구에서 선택된 파란 타일은 유지하면서 바탕을 흰색으로 사용하려는 요청으로
|
|
216
|
+
`configuration.tone: "brand" | "neutral"`을 추가했다. 기본 `brand`는 기존 surfaceAccent 바탕을 유지한다.
|
|
217
|
+
`neutral`은 `semanticColors.surface.default`(테마의 surface)를 사용한다. 라이트 기본 테마에서는 흰색,
|
|
218
|
+
다크에서는 어두운 공통 표면이며 선택 타일의 primary/onPrimary와 모양·간격·동작은 유지한다.
|
|
219
|
+
flat tile 전용이며 raised 표면과 함께 지정하면 오류다. 앱에서 팔레트나 style을 덮어쓰지 않는다.
|
|
220
|
+
|
|
221
|
+
```tsx
|
|
222
|
+
configuration={{ presentation: "floating", selection: "tile", tone: "neutral" }}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Web·Native의 `NeutralTiles`와 `NeutralTilesDark` Storybook 예제가 같은 공개 API를 사용한다.
|
|
226
|
+
로컬 개발 API이며 게시된 패키지 지원은 해당 릴리스에 포함된 뒤 확인한다.
|
package/docs/color-picker.md
CHANGED
|
@@ -1,30 +1,35 @@
|
|
|
1
|
-
# ColorPicker —
|
|
1
|
+
# ColorPicker — sRGB 색상 입력
|
|
2
2
|
|
|
3
|
-
2026-09-30: 사용자가 남은 세 후보의 개발을 명시적으로 요청하여 기존 수요 대기 결정을 대체했다.
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
2026-09-30: 사용자가 남은 세 후보의 개발을 명시적으로 요청하여 기존 수요 대기 결정을 대체했다. 처음에는 Web만 포함했다.
|
|
4
|
+
2026-10-25: Diairy 손그림 프로필 요청으로 Native 개발 후보를 추가했고, 같은 날 사용자 요청("다른 곳 인사이트를 얻으며 개편")으로
|
|
5
|
+
브라우저 색 팝업(Web)·RGB 막대(Native)를 HSV 편집기로 바꿨다. 저장값은 그대로 HEX sRGB다. HSV는 편집할 때만 쓰는 좌표다.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
`ColorPicker`는 controlled `value`와 `onValueChange`를 받는다. `label`과 `labels.hex`·`hue`·`saturation`·`brightness`·`opacity`·`invalid`
|
|
8
|
+
(프리셋이 있으면 `presets`)는 제품에서 번역하여 전달한다. `alpha`가 false면 `#rrggbb`, true면 `#rrggbbaa`를 내보낸다.
|
|
9
|
+
3·4자리 축약 HEX도 입력할 수 있다. alpha가 켜진 상태에서 3·6자리 HEX를 입력하면 색만 바꾸고 현재 투명도를 유지한다.
|
|
10
10
|
alpha를 끈 상태에서 불투명하지 않은 값을 전달하면 투명도를 조용히 버리지 않고 거부한다.
|
|
11
11
|
|
|
12
|
-
-
|
|
12
|
+
- 채도·밝기 영역: 가로가 채도, 세로가 밝기다. 누른 자리로 바로 이동하고 끄는 동안 연속으로 바뀐다. 상위 스크롤에 터치를 넘기지 않는다.
|
|
13
|
+
Web은 영역 안의 두 range(채도·밝기)로 키보드·보조기술을 지원한다. Native는 adjustable 하나로 밝기 증감, 사용자 정의 행동으로 채도 증감을 준다.
|
|
14
|
+
- 색조 막대 0–360°, 불투명도 막대 0–100%. Web은 range, Native는 HJM Slider의 제스처·접근성 로직을 내부 색 트랙으로 재사용한다.
|
|
15
|
+
- 검정·회색에서 사라지는 색조·채도는 직전 값을 유지한다(`pickerHsv(value, previous)`). HEX ↔ HSV는 모든 HEX가 원래 값으로 돌아온다(계약 테스트).
|
|
16
|
+
- HEX는 Enter/blur(Native submit/blur)에 확정한다. 잘못된 입력은 오류를 보여주고 외부 값은 유지한다.
|
|
13
17
|
Escape는 마지막 controlled 값으로 복구하며 Enter가 상위 폼을 제출하지 않게 한다.
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
|
|
18
|
-
- 제어부는 HJM canvas·border·focus 토큰을 사용한다. 견본의 사용자 색상은 콘텐츠 데이터다.
|
|
19
|
-
선택색을 제품의 본문/배경으로 사용할 때의 대비는 제품이 확인한다.
|
|
18
|
+
- `presets`는 `ColorSwatchPicker`(라디오 의미의 둥근 견본)로 그린다. 중복값은 정규화 후 제거한다.
|
|
19
|
+
- `disabled`는 모든 입력과 견본을 비활성화한다.
|
|
20
|
+
- 제어부는 HJM canvas·border·focus 토큰을 사용한다. 손잡이의 흰 테두리·그림자와 투명 체크 무늬는 어떤 색 위에서도 보이게 하는 고정값이다.
|
|
21
|
+
견본의 사용자 색상은 콘텐츠 데이터다. 선택색을 제품의 본문/배경으로 사용할 때의 대비는 제품이 확인한다.
|
|
20
22
|
|
|
21
23
|
```tsx
|
|
22
24
|
<ColorPicker label={t('color.title')} labels={{
|
|
23
|
-
|
|
25
|
+
hex: 'HEX', hue: t('color.hue'), saturation: t('color.saturation'), brightness: t('color.brightness'),
|
|
26
|
+
opacity: t('color.opacity'), invalid: t('color.invalid'), presets: t('color.presets'),
|
|
24
27
|
}} value={color} onValueChange={setColor} alpha presets={['#b94627ff', '#338844ff']} />
|
|
25
28
|
```
|
|
26
29
|
|
|
27
|
-
계약: [color-picker.ts](../src/color-picker.ts). UI: [
|
|
28
|
-
사용
|
|
29
|
-
|
|
30
|
-
[
|
|
30
|
+
계약: [color-picker.ts](../src/color-picker.ts). UI: [Web](../../react/src/color-picker.tsx), [Native](../../react-native/src/color-picker.tsx).
|
|
31
|
+
사용 지침: [usage/components/color-picker.md](usage/components/color-picker.md).
|
|
32
|
+
사용 예제: [Web additions](../../../showcase/web/src/patterns/WebAdditions.stories.tsx), [Native](../../../showcase/native/src/ColorPicker.stories.tsx).
|
|
33
|
+
검증: [계약 회귀](../test/web-additions.test.ts), [Web 동작](../../react/test/web-additions.browser.test.tsx),
|
|
34
|
+
[Native 동작](../../react-native/test/color-picker.test.tsx), [환경 행렬](../../react/test/scenario-matrix.browser.test.tsx).
|
|
35
|
+
Native는 `react-native-svg`가 필요하며 패키지 게시·기기 검증은 별도다.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# Component maturity and evidence manifest
|
|
2
2
|
|
|
3
|
-
> Generated from `@hjmds/design-contracts` 1.
|
|
3
|
+
> Generated from `@hjmds/design-contracts` 1.47.0. Do not edit this file directly; run `pnpm contracts:sync`.
|
|
4
4
|
|
|
5
5
|
This document is the human-readable projection of the same catalog and Showcase manifest consumed by product CI.
|
|
6
6
|
|
|
7
7
|
- Contract: stable 126 · beta 5
|
|
8
8
|
- Web renderer: stable 126 · beta 5
|
|
9
|
-
- Native renderer: stable 106 · beta
|
|
9
|
+
- Native renderer: stable 106 · beta 8 · unsupported 17
|
|
10
10
|
|
|
11
11
|
| Component | Canonical story ID | Contract | Web | Native | Documentation | Required evidence |
|
|
12
12
|
| --- | --- | --- | --- | --- | --- | --- |
|
|
@@ -54,7 +54,7 @@ This document is the human-readable projection of the same catalog and Showcase
|
|
|
54
54
|
| TimePicker | `input/time-picker` | stable | stable | stable | [authored](../time-picker.md) | contract: contract; web: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, keyboard; native: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, native-actions |
|
|
55
55
|
| DatePicker | `input/date-picker` | stable | stable | stable | [authored](../date-picker.md) | contract: contract; web: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, keyboard; native: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, native-actions |
|
|
56
56
|
| DateRangePicker | `input/date-range-picker` | stable | stable | stable | generated only | contract: contract; web: default, dark, large-text, rtl, reduced-motion, accessibility, keyboard; native: default, dark, large-text, rtl, reduced-motion, accessibility, native-actions |
|
|
57
|
-
| ColorPicker | `input/color-picker` | stable | stable |
|
|
57
|
+
| ColorPicker | `input/color-picker` | stable | stable | beta | [authored](../color-picker.md) | contract: contract; web: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, keyboard; native: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility |
|
|
58
58
|
| FilePicker | `input/file-picker` | stable | stable | stable | [authored](../file-picker.md) | contract: contract; web: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, keyboard; native: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, native-actions |
|
|
59
59
|
| Form | `input/form` | stable | stable | stable | [authored](../form.md) | contract: contract; web: default, dark, large-text, rtl, reduced-motion, accessibility, keyboard; native: default, dark, large-text, rtl, reduced-motion, accessibility, native-actions |
|
|
60
60
|
| Agreement | `input/agreement` | stable | stable | stable | [authored](../agreement.md) | contract: contract; web: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, keyboard; native: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, native-actions |
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"designSystemVersion": "1.
|
|
3
|
+
"designSystemVersion": "1.47.0",
|
|
4
4
|
"source": "packages/design-contracts/docs/generated/showcase-manifest.json",
|
|
5
5
|
"surfaces": {
|
|
6
6
|
"web": {
|
|
7
7
|
"packageName": "@hjmds/react",
|
|
8
|
-
"packageVersion": "1.
|
|
8
|
+
"packageVersion": "1.47.0",
|
|
9
9
|
"activeComponents": 131,
|
|
10
10
|
"claimedComponents": 131,
|
|
11
11
|
"completeScenarioComponents": 130,
|
|
@@ -2424,7 +2424,8 @@
|
|
|
2424
2424
|
"claimed": true,
|
|
2425
2425
|
"subpath": "./color-picker",
|
|
2426
2426
|
"exportNames": [
|
|
2427
|
-
"ColorPicker"
|
|
2427
|
+
"ColorPicker",
|
|
2428
|
+
"ColorSwatchPicker"
|
|
2428
2429
|
],
|
|
2429
2430
|
"proofs": [
|
|
2430
2431
|
{
|
|
@@ -7063,10 +7064,10 @@
|
|
|
7063
7064
|
},
|
|
7064
7065
|
"native": {
|
|
7065
7066
|
"packageName": "@hjmds/react-native",
|
|
7066
|
-
"packageVersion": "1.
|
|
7067
|
-
"activeComponents":
|
|
7068
|
-
"claimedComponents":
|
|
7069
|
-
"completeScenarioComponents":
|
|
7067
|
+
"packageVersion": "1.47.0",
|
|
7068
|
+
"activeComponents": 114,
|
|
7069
|
+
"claimedComponents": 114,
|
|
7070
|
+
"completeScenarioComponents": 111,
|
|
7070
7071
|
"components": [
|
|
7071
7072
|
{
|
|
7072
7073
|
"componentId": "text",
|
|
@@ -9354,6 +9355,57 @@
|
|
|
9354
9355
|
],
|
|
9355
9356
|
"missingScenarios": []
|
|
9356
9357
|
},
|
|
9358
|
+
{
|
|
9359
|
+
"componentId": "color-picker",
|
|
9360
|
+
"name": "ColorPicker",
|
|
9361
|
+
"status": "beta",
|
|
9362
|
+
"claimed": true,
|
|
9363
|
+
"subpath": "./color-picker",
|
|
9364
|
+
"exportNames": [
|
|
9365
|
+
"ColorPicker",
|
|
9366
|
+
"ColorSwatchPicker"
|
|
9367
|
+
],
|
|
9368
|
+
"proofs": [
|
|
9369
|
+
{
|
|
9370
|
+
"scenarios": [
|
|
9371
|
+
"default"
|
|
9372
|
+
],
|
|
9373
|
+
"file": "test/default-render.test.tsx",
|
|
9374
|
+
"caseId": "color-picker"
|
|
9375
|
+
},
|
|
9376
|
+
{
|
|
9377
|
+
"scenarios": [
|
|
9378
|
+
"dark",
|
|
9379
|
+
"long-copy",
|
|
9380
|
+
"large-text",
|
|
9381
|
+
"rtl",
|
|
9382
|
+
"reduced-motion",
|
|
9383
|
+
"accessibility"
|
|
9384
|
+
],
|
|
9385
|
+
"file": "test/scenario-matrix.test.tsx",
|
|
9386
|
+
"caseId": "color-picker"
|
|
9387
|
+
}
|
|
9388
|
+
],
|
|
9389
|
+
"requiredScenarios": [
|
|
9390
|
+
"default",
|
|
9391
|
+
"dark",
|
|
9392
|
+
"long-copy",
|
|
9393
|
+
"large-text",
|
|
9394
|
+
"rtl",
|
|
9395
|
+
"reduced-motion",
|
|
9396
|
+
"accessibility"
|
|
9397
|
+
],
|
|
9398
|
+
"claimedScenarios": [
|
|
9399
|
+
"default",
|
|
9400
|
+
"dark",
|
|
9401
|
+
"long-copy",
|
|
9402
|
+
"large-text",
|
|
9403
|
+
"rtl",
|
|
9404
|
+
"reduced-motion",
|
|
9405
|
+
"accessibility"
|
|
9406
|
+
],
|
|
9407
|
+
"missingScenarios": []
|
|
9408
|
+
},
|
|
9357
9409
|
{
|
|
9358
9410
|
"componentId": "file-picker",
|
|
9359
9411
|
"name": "FilePicker",
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Renderer evidence coverage
|
|
2
2
|
|
|
3
|
-
> Generated for HJM 1.
|
|
3
|
+
> Generated for HJM 1.47.0. Do not edit directly; run `pnpm evidence:sync`.
|
|
4
4
|
|
|
5
5
|
This projection joins the canonical surface maturity manifest with first-party renderer claims. Missing scenarios are explicit beta promotion debt; stable surfaces are blocked by CI until none remain.
|
|
6
6
|
|
|
7
7
|
- web: 131/131 active implementations; 130/131 required scenario sets
|
|
8
|
-
- native:
|
|
8
|
+
- native: 114/114 active implementations; 111/114 required scenario sets
|
|
9
9
|
|
|
10
10
|
| Component | Surface | Maturity | Renderer package | Export | Claimed scenarios | Missing required scenarios | Executable proofs |
|
|
11
11
|
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
@@ -182,6 +182,7 @@ This projection joins the canonical surface maturity manifest with first-party r
|
|
|
182
182
|
| TimePicker | native | stable | @hjmds/react-native | ./time-picker | default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, native-actions | none | test/default-render.test.tsx#time-picker, test/scenario-matrix.test.tsx#time-picker, test/time-picker.test.tsx#time-picker |
|
|
183
183
|
| DatePicker | native | stable | @hjmds/react-native | ./date-picker | default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, native-actions | none | test/default-render.test.tsx#date-picker, test/scenario-matrix.test.tsx#date-picker, test/stable-core.test.tsx#date-picker |
|
|
184
184
|
| DateRangePicker | native | stable | @hjmds/react-native | ./date-range | default, dark, large-text, rtl, reduced-motion, accessibility, native-actions | none | test/default-render.test.tsx#date-range-picker, test/scenario-matrix.test.tsx#date-range-picker, test/date-range-actions.test.tsx#date-range-picker |
|
|
185
|
+
| ColorPicker | native | beta | @hjmds/react-native | ./color-picker | default, dark, long-copy, large-text, rtl, reduced-motion, accessibility | none | test/default-render.test.tsx#color-picker, test/scenario-matrix.test.tsx#color-picker |
|
|
185
186
|
| FilePicker | native | stable | @hjmds/react-native | ./file-picker | default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, native-actions | none | test/default-render.test.tsx#file-picker, test/scenario-matrix.test.tsx#file-picker, test/file-picker-host-action.test.tsx#file-picker |
|
|
186
187
|
| Form | native | stable | @hjmds/react-native | ./forms | default, dark, large-text, rtl, reduced-motion, accessibility, native-actions | none | test/default-render.test.tsx#form, test/scenario-matrix.test.tsx#form, test/form.interaction.test.tsx#form |
|
|
187
188
|
| Agreement | native | stable | @hjmds/react-native | ./agreement | default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, native-actions | none | test/default-render.test.tsx#agreement, test/scenario-matrix.test.tsx#agreement, test/agreement.interaction.test.tsx#agreement |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
|
-
"designSystemVersion": "1.
|
|
3
|
+
"designSystemVersion": "1.47.0",
|
|
4
4
|
"packageName": "@hjmds/design-contracts",
|
|
5
5
|
"components": [
|
|
6
6
|
{
|
|
@@ -2294,14 +2294,16 @@
|
|
|
2294
2294
|
"storyId": "input/color-picker",
|
|
2295
2295
|
"name": "ColorPicker",
|
|
2296
2296
|
"label": "색상 선택기",
|
|
2297
|
-
"companions": [
|
|
2297
|
+
"companions": [
|
|
2298
|
+
"ColorSwatchPicker"
|
|
2299
|
+
],
|
|
2298
2300
|
"extensions": [],
|
|
2299
2301
|
"category": "input",
|
|
2300
|
-
"platform": "
|
|
2302
|
+
"platform": "adaptive",
|
|
2301
2303
|
"contractStatus": "stable",
|
|
2302
2304
|
"surfaces": {
|
|
2303
2305
|
"web": "stable",
|
|
2304
|
-
"native": "
|
|
2306
|
+
"native": "beta"
|
|
2305
2307
|
},
|
|
2306
2308
|
"requirements": [
|
|
2307
2309
|
{
|
|
@@ -2322,6 +2324,18 @@
|
|
|
2322
2324
|
"accessibility",
|
|
2323
2325
|
"keyboard"
|
|
2324
2326
|
]
|
|
2327
|
+
},
|
|
2328
|
+
{
|
|
2329
|
+
"surface": "native",
|
|
2330
|
+
"scenarios": [
|
|
2331
|
+
"default",
|
|
2332
|
+
"dark",
|
|
2333
|
+
"long-copy",
|
|
2334
|
+
"large-text",
|
|
2335
|
+
"rtl",
|
|
2336
|
+
"reduced-motion",
|
|
2337
|
+
"accessibility"
|
|
2338
|
+
]
|
|
2325
2339
|
}
|
|
2326
2340
|
],
|
|
2327
2341
|
"documentation": {
|
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.46.1의 생성 manifest에서 읽은 정규(canonical) API 기준이다. 동반·선택형 확장은 개별 계약을 확인한다.
|
|
11
11
|
Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품 반영을 의미하지 않는다.
|
|
12
12
|
`분류`는 Storybook 제목 `<배포|실험>/<단계>/<분류>/<항목>`의 셋째 마디이고, 토큰·구성·화면은 Storybook 메뉴와 같은 순서다.
|
|
13
13
|
|
|
@@ -54,7 +54,7 @@ Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품
|
|
|
54
54
|
| [Breadcrumb](components/breadcrumb.md) | 탐색 | Web의 깊은 계층 화면에서 현재 위치까지의 경로를 보여 주고 상위 계층으로 바로 돌아가게 할 때 쓴다. | 1.12.1 | Web | Web stable / Native unsupported | 배포 |
|
|
55
55
|
| [Button](components/button.md) | 동작 | 사용자가 누르면 무언가가 일어나는 텍스트 행동에 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
56
56
|
| [Calendar](components/calendar.md) | 데이터 표시 | 화면에 항상 펼쳐진 한 달 격자에서 날짜 하나를 고를 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
57
|
-
| [Card](components/card.md) |
|
|
57
|
+
| [Card](components/card.md) | — | 인용문과 출처를 묶으면 미게시 동반 API `QuoteCard`를 사용한다. | | | Web stable / Native stable | |
|
|
58
58
|
| [Carousel](components/carousel.md) | 데이터 표시 | 한 번에 카드 하나만 보이고 사용자가 순서대로 넘겨 보는 유한한 묶음에 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
59
59
|
| [Celebration](components/celebration.md) | 구성/직접 조작과 모션 | 목표 달성, 첫 완료처럼 드물게 일어나는 성공 순간에 한 번 터지는 색종이 효과에 쓴다. | 1.12.1 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
60
60
|
| [Chart](components/chart.md) | 데이터 표시 | 수치의 흐름·비교·몫·모양·관계를 그림으로 읽게 할 때 쓴다. | 1.21.0 | Web · Native | Web beta / Native beta | 배포 |
|
|
@@ -83,6 +83,7 @@ Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품
|
|
|
83
83
|
| [Container](components/container.md) | 레이아웃 | 화면 본문의 최대 폭과 좌우(논리 방향) 여백을 맞출 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
84
84
|
| [ContentTransition](components/content-transition.md) | 시각 효과 | 같은 자리의 내용이 상태에 따라 바뀔 때(필터 결과 패널, 단계별 본문) 새 내용이 짧게 나타나도록 감싼다. | 1.12.1 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
85
85
|
| [ContextMenu](components/context-menu.md) | 탐색 | Web에서 제품이 소유한 영역(카드·목록 행·캔버스)의 우클릭·길게 누르기·Shift+F10에 명령 목록을 띄울 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native unsupported | 배포 |
|
|
86
|
+
| [ConversationListScreen](components/conversation-list-screen.md) | 화면/소통 | DM·단체방 대화 목록의 공통 화면이다. | 미게시(1.46.1 이후) | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
86
87
|
| [ConversationRow](components/conversation-row.md) | 화면/소통 | 대화 목록에서 상대, 마지막 메시지, 상대 시각, 안 읽음 점을 표시한다. | 1.24.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
87
88
|
| [ConversionFunnel](components/conversion-funnel.md) | 구성/정보 표시 | 순차 단계(열기 → 작성 → 저장 등)의 인원을 가로 막대로 보여 주고, 단계를 골라 전체 대비·직전 대비 전환율과 이탈 수를 문구로 읽을 때 쓴다. | 1.21.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
88
89
|
| [CorrelationMatrix](components/correlation-matrix.md) | 구성/정보 표시 | 여러 지표 사이의 상관계수(-1~1)를 정사각 대칭 표와 양·음 두 방향 heat 색으로 보여 줄 때 쓴다. | 1.21.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
@@ -103,6 +104,7 @@ Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품
|
|
|
103
104
|
| [FilePicker](components/file-picker.md) | 입력 | 사용자가 업로드할 로컬 파일을 고르게 할 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
104
105
|
| [FilterRecovery](components/filter-recovery.md) | 구성/피드백과 복구 | 검색·필터 결과가 비었을 때 실제로 결과가 생기는 필터 완화 제안을 보여 주고, 사용자가 고른 하나를 명시적으로 적용할 때 쓴다. | 1.21.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
105
106
|
| [FloatingActionButton](components/floating-action-button.md) | 동작 | 목록·피드처럼 스크롤되는 콘텐츠 위에 떠 있는 **단일 생성 행동**(새 기록 추가, 새 글 작성)에 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
107
|
+
| [FollowListScreen](components/follow-list-screen.md) | 화면/소통 | 팔로워/팔로잉을 전환하고 사람을 검색하며 각 행에서 팔로우할 때 사용한다. | 미게시(1.46.1 이후) | Web · Native | 개별 API 계약 참조 | 실험 |
|
|
106
108
|
| [FollowProfileCard](components/follow-profile-card.md) | 구성/정보 표시 | 프로필 카드에서 팔로우·팔로잉 전환과 팔로워 수를 실제 mutation 결과와 함께 보여 줄 때 쓴다. | 1.21.0 | Web · Native | 개별 API 계약 참조 | 배포 |
|
|
107
109
|
| [Form](components/form.md) | 입력 | 여러 Field를 한 화면에 쌓고 한 번에 제출할 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
108
110
|
| [Grid](components/grid.md) | 레이아웃 | 카드·타일처럼 같은 모양의 자식을 창 크기에 따라 열 수를 바꿔 배치할 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
|
|
@@ -322,6 +324,7 @@ Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품
|
|
|
322
324
|
| [신고와 차단](screens/flow-moderation.md) | 소통 | ModerationScreen을 사용해 신고와 차단 흐름을 구성한다. | 구성 API 지침 참조 | Web · Native | 구성 API별 | 배포 |
|
|
323
325
|
| [알림함](screens/common-inbox.md) | 소통 | NotificationInboxScreen을 사용해 알림함 흐름을 구성한다. | 구성 API 지침 참조 | Web · Native | 구성 API별 | 배포 |
|
|
324
326
|
| [채팅](screens/common-chat.md) | 소통 | ChatScreen을 사용해 채팅 흐름을 구성한다. | 구성 API 지침 참조 | Web · Native | 구성 API별 | 배포 |
|
|
327
|
+
| [팔로워와 팔로잉](screens/common-follow-list.md) | 소통 | 두 관계 목록을 검색하고 프로필로 이동하며 팔로우한다. | 미게시(1.46.1 이후) | Web · Native | 구성 API별 | 실험 |
|
|
325
328
|
| [기록 표현 비교](screens/reference-comparison.md) | 화면 틀과 도구 | ScreenLayout을 사용해 같은 기록의 세 가지 구성 흐름을 구성한다. | 구성 API 지침 참조 | Web · Native | 구성 API별 | 배포 |
|
|
326
329
|
| [목업 편집](screens/mockup-studio.md) | 화면 틀과 도구 | 제품 화면 캡처를 휴대폰·브라우저 프레임에 넣어 스토어·소개용 이미지(PNG)와 짧은 장면 영상을 만드는 Web 전용 작업 도구 화면이다. | 1.12.1 | Web | 구성 API별 | 배포 |
|
|
327
330
|
| [화면 골격과 상태](screens/common-shell.md) | 화면 틀과 도구 | ScreenLayout을 사용해 화면 골격 흐름을 구성한다. | 구성 API 지침 참조 | Web · Native | 구성 API별 | 배포 |
|
package/docs/usage/SELECTION.md
CHANGED
|
@@ -150,3 +150,112 @@ HJM 공통 구성이 선택을 소유하고 제품 adapter는 `presentation`을
|
|
|
150
150
|
[Menu 전사 개발 선택](components/menu.md#전사-개발-적용-선택--2026-10-20)을 따른다.
|
|
151
151
|
|
|
152
152
|
2026-10-23 사용자 지시: 익숙한 아이콘 하나로 의미를 전달할 수 있는 보조 행동은 본문·오류 안내에서도 `IconButton`을 사용한다. 접근성 `label`과 Web 설명(title/Tooltip), pending·disabled·포커스 복구를 보존한다. 재전송은 refresh, 이전 상태로 돌아가기는 되돌리기 아이콘으로 구분한다. 메뉴 행의 이름과 삭제 확인·결제·동의 같은 최종 의사 확인 문구는 유지한다.
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
### 목록 이관의 확인 단위 (2026-10-25)
|
|
156
|
+
|
|
157
|
+
번뚝에서 행 컴포넌트만 공통으로 바꾸고 부모의 카드·여백·구분선을 남겨 화면이 달라졌다.
|
|
158
|
+
목록은 실제 route/scroll host → 공통 화면/구성 → 목록 → 행까지 함께 확인한다.
|
|
159
|
+
대화는 ConversationListScreen, 알림은 NotificationInboxScreen의 행 종류 계약,
|
|
160
|
+
검색은 SearchScreen과 List/ListRow를 먼저 선택한다. 일반 목록의 묶음 표면은 List appearance를
|
|
161
|
+
사용하며 단순 행을 Card로 다시 감싸지 않는다. 지도 위 정보판·선택 가능한 복합 카드처럼
|
|
162
|
+
고유 역할이 있는 표면까지 없애는 규칙은 아니다.
|
|
163
|
+
|
|
164
|
+
변경한 배치 확인에서는 실제 HJM 구현과 데이터가 있는 목록을 사용한다.
|
|
165
|
+
링크로 대체한 mock·빈 상태·타입 검사만으로 목록의 시각 일치를 보고하지 않는다.
|
|
166
|
+
이는 기존 변경 범위 검사의 대상 선택이며 새 CI 게이트나 전수 회귀 의무가 아니다.
|
|
167
|
+
|
|
168
|
+
### 소비 화면 조합 검사 (2026-10-25)
|
|
169
|
+
|
|
170
|
+
같은 공통 행을 쓰면서 바깥 카드·여백이 남고, 본문 Stack 간격이 행동 묶음에 적용됐으며,
|
|
171
|
+
제품 팔레트까지 공통 기본값으로 교체된 사고를 보완한다. 공통 레이아웃을 먼저 선택하고
|
|
172
|
+
제품의 데이터·문구·테마는 보존한다. 검사 통과는 실제 화면 일치의 증명이 아니다.
|
|
173
|
+
|
|
174
|
+
기존 `scripts/audit-consumer-ui.mjs`는 제품의 `app.contract.json`에 등록된 mobile/web 소스를
|
|
175
|
+
검사한다. 포트폴리오 루트를 주면 `portfolio.json`의 모든 제품을 순회한다. 폐기되어
|
|
176
|
+
checkout이 없는 제품은 제외 사유를 표시하고, 그 외 누락·분석 실패는 unavailable로 남긴다.
|
|
177
|
+
|
|
178
|
+
HJM 저장소에서 실행:
|
|
179
|
+
|
|
180
|
+
```sh
|
|
181
|
+
node scripts/audit-consumer-ui.mjs ../../apps/diairy /tmp/diairy-ui.json --check
|
|
182
|
+
node scripts/audit-consumer-ui.mjs ../.. /tmp/portfolio-ui.json --check
|
|
183
|
+
node --test scripts/audit-consumer-ui.test.mjs
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
- 간격 값은 authored `foundations.ts`·`component-recipes.ts`에서 읽는다. 별도 숫자 규격표를 복제하지 않는다.
|
|
187
|
+
- 확정 위반: 직접 HJM Button·standalone Link 행동의 인접 배치를 소유한 Stack의 정적 gap이 actionGroupRecipe와 다름.
|
|
188
|
+
- 검토 후보: 행을 감싼 카드/여백, 반복 행의 Stack 간격, 중첩 스크롤, 제품 탭 역할, 자체 상태 UI,
|
|
189
|
+
공통 컴포넌트 style 덮어쓰기, HEAD 대비 테마 주입 제거/기본 팔레트 교체. 후보를 자동 수정하거나 예외 목록으로 숨기지 않는다.
|
|
190
|
+
- 별칭·namespace·fragment·조건부 분기를 해석한다. 상호 배타적인 버튼을 동시에 놓인 것으로 세지 않는다.
|
|
191
|
+
단순 로컬 Button 어댑터는 import 경로로 추적하되 실제 geometry는 확정하지 않는다.
|
|
192
|
+
- CSS, 복잡한 어댑터·동적 스타일·portal·실행 상태·전체 route 도달성은 정적 검사만으로 보장하지 않는다.
|
|
193
|
+
보고서의 raw control/local component 목록과 화면 실측으로 확인한다. 후보 0개도 준수 완료가 아니다.
|
|
194
|
+
- `--check`는 확정 위반에 1, 범위 누락에 2를 반환한다. 후보는 보고서에서 별도로 검토한다.
|
|
195
|
+
배포 CI에는 새 게이트를 붙이지 않는다. 작은 수정은 대상 제품과 관련 테스트를 선택하고 전사 순회는 명시 요청 때 실행한다.
|
|
196
|
+
- 공통 화면의 실제 폭·여백·상태·안전 영역·행동 영역은 기존 Web browser/Native screen 테스트가 검사한다.
|
|
197
|
+
제품 테마는 실제 Provider 입력 팔레트와 제품 팔레트의 연결을 제품 테스트에서 확인한다.
|
|
198
|
+
다에리 Web/Native와 스핀트 Native는 2026-10-25 테마 소실 회귀를 추가했다.
|
|
199
|
+
|
|
200
|
+
2026-10-25 후보 후속 검토: 조건부 분기의 전체 조합을 열거하던 64개 한도는 제거했다.
|
|
201
|
+
첫/끝 요소와 가능한 인접 쌍을 합성해 조건부 영역이 많은 화면에서도 행동 간격 검사를 수행한다.
|
|
202
|
+
일반 텍스트 Link를 행동 묶음으로 오인하지 않으며 standalone Link만 버튼과 함께 검사한다.
|
|
203
|
+
검토 기록은 원래 파일 hash와 검토한 현재 hash, 판단 근거를 보존한다.
|
|
204
|
+
제품별 사용자 결정이나 지원되는 style 입력은 검토 사유이지 자동 검사 면제 목록이 아니다.
|
|
205
|
+
|
|
206
|
+
### Native 헤더와 상단 안전 영역 검사
|
|
207
|
+
|
|
208
|
+
2026-10-25 번뚝 팔로워 화면은 네이티브 헤더를 숨긴 뒤 FollowListScreen만 연결해 상태 표시줄과
|
|
209
|
+
제목이 겹쳤다. Provider가 inset을 알고 있다는 사실만으로 화면에 여백이 적용되지는 않는다.
|
|
210
|
+
네이티브 헤더가 없는 전체 화면은 `ScreenHost`가 상단·좌우 inset을 맡고 화면은 하단을 맡는다.
|
|
211
|
+
이미 navigator/상위 ScreenHost/SafeAreaView가 상단을 확보하면 다시 더하지 않는다.
|
|
212
|
+
`ScreenLayout.safeAreaTop`은 헤더 없는 본문용이며 표시되는 헤더 위 여백의 대체재가 아니다.
|
|
213
|
+
|
|
214
|
+
기존 소비 검사기는 Native 화면의 JSX 조상에 상단 ScreenHost 또는 SafeAreaView가 확인되지 않으면
|
|
215
|
+
`safe-area-top-owner` 검토 후보로 남긴다. 다른 파일의 navigator·SafeAreaView·Provider 연결을
|
|
216
|
+
추적해야 하므로 이 후보를 곧바로 위반으로 확정하거나 일괄 wrapper 추가하지 않는다.
|
|
217
|
+
정적으로 확인되는 상단 host 안의 ScreenHost 중첩은 `safe-area-top-duplicate` 위반이다.
|
|
218
|
+
동적 edges/spread는 소유자가 확인된 것으로 처리하지 않는다. 실제 기기에서는 상태 표시줄 아래
|
|
219
|
+
헤더 위치를 별도로 확인한다. Native host 테스트는 기기 좌표 측정의 대체 증거가 아니다.
|
|
220
|
+
|
|
221
|
+
### 예방 검사 범위와 판정 갱신 (2026-10-25)
|
|
222
|
+
|
|
223
|
+
목록·간격만 확인하면 행동 역할·상단 도구·입력 포커스가 빠진다는 사용자 지적을 반영했다.
|
|
224
|
+
기존 검사기에 역할/포커스 검토와 판정 근거 갱신을 추가하며 별도 배포 게이트는 만들지 않는다.
|
|
225
|
+
|
|
226
|
+
| 지침 경계 | 현재 자동 확인 | 반드시 별도로 판단할 범위 |
|
|
227
|
+
| --- | --- | --- |
|
|
228
|
+
| 행동 묶음 간격 | `action-group-gap`, authored recipe 값 | CSS/View/복잡한 wrapper의 최종 간격 |
|
|
229
|
+
| 주·보조 행동/같은 크기 | `competing-primary-actions`, `action-size-mismatch` 후보 | 독립 행동인지, 조건이 동시에 참인지, 실제 폭·높이 |
|
|
230
|
+
| 선택/설정 제어 | `selection-control` 후보 | 실행 결과 상태와 단일/다중 선택·설정의 구분 |
|
|
231
|
+
| 상단 도구 | `header-text-action`, `header-tool-size`, `header-tool-gap` 후보 | 제품 헤더 adapter, 아이콘 의미·개수, 탐색/제목 중복 |
|
|
232
|
+
| 목록·본문 여백 | `row-rhythm`, `list-wrapper`, `screen-gutter` 후보 | 카드의 도메인 의미, 최종 좌우·상하 대칭 |
|
|
233
|
+
| 상단 안전 영역 | `safe-area-top-owner`, `safe-area-top-duplicate` | route/navigator/Sheet의 상단 소유권, 실제 상태 표시줄 좌표 |
|
|
234
|
+
| 스크롤·상태 | `scroll-owner`, `state-owner` 후보, 기존 composition-state-height 테스트 | 가상화·overflow·키보드·footer·정중앙·경계 배경 |
|
|
235
|
+
| 입력 포커스 | `input-focus-owner`, `imperative-focus` 후보, 기존 initial-focus 테스트 | 제출 오류/명시적 편집/복귀와 진입·단계 자동 포커스의 구분 |
|
|
236
|
+
| 테마/표현 | HEAD 대비 팔레트 제거 탐지, 공개 style override 후보 | 제품별 승인·라이트/다크·장면 artwork·색 대비 |
|
|
237
|
+
| 전체 화면 기하 | 기존 screen-chrome/screen-insets browser 테스트 | 소비 앱의 실제 화면·긴 문구·좁은 폭·오버레이/스크롤 상태 |
|
|
238
|
+
| 키보드/접근성 | 기존 keyboard-field-visibility·focus 테스트 | 소비 앱 이름/읽기 순서/동작, 실제 플랫폼 키보드 |
|
|
239
|
+
| 사용 계약/버전 | 소스 inventory와 앱 contract 표면 목록 | 공개 export/설치 버전, 실제 실행 bundle, route 도달성 |
|
|
240
|
+
|
|
241
|
+
단순 named import와 barrel 재수출, React `forwardRef`/`memo` Button·IconButton 어댑터를 추적한다.
|
|
242
|
+
어댑터의 prop 기본값·동적 값까지 증명하는 것은 아니므로 해당 결과는 검토 후보다.
|
|
243
|
+
조건 요약은 JSX 분기를 보존하지만 서로 다른 boolean 식의 논리적 상호 배타성까지 증명하지 않는다.
|
|
244
|
+
후보가 없어도 위 표의 수동/실측 범위는 통과로 바꾸지 않는다. 최대 글자 설정은 포트폴리오 지침대로 제외한다.
|
|
245
|
+
|
|
246
|
+
포트폴리오 루트와 기존 판정 보고서를 함께 주면 근거 변경을 확인한다:
|
|
247
|
+
|
|
248
|
+
```sh
|
|
249
|
+
node scripts/audit-consumer-ui.mjs ../.. /tmp/portfolio-ui.json --reviews ../../docs/design/audits/2026-10-25-ui-composition.json --check
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
`candidateReview`·`headerSafetyAudit`·`extendedReview`의 현재 소스 해시와 `evidence` 경로/해시를
|
|
253
|
+
대조한다. 바뀌거나 삭제되면 `stale`, 의존 근거가 없으면 `dependencies-unrecorded`, 모두 같으면
|
|
254
|
+
`source-unchanged`다. **마지막 값도 화면 합격을 뜻하지 않는다.** 후보를 숨기지 않고 다시 보여주며,
|
|
255
|
+
변경된 소유 구현/조건을 재검토한 뒤에만 판정·근거를 갱신한다. 파일을 다시 읽지 않고 해시만 덮어쓰지 않는다.
|
|
256
|
+
|
|
257
|
+
### 회원 사진의 기본 동작 (2026-10-25)
|
|
258
|
+
|
|
259
|
+
댓글·공용 채팅까지 모든 회원 아바타는 해당 회원 프로필로 연결한다. [Avatar의 회원 프로필 이동](components/avatar.md#회원-프로필-이동-2026-10-25)을 따른다.
|
|
260
|
+
상위 구성의 avatarAction/leadingAction/memberProfile을 우선 연결하고 회원 ID·route는 제품이 소유한다.
|
|
261
|
+
사진 확대만 연결하거나, 본문 링크 안에 프로필 버튼을 중첩하거나, 장식 접근성 wrapper 안에 버튼을 넣지 않는다.
|
|
@@ -70,9 +70,9 @@ import { Avatar } from "@hjmds/react-native/data-display";
|
|
|
70
70
|
| `name` | `string` | 의미 있는 아바타는 필수 | 이니셜과 기본 접근성 이름의 원천. 공백뿐이면 `TypeError`. `decorative`이면 생략할 수 있다(이니셜 없이 액자·대체 그림만) |
|
|
71
71
|
| `decorative` | `boolean` | `false` | 옆에 이름이 보이는 작성자 표시나 사람 없는 장식. Web은 루트 `aria-hidden`·`img alt=""`이고 `alt`를 함께 줄 수 없다. Native는 `accessibilityLabel`을 함께 줄 수 없다 |
|
|
72
72
|
| Web `src` · Native `source` | `string` · `ImageSourcePropType` | — | 사진이 없으면 prop을 뺀다. 주소(Native는 source 내용)가 바뀌면 실패 상태를 지우고 다시 시도한다 |
|
|
73
|
-
| `size` | `xxsmall`(22) · `xsmall`(28) · `small`(32) · `medium`(40) · `touch`(44) · `large`(48) · `xlarge`(64). Native는 기존 숫자(pt)도 받는다 | Web
|
|
73
|
+
| `size` | `xxsmall`(22) · `xsmall`(28) · `small`(32) · `medium`(40) · `touch`(44) · `large`(48) · `xlarge`(64). Native는 기존 숫자(pt)도 받는다 | Web·Native `large`(48) | `avatarRecipe.sizes`. Native 숫자가 22 미만이면 `RangeError`(2026-10-23 전에는 24). 새 코드는 단계 이름을 쓴다 |
|
|
74
74
|
| `shape` | `circle` · `rounded` | `circle` | `rounded`는 `radius.md`(가장 가까운 디자인 프로필) |
|
|
75
|
-
| `frame` | `outlined` · `surface` · `none` | `outlined` | `avatarRecipe.frames`. `outlined`=canvas 바탕+1px
|
|
75
|
+
| `frame` | `outlined` · `surface` · `none` | `outlined` | `avatarRecipe.frames`. `outlined`=canvas 바탕+borderControl 50% alpha의 1px 테두리, `surface`=바탕만, `none`=바탕·테두리 없음(제품 그림이 액자를 채울 때) |
|
|
76
76
|
| `accessory` · `accessoryPlacement` | `ReactNode` · `bottom-end` · `top-end` | — · `bottom-end` | 팀 배지·상태 점 같은 모서리 표식. 아바타 상자 모서리(`avatarRecipe.accessory.offset` 0, Asset·IconTile처럼 바깥으로 나가는 거리)에 붙고 액자에 잘리지 않는다. 누르는 요소를 넣지 않는다 |
|
|
77
77
|
| `renderFallback` | `(context: { size: number; decorative: true }) => ReactNode` | — | 사진이 없거나 실패했을 때만 불린다. `size`는 px/pt 값. null·undefined를 돌려주면 기본 대체 표시(Web `fallback`→이니셜, Native 이니셜)를 쓴다 |
|
|
78
78
|
| Web `alt` | `string` | `name` | `""`이면 보조기기에서 숨긴다 |
|
|
@@ -82,13 +82,13 @@ import { Avatar } from "@hjmds/react-native/data-display";
|
|
|
82
82
|
| Native `renderImage` | `(context: AvatarImageRenderProps) => ReactNode` | 기본 Native Image | 제품의 이미지 캐시·표시 호스트를 연결한다(1.14.0 추가). `source`, `size`, HJM `fallback`, 세대가 보호된 `onError` 제공 |
|
|
83
83
|
| Native `initials` | `string` | 이름에서 계산 | 앞뒤 공백을 지우고 최대 3자, 대문자 |
|
|
84
84
|
| `layoutStyle` | margin·width·flex·`alignSelf` | — | 배치 전용. Native `style`·`imageStyle`은 제거된 속성 — layoutStyle 또는 `size`/`renderFallback` |
|
|
85
|
-
| `AvatarGroup`(Web) `label` · `size` · `overflow` | `string` · Avatar 크기 · `ReactNode` | `label` 필수 · `size` `
|
|
85
|
+
| `AvatarGroup`(Web) `label` · `size` · `overflow` | `string` · Avatar 크기 · `ReactNode` | `label` 필수 · `size` `large` | 빈 `label`은 `TypeError`. `overflow`는 제품이 만든 "+3" 같은 문구이며 `aria-hidden`이다(남은 인원은 `label`에 담는다). 겹침은 크기의 30%다 |
|
|
86
86
|
|
|
87
87
|
## 배치
|
|
88
88
|
|
|
89
89
|
| 항목 | 값 | 근거 |
|
|
90
90
|
| --- | --- | --- |
|
|
91
|
-
| 크기 | `xxsmall` 22 · `xsmall` 28 · `small` 32 · `medium` 40 · `touch` 44 · `large` 48 · `xlarge` 64. 댓글·칩 안 작은 작성자 표시는 `xxsmall`/`xsmall`,
|
|
91
|
+
| 크기 | `xxsmall` 22 · `xsmall` 28 · `small` 32 · `medium` 40 · `touch` 44 · `large` 48 · `xlarge` 64. 댓글·칩 안 작은 작성자 표시는 `xxsmall`/`xsmall`, 일반 회원 목록과 프로필 머리에는 `large`(48). 감싼 요소 크기(`h-8` 등)로 맞추지 말고 단계를 고른다. 표시 전용 Avatar는 터치 대상이 아니다. 프로필 이동은 상위 구성의 전용 행동 또는 Avatar.action을 연결해 최소 44를 확보한다 | `.hjm-avatar[data-size]`, `react-native/src/data-display.tsx` |
|
|
92
92
|
| 간격 | 자체 바깥 여백이 없다. `AvatarGroup`은 크기의 30%만큼 겹치고 각 아바타에 `bg` 색 2px 테두리를 둘러 경계를 만든다 | `.hjm-avatar-group` |
|
|
93
93
|
| 순서·정렬 | 행·카드·댓글 머리의 시작 쪽에 두고 이름·본문이 끝 쪽으로 이어진다. `AvatarGroup`의 넘친 수 표시는 맨 끝에 온다 | `.hjm-avatar-group__overflow` |
|
|
94
94
|
| 고정·스크롤 | 고정 영역이 없다 | — |
|
|
@@ -163,7 +163,32 @@ Avatar를 쓰지 못한 이유(이름 필수, Web 이미지 호스트 없음, 4
|
|
|
163
163
|
// Web: 작성자 이름 옆의 장식 아바타, 제품 SVG가 액자를 채운다
|
|
164
164
|
<Avatar decorative size="xsmall" frame="none" {...(svgUrl ? { src: svgUrl } : {})} fallback={emoji} />
|
|
165
165
|
|
|
166
|
-
// Native:
|
|
167
|
-
<Avatar name={player.name} accessibilityLabel={player.name} size="large" shape="
|
|
166
|
+
// Native: 원형 선수 사진 + 모서리 팀 배지
|
|
167
|
+
<Avatar name={player.name} accessibilityLabel={player.name} size="large" shape="circle"
|
|
168
168
|
{...(uri ? { source: { uri } } : {})} accessory={<TeamBadge team={team} />} />
|
|
169
169
|
```
|
|
170
|
+
|
|
171
|
+
### 회원 프로필 이동 (2026-10-25)
|
|
172
|
+
|
|
173
|
+
회원 사진을 표시만 하거나 확대 보기만 연결한 사용처가 남아 사용자 요청으로 기본 행동을 통일했다.
|
|
174
|
+
`Avatar`는 Web·Native 모두 `action={{label: t("profile.open"), onPress: () => openMember(member.id)}}`를 받는다.
|
|
175
|
+
이름 있는 버튼이 장식 사진을 감싸며 사진이 실패하거나 이니셜만 있어도 이동은 유지된다.
|
|
176
|
+
라우트·회원 ID·권한은 제품이 공급하고, HJM은 최소 44px/pt 영역과 접근성 이름을 소유한다.
|
|
177
|
+
별도 프로필 행동이 있는 사진 자식은 항상 장식이다. 프로필 버튼 자체를 `aria-hidden`/`no-hide-descendants`로 숨기지 않는다.
|
|
178
|
+
|
|
179
|
+
상위 구성의 전용 API를 먼저 사용한다. 댓글은 `avatarAction`, 채팅은 `avatarAction`, 알림은 `NotificationRow.avatarAction`,
|
|
180
|
+
일반 목록은 `ListRow.leadingAction`, 카드 작성자는 `Card.leadingAction`, 대화 목록은 `ConversationRow.avatarAction` + `renderBody`, 참여자는 `ChatRoomMembers.memberProfile`이다.
|
|
181
|
+
같은 사진에 `Avatar.action`과 상위 `avatarAction`을 함께 넣지 않는다. 본문 링크/버튼과 독립 프로필 버튼은 형제다.
|
|
182
|
+
|
|
183
|
+
회원 식별자가 없는 장식·방 사진을 회원 프로필로 연결하지 않는다. 명시적인 사진 편집·공유 대상 선택은 원래 작업을 유지한다.
|
|
184
|
+
|
|
185
|
+
내 프로필 화면의 내 사진은 예외로 그 자체가 사진 변경 버튼이다(2026-10-25 사용자 지시). `action={{label: t("photo.change"), onPress: openPhotoPicker}}`를 연결하고 사진 고르기·자르기·업로드는 제품이 소유한다. 같은 화면에 중복 "사진 바꾸기" 버튼을 두지 않는다.
|
|
186
|
+
제품의 실제 회원 화면이 없으면 실제 공개 데이터의 화면부터 제공한다. 이미 그 회원 화면이면 중복 이동하지 않는다.
|
|
187
|
+
|
|
188
|
+
프로필 행동의 `disabled`는 전송·삭제 등 현재 작업이 경로 이탈을 막는 동안 사용한다. 버튼을 없애거나 활성 버튼에서 오류를 무시하는 대신 동일한 이름과 비활성 의미를 유지한다.
|
|
189
|
+
|
|
190
|
+
## 일반 회원 크기 (2026-10-25)
|
|
191
|
+
|
|
192
|
+
사용자 요청으로 Web·Native 기본값은 `size="large"`(48), `shape="circle"`이다. 프로필과 일반 회원 목록에도 48을 쓰고 댓글·채팅 등 촘촘한 목록의 명시적인 작은 단계는 유지한다. 제품별 사진·이니셜·이모지·동물 그림도 같은 회원 프레임을 따른다. 콘텐츠 썸네일·앱 아이콘의 모양이나 크기에는 적용하지 않는다.
|
|
193
|
+
|
|
194
|
+
기본 `frame="outlined"`는 `border.control` 50% alpha, 1px의 원형 윤곽이다. 2026-10-25 번뚝 이모지 아바타에서 기존 선은 흐리고 2px 불투명 선은 진하다는 피드백을 거쳐 1px·50%로 조정했으며, 사용자가 이 값을 디자인 시스템 기본값으로 지정했다. 지름은 테두리 포함이고 Web·Native에 동일하다. 미게시 개발 중 추가했던 `strong` 옵션은 기본값과 합쳐 제거했다. 제품에서 별도 frame을 지정할 필요가 없다.
|
|
@@ -279,3 +279,19 @@ Tab은 탐색 막대에 한 번 진입하고, 방향키·Home·End는 포커스
|
|
|
279
279
|
|
|
280
280
|
`presentation: "capsule"`의 선택 항목은 `selectionCapsule`의 neutral 선택 배경과 글자를 쓴다.
|
|
281
281
|
기본 아이콘·글자 탐색의 위치 강조와 명시적 `selection: "tile"`의 브랜드 면은 기존 계약을 따른다.
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
## 타일 바탕과 선택 강조 분리 (2026-10-25)
|
|
285
|
+
|
|
286
|
+
오늘야구에서 선택된 파란 타일은 유지하면서 바탕을 흰색으로 사용하려는 요청으로
|
|
287
|
+
`configuration.tone: "brand" | "neutral"`을 추가했다. 기본 `brand`는 기존 surfaceAccent 바탕을 유지한다.
|
|
288
|
+
`neutral`은 `semanticColors.surface.default`(테마의 surface)를 사용한다. 라이트 기본 테마에서는 흰색,
|
|
289
|
+
다크에서는 어두운 공통 표면이며 선택 타일의 primary/onPrimary와 모양·간격·동작은 유지한다.
|
|
290
|
+
flat tile 전용이며 raised 표면과 함께 지정하면 오류다. 앱에서 팔레트나 style을 덮어쓰지 않는다.
|
|
291
|
+
|
|
292
|
+
```tsx
|
|
293
|
+
configuration={{ presentation: "floating", selection: "tile", tone: "neutral" }}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Web·Native의 `NeutralTiles`와 `NeutralTilesDark` Storybook 예제가 같은 공개 API를 사용한다.
|
|
297
|
+
로컬 개발 API이며 게시된 패키지 지원은 해당 릴리스에 포함된 뒤 확인한다.
|
|
@@ -108,6 +108,17 @@ import { Button } from "@hjmds/react-native/actions";
|
|
|
108
108
|
└──────────────────────────────┘ └──────────────────────┘
|
|
109
109
|
```
|
|
110
110
|
|
|
111
|
+
## 연속 버튼의 색상 구분 (2026-10-25)
|
|
112
|
+
|
|
113
|
+
번뚝의 ‘내 버전 만들기’와 ‘그대로 가져가기’가 같은 파란색으로 연속 표시되어 행동의 우선순위가
|
|
114
|
+
구분되지 않았다는 사용자 지적을 반영한다. **가로·세로로 연속되는 서로 다른 행동 버튼에는 다른 색을 쓴다.**
|
|
115
|
+
주 행동은 `tone="primary"`, 보조 행동은 `tone="secondary"` 또는 `ghost`로 배경·글자색을 구분한다.
|
|
116
|
+
단순히 tone 이름만 다르게 지정하지 말고 제품 테마의 실제 색도 구분되는지 확인한다.
|
|
117
|
+
색은 HJM tone·semantic token으로 연결하며 버튼별 임의 색상 하드코딩이나 의미 없는 무지개색 배치는 하지 않는다.
|
|
118
|
+
세 개 이상이면 주 행동 하나를 강조하고 나머지 보조 행동은 같은 중립색 계열을 공유할 수 있다.
|
|
119
|
+
선택지·탭·토글의 같은 역할 항목은 각 선택 컴포넌트의 상태 색상 계약을 따른다.
|
|
120
|
+
Web·Native와 라이트·다크 테마에 동일하게 적용한다.
|
|
121
|
+
|
|
111
122
|
## 꼭 지킬 것
|
|
112
123
|
|
|
113
124
|
- Button은 callback의 Promise를 자동으로
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Card
|
|
2
2
|
|
|
3
|
+
2026-10-25 번뚝 글자 크기 리뷰 반영(개발 소스·미게시): 카드 제목은 `bodyLarge` 16/24, `medium` 굵기를 사용한다. 반복 카드가 페이지 제목과 경쟁하지 않도록 양 renderer에 동일하게 적용한다.
|
|
4
|
+
|
|
3
5
|
- 단계: 컴포넌트
|
|
4
6
|
- 상태: 배포
|
|
5
7
|
- 지원: Web · Native
|
|
@@ -293,3 +295,7 @@ QuoteCard가 자동으로 원문을 자르거나 열지 않는다. 이 API의
|
|
|
293
295
|
다에리 편지·장소 기록은 새 탭·가운데 클릭·링크 미리보기를 보존해야 하므로 버튼 callback으로 바꾸지 않는다. `href`는 공통 카드의 media·본문을 덮는 별도 이름 있는 anchor를 만들고, `actions`는 그 위의 독립 대상으로 남긴다. 본문/그림은 링크 이름에 모두 합치지 않고 `aria-label`에 제품이 고른 짧은 이름을 준다. 프레임워크 링크·소리·초안 정리는 `renderLink`가 받은 href/className/접근성 props를 그대로 전달하면서 연결한다. 카드·배지 위치·표면·누름 피드백을 제품 CSS로 다시 조립하지 않는다. Native 목적지 이동은 기존 `onActivate` 콜백으로 연결한다.
|
|
294
296
|
|
|
295
297
|
<!-- usage-example: Web ../../../../../showcase/web/src/components/Card.stories.tsx -->
|
|
298
|
+
|
|
299
|
+
### 회원 프로필 이동 (2026-10-25)
|
|
300
|
+
|
|
301
|
+
`leadingAction={label,onPress}`로 leading의 작성자 사진을 해당 회원 프로필에 연결한다. 카드 전체 `onActivate`/`href`와 독립된 형제 컨트롤이며 Native의 접근성 카드 안에 프로필 버튼을 중첩하지 않는다. 사진에는 별도 Avatar.action을 함께 넣지 않는다.
|
|
@@ -135,7 +135,7 @@ import { Text } from "@hjmds/react-native/primitives";
|
|
|
135
135
|
| 반응 메뉴 | Popover(Escape·외부 클릭·포커스 복귀), 우클릭·말풍선 자체의 Enter/Space로도 열림. 시각적으로 숨긴 닫기 버튼은 포커스를 받으면 보인다 | 전체 화면 `Modal`, 접근성 activate로도 열림. 닫기 대상은 표준 `activate` 동작에 답해 VoiceOver·TalkBack 모두 닫을 수 있다 |
|
|
136
136
|
| 낭독 | 메시지 행 `article`의 이름이 `author`, 말풍선 이름이 `picker.label`(반응이 있을 때) | 말풍선은 본문 텍스트로 읽히고 `picker.label`은 힌트. 작성자·시각은 별도 요소 |
|
|
137
137
|
| 키보드·보조기기 답장 | 메시지 포커스 후 Alt+←/→ | 접근성 custom action `reply` |
|
|
138
|
-
| `interactiveContent` | 말풍선을 `group`으로 두고, 안쪽 버튼·링크의 누름·Enter/Space는 반응 메뉴가 아니라 그 컨트롤이 받는다 | 반응이 있으면 별도
|
|
138
|
+
| `interactiveContent` | 말풍선을 `group`으로 두고, 안쪽 버튼·링크의 누름·Enter/Space는 반응 메뉴가 아니라 그 컨트롤이 받는다 | 반응이 있으면 별도 `⋮` IconButton이 메뉴를 열고 `reply` 동작도 가진다. 댓글과 같은 도형 세로 점(`glyph.sm`)을 쓴다(2026-10-25 사용자 통일 요청, 개발 소스). 반응이 없으면 `reply` 동작이 시각 caption(시각이 없으면 작성자 caption)에 붙는다 |
|
|
139
139
|
| `menuAction` | 즉시 실행 | 모달이 닫힌 뒤 실행(iOS 모달 경합 방지) |
|
|
140
140
|
|
|
141
141
|
## 함정
|
|
@@ -170,4 +170,12 @@ import { Text } from "@hjmds/react-native/primitives";
|
|
|
170
170
|
|
|
171
171
|
2026-10-23: 말풍선 메뉴의 `reactions.menuActions`에 수정·삭제를 연결한다. 반응 선택 없이 메뉴만 필요하면 `options: []`를 쓴다. 수정은 같은 `MessageComposer`의 `editTarget`으로 전환하고 제품이 기존 새 메시지 초안·첨부를 보존한다. 저장 성공 전 원문을 덮지 않으며 삭제는 확인 대화상자 이후 서버 확인을 기다린다. 삭제 결과는 안내 말풍선으로 남기고 메뉴·첨부·반응을 제거한다.
|
|
172
172
|
|
|
173
|
-
`deliveryLabel`은 제품 서버가 계산한 수정 상태 또는 단체 대화의 안 읽은 인원 수를 표시한다. 인원 수가 0이면 읽음 숫자를 전달하지 않는다. 가입·퇴장, 메시지 열람 여부와 기록 저장은 제품 소유다. 조회 성공을 읽음으로 추정하거나 예시의 숫자를 제품에 복사하지 않는다. 웹·네이티브 대화 메시지 스토리에서 수정·삭제의 실패 복구와 단체 읽음 수 감소를 확인할 수 있다.
|
|
173
|
+
`deliveryLabel`은 제품 서버가 계산한 수정 상태 또는 단체 대화의 안 읽은 인원 수를 표시한다. 단체 대화의 미확인 수는 `3`처럼 숫자만 전달하며 Web·Native 공통 `caption`(11, 줄 높이 16) 크기로 작게 표시한다. 인원 수가 0이면 읽음 숫자를 전달하지 않는다. 가입·퇴장, 메시지 열람 여부와 기록 저장은 제품 소유다. 조회 성공을 읽음으로 추정하거나 예시의 숫자를 제품에 복사하지 않는다. 웹·네이티브 대화 메시지 스토리에서 수정·삭제의 실패 복구와 단체 읽음 수 감소를 확인할 수 있다.
|
|
174
|
+
|
|
175
|
+
### 작성자 프로필 이동 (2026-10-25, 개발 소스)
|
|
176
|
+
|
|
177
|
+
`avatarAction={{ label: t("profile.open"), onPress: () => openMember(message.authorId) }}`로 사진·이니셜을
|
|
178
|
+
해당 회원의 프로필로 연결한다(Web·Native 동일). Avatar는 표시를 담당하고 ChatMessage가 이름 있는 버튼과
|
|
179
|
+
44px/pt 누르기 영역을 소유한다. 사진은 기존 32px/pt를 유지하고 이동 버튼이 있으면 아바타 열에 44px/pt를 확보한다. 묶음 뒤 메시지는 같은 열 폭을 비우고 중복 버튼을 만들지 않는다.
|
|
180
|
+
제품이 작성자 ID와 프로필 경로를 결정한다. 동작을 생략하면 기존 장식 아바타를 유지한다.
|
|
181
|
+
사진 확대·답장·반응과 프로필 이동을 섞지 않으며 프로필 누르기는 말풍선 제스처를 시작하지 않는다.
|