@hjmds/design-contracts 1.14.0 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/dist/design-profile-layout.d.ts +11 -0
  2. package/dist/design-profile-layout.d.ts.map +1 -0
  3. package/dist/design-profile-layout.js +18 -0
  4. package/dist/design-profile-layout.js.map +1 -0
  5. package/dist/design-profile.d.ts +89 -0
  6. package/dist/design-profile.d.ts.map +1 -0
  7. package/dist/design-profile.js +262 -0
  8. package/dist/design-profile.js.map +1 -0
  9. package/dist/design-system-provider.d.ts +6 -0
  10. package/dist/design-system-provider.d.ts.map +1 -1
  11. package/dist/design-system-provider.js +4 -2
  12. package/dist/design-system-provider.js.map +1 -1
  13. package/dist/gooey-navigation.d.ts +19 -1
  14. package/dist/gooey-navigation.d.ts.map +1 -1
  15. package/dist/gooey-navigation.js +37 -2
  16. package/dist/gooey-navigation.js.map +1 -1
  17. package/dist/palette-contrast.d.ts +6 -0
  18. package/dist/palette-contrast.d.ts.map +1 -1
  19. package/dist/palette-contrast.js +17 -0
  20. package/dist/palette-contrast.js.map +1 -1
  21. package/dist/screen-patterns.d.ts +16 -1
  22. package/dist/screen-patterns.d.ts.map +1 -1
  23. package/dist/screen-patterns.js +4 -0
  24. package/dist/screen-patterns.js.map +1 -1
  25. package/dist/toast-liquid.d.ts +3 -1
  26. package/dist/toast-liquid.d.ts.map +1 -1
  27. package/dist/toast-liquid.js +6 -2
  28. package/dist/toast-liquid.js.map +1 -1
  29. package/dist/version.d.ts +1 -1
  30. package/dist/version.js +1 -1
  31. package/dist/version.js.map +1 -1
  32. package/docs/asset.md +7 -0
  33. package/docs/brand-boundary.md +14 -5
  34. package/docs/code-block.md +12 -1
  35. package/docs/collapsible.md +6 -0
  36. package/docs/design-profile.md +263 -0
  37. package/docs/design-system-provider.md +7 -0
  38. package/docs/dialog.md +5 -1
  39. package/docs/generated/component-maturity.md +1 -1
  40. package/docs/generated/renderer-evidence.json +3 -3
  41. package/docs/generated/renderer-evidence.md +1 -1
  42. package/docs/generated/showcase-manifest.json +1 -1
  43. package/docs/gooey-navigation.md +37 -6
  44. package/docs/heading.md +15 -0
  45. package/docs/theming.md +18 -5
  46. package/docs/usage/README.md +5 -0
  47. package/docs/usage/components/activity-heatmap.md +3 -1
  48. package/docs/usage/components/agreement.md +2 -0
  49. package/docs/usage/components/alert-dialog.md +9 -0
  50. package/docs/usage/components/asset.md +9 -2
  51. package/docs/usage/components/badge.md +3 -1
  52. package/docs/usage/components/bottom-cta.md +3 -1
  53. package/docs/usage/components/bottom-navigation.md +5 -1
  54. package/docs/usage/components/button.md +7 -1
  55. package/docs/usage/components/calendar.md +3 -1
  56. package/docs/usage/components/card.md +19 -2
  57. package/docs/usage/components/carousel.md +5 -0
  58. package/docs/usage/components/code-block.md +14 -2
  59. package/docs/usage/components/collapsible.md +10 -2
  60. package/docs/usage/components/combobox.md +12 -1
  61. package/docs/usage/components/command-palette.md +11 -6
  62. package/docs/usage/components/content-transition.md +1 -1
  63. package/docs/usage/components/context-menu.md +7 -1
  64. package/docs/usage/components/date-picker.md +3 -1
  65. package/docs/usage/components/design-system-provider.md +7 -5
  66. package/docs/usage/components/dialog.md +53 -1
  67. package/docs/usage/components/field.md +3 -1
  68. package/docs/usage/components/form.md +7 -2
  69. package/docs/usage/components/heading.md +7 -1
  70. package/docs/usage/components/image.md +2 -0
  71. package/docs/usage/components/list-row.md +2 -0
  72. package/docs/usage/components/list.md +2 -0
  73. package/docs/usage/components/load-more.md +3 -1
  74. package/docs/usage/components/mentions.md +3 -1
  75. package/docs/usage/components/menu.md +3 -1
  76. package/docs/usage/components/menubar.md +7 -1
  77. package/docs/usage/components/message-composer.md +11 -5
  78. package/docs/usage/components/notice.md +9 -0
  79. package/docs/usage/components/number-field.md +3 -1
  80. package/docs/usage/components/onboarding-screen.md +16 -9
  81. package/docs/usage/components/overview-screen.md +73 -0
  82. package/docs/usage/components/password-field.md +5 -1
  83. package/docs/usage/components/popover.md +7 -0
  84. package/docs/usage/components/saved-items-screen.md +3 -1
  85. package/docs/usage/components/screen-layout.md +9 -1
  86. package/docs/usage/components/search-field.md +3 -1
  87. package/docs/usage/components/select.md +9 -0
  88. package/docs/usage/components/sheet.md +14 -1
  89. package/docs/usage/components/skeleton.md +9 -0
  90. package/docs/usage/components/slider.md +3 -1
  91. package/docs/usage/components/statistic.md +3 -1
  92. package/docs/usage/components/surface.md +8 -1
  93. package/docs/usage/components/tabs.md +11 -2
  94. package/docs/usage/components/tag.md +3 -1
  95. package/docs/usage/components/tags-input.md +6 -1
  96. package/docs/usage/components/text-area.md +3 -1
  97. package/docs/usage/components/text-transition.md +8 -2
  98. package/docs/usage/components/text.md +3 -1
  99. package/docs/usage/components/toast.md +18 -1
  100. package/docs/usage/components/top-bar.md +3 -1
  101. package/docs/usage/compositions/command-records.md +106 -0
  102. package/docs/usage/compositions/content-transition-comparison.md +108 -0
  103. package/docs/usage/compositions/date-time-selection.md +110 -0
  104. package/docs/usage/compositions/design-profile-comparison.md +114 -0
  105. package/docs/usage/tokens/color.md +9 -2
  106. package/docs/usage/tokens/elevation-opacity.md +8 -1
  107. package/docs/usage/tokens/motion.md +10 -1
  108. package/docs/usage/tokens/radius.md +8 -1
  109. package/docs/usage/tokens/typography.md +15 -1
  110. package/package.json +13 -1
@@ -1,6 +1,6 @@
1
1
  # 브랜드 경계 — 제품이 바꿀 수 있는 것과 그 경로
2
2
 
3
- 상태: 규범 · 2026-09-26 · 이 문서가 브랜드·테마 주입 규칙의 단일 원본이다.
3
+ 상태: 규범 · 검토일: 2026-10-07 · 이 문서가 브랜드·테마 주입 규칙의 단일 원본이다.
4
4
  [theming.md](./theming.md)는 사용법 예시, [consumer-policy.md](./consumer-policy.md)는 채택 정책,
5
5
  [design-system-provider.md](./design-system-provider.md)는 환경 축 설계를 다루며 브랜드 규칙은 여기로 링크한다.
6
6
 
@@ -9,11 +9,11 @@ CSS 변수 재정의, 제품 자체 토큰 생성기)였고, 문서 세 개가
9
9
  (`.hjm-*` 재정의 금지 vs 특이도를 맞추면 허용, 부분 덮어쓰기 배제 vs `brandPalette` 권장). 그리고 제품 팔레트의
10
10
  대비를 아무도 검사하지 않았다. 이 문서가 그 셋을 하나로 정한다.
11
11
 
12
- ## 1. 지원하는 경로는 `brandPalette` 하나다
12
+ ## 1. 지원하는 제품 설정 경로
13
13
 
14
- - 제품 브랜드는 Provider의 `brandPalette` prop으로 넣는다(`<HjmProvider brandPalette={…}>`,
14
+ - 색만 바꾸는 제품 브랜드는 Provider의 `brandPalette` prop으로 넣는다(`<HjmProvider brandPalette={…}>`,
15
15
  `<HjmNativeProvider brandPalette={…}>`, 1.5.0). theme별로 17개 `ThemeColors` key 중 필요한 것만 넘기고,
16
- 나머지는 HJM 기본값을 쓴다(부분 병합). Provider는 계속 OS theme·글자 크기·모션 설정을 따르고,
16
+ 나머지는 선택된 프로필 또는 HJM 기본값을 쓴다(부분 병합). Provider는 계속 OS theme·글자 크기·모션 설정을 따르고,
17
17
  중첩 Provider는 가장 가까운 상위의 `brandPalette`를 물려받는다.
18
18
  - 상태 강조색(`statusAccents`·`statusAccentFills`)은 덮을 수 없다. "오류·성공"과 "브랜드"가 같은 색이 되는
19
19
  것을 막는다.
@@ -24,11 +24,20 @@ CSS 변수 재정의, 제품 자체 토큰 생성기)였고, 문서 세 개가
24
24
  브랜드 경로가 아니다. 부분 병합으로 표현할 수 없는 요구는 계약 공백이므로 이슈로 올린다.
25
25
  17개 key를 모두 채운 `brandPalette`는 허용되지만 아래 대비 검사를 반드시 통과해야 한다.
26
26
 
27
+ 2026-10-07 사용자 요청으로 색뿐 아니라 질감·컴포넌트 기본 전환·구성·화면 배치를 한 번 선택하는
28
+ [디자인 프로필](./design-profile.md)을 추가했다(현재 실험·미게시). `defineHjmDesignProfile`로 정규화한
29
+ 앱 소유 데이터를 Provider의 `designProfile`로 주입한다. CSS/전체 value 우회나 테마별 상태 엔진 복제는
30
+ 허용하지 않는다. `brandPalette`는 프로필의 해당 light/dark 팔레트 위에 병합된다. 글꼴 자산·로고·문구·데이터는
31
+ 제품 소유이며 현재 연결 범위와 미지원 표현은 프로필 계약에 명시한다.
32
+
27
33
  ## 2. 모든 브랜드 팔레트는 대비 검사를 통과해야 한다
28
34
 
29
35
  `@hjmds/design-contracts/palette-contrast`의 `checkBrandPaletteContrast(brandPalette)`가 Provider와 같은 방식으로
30
36
  theme별 병합 결과를 검사하고, theme별 기준 미달 쌍을 돌려준다. 반환 객체의 `light`와 `dark` 배열이 모두 비어 있어야 한다(MUST). 제품은 이 호출을
31
37
  자기 테스트에 두어 팔레트 변경마다 실행한다. 전체 팔레트는 `checkPaletteContrast(palette)`를 쓴다.
38
+ 프로필도 쓸 때는 기본 팔레트만 검사하는 `checkBrandPaletteContrast` 대신 각 모드의
39
+ `{ ...designProfile.palette[mode], ...brandPalette[mode] }` 최종 결과를 `checkPaletteContrast`로 검사한다.
40
+ 프로필 자체의 검증이 뒤에 얹은 브랜드색의 대비까지 보장하지는 않는다.
32
41
 
33
42
  | 쌍 | 최소 | 근거 |
34
43
  | --- | --- | --- |
@@ -84,6 +93,6 @@ HJM 기본 light·dark 팔레트도 같은 검사를 통과한다(`test/palette-
84
93
  HJM: semantic color role과 light/dark 대비, spacing·type scale·radius·motion·touch target, component anatomy·상태·
85
94
  키보드·screen-reader 행동, loading·empty·error·disabled·focus 문법.
86
95
 
87
- 제품: 이름·로고·대표 이미지, `brandPalette`로 표현한 브랜드 색, 도메인 상태 → `AccentTone` 매핑, 콘텐츠 밀도와
96
+ 제품: 이름·로고·대표 이미지, 검증한 `designProfile` 데이터와 `brandPalette`로 표현한 브랜드 색, 도메인 상태 → `AccentTone` 매핑, 콘텐츠 밀도와
88
97
  정보 우선순위, copy·i18n·내비게이션 구조. 제품 고유 gradient는 light/dark·on-color 대비와 reduce-motion을 제품 테스트로
89
98
  검증한다([consumer-policy.md §4](./consumer-policy.md#4-제품-정체성-경계)).
@@ -1,6 +1,6 @@
1
1
  # Code block
2
2
 
3
- Reviewed: 2026-10-01. Optional `/code-block` entries in both renderers expose
3
+ Reviewed: 2026-10-07. Optional `/code-block` entries in both renderers expose
4
4
  `CodeBlock`. This is a source preview, not an editor or executable HTML renderer.
5
5
  The visual integration request required syntax presentation without another input
6
6
  or clipboard engine, so source validation belongs to contracts and actions are slots.
@@ -30,3 +30,14 @@ host tests check selectable content and scroll/wrap composition. The
30
30
  200% controlled text scaling and actual iOS simulator long-press Copy, with exact
31
31
  source/clipboard equality. Header and source use the common text-scale helper;
32
32
  token spans inherit once. Android clipboard and physical-device verification remain separate.
33
+
34
+
35
+ The product design profile supplies `tokens.fontFamily.code` and `tokens.typography.body`
36
+ to both source hosts. Syntax spans inherit those metrics and the original code remains
37
+ unchanged. Native translates the default generic monospace intent to Menlo on iOS and
38
+ monospace on Android; custom font installation stays with the product. The source is
39
+ LTR inside an RTL shell: an actual RTL comparison moved the trailing semicolon to the
40
+ beginning of the displayed statement. Localized headings and surrounding controls retain
41
+ the product direction. This is a reading-order decision, not a source-text rewrite.
42
+
43
+ Native 제목은 제품 UI font, 원문과 span은 code font를 읽는다. 두 역할은 같은 내부 플랫폼 font 해석을 공유하며, 제목이 OS 서체로 남던 경로를 보완했다. 실제 font 등록은 제품이 맡는다.
@@ -29,3 +29,9 @@ chrome이 따라오고 그걸 다시 CSS로 지우게 된다. 그래서 별도
29
29
  host-renderer evidence; it does not claim physical keyboard, VoiceOver, or TalkBack verification.
30
30
  - Native and Web long-copy fixtures put the long label in the trigger itself. The child body stays
31
31
  short so the scenario tests the constrained interactive label rather than arbitrary content.
32
+
33
+ ## 프로필 도구의 표현
34
+
35
+ 2026-10-07 테마 전환 시 입력이 사라지는 문제를 피하려고 `presentation="inline"`과 `keepMounted`를 추가했다.
36
+ inline은 트리거를 숨기고 항상 내용을 펼친다. 기본 disclosure는 기존 open/defaultOpen 규칙을 유지한다.
37
+ keepMounted가 있어도 닫힌 내용은 포커스·스크린리더·터치 대상에서 제외한다. 단순 read-only 내용은 기존 기본값을 쓴다.
@@ -0,0 +1,263 @@
1
+ # 디자인 프리셋 계약
2
+
3
+ 검토일: 2026-10-07 · 상태: 10종 실험 구현·대상 로컬 검사 완료 · 미게시(1.14.0 이후)
4
+
5
+ 사용자가 레트로·종이·숲 등의 테마에 따라 같은 기능의 상호작용·구성·화면 배치도 자동으로 달라지고, 앱이 자기 테마를 한 번 주입하기를 요청했다. 색상 프리셋만으로는 그 요구를 충족하지 못하므로 네 축을 하나의 데이터 계약으로 둔다. 기존 상태 엔진을 테마마다 복제하는 방식은 채택하지 않는다.
6
+
7
+ ## 소유권과 공개 경로
8
+
9
+ `@hjmds/design-contracts/design-profile`은 `hjmDesignPresets`, `defineHjmDesignProfile`, `resolveDesignProfileSurfaceMaterial`, `HjmDesignProfile`, `HjmDesignProfileInput`, `HjmDesignPreset`을 제공한다. 이 subpath는 기존 ThemeStudio의 색상 편집과 역할이 다르다. 색상 편집 subpath에 질감/구성 그래프를 추가하지 않고 선택형 프로필 진입점으로 분리했다. package export 추가의 근거는 이 절이다.
10
+
11
+ 제품은 설정 파일에서 preset을 상속하고 필요한 축만 수정한다. 설정은 Web/Native renderer를 import하지 않으며 글꼴 자산의 설치·라이선스·로딩, 브랜드 자산, 데이터·권한·라우팅·서버 확정은 제품이 소유한다. HJM은 지원 가능한 표현/행동/배치와 환경 대체 경로를 소유한다.
12
+
13
+ ```ts
14
+ import { defineHjmDesignProfile } from "@hjmds/design-contracts/design-profile";
15
+
16
+ export const productDesign = defineHjmDesignProfile({
17
+ extends: "forest",
18
+ id: "product-design",
19
+ compositions: { collection: "rows" },
20
+ });
21
+ ```
22
+
23
+ 이 helper는 검증한 불변 프로필을 만든다. Web `HjmProvider.designProfile`, Native `HjmNativeProvider.designProfile`에 넣으며, 중첩 Provider는 가장 가까운 프로필을 상속한다. 기존 프로필 없는 소비자의 기본값은 유지한다.
24
+
25
+ ### 제품 설정과 참고 테마를 조합하기
26
+
27
+ 같은 제품이 `extends`만 바꾸면 나머지 부분 지정은 계속 제품 소유다. `palette`는 light/dark의 지정 역할만,
28
+ `compositions`·`screens`·`interactions`는 지정 축만 덮고 모서리·글자·질감 등의 미지정 값은 참고 테마를 상속한다.
29
+ 기록/계정/라우팅 상태를 프로필 객체에 넣거나 프로필 id를 React subtree key로 써서 교체하지 않는다.
30
+
31
+ 2026-10-07 필요한 조사 후 기존 테마 조합 실험에 산책 노트(녹색/cards/landscape)와 문장 모음(보라/rows/editorial)
32
+ 두 앱 설정 fixture를 추가했다. 두 플랫폼은 같은 순수 설정을 공유하며 각 workspace의 실제 공개 helper로 검증한다.
33
+ 앱 브랜드를 새 HJM preset/global registry로 등록하지 않고 기존 10종 위에 조합하는 경계를 보여 주기 위한 선택이다.
34
+ 이 fixture는 운영 제품의 테마 적용이나 Native 기기 검증 증거가 아니다. 앱은 자신의 설정 파일과 제품 데이터를 넣는다.
35
+ 행동·상태와 실제 지원 축은 [사용 지침](usage/compositions/design-profile-comparison.md)을 따른다.
36
+
37
+ ## 축과 기본값
38
+
39
+ | 축 | 중립 기본값 | 참고 프리셋의 차이 |
40
+ | --- | --- | --- |
41
+ | palette | 현재 HJM light/dark 17 semantic roles | 레트로의 잉크/황갈색, 종이의 따뜻한 중립색, 숲의 녹색 |
42
+ | tokens | 기존 radius/fontFamily/typography/heading/shadow | 모서리·글자 크기/행간/강조·그림자와 일반 monospace fallback; 폰트 자산은 번들하지 않음 |
43
+ | material | canvas/card/surface 모두 null | 레트로 noise, 종이 grain, 숲 mesh+glow; 오로라만 active=true, 나머지는 정적 |
44
+ | interactions | contentTransition=fade, selectionMotion=none | 레트로 slide, 종이 fade, 숲 rise와 slide 선택 배경 |
45
+ | compositions | collection=rows, toolbar=inline | 레트로 grid/inline, 종이 rows/collapsible, 숲 cards/collapsible |
46
+ | screens | overview=dashboard | 종이 editorial, 숲 landscape |
47
+
48
+ 상속 후 데이터는 재귀적으로 동결한다. 호출자의 배열/descriptor를 동결하지 않고 복사해 앱 소유 상태에 영향을 주지 않는다. light/dark 팔레트와 nested 토큰은 역할별로 병합하며, preset 원본은 바뀌지 않는다. 고정된 원·pill 의미 때문에 radius.full=999는 유지한다. 글자 크기·줄 높이·그림자·질감 범위와 지원하는 변형 이름을 검사하고 지정 색상 쌍의 대비 미달을 거부한다. 이 검사는 완성 화면 접근성 인증이 아니다.
49
+
50
+ ## 기존 API 비교와 연결 순서
51
+
52
+ - 기존 Provider/brandPalette/environment는 유지한다. 프리셋은 별도 환경 축이 아니라 네 단계의 표현/배치 기본값이며 명시적인 props가 우선한다.
53
+ - `ContentTransition`의 fade/rise/slide/scale와 `SegmentedControl`·`Tabs`의 selectionMotion을 재사용한다. Tabs의 명시 appearance가 우선이며 세로는 standard다. 없는 피드백 엔진을 제공했다고 표시하지 않는다.
54
+ - Surface와 Web 테마 변수, Native tokens 및 직접 foundation을 읽는 소비자를 함께 연결한다. `tokens.radius` 값 정의만으로 전체 컴포넌트 적용을 주장하지 않는다.
55
+ - 구성은 기존 Grid/List/Collapsible/도구 묶음과 공개 슬롯을 대조한다. 화면은 기존 ScreenLayout의 제목·본문·상태·주 행동 계약을 유지하며 배치 변형을 추가한다. 같은 화면의 데이터/초안을 variant subtree 안에 저장해 전환 시 버리지 않는다.
56
+ - 질감은 optional EffectSurface renderer의 host/peer 경계를 유지한다. 프로필의 descriptor 정의만으로 native SVG peer 설치나 실제 표시를 보증하지 않는다.
57
+
58
+ ## 현재 증거와 남은 조건
59
+
60
+ 공통 데이터·Provider·기본 토큰 소비·상호작용 기본값·OverviewScreen 구성과 화면·양쪽 Storybook 비교를 구현했다. 전체 기존 컴포넌트의 정적 토큰 소비 감사는 진행 중이다. 브라우저의 입력 유지·복구와 light/dark·좁은 폭·큰 글자·RTL·모션 축소는 [QA 기록](../../../docs/qa/2026-10-07-design-profile-research.md)에서 확인했다. Native 실기기 검증은 아직 미완료다. 실험 등록·승격·게시·Utilverse 적용을 분리한다. 완료 기준은 [작업 계획](../../../docs/plans/reference-release-utilverse-2026-10-07.md)의 프리셋 절을 따른다.
61
+
62
+ ## 10종 확장과 현재 연결
63
+
64
+ 2026-10-07 사용자 요청으로 참조 팩은 최소 10종이며 neutral은 수에서 제외한다.
65
+ [조사/QA 기록](../../../docs/qa/2026-10-07-design-profile-research.md)에 개별 출처와 원본 관찰/HJM 해석을 구분한다.
66
+ Provider의 `designProfile`에 `hjmDesignPresets.forest` 또는 `defineHjmDesignProfile(...)` 결과를 넣는다.
67
+ 부분 JSON을 Provider에 직접 넣지 않는다. 앱의 파일·등록·설정 저장과 폰트 로딩은 앱이 소유한다.
68
+ `brandPalette`는 선택된 프로필의 해당 테마 팔레트 위에 놓인다.
69
+
70
+ 프로필은 현재 양 플랫폼 Provider, 기본 Text/Surface/Button·필드 모서리, ContentTransition,
71
+ SegmentedControl·Tabs, ScreenLayout 및 optional OverviewScreen에 연결한다. 모든 기존 공개 컴포넌트의
72
+ 정적 recipe 경로까지 자동 반영 완료를 뜻하지 않는다. ScreenLayout의 기존 기본 배치는 프로필이 없으면 유지한다.
73
+ 유리의 실제 backdrop blur와 클레이 inset shadow는 아래 Surface 질감 계약으로 연결한다. Native의 선택형 host·OS·architecture 조건과 실제 기기 검증은 별도다.
74
+
75
+
76
+ ## 큰 제목까지 한 번에 지정하기
77
+
78
+ `tokens.heading`은 `level1`~`level5`의 fontSize/lineHeight/fontWeight를 부분 지정한다.
79
+ 현재 Heading은 두 renderer 모두 이 값으로 그리고 문서 `semanticLevel`과 textScale을
80
+ 따로 유지한다. 중립은 foundation의 40/32/24/20/18px를 그대로 쓰며, 에디토리얼의
81
+ level1/2는 44/34px·행간 54/44px·굵기 500, 브루탈리즘은 48/38px·행간 56/46px·굵기
82
+ 800이다. 이 두 큰 제목 선택은 원본 치수 복제가 아니라 편집형/강한 강조 프리셋의
83
+ 시각 계층을 구분한 HJM 실험값이며 좁은 폭·큰 글자 QA와 함께 판단한다.
84
+
85
+ ```ts
86
+ const productDesign = defineHjmDesignProfile({
87
+ extends: "paper",
88
+ tokens: { heading: { level1: { fontSize: 52, lineHeight: 64, fontWeight: "500" } } },
89
+ });
90
+ ```
91
+
92
+ 미지정 값은 preset을 상속한다. `tokens.typography.heading/titleLarge/title`은 이전과
93
+ 같이 Heading level3/4/5의 변경 기본값이며, 같은 필드에 명시한 `tokens.heading`이
94
+ 우선한다. 나머지 프로필 축·본문 Text typography와 문서 순서는 바꾸지 않는다.
95
+ 지원하지 않는 persisted heading 단계는 조용히 무시하지 않고 거부한다.
96
+
97
+ ## 오버레이·선택 입력의 프로필 연결 보완
98
+
99
+ 2026-10-07 실제 소비 경로 대조에서 Web의 Dialog/Sheet/Toast 전용 그림자 변수와 Native의
100
+ Dialog/AlertDialog/Sheet, Select/Combobox, Notice/Progress/Skeleton/Toast가 프로필의 해당
101
+ 역할 대신 foundation/recipe 값을 직접 읽었다. Provider 값만 바꾸는 방식으로는 동일 화면의
102
+ 카드와 열린 오버레이가 다른 표현을 유지했으므로 기존 API의 소비 경로를 연결했다.
103
+
104
+ - Web Dialog/Sheet/Toast와 Native Dialog/AlertDialog/Sheet/일반 Toast는 `tokens.shadow.floating`을
105
+ 읽는다. 프로필 없는 소비자는 각 recipe의 기존 그림자와 Native elevation을 유지한다.
106
+ - Native에서 모서리의 역할 이름은 각 recipe가 정하고 값은 Provider의 `tokens.radius`가 정한다.
107
+ 원·pill의 full=999, Sheet 하단의 바닥 모서리 0, 명시한 Skeleton 반지름은 유지한다.
108
+ - Android elevation은 별도 플랫폼 그림자를 그리므로 프로필 opacity=0이면 elevation도 0이다.
109
+ 나머지는 radius/offsetY의 최대값으로 근사한다. CSS blur와 기기 그림자의 픽셀 동등성을 뜻하지
110
+ 않는다. [플랫폼 근거](https://reactnative.dev/docs/view-style-props#elevation).
111
+ - 액션·선택·초안·Modal lifecycle·safe area·키보드 처리는 바꾸지 않는다. Liquid Toast의
112
+ managed presentation은 기존 별도 표현 host가 계속 소유한다.
113
+
114
+ 기존 테마 조합 실험에서 Notice/Skeleton/Toast와 Dialog/Sheet를 직접 열고, 오버레이 안의
115
+ 다음 테마 버튼으로 10종을 순회한다. 같은 제어 초안을 닫기/재열기에서도 유지한다.
116
+ Web의 10개 밝은 Dialog와 10개 dark/RTL/2배 Sheet 및 390px 검토는 위 QA 기록에 있다.
117
+ Native 테스트는 실제 기기의 표시·VoiceOver 증거가 아니다. 오버레이 토큰 연결만으로 모든 질감이 적용되는 것은 아니다. 아래 Surface 질감 연결과 별도로 남은 다른 컴포넌트의 직접 토큰/recipe 소비 경로도 계속 대조한다.
118
+
119
+
120
+ ## Surface/Card의 유리·클레이 질감
121
+
122
+ 2026-10-07 원본 대조에서 유리는 glow만, 클레이는 grain만 있어 물리적인 표면 표현이 빠져 있었다.
123
+ `material.surface`를 기존 Surface와 그 소비자인 Card에 연결한다. 새 wrapper나 상태 엔진을 만들지 않는다.
124
+ EffectSurface는 mesh/glow/noise/grain 장식이며, ProgressiveBlur는 스크롤·입력 가림을 판단하는 가장자리
125
+ 마스크다. 배경 영역 전체의 blur/inset은 이들과 역할이 달라 Surface가 소유한다.
126
+
127
+ | 필드 | 중립/미지정 | 범위와 실제 사용 |
128
+ | --- | --- | --- |
129
+ | `material.surface` | null | 부분 객체는 선택 preset의 surface를 상속, null은 해당 처리를 해제 |
130
+ | `blurStrength` | 0 | 0~1. glass 0.75 → Web 24px. Native host의 강도는 기기별로 보정하며 픽셀 동등성 아님 |
131
+ | `fillOpacity` | 1 | 0.85~1. glass 요청 0.88. blur가 0이거나 지원되지 않으면 불투명 |
132
+ | `insetShadows` | 빈 배열 | 최대 2개. color 6자리 HEX·opacity 0~1·radius 0~96·offsetX/Y -96~96 |
133
+
134
+ clay의 안쪽 빛은 white/0.22/radius10/offset3,4, 그림자는 black/0.12/radius12/offset-3,-4다.
135
+ 밝은 glass의 textSub=#5b6879·textWeak=#748292는 중립 팔레트의 약한 색이 대비 보정에서 opacity=1을
136
+ 요구했던 실제 비교 결과 때문에 더 짙게 정했다. 대비 기준을 낮추지 않고 질감과 읽기 경계를 함께 유지한다.
137
+ 이 값은 외부 원본 치수·브랜드색의 복사가 아니라 HJM의 정적인 표면 실험값이다. 바깥 그림자는 기존
138
+ `tokens.shadow.floating`, 모서리는 같은 `tokens.radius` 역할을 계속 읽는다.
139
+
140
+ ```ts
141
+ const productDesign = defineHjmDesignProfile({
142
+ extends: "glass",
143
+ material: { surface: { blurStrength: 0.5 } },
144
+ });
145
+ ```
146
+
147
+ `resolveDesignProfileSurfaceMaterial(profile, finalThemePalette)`는 Provider의 최종 제품 팔레트에서
148
+ bg 위의 기존 대비 쌍이 검정/흰색 배경 합성 후에도 유지되도록 요청 opacity를 0.01씩 높인다.
149
+ 질감 뒤의 실제 이미지가 글자 대비의 근거가 될 수 없기 때문이다. 두 renderer는 같은 엔진인
150
+ `@hjmds/design-contracts/palette-contrast`의 `resolveSurfaceFillOpacity(requested, palette)`를 읽는다.
151
+ 이 palette-only 진입점을 재사용해 일반 Provider가 선택형 전체 preset registry를 runtime import하지 않는다. 이 함수는 장식·선택된 입력·이미지·
152
+ 실제 화면 전체 접근성을 인증하지 않는다. inset의 가장자리와 미디어/결과 상태는 실제 화면에서도 확인한다.
153
+
154
+ ### Web
155
+
156
+ Provider가 네 surface CSS 변수를 매번 해석한다. 중첩 neutral은 상위 glass/clay를 지운다.
157
+ 실제 `backdrop-filter` 또는 Safari의 prefixed 속성을 지원할 때만 투명 fill을 쓰고, OS
158
+ `prefers-reduced-transparency: reduce`이면 opaque/none으로 대체한다. blur=0이면 `none`으로
159
+ 내보내므로 평범한 Surface에 불필요한 backdrop stacking context를 만들지 않는다.
160
+
161
+ ### Native의 한 번 등록하는 host
162
+
163
+ `HjmNativeProvider.surfaceEffects`는 `renderBackdrop({ strength, theme })`와 `insetShadows`를
164
+ 제품 루트에서 공급한다. 중첩 Provider는 그대로 상속하며 `{}`는 그 subtree를 해제한다.
165
+ core renderer는 Expo/Skia/blur 라이브러리를 import하지 않는다. `renderBackdrop`은 실제 backdrop
166
+ React element를 반환하고 사용할 수 없으면 null을 반환한다. callback은 앱 setup에서 안정적으로 둔다.
167
+
168
+ - iOS는 [AccessibilityInfo](https://reactnative.dev/docs/0.81/accessibilityinfo)의 투명도 줄이기 설정을
169
+ 한 번 관찰한다. unknown/reject/설정 활성화는 불투명이다. 실시간 이벤트가 초기 비동기 응답보다 우선한다.
170
+ - 장식만 pointer/접근성에서 제외하고 모서리 clip을 한다. 본문은 stable keyed sibling이므로 optional host
171
+ 실패·테마 전환이 초안을 remount하지 않는다. 실패는 opaque로 대체하고 host 함수 교체/질감 변경 때만 재시도한다.
172
+ - `insetShadows=true`는 제품이 [RN New Architecture와 Android API 29 이상](https://reactnative.dev/docs/0.81/view-style-props#boxshadow)을 확인한 경우만 쓴다. 기본 false이며 core는 기존 architecture도 지원한다.
173
+ - [Expo BlurView](https://docs.expo.dev/versions/latest/sdk/blur-view/)를 쓰는 Android 제품은 먼저 렌더한
174
+ BlurTargetView의 ref를 host에 공급한다. Target은 효과가 그려지는 범위를 덮어야 한다. Showcase는 API31 미만을
175
+ 불투명으로 유지하며, 지원 기기에서 strength×100과 `dimezisBlurViewSdk31Plus`를 쓴다.
176
+
177
+ ```tsx
178
+ // 선택형 blur 모듈이 설치된 제품 host. capability 확인과 Target 배경은 제품 setup 소유.
179
+ const effects = useMemo(() => ({
180
+ insetShadows: hostSupportsInsetShadows,
181
+ renderBackdrop: ({ strength, theme }: { strength: number; theme: "light" | "dark" }) =>
182
+ hostSupportsBlur ? <BlurView style={StyleSheet.absoluteFill} blurTarget={targetRef}
183
+ intensity={strength * 100} tint={theme} blurMethod="dimezisBlurViewSdk31Plus" /> : null,
184
+ }), [hostSupportsBlur, hostSupportsInsetShadows, targetRef]);
185
+
186
+ <HjmNativeProvider designProfile={productDesign} surfaceEffects={effects}>{children}</HjmNativeProvider>
187
+ ```
188
+
189
+ 실험 ‘테마 조합’의 무늬 배경 위 공개 Card에서 입력한 초안과 다음 테마 버튼으로 비교한다.
190
+ Web 실제 표시·Native mock-host 회귀·기기 미확인 범위는 [QA 기록](../../../docs/qa/2026-10-07-design-profile-research.md)에 보존한다.
191
+ 오버레이/상단 바 등 Surface를 쓰지 않는 모든 공개 소비자에 이 material까지 반영 완료한 것은 아니다.
192
+
193
+
194
+ ## 모서리·서체 소비 경로 보완
195
+
196
+ 2026-10-07 후속 감사에서 Native의 날짜·태그·약관·목록·메뉴·상단 바·저장 컬렉션 등은
197
+ recipe가 정한 역할을 foundation에서 직접 읽어 프로필의 모서리를 놓쳤다. 같은 공개 API가
198
+ Provider의 `tokens.radius`에서 역할을 해석하도록 연결했다. 원·pill의 full, 날짜 셀의 원형,
199
+ selection glyph의 고정 geometry는 별도 계약으로 유지한다. 테마가 상태 엔진을 대체하지 않는다.
200
+
201
+ PasswordField large, Calendar custom content, CodeBlock, optional GestureSheetInput도
202
+ Provider typography를 읽는다. PasswordField는 같은 줄 높이로 프레임을 계산하며 size recipe는
203
+ 최소 높이로만 사용한다. CodeBlock의 `fontFamily.code`는 Web CSS 변수와 Native host로 연결하고
204
+ 글자 확대는 한 번만 적용한다. 사용자 font 등록·실기기 glyph/줄바꿈은 제품 검증 대상이다.
205
+
206
+ 구조 비교 근거: [Tailwind theme 변수](https://tailwindcss.com/docs/theme)는 서체·모서리 등
207
+ 범주별 token과 실제 소비 utility를 연결하고, [shadcn theme](https://ui.shadcn.com/docs/theming)는
208
+ semantic foreground/background와 공유 radius scale을 소비 컴포넌트에 연결한다. HJM도 기존
209
+ semantic role을 재사용하되 CSS 생성기·단일 비율 radius를 새 의존성으로 도입하지 않는다.
210
+ 기존 프로필의 sm/md/lg/xl 개별 값과 네이티브 번역·상태 계약을 유지하는 선택이다.
211
+
212
+
213
+ ## Native UI 서체의 실제 host 연결
214
+
215
+ 2026-10-07 raw Text/TextInput 대조에서 Text는 UI 서체를 읽었지만 FieldRenderer,
216
+ Combobox, NumberField, Slider, TagsInput, optional GestureSheetInput과 CodeBlock 제목은
217
+ 시스템 서체를 유지했다. [React Native 텍스트 상속](https://reactnative.dev/docs/text)은 Text
218
+ 하위 트리에 한정되므로 상위 View 스타일만으로 해결하지 않는다. 내부 font resolver를 공유하고
219
+ 각 입력/라벨 host에서 Provider의 UI 역할을 읽는다. CodeBlock 원문만 code 역할을 유지한다.
220
+ 고정 체크·닫기 glyph와 투명 OTP editor는 기존 의미를 유지한다.
221
+
222
+ 기본 UI stack 전체는 Native OS 서체로 유지한다. 첫 항목만 비교하면 제품이 직접 등록한
223
+ `ui: ["Inter"]`까지 기본 stack으로 오인하므로 전체 stack과 비교한다. 제품의 명시적인 named
224
+ font는 첫 항목을 Native에 전달한다. Native는 CSS fallback 목록을 그대로 해석하지 않는다.
225
+ `ui-monospace`/`monospace`는 기존 iOS Menlo·Android monospace로 번역한다. 나머지 제품 font는
226
+ 유효한 플랫폼 등록 이름과 글리프/굵기 지원을 제품이 검증해야 한다. 제품 자산은 HJM에 번들하지 않는다.
227
+
228
+ TagsInput의 실제 입력칸은 body 글자·줄 높이와 같은 controlled scale을 한 번만 읽는다.
229
+ 부모/중첩 프로필 전환은 입력 요소·초안·NumberField의 미확정 숫자·검색어를 유지한다.
230
+ [Refero token 지침](https://styles.refero.design/ai-agents/css-variables-design-tokens)의 역할 소비,
231
+ [컴포넌트 비교](https://styles.refero.design/ai-agents/component-design-prompts)의 반복되는 서체 역할,
232
+ [검수 지침](https://styles.refero.design/ai-agents/agentic-ui-quality-checklist)의 실제 상태 검토를
233
+ 기존 HJM 계약과 대조한 후속 보완이다. linked 제품 소스와 모든 상태를 검수한 결과는 아니다.
234
+ 실제 기기의 폰트 로딩·텍스트 줄바꿈·접근성 증거는 계속 별도 검증한다.
235
+
236
+ ## 팝오버와 하단 chrome의 그림자 상속
237
+
238
+ 2026-10-07 추가 소비 감사에서 Web Popover의 inline recipe 값과 Native BottomCTA·
239
+ floating/capsule BottomNavigation의 recipe 그림자가 프로필을 우회하는 것을 확인했다.
240
+ 기존 API에 `shadow.floating`을 연결했다. bar는 무그림자를 유지하고 BottomCTA는 footer가
241
+ 위 콘텐츠와 겹치는 역할이라 offsetY의 절댓값을 위쪽으로 뒤집는다(bottomCtaRecipe 근거).
242
+ 별도의 그림자 토큰/엔진을 추가하지 않는다. Native의 0-opacity는 iOS 값뿐 아니라 기존
243
+ 공통 helper로 Android elevation도 제거한다. 프로필 없는 경로는 이전 renderer 외형이다.
244
+
245
+ 양 Showcase의 같은 저장/실패 행동은 공개 BottomCTA로 비교하고 Web chrome 비교에는
246
+ 기존 공개 Popover를 연결했다. 열린 초안/포커스·safe area·선택 route·행동 소유권 검증과
247
+ Native 기기 미확인 범위는 [QA](../../../docs/qa/2026-10-07-design-profile-research.md)에 남긴다.
248
+
249
+ ## 선택형 리퀴드 알림의 프로필 소비
250
+
251
+ 2026-10-07 optional Native `/toast-liquid`를 별도로 대조한 결과 settled 카드와 RN 내용 clip은
252
+ 고정 모서리 12, Skia 그림자는 foundation `raised`를 읽고 있었다. 가장 가까운 프로필의
253
+ `radius.lg`와 `shadow.raised`로 연결한다. 일반 Toast의 `floating`과 합치지 않은 이유는
254
+ [기존 깊이 검토](../../react-native/docs/liquid-toast.md#current-shape--2026-10-02)에서 정한 얕은 카드 역할이다.
255
+ 프로필 없는 소비자는 이전 12와 raised를 유지한다. 그림자의 양방향 offset을 포함해 Canvas
256
+ 네 가장자리의 paint 여유를 함께 계산한다. 프로필이 얕은/무그림자를 고르면 그 값도 그대로 소비한다.
257
+
258
+ `buildLiquidToastGeometry`는 네 번째 선택 인자로 유한한 0 이상 settled radius를 받는다(기본 12).
259
+ 모서리는 측정 폭·높이의 절반으로 제한한다. 원형 origin, 큐, 행동·닫힘, 모션 감소·화면 읽기
260
+ fallback은 유지한다. Web은 일반 Toast fallback이므로 Native 효과를 양 플랫폼 제공으로 세지 않는다.
261
+ 기존 테마 비교 구성의 Native 예제로 같은 visible 알림을 보존한 채 10종을 순회한다.
262
+ 선택 peer는 optional subpath에 유지하며 새 공개 컴포넌트나 상태 엔진을 추가하지 않는다.
263
+ 실제 기기 외형·제스처·음성·성능은 [QA](../../../docs/qa/2026-10-07-design-profile-research.md)의 미확인 범위다.
@@ -143,3 +143,10 @@ catalog 상태는 `beta`다. Web과 RN, 두 제품에서 값 해석·Context 전
143
143
  중첩 Provider의 omitted axis 상속 경계까지 확인됐다. 다만 이 상속 adapter가 포함된
144
144
  추가 제품 릴리스 증거는 아직 없으므로 roadmap은 다음 승격 조건을
145
145
  `evidence-needed`로 기록하고 `stable`을 과장하지 않는다.
146
+
147
+ ## 디자인 프로필 연결(실험·미게시)
148
+
149
+ 2026-10-07 사용자 요청으로 options의 `designProfile`에 정규화한 프로필을 받고 해석된 값에도 전달한다.
150
+ 기본 semantic 팔레트는 프로필의 현재 테마 값이며 `brandPalette`가 그 위에 병합된다. 환경·상태 강조색은
151
+ 기존 계약을 유지한다. 코어 Provider는 프로필 레지스트리를 런타임 import하지 않는다(type-only).
152
+ renderer 기본값·선택 기준·부분 상속은 [디자인 프로필 계약](design-profile.md)을 따른다.
package/docs/dialog.md CHANGED
@@ -46,7 +46,11 @@ Native accessibility follow-up (2026-10-01): at 200% text scale, the close glyph
46
46
 
47
47
  Native viewport candidate (BT-QA-027, 2026-10-05): BurnTok local QA exposed a long confirmation extending beyond the visible screen. Dialog and AlertDialog now constrain the content surface and provide a shrinking scroll body, with actions outside that body and provider safe-area padding. Host tests cover those structural contracts and cancellation; they cannot prove Yoga geometry. Ordinary-size iOS confirmation and cancellation were checked. Enlarged-text device verification remains pending: the user stopped that QA scope before the candidate was confirmed, so this is not a completed device fix. Font caps and clipped copy were rejected because they remove readable content.
48
48
 
49
- ## Optional measured origin motion (unpublished experiment)
49
+ ## Optional measured origin motion (published API, experimental presentation)
50
+
51
+ 2026-10-07 Aceternity card/grid comparison exposed a stale publication label here.
52
+ Both npm 1.14.0 renderer tarballs include `DialogProps.motionOrigin` in `dist/overlays.d.ts`,
53
+ matching release commit `8d6f665`. Publication does not close the device/performance debt below.
50
54
 
51
55
  `motionOrigin` supplies a trigger rectangle measured immediately before opening in the same physical
52
56
  viewport/window coordinate system as the destination. The existing content-transition resolver supplies
@@ -1,6 +1,6 @@
1
1
  # Component maturity and evidence manifest
2
2
 
3
- > Generated from `@hjmds/design-contracts` 1.14.0. Do not edit this file directly; run `pnpm contracts:sync`.
3
+ > Generated from `@hjmds/design-contracts` 1.15.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
 
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "designSystemVersion": "1.14.0",
3
+ "designSystemVersion": "1.15.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.14.0",
8
+ "packageVersion": "1.15.0",
9
9
  "activeComponents": 103,
10
10
  "claimedComponents": 103,
11
11
  "completeScenarioComponents": 103,
@@ -5642,7 +5642,7 @@
5642
5642
  },
5643
5643
  "native": {
5644
5644
  "packageName": "@hjmds/react-native",
5645
- "packageVersion": "1.14.0",
5645
+ "packageVersion": "1.15.0",
5646
5646
  "activeComponents": 83,
5647
5647
  "claimedComponents": 83,
5648
5648
  "completeScenarioComponents": 83,
@@ -1,6 +1,6 @@
1
1
  # Renderer evidence coverage
2
2
 
3
- > Generated for HJM 1.14.0. Do not edit directly; run `pnpm evidence:sync`.
3
+ > Generated for HJM 1.15.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
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
- "designSystemVersion": "1.14.0",
3
+ "designSystemVersion": "1.15.0",
4
4
  "packageName": "@hjmds/design-contracts",
5
5
  "components": [
6
6
  {
@@ -1,10 +1,13 @@
1
1
  # Gooey navigation
2
2
 
3
- Reviewed: 2026-10-01
3
+ Reviewed: 2026-10-07
4
4
 
5
5
  Use the existing `Tabs` from `@hjmds/react/navigation` or
6
- `@hjmds/react-native/navigation` with `appearance="gooey"`. The default remains
7
- `standard`. A new navigation controller would duplicate existing selection,
6
+ `@hjmds/react-native/navigation` with an explicit `appearance="standard"`, `"slide"` or `"gooey"`.
7
+ The unpublished follow-up after 1.14.0 inherits `designProfile.interactions.selectionMotion`
8
+ when appearance is omitted: `slide` selects a plain moving line and `none` selects
9
+ `standard`. Without a profile the default remains `standard`. Explicit appearance
10
+ wins over the profile. A new navigation controller would duplicate existing selection,
8
11
  keyboard, disabled-item and panel contracts, so only the selected indicator is
9
12
  extended. Vertical tabs deliberately retain the standard line: stretching a
10
13
  horizontal bridge across a vertical list would obscure unrelated items.
@@ -21,10 +24,11 @@ coordinates also support RTL and horizontal scrolling.
21
24
  Reduced motion, backgrounding and cleanup settle the indicator without changing
22
25
  selection. Native width animation uses Core Animated's JS driver because width
23
26
  cannot use the native transform driver without distorting corner radii. No new
24
- optional animation dependency is introduced. Rapid re-selection targets the last
25
- selected tab; this is deterministic selection feedback, not a physics simulation.
27
+ optional animation dependency is introduced. Rapid re-selection captures the visible intermediate bounds before cancellation
28
+ and starts the next animation there, while selection targets the last chosen tab.
29
+ This is deterministic selection feedback, not a physics simulation.
26
30
 
27
- Both Storybooks expose `컴포넌트 / 탐색 / Gooey Navigation` with Default,
31
+ Both Storybooks expose `배포/컴포넌트/탐색/선택 표시가 이어지는 탭` with Default,
28
32
  Dark and LargeText plus a direction toggle. Disabled tabs, existing activation
29
33
  mode and panel associations remain canonical. The Native renderer is tested with
30
34
  mock layout events; actual device appearance remains to be verified.
@@ -34,3 +38,30 @@ content bounds when selection, direction or viewport width changes. This correct
34
38
  LargeText RTL selected-label clipping issue found in the [device flow audit](../../../docs/evidence/component-flows-2026-10-01/README.md).
35
39
  The standard appearance shares this behavior; fitted and non-scrollable lists do not
36
40
  programmatically scroll. Selection semantics and the host's panel ownership are unchanged.
41
+
42
+ ## Plain sliding and profile inheritance (unpublished after 1.14.0)
43
+
44
+ The Aceternity [comparison](../../../docs/plans/aceternity-interaction-adoption-2026-10-07.md)
45
+ found that profile sliding reached SegmentedControl but not Tabs. The existing
46
+ Tabs renderer now resolves the appearance through `resolveTabsAppearance`;
47
+ selection, keyboard, disabled items and panel mounting keep their existing owner.
48
+ It does not recreate stacked panels or shared-element content transitions.
49
+
50
+ `resolveTabIndicator` uses the shared `motion.normal` (200ms) and
51
+ `easing.standard` for plain sliding: source and destination x/width interpolate
52
+ without the elastic union bridge. Plain/standard indicators keep the existing
53
+ 2-point height; explicit gooey keeps its 6-point decorative geometry, 320ms bridge
54
+ and established platform easing. Vertical orientation always resolves to standard.
55
+
56
+ Web tracks list and tab measurements, including fitted RTL width changes, and
57
+ samples running or paused WAAPI frames before cancellation. Native tracks its
58
+ JS-driver frame in a ref through an Animated listener, removed on cleanup. This
59
+ adds no animation dependency or per-frame React render. Background/reduced motion
60
+ settles the indicator at the selected tab.
61
+
62
+ `실험/구성/비교와 검증/테마 조합` compares inherited, standard, slide and gooey
63
+ through the public Tabs API with visited panel mounting. Changing a theme does
64
+ not choose a different panel lifetime: products still own controlled drafts or
65
+ `mountPolicy`. The [QA record](../../../docs/qa/2026-10-07-design-profile-research.md)
66
+ separates actual Chromium checks from Native mock-host tests; Native device
67
+ appearance/performance and experiment promotion remain pending.
package/docs/heading.md CHANGED
@@ -23,3 +23,18 @@ level5 18px까지 다섯 단계가 있었지만 어떤 renderer도 노출하지
23
23
  구조를 왜곡하는 대신 둘을 따로 적는다. 생략하면 `level`의 숫자를 따른다.
24
24
 
25
25
  **Native.** 접근성 role은 `header` 하나뿐이라 문서 단계는 `aria-level`로 함께 싣는다.
26
+
27
+
28
+ ## 디자인 프로필의 전체 제목 크기(실험·미게시)
29
+
30
+ 2026-10-07 [Heading 갤러리](https://component.gallery/components/heading/)를 비교하며
31
+ 현재 renderer가 level3~5만 프로필 typography에 연결하고 level1/2는 고정값으로 남긴
32
+ 누락을 확인했다. 앱이 테마를 한 번 넣어 큰 제목까지 재사용하려는 요구 때문에
33
+ [디자인 프로필](design-profile.md)의 `tokens.heading`을 다섯 시각 단계로 둔다.
34
+ 본문 크기에서 큰 제목을 임의로 배율 계산하는 대안은 계층과 행간이 달라질 수 있어
35
+ 채택하지 않는다. 원본 갤러리의 수치·코드·폰트 자산을 복사한 것이 아니다.
36
+
37
+ 프로필이 없으면 원래 40/32/24/20/18 크기를 유지한다. 기존 level3~5 typography
38
+ alias는 helper에서 병합하고 명시적인 heading override가 마지막에 우선한다.
39
+ Web은 CSS 변수, Native는 Text host의 metrics로 반영하고 `semanticLevel`·문구·초점을
40
+ 바꾸지 않는다. 테마 전환은 시각 크기만 바꾸며 실제 문서 단계는 기존 계약이 소유한다.
package/docs/theming.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # 테마 주입 — 내 브랜드색으로 시작하기
2
2
 
3
- 검토일: 2026-10-06 (`value` 중심 예시를 1.5.0 `brandPalette` prop 경로로 정정)
3
+ 검토일: 2026-10-07 (`value` 중심 예시를 1.5.0 `brandPalette` prop 경로로 정정)
4
4
 
5
5
  HJM은 `theme`(light/dark/system) 같은 **환경**과, 그 환경이 해석된 **값**을 분리해서
6
6
  받는다. 제품 브랜드색은 값 쪽에 넣는다. 이 문서는 새 제품이 처음 부딪히는 그 경로만
@@ -8,7 +8,7 @@ HJM은 `theme`(light/dark/system) 같은 **환경**과, 그 환경이 해석된
8
8
  단일 원본이다.** 팔레트를 어떻게 고를지는 [theme-palette.md](./theme-palette.md), 색의 의미 구분은
9
9
  [identity.md](./identity.md)에 있다.
10
10
 
11
- ## 두 가지 사용 방식
11
+ ## 제품 설정 사용 방식
12
12
 
13
13
  ### 1. 기본 팔레트로 시작 (환경만 넘긴다)
14
14
 
@@ -56,7 +56,7 @@ React Native도 같은 모양이다(`<HjmNativeProvider theme={preference} brand
56
56
 
57
57
  `value`(`resolveDesignSystemProviderValue` 결과 전체)는 1.4까지 브랜드를 넣는 유일한 방법이었고, 지금도
58
58
  타입상 지원한다. 하지만 `value`를 넘기면 Provider가 OS 설정 관찰을 멈추고 `brandPalette` 상속도 끊기므로
59
- 브랜드 경로로 쓰지 않는다([brand-boundary.md §1](./brand-boundary.md#1-지원하는-경로는-brandpalette-하나다)).
59
+ 브랜드 경로로 쓰지 않는다([brand-boundary.md §1](./brand-boundary.md#1-지원하는-제품-설정-경로)).
60
60
  남은 용도는 다음뿐이다.
61
61
 
62
62
  - 테스트·스토리에서 환경을 결정적으로 고정할 때(SSR·테스트만 필요하면 `systemTheme` prop으로도 충분한지 먼저 본다).
@@ -73,10 +73,23 @@ import { checkBrandPaletteContrast } from "@hjmds/design-contracts/palette-contr
73
73
  expect(checkBrandPaletteContrast(PRODUCT_BRAND_PALETTE)).toEqual({ light: [], dark: [] });
74
74
  ```
75
75
 
76
+ ### 3. 표현·구성도 함께 선택 (`designProfile`, 실험·미게시)
77
+
78
+ ```tsx
79
+ import { defineHjmDesignProfile } from "@hjmds/design-contracts/design-profile";
80
+ const productDesign = defineHjmDesignProfile({ extends: "forest", id: "product-forest", compositions: { collection: "rows" } });
81
+ <HjmProvider designProfile={productDesign}><App /></HjmProvider>
82
+ // Native는 동일 데이터를 HjmNativeProvider.designProfile에 넣는다.
83
+ ```
84
+
85
+ 앱이 설정 파일을 소유하고 한 번 주입한다. 기본 팩은 참고용이며 제품 목적에 맞게 선택·수정한다.
86
+ 상태·서버 확정은 테마에 넣지 않는다. 현재 지원 API와 연결 범위는 [프로필 계약](design-profile.md)을 따른다.
87
+
76
88
  ## 덮어도 되는 것과 아닌 것
77
89
 
78
- 규칙은 [brand-boundary.md](./brand-boundary.md)에 있다. 요약하면 `brandPalette`의 17개 semantic key만 바꿀 수 있고,
79
- 상태 강조색과 컴포넌트별 색은 바꿀 수 없으며, `.hjm-*`·`--hjm-*` CSS 재정의는 지원하는 경로가 아니다.
90
+ 규칙은 [brand-boundary.md](./brand-boundary.md)에 있다. 색만 바꿀 때는 `brandPalette`의 17개 semantic key를 쓰고,
91
+ 표현·기본 전환·배치를 바꿀 때는 검증한 `designProfile` 축을 쓴다.
92
+ 상태 강조색과 임의 컴포넌트별 색은 바꿀 수 없으며, `.hjm-*`·`--hjm-*` CSS 재정의는 지원하는 경로가 아니다.
80
93
 
81
94
  ## 어댑터를 두는 이유
82
95
 
@@ -107,6 +107,7 @@
107
107
  | [NumberField](components/number-field.md) | 입력 | 범위가 정해진 **정확한 수 하나**를 입력받을 때 쓴다. | 배포 | Web · Native |
108
108
  | [OnboardingScreen](components/onboarding-screen.md) | 화면/소개 | 첫 실행 소개·초기 설정처럼 **몇 단계를 차례로 넘기는 화면**에 쓴다. | 배포 | Web · Native |
109
109
  | [OtpField](components/otp-field.md) | 입력 | 문자·메일로 받은 **숫자 인증번호**를 칸 모양으로 입력받을 때 쓴다. | 배포 | Web · Native |
110
+ | [OverviewScreen](components/overview-screen.md) | 레이아웃 | 같은 데이터와 기능을 유지하면서 테마별 행·카드·격자와 도구 배치를 선택하는 목록 화면에 쓴다. | 실험 | Web · Native |
110
111
  | [Pagination](components/pagination.md) | 탐색 | 총 개수(또는 총 페이지 수)가 정해진 결과 집합에서 사용자가 **임의의 페이지로 바로 이동**해야 할 때 Web에서 쓴다. | 배포 | Web |
111
112
  | [PasswordField](components/password-field.md) | 입력 | 비밀번호를 입력받고, 필요할 때만 값을 눈으로 확인하게 할 때 쓴다. | 배포 | Web · Native |
112
113
  | [PermissionScreen](components/permission-screen.md) | 화면/소개 | 카메라·위치·알림 같은 권한이 **왜 필요한지 설명하고 다음 행동을 고르게 하는** 화면에 쓴다. | 배포 | Web · Native |
@@ -186,6 +187,7 @@
186
187
  | [입력을 유지하는 도구](compositions/context-toolbar.md) | 입력과 작성 | 작성 중인 입력을 보존한 채 선택적 도구를 펼쳐야 할 때 쓴다. | 배포 | Web · Native |
187
188
  | [첫 작업을 만들고 이어하기](compositions/reference-first.md) | 입력과 작성 | 첫 기록을 단계별 작성하고 중단한 초안 이어가기 흐름이 필요할 때 쓴다. | 배포 | Web · Native |
188
189
  | [날짜 선택과 예정 목록](compositions/stea-schedule-card.md) | 선택과 필터 | 한 주처럼 짧은 날짜 범위에서 날짜 하나를 고르면 같은 카드 안의 일정 목록이 그 날짜로 바뀌는 요약 카드에 쓴다. | 배포 | Web · Native |
190
+ | [날짜와 시각 선택](compositions/date-time-selection.md) | 선택과 필터 | 기록·알림의 날짜 하나와 하루 안의 시각을 함께 고를 때 쓴다. | 실험 | Web · Native |
189
191
  | [대표 항목과 묶음 전체 선택](compositions/selection-scope.md) | 선택과 필터 | 사진 묶음·스레드처럼 대표 항목 하나와 묶음 전체가 같은 모양으로 보일 때, 공유·삭제·이동 전에 대상 범위와 개수를 고르고 문구로 확인한 뒤 적용하게 할 때 쓴다. | 배포 | Web · Native |
190
192
  | [사진 촬영과 앨범 선택](compositions/photo-source.md) | 선택과 필터 | 명시적으로 선택 후 플랫폼 picker 실행 흐름이 필요할 때 쓴다. | 배포 | Web · Native |
191
193
  | [선택 후 적용·취소](compositions/interaction-flow-apply.md) | 선택과 필터 | 표시 방식·정렬·필터처럼 시트에서 여러 번 바꿔 본 뒤 적용을 눌러야 화면에 반영되고, 취소하거나 닫으면 기존 선택을 유지해야 할 때 쓴다. | 배포 | Web · Native |
@@ -193,6 +195,7 @@
193
195
  | [보관함과 페이지 이동](compositions/web-navigation.md) | 탐색과 이동 | Web에서 상위 보관함 → 하위 모음으로 들어가고, 그 모음의 긴 목록을 페이지 단위로 넘겨 보는 탐색에 쓴다. | 배포 | Web |
194
196
  | [펼침과 메뉴](compositions/disclosure.md) | 탐색과 이동 | Web에서 내용을 숨겼다 펼치거나(Collapsible), 대상에 붙은 작업 메뉴를 우클릭·키보드로 열거나(ContextMenu), 데스크톱 앱처럼 상단 메뉴 막대를 두는(Menubar) 세 방식을 각각 보여 주는 모음이다. | 배포 | Web |
195
197
  | [대화 메시지](compositions/common-message.md) | 정보 표시 | 말풍선 하나하나에 반응·답장·원문 이동·전송 실패 후 다시 보내기를 붙일 때 쓴다. | 배포 | Web · Native |
198
+ | [명령 기록 표시](compositions/command-records.md) | 정보 표시 | 명령 원문과 출력 기록을 선택·읽기·복사할 때 쓴다. | 실험 | Web · Native |
196
199
  | [문서와 파일](compositions/document-resource.md) | 정보 표시 | 이름·형식·크기와 미리보기·내보내기·별도 메뉴를 함께 제공하는 문서에 쓴다. | 배포 | Web · Native |
197
200
  | [수치와 이전 대비 변화](compositions/stea-stat-summary.md) | 정보 표시 | 매출·주문·반품처럼 몇 개의 핵심 수치를 비교 기간과 함께 보이고, 증감의 방향과 좋고 나쁨을 색 없이도 읽히게 할 때 쓴다. | 배포 | Web · Native |
198
201
  | [알림 항목](compositions/common-notification.md) | 정보 표시 | 알림 한 행을 누르면 바로 읽음으로 바꾸고, 서버가 실패하면 읽지 않음으로 되돌릴 때 쓴다. | 배포 | Web · Native |
@@ -218,10 +221,12 @@
218
221
  | [숫자 변화와 메뉴 변형](compositions/optional-motion.md) | 직접 조작과 모션 | 선택 설치 모션(숫자 자리 단위 변화, 메뉴 형태 변환)을 기존 컴포넌트 자리에 끼워 넣을 때 쓴다. | 배포 | Web |
219
222
  | [이미지·시트·키보드 조작](compositions/optional-adapters.md) | 직접 조작과 모션 | Native 앱 한 화면에서 이미지 확대 보기, 끌어서 높이를 바꾸는 시트, OS 길게 누르기 메뉴, 키보드를 따라 올라가는 하단 행동을 함께 쓸 때 provider 중첩 순서와 각 요소의 자리를 확인하는 구성이다. | 배포 | Native |
220
223
  | [내비게이션 바 비교](compositions/navigation-bar-collection.md) | 비교와 검증 | 하단 탭에 목적지 이동과 별개의 행동(작성·전원·기록 추가)을 함께 둘지, 선택한 목적지를 어떻게 보여 줄지 고를 때 이 비교를 본다. | 배포 | Web · Native |
224
+ | [내용 전환 비교](compositions/content-transition-comparison.md) | 비교와 검증 | 동일 내용의 전환 표현을 테마와 비교하거나 단계별 입력·완료·복구를 검토할 때 쓴다. | 실험 | Web · Native |
221
225
  | [네이티브 컴포넌트 기기 확인](compositions/native-renderers.md) | 비교와 검증 | Native 공개 컴포넌트가 실제 기기·시뮬레이터에서 그려지고 눌리는지 범주별로 한 화면에서 확인할 때 쓴다. | 배포 | Native |
222
226
  | [복합 입력 모음](compositions/compound-controls.md) | 비교와 검증 | 기존 컨트롤을 묶은 네 가지 복합 입력(소요 시간, 버튼 자리 확인, 이모지 반응, 알림 종)을 화면 안 한 블록으로 둘 때 쓴다. | 배포 | Web · Native |
223
227
  | [시각 효과 모음](compositions/visual-foundations.md) | 비교와 검증 | 배경 질감, 의미 이름 아이콘, 사진 없는 프로필 얼굴, 문장 전환처럼 화면의 분위기를 더하는 선택 표현을 고를 때 이 모음을 본다. | 배포 | Web · Native |
224
228
  | [웹 전용 보조 컴포넌트](compositions/web-additions.md) | 비교와 검증 | Web에만 있는 보조 컴포넌트 세 개(색 고르기, 문서 워터마크, 스크롤 중 고정되는 실행 영역)를 실제 쓰임 하나씩과 함께 보여 주는 모음이다. | 배포 | Web |
229
+ | [테마 조합](compositions/design-profile-comparison.md) | 비교와 검증 | 같은 기능에 10가지 표현을 적용하고, 앱 소유 테마 설정을 넣었을 때 네 단계의 전파와 상태 유지를 검토할 때 쓴다. | 실험 | Web · Native |
225
230
  | [토스트 배치 비교](compositions/toast-layout.md) | 비교와 검증 | Toast 카드 한 장의 내부 배치(톤 배지·제목·설명·닫기·실행 버튼)와 화면 위 위치를 좁은 폭·큰 글자·긴 문구·톤별로 확인하는 비교 스토리다. | 배포 | Web |
226
231
  | [환경 조합 검증](compositions/environment-matrix.md) | 비교와 검증 | 제품 화면이 테마·쓰기 방향·글자 크기·모션 설정이 달라져도 같은 의미를 유지하는지 확인할 때, 어떤 환경 조합과 검증 항목을 골라 볼지 정하는 기준표로 쓴다. | 배포 | Web |
227
232