@hjmds/design-contracts 1.27.2 โ†’ 1.28.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 (129) hide show
  1. package/dist/activity-chip.d.ts +1 -1
  2. package/dist/activity-chip.js +1 -1
  3. package/dist/activity-chip.js.map +1 -1
  4. package/dist/auth-screen.d.ts +71 -5
  5. package/dist/auth-screen.d.ts.map +1 -1
  6. package/dist/auth-screen.js +60 -2
  7. package/dist/auth-screen.js.map +1 -1
  8. package/dist/base-recipes.d.ts +1 -1
  9. package/dist/base-recipes.js +1 -1
  10. package/dist/base-recipes.js.map +1 -1
  11. package/dist/behaviors.d.ts +1 -1
  12. package/dist/breadcrumb.d.ts +1 -1
  13. package/dist/breadcrumb.js +1 -1
  14. package/dist/breadcrumb.js.map +1 -1
  15. package/dist/calendar.d.ts +1 -1
  16. package/dist/calendar.js +2 -2
  17. package/dist/calendar.js.map +1 -1
  18. package/dist/catalog.d.ts +131 -87
  19. package/dist/catalog.d.ts.map +1 -1
  20. package/dist/component-contracts.d.ts +1 -1
  21. package/dist/component-contracts.js +1 -1
  22. package/dist/component-contracts.js.map +1 -1
  23. package/dist/component-recipes.d.ts +85 -57
  24. package/dist/component-recipes.d.ts.map +1 -1
  25. package/dist/component-recipes.js +95 -60
  26. package/dist/component-recipes.js.map +1 -1
  27. package/dist/conversation-row.d.ts +2 -2
  28. package/dist/conversation-row.d.ts.map +1 -1
  29. package/dist/conversation-row.js +6 -4
  30. package/dist/conversation-row.js.map +1 -1
  31. package/dist/counter-badge-recipe.d.ts +1 -1
  32. package/dist/counter-badge-recipe.js +1 -1
  33. package/dist/counter-badge-recipe.js.map +1 -1
  34. package/dist/data-table.d.ts +4 -4
  35. package/dist/data-table.js +4 -4
  36. package/dist/data-table.js.map +1 -1
  37. package/dist/date-picker.d.ts +1 -1
  38. package/dist/design-profile.d.ts.map +1 -1
  39. package/dist/design-profile.js +19 -16
  40. package/dist/design-profile.js.map +1 -1
  41. package/dist/file-picker.d.ts +1 -1
  42. package/dist/file-picker.js +1 -1
  43. package/dist/file-picker.js.map +1 -1
  44. package/dist/foundations.d.ts +18 -14
  45. package/dist/foundations.d.ts.map +1 -1
  46. package/dist/foundations.js +18 -13
  47. package/dist/foundations.js.map +1 -1
  48. package/dist/heading.d.ts +13 -13
  49. package/dist/heading.js.map +1 -1
  50. package/dist/number-field.d.ts +1 -1
  51. package/dist/otp-field.d.ts +1 -1
  52. package/dist/password-field.d.ts +1 -1
  53. package/dist/result.d.ts +1 -1
  54. package/dist/result.js +2 -2
  55. package/dist/result.js.map +1 -1
  56. package/dist/semantic-colors.d.ts +10 -0
  57. package/dist/semantic-colors.d.ts.map +1 -1
  58. package/dist/semantic-colors.js +6 -0
  59. package/dist/semantic-colors.js.map +1 -1
  60. package/dist/sheet.d.ts +7 -4
  61. package/dist/sheet.d.ts.map +1 -1
  62. package/dist/sheet.js +8 -5
  63. package/dist/sheet.js.map +1 -1
  64. package/dist/side-panel.d.ts +1 -1
  65. package/dist/side-panel.js +2 -2
  66. package/dist/side-panel.js.map +1 -1
  67. package/dist/steps.d.ts +1 -1
  68. package/dist/steps.js +1 -1
  69. package/dist/steps.js.map +1 -1
  70. package/dist/tag.d.ts +1 -1
  71. package/dist/tag.js +1 -1
  72. package/dist/tag.js.map +1 -1
  73. package/dist/timeline.d.ts +1 -1
  74. package/dist/timeline.js +1 -1
  75. package/dist/timeline.js.map +1 -1
  76. package/dist/top.d.ts +4 -4
  77. package/dist/top.d.ts.map +1 -1
  78. package/dist/top.js +3 -1
  79. package/dist/top.js.map +1 -1
  80. package/dist/version.d.ts +1 -1
  81. package/dist/version.js +1 -1
  82. package/dist/version.js.map +1 -1
  83. package/docs/activity-chip.md +5 -1
  84. package/docs/auth-screen.md +2 -0
  85. package/docs/design-profile.md +14 -10
  86. package/docs/generated/component-maturity.md +1 -1
  87. package/docs/generated/renderer-evidence.json +9 -5
  88. package/docs/generated/renderer-evidence.md +1 -1
  89. package/docs/generated/showcase-manifest.json +1 -1
  90. package/docs/heading.md +14 -9
  91. package/docs/sheet.md +2 -0
  92. package/docs/top.md +4 -3
  93. package/docs/usage/README.md +1 -1
  94. package/docs/usage/components/auth-screen-layout.md +26 -9
  95. package/docs/usage/components/bottom-cta.md +6 -2
  96. package/docs/usage/components/breadcrumb.md +5 -1
  97. package/docs/usage/components/checkbox-group.md +5 -1
  98. package/docs/usage/components/collapsible.md +1 -0
  99. package/docs/usage/components/effect-surface.md +2 -2
  100. package/docs/usage/components/heading.md +14 -12
  101. package/docs/usage/components/list-row.md +7 -3
  102. package/docs/usage/components/list.md +5 -4
  103. package/docs/usage/components/notification-item.md +5 -1
  104. package/docs/usage/components/photo-source-sheet.md +1 -1
  105. package/docs/usage/components/screen-layout.md +7 -3
  106. package/docs/usage/components/search-screen.md +1 -1
  107. package/docs/usage/components/section.md +5 -1
  108. package/docs/usage/components/segmented-control.md +1 -1
  109. package/docs/usage/components/sheet.md +17 -13
  110. package/docs/usage/components/skeleton.md +41 -15
  111. package/docs/usage/components/statistic.md +5 -1
  112. package/docs/usage/components/switch.md +3 -2
  113. package/docs/usage/components/tag.md +5 -1
  114. package/docs/usage/components/text.md +6 -4
  115. package/docs/usage/components/top.md +1 -1
  116. package/docs/usage/compositions/adaptive-content.md +5 -1
  117. package/docs/usage/compositions/compound-controls.md +2 -1
  118. package/docs/usage/compositions/design-profile-comparison.md +1 -1
  119. package/docs/usage/compositions/family-drawer.md +5 -3
  120. package/docs/usage/compositions/input-sheet.md +1 -1
  121. package/docs/usage/compositions/interaction-flow-apply.md +3 -3
  122. package/docs/usage/compositions/photo-source.md +3 -3
  123. package/docs/usage/compositions/selection-motion.md +5 -1
  124. package/docs/usage/compositions/visual-foundations.md +5 -4
  125. package/docs/usage/screens/common-login.md +9 -7
  126. package/docs/usage/screens/landing.md +15 -14
  127. package/docs/usage/screens/notification-settings.md +4 -2
  128. package/docs/usage/tokens/typography.md +21 -13
  129. package/package.json +1 -1
@@ -4,7 +4,7 @@
4
4
  - ์ƒํƒœ: ๋ฐฐํฌ
5
5
  - ์ง€์›: Web ยท Native
6
6
  - ์ ์šฉ: 1.12.1
7
- - ๊ฒ€ํ† ์ผ: 2026-10-07
7
+ - ๊ฒ€ํ† ์ผ: 2026-10-17
8
8
  - ๊ทผ๊ฑฐ: [๋กœ๊ทธ์ธ ํ™”๋ฉด ๊ณจ๊ฒฉ](../../auth-screen.md), [1.4 ์ œํ’ˆ ์ฑ„ํƒ ๊ฐ€์ด๋“œ](../../product-adoption-1.4.md), recipe `authScreenRecipe`(`src/auth-screen.ts`), ํฌํŠธํด๋ฆฌ์˜ค ์ƒ์œ„ ๊ธฐ์ค€ ๋ฃจํŠธ `docs/LOGIN_SCREEN_STANDARD.md`(LS)
9
9
  - ์Šคํ† ๋ฆฌ๋ถ: `๋ฐฐํฌ/์ปดํฌ๋„ŒํŠธ/๋ ˆ์ด์•„์›ƒ/๋กœ๊ทธ์ธ ํ™”๋ฉด`
10
10
 
@@ -12,7 +12,8 @@
12
12
 
13
13
  ๋กœ๊ทธ์ธยท๊ฐ€์ž… ์ง„์ž… ํ™”๋ฉด์˜ ๋ฐฐ์น˜์— ์“ด๋‹ค. ์œ„ ์˜์—ญ(`hero` + `main`)์€ ๋‚จ๋Š” ์„ธ๋กœ ๊ณต๊ฐ„์—์„œ ๊ฐ€์šด๋ฐ ์ •๋ ฌ๋˜๊ณ ,
14
14
  `footer`(๋™์˜ ๊ณ ์ง€ยท์ •์ฑ… ๋งํฌ)๋Š” ๋ฐ”๋‹ฅ์— ๋ถ™๋Š”๋‹ค. ๋‚ด์šฉ์ด ํ™”๋ฉด๋ณด๋‹ค ๊ธธ๋ฉด ์Šคํฌ๋กค๋กœ ๋ฐ”๋€๋‹ค.
15
- ์ด ์ปดํฌ๋„ŒํŠธ๋Š” ๋ฐฐ์น˜๋งŒ ์†Œ์œ ํ•˜๋ฉฐ ์Šฌ๋กฏ ์•ˆ์˜ ๋‚ด์šฉ์€ ๊ทธ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค.
15
+ `AuthScreenLayout`์€ ๋ฐฐ์น˜๋ฅผ ์†Œ์œ ํ•˜๊ณ , ํžˆ์–ด๋กœ ๋ฌธ๊ตฌ์™€ ๋™์˜ ๊ณ ์ง€ยท์ •์ฑ… ๋งํฌ๋Š” ๊ฐ™์€ ๋ชจ๋“ˆ์˜ `AuthScreenHero`ยท`AuthScreenFooter`๊ฐ€
16
+ ๊ธ€์ž ๋‹จ๊ณ„ยท์ƒ‰ยท๊ฐ„๊ฒฉ์„ ์†Œ์œ ํ•œ๋‹ค. ์ œํ’ˆ์€ ๋ฌธ์ž์—ดยท๋งˆํฌยท๋งํฌ ๋ชฉ์ ์ง€๋งŒ ๋„˜๊ธด๋‹ค.
16
17
 
17
18
  ## ์“ฐ์ง€ ์•Š์„ ๋•Œ
18
19
 
@@ -25,33 +26,35 @@
25
26
 
26
27
  | ์ด๋ฆ„ | ์—ญํ•  | Web | Native |
27
28
  | --- | --- | --- | --- |
28
- | `AuthScreenLayout` | ๊ธฐ๋ณธ | `@hjmds/react`, `/auth-screen` | `@hjmds/react-native`, `/auth-screen` |
29
+ | `AuthScreenLayout` | ๊ธฐ๋ณธ(๋ฐฐ์น˜) | `@hjmds/react`, `/auth-screen` | `@hjmds/react-native`, `/auth-screen` |
30
+ | `AuthScreenHero` | `hero` ์Šฌ๋กฏ: ๋งˆํฌยทeyebrowยทํƒœ๊ทธ๋ผ์ธยท์„ค๋ช… | ๊ฐ™์Œ | ๊ฐ™์Œ |
31
+ | `AuthScreenFooter` | `footer` ์Šฌ๋กฏ: ๋™์˜ ๊ณ ์ง€ยท์ •์ฑ… ๋งํฌ(ยท๊ตฌ๋ถ„) | ๊ฐ™์Œ, ๋งํฌ `href` ๋˜๋Š” `onClick` | ๊ฐ™์Œ, ๋งํฌ `onPress` |
29
32
 
30
33
  ## ์ตœ์†Œ ์‚ฌ์šฉ ์˜ˆ
31
34
 
32
35
  ```tsx
33
36
  // Web
34
- import { AuthScreenLayout } from "@hjmds/react/auth-screen";
37
+ import { AuthScreenFooter, AuthScreenHero, AuthScreenLayout } from "@hjmds/react/auth-screen";
35
38
 
36
39
  <AuthScreenLayout
37
40
  mainCard
38
41
  {...(pending ? { pendingLabel: t("auth.pending") } : {})}
39
- hero={<ProductHero />} // ์ œํ’ˆ ๋งˆํฌยท์ œ๋ชฉยท์„ค๋ช…
42
+ hero={<AuthScreenHero mark={<ProductMark />} title={t("auth.tagline")} description={t("auth.description")} />}
40
43
  main={<ProviderButtons />} // pending์ด์–ด๋„ ๊ฐ™์€ ๋ชฉ๋ก
41
- footer={<ConsentAndPolicyLinks />}
44
+ footer={<AuthScreenFooter notice={t("auth.consent")} links={[{ label: t("legal.privacy"), href: privacyUrl }, { label: t("legal.terms"), href: termsUrl }]} />}
42
45
  />
43
46
  ```
44
47
 
45
48
  ```tsx
46
49
  // Native
47
- import { AuthScreenLayout } from "@hjmds/react-native/auth-screen";
50
+ import { AuthScreenFooter, AuthScreenHero, AuthScreenLayout } from "@hjmds/react-native/auth-screen";
48
51
 
49
52
  <AuthScreenLayout
50
53
  mainCard
51
54
  {...(pending ? { pendingLabel: t("auth.pending") } : {})}
52
- hero={<ProductHero />}
55
+ hero={<AuthScreenHero mark={<ProductMark />} title={t("auth.tagline")} description={t("auth.description")} />}
53
56
  main={<ProviderButtons />}
54
- footer={<ConsentAndPolicyLinks />}
57
+ footer={<AuthScreenFooter links={[{ label: t("legal.privacy"), onPress: openPrivacy }, { label: t("legal.terms"), onPress: openTerms }]} />}
55
58
  testID="login-screen"
56
59
  />
57
60
  ```
@@ -69,6 +72,8 @@ import { AuthScreenLayout } from "@hjmds/react-native/auth-screen";
69
72
  | Web `as` | `main` ยท `section` | `main` | ์ตœ๋Œ€ ํญ์€ 416์ด๋‹ค |
70
73
  | `layoutStyle` | marginยทwidthยทflexยท`alignSelf` | โ€” | ๋ฐ”๊นฅ ๋ฐฐ์น˜ ์ „์šฉ(WebยทNative ๋ชจ๋‘) |
71
74
  | Native `testID` | `string` | โ€” | ๋ฟŒ๋ฆฌ `ScrollView` ์‹๋ณ„ |
75
+ | `AuthScreenHero` `title` ยท `eyebrow` ยท `description` ยท `mark` ยท `headingLevel` | ๋ฌธ์ž์—ด ยท `ReactNode` ยท `1`~`3` | `headingLevel` 1 | ์ œ๋ชฉ์€ ํ•„์ˆ˜์ด๊ณ  ๋นˆ ๋ฌธ์ž์—ด์ด๋ฉด `TypeError`. ๋ฐ€๋„๋Š” ๋ฐ”๊นฅ `AuthScreenLayout`์„ ๋”ฐ๋ฅธ๋‹ค |
76
+ | `AuthScreenFooter` `links` ยท `notice` ยท `children` | ๋งํฌ ๋ฐฐ์—ด(1๊ฐœ ์ด์ƒ) ยท `ReactNode` | โ€” | ๋นˆ ๋งํฌ ๋ชฉ๋กยท๋นˆ ๋ผ๋ฒจ์€ `TypeError`(LS-04: ์•ฝ๊ด€ ๋งํฌ๋Š” ๋กœ๊ทธ์ธ ์ „ ๊ฐ™์€ ํ™”๋ฉด์— ์žˆ์–ด์•ผ ํ•œ๋‹ค). `children`์€ ๋งํฌ ์•„๋ž˜ ์ œํ’ˆ ๋‚ด์šฉ |
72
77
 
73
78
  ## ๋ฐฐ์น˜
74
79
 
@@ -76,6 +81,8 @@ import { AuthScreenLayout } from "@hjmds/react-native/auth-screen";
76
81
  | --- | --- | --- |
77
82
  | ํฌ๊ธฐ | ํ™”๋ฉด ์ „์ฒด(Web `min-block-size: 100dvh`, Native `ScrollView flex: 1`). ์œ„ ๋ธ”๋ก๊ณผ footer๋Š” ์ตœ๋Œ€ ํญ 416, ๋งˆํฌ 72(`markSize`, `radius.lg`), ์ •์ฑ… ๋งํฌ ์ตœ์†Œ 44(`footerMinTouchTarget`), mainCard ๋ชจ์„œ๋ฆฌ profile์˜ `radius.lg`(neutral/๋ฏธ์ง€์ • 16) | `authScreenRecipe`, `.hjm-auth-screen*` |
78
83
  | ๊ฐ„๊ฒฉ | `regular` / `compact`: ๋ฐ”๊นฅ ์ขŒ์šฐ `layout.pagePadding.regular` 20 / `.compact` 16, ๋ฐ”๊นฅ ์œ„์•„๋ž˜ `spacing.xxxl` 40 / `spacing.lg` 20, hero ์•ˆ `spacing.md` 16 / `spacing.xs` 8, heroโ†”main `spacing.xl` 24 / `spacing.md` 16, ์œ„ ๋ธ”๋กโ†”footer ์ตœ์†Œ `spacing.xl` 24 / `spacing.md` 16. mainCard ์•ˆ์ชฝ `spacing.md` 16 | `authScreenRecipe.densities`ยท`mainCard` |
84
+ | ํžˆ์–ด๋กœ ๋ฌธ๊ตฌ | ๋งˆํฌ โ†” ๋ฌธ๊ตฌ ๋ฌถ์Œ์€ hero ๊ฐ„๊ฒฉ. eyebrow `label` 12/18ยท500ยท๋ธŒ๋žœ๋“œ์ƒ‰, ์•„๋ž˜ `spacing.xxs` 4 โ†’ ํƒœ๊ทธ๋ผ์ธ `regular` `typography.heading` 24/32 ยท `compact` `titleLarge` 20/28, ๊ตต๊ธฐ๋Š” ์ œ๋ชฉ ๋‹จ๊ณ„ 500, ๊ธฐ๋ณธ ๊ธ€์ž์ƒ‰, ์‹ค์ œ heading ์š”์†Œ(Native `header`) โ†’ ์„ค๋ช… `body` 14/20ยท400ยท๋ณด์กฐ์ƒ‰(`muted`), ์œ„ `spacing.xs` 8 | `authScreenRecipe.hero`, `densities.*.titleVariant` |
85
+ | ๋™์˜ ๊ณ ์ง€ยท์ •์ฑ… ๋งํฌ | ๊ณ ์ง€ `caption` 11/16 ํ๋ฆฐ ์ƒ‰, ๋งํฌ ์ค„๊ณผ `spacing.xxs` 4. ๋งํฌ `caption`ยท๋ธŒ๋žœ๋“œ์ƒ‰ยท๋ฐ‘์ค„, ๋งํฌ ์‚ฌ์ด `linkGap` 8 + `ยท` + 8(๋ณด์ด๋Š” ๊ธ€์ž ๊ฐ„๊ฒฉ ์•ฝ 19). ๊ฐ ๋งํฌ ๋†’์ด 44(๋ฐฐ๊ฒฝ ์—†์Œ), ๊ฐ€๋กœ ํ„ฐ์น˜ ํญ์€ ๊ตฌ๋ถ„์  ์•ž๊นŒ์ง€ ๋ณด์ด์ง€ ์•Š๊ฒŒ ๋„“ํž˜(Web ๊ฐ€์ƒ ์š”์†Œ, Native `hitSlop`) | `authScreenRecipe.footer`, `.hjm-auth-screen__link` |
79
86
  | ์ˆœ์„œยท์ •๋ ฌ | ์œ„โ†’์•„๋ž˜ hero(๊ฐ€์šด๋ฐ ์ •๋ ฌ ๋ฌธ๊ตฌ) โ†’ main(ํญ ๊ฝ‰ ์ฑ„์›€) โ†’ footer(๋™์˜ ๊ณ ์ง€ยท์ •์ฑ… ๋งํฌ). ์œ„ ๋ธ”๋ก์€ ๋‚จ๋Š” ์„ธ๋กœ ๊ณต๊ฐ„์—์„œ ๊ฐ€์šด๋ฐ, footer๋Š” ๋ฐ”๋‹ฅ์— ๋ถ™๋Š”๋‹ค. ์ง„ํ–‰ ์ค‘ ๋กœ๋”ฉ์€ main ์นด๋“œ ๊ฐ€์šด๋ฐ์— ๊ฒน์นœ๋‹ค | `.hjm-auth-screen__block`(`justify-content: center`), `.hjm-auth-screen__pending` |
80
87
  | ๊ณ ์ •ยท์Šคํฌ๋กค | ๊ณ ์ • ์˜์—ญ์ด ์—†๋‹ค. ๋„˜์น˜๋ฉด ํ™”๋ฉด ์ „์ฒด๊ฐ€ ์Šคํฌ๋กคํ•œ๋‹ค. ์•ˆ์ „ ์˜์—ญ์€ Native `contentInsetAdjustmentBehavior="automatic"`๊ณผ ํ‚ค๋ณด๋“œ inset ์ž๋™ ์กฐ์ •์ด ์ฒ˜๋ฆฌํ•˜๊ณ , Web์€ safe-area inset์„ ๋”ํ•˜์ง€ ์•Š๋Š”๋‹ค | `react-native/src/auth-screen.tsx`, `.hjm-auth-screen` |
81
88
  | ์ข์€ ํญยทํฐ ๊ธ€์ž | ํ‚ค ์ž‘์€ ํ™”๋ฉดยทํฐ ๊ธ€์ž์—์„œ๋Š” `compact`๋ฅผ ๊ณ ๋ฅธ๋‹ค. ๊ทธ๋ž˜๋„ ๋„˜์น˜๋ฉด ์Šคํฌ๋กค๋˜๋ฉฐ footer๋Š” ๋งจ ์•„๋ž˜๋กœ ๋ฐ€๋ฆฐ๋‹ค | `authScreenRecipe.densities` |
@@ -104,6 +111,8 @@ import { AuthScreenLayout } from "@hjmds/react-native/auth-screen";
104
111
  - `pendingLabel`์€ ์Šคํฌ๋ฆฐ๋ฆฌ๋” ์•ˆ๋‚ด๋กœ๋งŒ ์“ฐ์ธ๋‹ค. ๋กœ๋”ฉ ์•„๋ž˜์— ๋ณด์ด๋Š” ๋ฌธ๊ตฌ๋ฅผ ๋”ฐ๋กœ ๋‘์ง€ ์•Š๋Š”๋‹ค.
105
112
  ์™„๋ฃŒยท์ทจ์†Œยท์‹คํŒจ ์‹œ prop์„ ์ œ๊ฑฐํ•œ๋‹ค. ์ทจ์†Œ๋Š” ์‹คํŒจ ๋ฌธ์žฅ ์—†์ด ๋ฒ„ํŠผ๋งŒ ๋ณต๊ตฌํ•œ๋‹ค(LS-09).
106
113
  - `pendingLabel`์€ ๊ธฐ์กด ์นด๋“œ์—์„œ ์ „ํ™˜ํ•˜๋Š” ์ƒํƒœ๋‹ค. ์ œ๊ณต์ž ๋ชฉ๋ก ์ตœ์ดˆ ์กฐํšŒ์˜ ๋กœ๋”ฉ์„ ๋Œ€์‹ ํ•˜์ง€ ์•Š๋Š”๋‹ค.
114
+ - ํžˆ์–ด๋กœ์— `Top`(ํ™”๋ฉด ์ฒซ ์ œ๋ชฉ, large = display 32/40)์ด๋‚˜ ์ง์ ‘ ์กฐ๋ฆฝํ•œ `Text`๋ฅผ ๋„ฃ์ง€ ์•Š๋Š”๋‹ค. `AuthScreenHero`๋ฅผ ์“ด๋‹ค.
115
+ ์ •์ฑ… ๋งํฌ๋ฅผ ghost `Button` + Stack gap์œผ๋กœ ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค โ€” ๋ฒ„ํŠผ ์•ˆ์ชฝ ์—ฌ๋ฐฑ์ด ๊ฐ„๊ฒฉ์— ๋”ํ•ด์ง„๋‹ค. `AuthScreenFooter`๋ฅผ ์“ด๋‹ค.
107
116
  - ์Šฌ๋กฏ ๋‚ด์šฉ์€ ์ „๋ถ€ ์ œํ’ˆ ์†Œ์œ ๋‹ค: ๋งˆํฌ ์ž์‚ฐ, ๋ชจ๋“  ๋ฌธ๊ตฌ(i18n ํ‚ค), ์ œ๊ณต์ž ๋ชฉ๋ก๊ณผ ์ˆœ์„œ, ์ •์ฑ… ๋งํฌ ๋ชฉ์ ์ง€,
108
117
  ์‹ฌ์‚ฌ์ž ํผ ๋…ธ์ถœ ์กฐ๊ฑด. ์ œ๊ณต์ž ๋กœ๊ณ ๋ฅผ HJM์— ๋„ฃ์ง€ ์•Š๋Š”๋‹ค([AuthProviderButton](auth-provider-button.md)).
109
118
  - iOS ์•ฑ์˜ ์ œ๊ณต์ž ๋ชฉ๋ก์—๋Š” Apple์ด ์žˆ์–ด์•ผ ํ•œ๋‹ค(LS-02). ์‹ฌ์‚ฌ์ž ์ด๋ฉ”์ผ ํผ์€ ์„œ๋ฒ„ env์™€ `review=1` ๋‘ ์กฐ๊ฑด์ด
@@ -131,3 +140,11 @@ import { AuthScreenLayout } from "@hjmds/react-native/auth-screen";
131
140
  ### ํ…Œ๋งˆ ์นด๋“œ ๋ชจ์„œ๋ฆฌ
132
141
 
133
142
  `mainCard`๋Š” ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด Provider์˜ `designProfile.tokens.radius.lg`๋ฅผ ์–‘ ํ”Œ๋žซํผ์—์„œ ์†Œ๋น„ํ•œ๋‹ค. ํ…Œ๋งˆ๊ฐ€ ์—†์œผ๋ฉด ๊ธฐ์กด recipe์˜ 16์„ ์œ ์ง€ํ•œ๋‹ค. ์ œ๊ณต์ž ๋ฒ„ํŠผ์€ ์ œ๊ณต์ž ๋ธŒ๋žœ๋“œ ๊ทœ๊ฒฉ์„ ์œ ์ง€ํ•˜๋ฉฐ, ์ฒ˜๋ฆฌ ์ค‘์—๋„ ์นด๋“œ์™€ ์ž…๋ ฅ์„ ์ œ๊ฑฐํ•˜์ง€ ์•Š๋Š”๋‹ค. ์นด๋“œ ํ‘œ๋ฉด๊ณผ ์ œ๊ณต์ž ๋ธŒ๋žœ๋“œ๋ฅผ ๊ฐ™์€ radius๋กœ ๊ฐ•์ œํ•˜๋ฉด ์ œํ’ˆ ํ…Œ๋งˆ๊ฐ€ ์ œ๊ณต์ž ๊ทœ๊ฒฉ์„ ๋ฎ๊ธฐ ๋•Œ๋ฌธ์— ์—ญํ• ์„ ๋‚˜๋ˆˆ๋‹ค.
143
+
144
+ ## ๊ทผ๊ฑฐ
145
+
146
+ - `AuthScreenHero`ยท`AuthScreenFooter`์™€ ํžˆ์–ด๋กœยท๋งํฌ ์ˆ˜์น˜: 2026-10-17 ์‚ฌ์šฉ์ž ํ”ผ๋“œ๋ฐฑ("๊ตต๊ธฐ๋ž‘ ํฌ๊ธฐ ์ค„์—ฌ", "๊ฐ„๊ฒฉ ์ค„์—ฌ").
147
+ ์˜ˆ์ œ๊ฐ€ ํžˆ์–ด๋กœ์— `Top large`(display 32/40ยท600)๋ฅผ ๋„ฃ์–ด 402 ํญ์—์„œ ํƒœ๊ทธ๋ผ์ธ์ด ๋‘ ์ค„์ด ๋๊ณ , ์ •์ฑ… ๋งํฌ๋Š” ghost Button
148
+ ์•ˆ์ชฝ ์—ฌ๋ฐฑ 12+12์— Stack gap 16์ด ๋”ํ•ด์ ธ ๊ธ€์ž ์‚ฌ์ด๊ฐ€ Web 42ยทNative 40์ด์—ˆ๋‹ค. ์Šฌ๋กฏ ๋‚ด์šฉ์„ ์•ฑ์ด ์กฐ๋ฆฝํ•˜๋ฉด ๊ฐ™์€ ์‹ค์ˆ˜๊ฐ€
149
+ ์ œํ’ˆ๋งˆ๋‹ค ๋ฐ˜๋ณต๋˜๋ฏ€๋กœ HJM์ด ๊ธ€์ž ๋‹จ๊ณ„ยท๊ฐ„๊ฒฉ์„ recipe๋กœ ์†Œ์œ ํ•œ๋‹ค. ๋ณ€๊ฒฝ ํ›„ Web 402์—์„œ ํƒœ๊ทธ๋ผ์ธ 24/32ยท500 ํ•œ ์ค„,
150
+ ๋งํฌ ๊ธ€์ž ๊ฐ„๊ฒฉ ์•ฝ 19, ๋งํฌ ๋†’์ด 44๋ฅผ ์ธก์ •ํ–ˆ๋‹ค. ๋ฃจํŠธ LS ยง3๋„ ๊ฐ™์€ ๊ฐ’์œผ๋กœ ๊ฐฑ์‹ ํ–ˆ๋‹ค.
@@ -79,7 +79,7 @@ const insets = useSafeAreaInsets();
79
79
  | ๊ฐ„๊ฒฉ | ์ขŒ์šฐ `layout.pagePadding.regular` 20, ์œ„ `spacing.sm` 12, ์•„๋ž˜ `spacing.sm` 12์™€ ํ•˜๋‹จ inset ์ค‘ ํฐ ๊ฐ’(Web์€ `env(safe-area-inset-bottom)`ยท`safeAreaBottom`๋„ ๋น„๊ต). ์„ค๋ช…โ†”ํ–‰๋™, ํ–‰๋™ ์‚ฌ์ด `spacing.sm` 12. ์œ„ ๊ฒฝ๊ณ„๋Š” `border.default` 1px(`stroke.default`), Native๋Š” ์œ„๋กœ ๋“œ๋ฆฌ์šฐ๋Š” ๊ทธ๋ฆผ์ž(opacity 0.08, radius 8) | `bottomCtaRecipe`, `.hjm-bottom-cta` |
80
80
  | ์ˆœ์„œยท์ •๋ ฌ | ์œ„โ†’์•„๋ž˜ [์„ค๋ช… ํ•œ ์ค„(caption, muted)] โ†’ ํ–‰๋™ ์ค„. ํ–‰๋™ ์ค„์€ [๋ณด์กฐ][์ฃผ] ์ˆœ์„œ๋กœ ๊ฐ™์€ ํญ์„ ๋‚˜๋ˆˆ๋‹ค. ์ฃผ ํ–‰๋™์€ ํ•˜๋‚˜๋‹ค | `react/src/bottom-cta.tsx`, `react-native/src/actions.tsx` |
81
81
  | ๊ณ ์ •ยท์Šคํฌ๋กค | ๋ณธ๋ฌธ ์Šคํฌ๋กค ์˜์—ญ ์•„๋ž˜์— ๋ถ™๋Š”๋‹ค. Web์€ `flow`(๋ฌธ์„œ ํ๋ฆ„ ๋) ๋˜๋Š” `sticky`(์•„๋ž˜ 0์— ๋ถ™์Œ, z-index `layer.sticky` 100). Native๋Š” ์ œํ’ˆ ํ™”๋ฉด ๋ ˆ์ด์•„์›ƒ์ด ์Šคํฌ๋กค ์˜์—ญ ๋ฐ– ์•„๋ž˜์— ๋‘”๋‹ค. ํ‚ค๋ณด๋“œ๊ฐ€ ์—ด๋ฆฌ๋Š” ํผ์€ `KeyboardAvoiding` ๋˜๋Š” `KeyboardDock`์œผ๋กœ ๊ฐ์‹ผ๋‹ค | `.hjm-bottom-cta[data-position="sticky"]`, `react-native/src/keyboard-controller.tsx` |
82
- | `ScreenLayout` `footer` ์•ˆ | footer๊ฐ€ ์œ„ ๊ฒฝ๊ณ„ยท`screenPatternRecipe.padding` 16ยท๋ฐ”ํƒ•ยทsafe area๋ฅผ ๋งก์œผ๋ฏ€๋กœ BottomCTA๋Š” ๋ฐ”(๊ฒฝ๊ณ„ยท์—ฌ๋ฐฑยท๋ฐ”ํƒ•ยท๊ทธ๋ฆผ์žยท์ตœ์†Œ ๋†’์ด)๋ฅผ ๊ทธ๋ฆฌ์ง€ ์•Š๊ณ  ์„ค๋ช…๊ณผ ํ–‰๋™ ์ค„๋งŒ ๊ทธ๋ฆฐ๋‹ค. ์ง์ ‘ ๋„˜๊ธด `safeAreaBottom`๋งŒ ์•„๋ž˜ ์—ฌ๋ฐฑ์œผ๋กœ ๋‚จ๊ธด๋‹ค. 2026-10-17 ํ™”๋ฉด ๋ฆฌ๋ทฐ: footer ์•ˆ์˜ BottomCTA๊ฐ€ ๊ฒฝ๊ณ„๋ฅผ ๋‘ ๊ฒน ๊ธ‹๊ณ  ๋ฒ„ํŠผ์„ ํ•œ ๋ฒˆ ๋” ๋“ค์˜€์œผ๋ฉฐ Native๋Š” footer ์•ˆ์— ๊ทธ๋ฆผ์ž ์žˆ๋Š” ํฐ ์ƒ์ž๋ฅผ ํ•˜๋‚˜ ๋” ๊ทธ๋ ธ๋‹ค | ๋‚ด๋ถ€ `ScreenFooterContext`, Web `.hjm-bottom-cta[data-placement="screen-footer"]`, Native `BottomCTA` |
82
+ | `ScreenLayout` `footer` ์•ˆ | footer๊ฐ€ ์œ„ ๊ฒฝ๊ณ„ยท`screenPatternRecipe.padding` 16ยท๋ฐ”ํƒ•ยทsafe area๋ฅผ ๋งก์œผ๋ฏ€๋กœ BottomCTA๋Š” ๋ฐ”(๊ฒฝ๊ณ„ยท์—ฌ๋ฐฑยท๋ฐ”ํƒ•ยท๊ทธ๋ฆผ์žยท์ตœ์†Œ ๋†’์ด)๋ฅผ ๊ทธ๋ฆฌ์ง€ ์•Š๊ณ  ์„ค๋ช…๊ณผ ํ–‰๋™ ์ค„๋งŒ ๊ทธ๋ฆฐ๋‹ค. ๋ฒ„ํŠผ ์•„๋ž˜ ์—ฌ๋ฐฑ์€ `max(footer ์•„๋ž˜ ์—ฌ๋ฐฑ, safeAreaBottom)`์ด๋‹ค โ€” ์ง์ ‘ ๋„˜๊ธด `safeAreaBottom`์€ footer๊ฐ€ ์ด๋ฏธ ์ค€ ์—ฌ๋ฐฑ์„ ๋„˜๋Š” ๋งŒํผ๋งŒ ๋”ํ•œ๋‹ค(16 + 34๊ฐ€ ์•„๋‹ˆ๋ผ 34). Native๋Š” ํ™”๋ฉด inset์„ ScreenLayout `safeAreaBottom`์œผ๋กœ ๋„˜๊ธฐ๋Š” ๊ฒƒ์ด ๊ธฐ๋ณธ์ด๋‹ค. 2026-10-17 ํ™”๋ฉด ๋ฆฌ๋ทฐ: footer ์•ˆ์˜ BottomCTA๊ฐ€ ๊ฒฝ๊ณ„๋ฅผ ๋‘ ๊ฒน ๊ธ‹๊ณ  ๋ฒ„ํŠผ์„ ํ•œ ๋ฒˆ ๋” ๋“ค์˜€์œผ๋ฉฐ Native๋Š” footer ์•ˆ์— ๊ทธ๋ฆผ์ž ์žˆ๋Š” ํฐ ์ƒ์ž๋ฅผ ํ•˜๋‚˜ ๋” ๊ทธ๋ ธ๋‹ค | ๋‚ด๋ถ€ `ScreenFooterContext`, Web `.hjm-bottom-cta[data-placement="screen-footer"]`, Native `BottomCTA` |
83
83
  | ์ข์€ ํญยทํฐ ๊ธ€์ž | Web์€ ํ–‰๋™ ์นธ ๊ธฐ์ค€ ํญ 132(`control.minTouchTarget` ร— 3)๋ณด๋‹ค ์ข์œผ๋ฉด ์ค„๋ฐ”๊ฟˆํ•œ๋‹ค. ํฐ ๊ธ€์ž์—์„œ๋Š” ์„ธ๋กœ๋กœ ์Œ“๊ณ  ์ฃผ ํ–‰๋™์ด ์œ„์— ์˜จ๋‹ค | `.hjm-bottom-cta__actions > div`, `.hjm-bottom-cta[data-large-text="true"]` |
84
84
 
85
85
  ```text
@@ -103,7 +103,7 @@ const insets = useSafeAreaInsets();
103
103
  Native Form์€ ๋‚ด์žฅ ์ œ์ถœ ๋ฒ„ํŠผ(`submitLabel` ํ•„์ˆ˜)์„ ํ•ญ์ƒ ๊ทธ๋ฆฌ๋ฏ€๋กœ Form ๋Œ€์‹  ํ•„๋“œ + contracts `createFormSubmitSession`
104
104
  (`@hjmds/design-contracts/components/form`)์œผ๋กœ ์ œ์ถœ ์„ธ์…˜์„ ์žก๊ณ  ๊ทธ ์ƒํƒœ๋ฅผ `primaryAction.loading`์— ์—ฐ๊ฒฐํ•œ๋‹ค.
105
105
  - ๋ฐฐ์น˜๋Š” `layoutStyle`๋กœ๋งŒ ํ•œ๋‹ค. Native `style`์€ ์ œ๊ฑฐ๋œ ์†์„ฑ์ด๋‹ค.
106
- - ํ•˜๋‹จ inset์„ ๋„˜๊ธด๋‹ค. Native๋Š” ์ž๋™์œผ๋กœ ์ฝ์ง€ ์•Š์œผ๋ฏ€๋กœ `safeAreaBottom`์ด ์—†์œผ๋ฉด ํ™ˆ ์ธ๋””์ผ€์ดํ„ฐ์— ๋ถ™๋Š”๋‹ค.
106
+ - ํ•˜๋‹จ inset์„ ๋„˜๊ธด๋‹ค. Native๋Š” ์ž๋™์œผ๋กœ ์ฝ์ง€ ์•Š์œผ๋ฏ€๋กœ `safeAreaBottom`์ด ์—†์œผ๋ฉด ํ™ˆ ์ธ๋””์ผ€์ดํ„ฐ์— ๋ถ™๋Š”๋‹ค. ScreenLayout `footer` ์•ˆ์ด๋ฉด ScreenLayout `safeAreaBottom`์— ๋„˜๊ธฐ๊ณ , host SafeAreaView์˜ ์•„๋ž˜ edge์™€ ๊ฐ™์ด ์“ฐ์ง€ ์•Š๋Š”๋‹ค(inset ์œ„์— footer 16์ด ๋”ํ•ด์ง„๋‹ค).
107
107
  - ํ‚ค๋ณด๋“œ๊ฐ€ ์—ด๋ฆฌ๋Š” ํผ ํ™”๋ฉด(Native)์€ `KeyboardAvoiding`(`/keyboard`) ๋˜๋Š” `KeyboardDock`(`/keyboard-controller`,
108
108
  optional peer `react-native-keyboard-controller` ์„ค์น˜ ํ•„์š”)๋กœ ๊ฐ์‹ผ๋‹ค.
109
109
 
@@ -126,3 +126,7 @@ const insets = useSafeAreaInsets();
126
126
  - Native๋Š” ํ•˜๋‹จ inset์„ ์Šค์Šค๋กœ ์ฝ์ง€ ์•Š๋Š”๋‹ค. `safeAreaBottom`์„ ๋น ๋œจ๋ ค๋„ ์˜ค๋ฅ˜๊ฐ€ ์—†๊ณ  ํ™ˆ ์ธ๋””์ผ€์ดํ„ฐ์— ๋ถ™์–ด ๋ณด์ธ๋‹ค.
127
127
 
128
128
  1.15.0 ๋ณ€๊ฒฝ: ํ”„๋กœํ•„์˜ `shadow.floating` ์ƒ‰ยท๊ฐ•๋„ยท๋ฐ˜๊ฒฝ์„ ์ƒ์†ํ•˜๋˜, ์œ„ ์ฝ˜ํ…์ธ ์™€ ๊ฒน์น˜๋Š” footer ์—ญํ• ์ด๋ผ offsetY๋Š” `-abs(offsetY)`๋กœ ์œ„์ชฝ์— ํ‘œ์‹œํ•œ๋‹ค. Native์˜ 0-opacity ํ”„๋กœํ•„์€ Android elevation๋„ 0์ด๋‹ค. ํ”„๋กœํ•„ ์—†๋Š” Web์€ ๊ธฐ์กด ๋ฌด๊ทธ๋ฆผ์ž, Native๋Š” ๊ธฐ์กด ์œ„์ชฝ recipe ๊ทธ๋ฆผ์ž๋ฅผ ์œ ์ง€ํ•œ๋‹ค. safe areaยทํฐ ๊ธ€์žยท๋กœ๋”ฉ/์‹คํŒจ์™€ ์ œํ’ˆ ํ–‰๋™ ์†Œ์œ ๊ถŒ์€ ๋ฐ”๋€Œ์ง€ ์•Š๋Š”๋‹ค.
129
+
130
+ ## ๊ทผ๊ฑฐ
131
+
132
+ - footer ์•ˆ ํ•˜๋‹จ inset์€ ํ•ฉ์ด ์•„๋‹ˆ๋ผ max: 2026-10-17 ์‚ฌ์šฉ์ž ๋ณด๊ณ  "์ „์ฒด์ ์œผ๋กœ ๋ฒ„ํŠผ ์•„๋ž˜ ์—ฌ๋ฐฑ์ด ๋งŽ์•„". footer 16 ์œ„์— `safeAreaBottom`์„ ๋”ํ•ด ํ™ˆ ์ธ๋””์ผ€์ดํ„ฐ ๊ธฐ๊ธฐ์—์„œ ๋ฒ„ํŠผ ์•„๋ž˜๊ฐ€ 50์ด ๋๋‹ค. ๋งˆ์ง€๋ง‰ ์ปจํŠธ๋กค ์•„๋ž˜ ์—ฌ๋ฐฑ์„ footer ์œ„ ์—ฌ๋ฐฑ 16๊ณผ ๊ฐ™๊ฒŒ ๋‘๊ณ , ํ™ˆ ์ธ๋””์ผ€์ดํ„ฐ๊ฐ€ ์žˆ์œผ๋ฉด max(16, inset)๋งŒ ๋‘”๋‹ค([ScreenLayout ๊ทผ๊ฑฐ](screen-layout.md#๊ทผ๊ฑฐ)).
@@ -65,7 +65,7 @@ Native renderer๋Š” ์—†๋‹ค.
65
65
  | --- | --- | --- |
66
66
  | ํฌ๊ธฐ | ๋‚ด์šฉ ํญ๋งŒ ์ฐจ์ง€ํ•˜๋Š” ํ•œ ์ค„ ๊ฒฝ๋กœ. ๊ธ€์ž๋Š” `label` ๋ณ€ํ˜•(12/18). ๋งํฌ ๋†’์ด๊ฐ€ 44์— ๋ชป ๋ฏธ์น˜๋ฏ€๋กœ ํ„ฐ์น˜ ์ค‘์‹ฌ ํ™”๋ฉด์˜ ์ฃผ ํƒ์ƒ‰์œผ๋กœ ์“ฐ์ง€ ์•Š๋Š”๋‹ค | `breadcrumbRecipe.link`ยท`current` |
67
67
  | ๊ฐ„๊ฒฉ | ํ•ญ๋ชฉยท๊ตฌ๋ถ„์ž ์‚ฌ์ด `spacing.xxs` 4. ๋ฐ”๊นฅ ์—ฌ๋ฐฑ์ด ์—†์œผ๋ฏ€๋กœ ์•„๋ž˜ ์ œ๋ชฉยท๋ณธ๋ฌธ๊ณผ์˜ ๊ฐ„๊ฒฉ์€ ํ™”๋ฉด์˜ ์„ธ๋กœ [Stack](stack.md)์ด ์ •ํ•œ๋‹ค | `breadcrumbRecipe.gap`, `.hjm-breadcrumb` |
68
- | ์ˆœ์„œยท์ •๋ ฌ | ํŽ˜์ด์ง€ ์ œ๋ชฉ ๋ฐ”๋กœ ์œ„, ๋ณธ๋ฌธ ์‹œ์ž‘ ์ชฝ ์ •๋ ฌ. ์ƒ์œ„ โ†’ ํ˜„์žฌ ์ˆœ์„œ์ด๊ณ  ํ˜„์žฌ ์œ„์น˜(๋งˆ์ง€๋ง‰)๋Š” ๋งํฌ๊ฐ€ ์•„๋‹ˆ๋ฉฐ `semibold`๋กœ ํ‘œ์‹œํ•œ๋‹ค | `.hjm-breadcrumb__current` |
68
+ | ์ˆœ์„œยท์ •๋ ฌ | ํŽ˜์ด์ง€ ์ œ๋ชฉ ๋ฐ”๋กœ ์œ„, ๋ณธ๋ฌธ ์‹œ์ž‘ ์ชฝ ์ •๋ ฌ. ์ƒ์œ„ โ†’ ํ˜„์žฌ ์ˆœ์„œ์ด๊ณ  ํ˜„์žฌ ์œ„์น˜(๋งˆ์ง€๋ง‰)๋Š” ๋งํฌ๊ฐ€ ์•„๋‹ˆ๋ฉฐ medium(500)์œผ๋กœ ํ‘œ์‹œํ•œ๋‹ค | `.hjm-breadcrumb__current` |
69
69
  | ๊ณ ์ •ยท์Šคํฌ๋กค | ๊ณ ์ •๋˜์ง€ ์•Š๊ณ  ๋ณธ๋ฌธ๊ณผ ํ•จ๊ป˜ ์Šคํฌ๋กคํ•œ๋‹ค | `.hjm-breadcrumb__list` |
70
70
  | ์ข์€ ํญยทํฐ ๊ธ€์ž | ์ค„๋ฐ”๊ฟˆ๋œ๋‹ค(`flex-wrap: wrap`). ํ•ญ๋ชฉ label๋„ ์ค„๋ฐ”๊ฟˆ๋˜๊ณ  ๊ตฌ๋ถ„์ž๋Š” ์ค„์–ด๋“ค์ง€ ์•Š๋Š”๋‹ค | `.hjm-breadcrumb__list`, `.hjm-breadcrumb__separator { flex-shrink: 0 }` |
71
71
 
@@ -79,3 +79,7 @@ Native renderer๋Š” ์—†๋‹ค.
79
79
 
80
80
  - ์กฐ์ƒ ํ•ญ๋ชฉ์€ ์ผ๋ฐ˜ `<a href>`๋กœ ๊ทธ๋ฆฐ๋‹ค. ๋ผ์šฐํ„ฐ adapter prop(`renderLink` ๋“ฑ)์ด ์—†์œผ๋ฏ€๋กœ
81
81
  Next.js `Link` ๊ฐ™์€ ํด๋ผ์ด์–ธํŠธ ์ „ํ™˜์„ ๊ธฐ๋Œ€ํ•˜์ง€ ์•Š๋Š”๋‹ค.
82
+
83
+ ## ๊ทผ๊ฑฐ
84
+
85
+ 2026-10-17 ์‚ฌ์šฉ์ž ๊ฒฐ์ •("๊ตต๊ธฐ ์ข€๋” ์ค„์—ฌ"): ๋ชจ๋“  ๊ธ€์ž ๊ตต๊ธฐ๋ฅผ ํ•œ ๋‹จ๊ณ„ ๋‚ฎ์ท„๋‹ค. ํฐ ์ˆซ์žยท์„ ํƒ ์ƒํƒœ 600(ํฐ ์ œ๋ชฉ ๋‹จ๊ณ„๋Š” ๊ฐ™์€ ๋‚  ํ์ง€), ์ œ๋ชฉยท๊ฐ•์กฐ 500, label 500, ๋ณธ๋ฌธ 400์ด๋ฉฐ ์ •๋ณธ์€ [ํƒ€์ดํฌ๊ทธ๋ž˜ํ”ผ](../tokens/typography.md)๋‹ค.
@@ -79,7 +79,7 @@ import { CheckboxGroup } from "@hjmds/react-native/inputs";
79
79
  | --- | --- | --- |
80
80
  | ํฌ๊ธฐ | ํญ์„ ์ฑ„์šฐ๋Š” ๋ฌถ์Œ. ๊ฐ ํ–‰์€ [Checkbox](checkbox.md) ๊ทœ๊ฒฉ(์ตœ์†Œ ๋†’์ด `medium` 56 ยท `small` 44, ํ‘œ์‹œ 24 ยท 20) | `selectionControlRecipe.sizes`, `.hjm-choice` |
81
81
  | ๊ฐ„๊ฒฉ | ๊ทธ๋ฃน ์ด๋ฆ„(legend)โ†”ํ•ญ๋ชฉ `spacing.xs` 8. ํ•ญ๋ชฉ ์‚ฌ์ด ์„ธ๋กœ `card` `spacing.xs` 8 ยท `plain` `spacing.xxs` 4 ยท `grouped` 0, ๊ฐ€๋กœ `card` `spacing.md` 16 ยท `plain` `spacing.sm` 12 ยท `grouped` 0. ์„ค๋ช…ยท์˜ค๋ฅ˜๋Š” `formSupportContract.gap` `spacing.xs` 8 | `selectionGroupRecipe.orientations`, `.hjm-checkbox-group*` |
82
- | ์ˆœ์„œยท์ •๋ ฌ | ์œ„โ†’์•„๋ž˜ [๊ทธ๋ฃน ์ด๋ฆ„(semibold)] โ†’ [์„ค๋ช…] โ†’ [ํ•ญ๋ชฉ๋“ค] โ†’ [์˜ค๋ฅ˜]. ํ•ญ๋ชฉ์€ ์‹œ์ž‘ ์ชฝ ์ •๋ ฌ. `grouped`๋Š” ํ•ญ๋ชฉ๋“ค์„ ํ…Œ๋‘๋ฆฌ 1pxยท`radius.lg` 16 ์นด๋“œ ํ•˜๋‚˜์— ๋ถ™์—ฌ ๋‹ด๋Š”๋‹ค | `selectionGroupRecipe.slots`, `.hjm-checkbox-group[data-presentation="grouped"]` |
82
+ | ์ˆœ์„œยท์ •๋ ฌ | ์œ„โ†’์•„๋ž˜ [๊ทธ๋ฃน ์ด๋ฆ„(medium 500)] โ†’ [์„ค๋ช…] โ†’ [ํ•ญ๋ชฉ๋“ค] โ†’ [์˜ค๋ฅ˜]. ํ•ญ๋ชฉ์€ ์‹œ์ž‘ ์ชฝ ์ •๋ ฌ. `grouped`๋Š” ํ•ญ๋ชฉ๋“ค์„ ํ…Œ๋‘๋ฆฌ 1pxยท`radius.lg` 16 ์นด๋“œ ํ•˜๋‚˜์— ๋ถ™์—ฌ ๋‹ด๋Š”๋‹ค | `selectionGroupRecipe.slots`, `.hjm-checkbox-group[data-presentation="grouped"]` |
83
83
  | ๊ณ ์ •ยท์Šคํฌ๋กค | ๊ณ ์ • ์˜์—ญ์ด ์—†๋‹ค. ๋ชฉ๋ก์ด ๊ธธ์–ด๋„ ๊ทธ๋ฃน ์•ˆ์—์„œ ์Šคํฌ๋กค ์˜์—ญ์„ ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค | `.hjm-checkbox-group__items` |
84
84
  | ์ข์€ ํญยทํฐ ๊ธ€์ž | `horizontal`์€ ์ค„๋ฐ”๊ฟˆ๋œ๋‹ค(`flex-wrap: wrap`). ์ข์€ ํญยทํฐ ๊ธ€์ž์—์„œ๋Š” `vertical`์„ ์“ด๋‹ค | `.hjm-checkbox-group[data-orientation="horizontal"]` |
85
85
 
@@ -102,3 +102,7 @@ import { CheckboxGroup } from "@hjmds/react-native/inputs";
102
102
  | ๊ทธ๋ฃน ์ „์ฒด ๋น„ํ™œ์„ฑ | `disabled`(fieldset) | `disabled` |
103
103
  | ํ•„์ˆ˜ยท์ฝ๊ธฐ ์ „์šฉ ์•ˆ๋‚ด | `aria-required`ยท`aria-readonly` | `requiredLabel`ยท`readOnlyLabel`์„ ํ–‰ hint๋กœ ์ฝ์Œ |
104
104
  | ์„ ํƒ ํ‘œ์‹œ ๊ต์ฒด | ์—†์Œ | `indicator="none"`, `renderIndicator(item, props)` |
105
+
106
+ ## ๊ทผ๊ฑฐ
107
+
108
+ 2026-10-17 ์‚ฌ์šฉ์ž ๊ฒฐ์ •("๊ตต๊ธฐ ์ข€๋” ์ค„์—ฌ"): ๋ชจ๋“  ๊ธ€์ž ๊ตต๊ธฐ๋ฅผ ํ•œ ๋‹จ๊ณ„ ๋‚ฎ์ท„๋‹ค. ํฐ ์ˆซ์žยท์„ ํƒ ์ƒํƒœ 600(ํฐ ์ œ๋ชฉ ๋‹จ๊ณ„๋Š” ๊ฐ™์€ ๋‚  ํ์ง€), ์ œ๋ชฉยท๊ฐ•์กฐ 500, label 500, ๋ณธ๋ฌธ 400์ด๋ฉฐ ์ •๋ณธ์€ [ํƒ€์ดํฌ๊ทธ๋ž˜ํ”ผ](../tokens/typography.md)๋‹ค.
@@ -124,4 +124,5 @@ Web์—์„œ ์™ธ๋ถ€ ์ƒํƒœ ๋ณ€๊ฒฝ์œผ๋กœ ๋‹ซํž ๋•Œ ๋‚ด๋ถ€์— ์žˆ๋˜ ์ดˆ์ ์€ trigg
124
124
 
125
125
  ## ๊ทผ๊ฑฐ
126
126
 
127
+ - `edge` ์ถ•์„ ๋‘์ง€ ์•Š๋Š”๋‹ค: 2026-10-17 1.27.2 ์ฑ„ํƒ ์ ๊ฒ€. ํฌํŠธํด๋ฆฌ์˜ค ์‚ฌ์ดํŠธ ํ—ค๋” ๋ ๋ฉ”๋‰ด ํŠธ๋ฆฌ๊ฑฐ(402)์˜ ํŽผ์นจ ํ‘œ์‹œ ์นธ ๋์€ ํ™”๋ฉด ๋์—์„œ 36์ด์—ˆ๋Š”๋ฐ, ํŠธ๋ฆฌ๊ฑฐ ์ž์ฒด๋Š” ์ขŒ์šฐ padding 0์ด๊ณ  ํ‘œ์‹œ ์นธ ๋์ด ํŠธ๋ฆฌ๊ฑฐ ๋๊ณผ ๊ฐ™๋‹ค(Storybook ์ธก์ •: ํ‘œ์‹œ ์นธ ๋ = ํŠธ๋ฆฌ๊ฑฐ ๋ = ๋ฃจํŠธ ๋). 36์€ ์ œํ’ˆ์ด TopBar(์ž๊ธฐ ์—ฌ๋ฐฑ 16)๋ฅผ `Container gutter="regular"`(20) ์•ˆ์— ๋‘” ๊ฒฐ๊ณผ๋‹ค. IconButton/Button `edge`๋Š” frameless ์ปจํŠธ๋กค์˜ ์•ˆ์ชฝ padding๋งŒํผ ๋ฐ”๊นฅ์œผ๋กœ ๋‚ด๋ฏธ๋Š” ๊ทœ์น™์ธ๋ฐ ์ด ํŠธ๋ฆฌ๊ฑฐ๋Š” ๋‚ด๋ฐ€ padding์ด ์—†์–ด `edge`๋Š” ์•„๋ฌด๊ฒƒ๋„ ๋ฐ”๊พธ์ง€ ๋ชปํ•œ๋‹ค. ์œ„์น˜๋Š” ์ œํ’ˆ์˜ ๊ฒน์นœ ์—ฌ๋ฐฑ์—์„œ ๊ณ ์นœ๋‹ค.
127
128
  - 2026-10-17 ๊ตฌ์„ฑ ๋ฆฌ๋ทฐ: ํ…์ŠคํŠธ ํ‘œ์‹œ โ–ธ๊ฐ€ ์•ฝ 8px๋กœ ๊ทธ๋ ค์ ธ ํŠธ๋ฆฌ๊ฑฐ๊ฐ€ ์ •์  ๋ฌธ๊ตฌ์ฒ˜๋Ÿผ ๋ณด์˜€๋‹ค. ๊ทธ๋ž˜์„œ ๋‘ ํ”Œ๋žซํผ ๋ชจ๋‘ glyph.sm 20 chevron ์•„์ด์ฝ˜์œผ๋กœ ๋ฐ”๊ฟจ๋‹ค.
@@ -85,14 +85,14 @@ import { EffectSurface } from "@hjmds/react-native/effect-surface";
85
85
  | --- | --- | --- |
86
86
  | ํฌ๊ธฐ | ๊ธฐ๋ณธ ์—ฌ๋ฐฑ์€ ์—†๋‹ค(`padding="none"`). ํฌ๊ธฐ๋Š” children๊ณผ `padding`์ด ์ •ํ•˜๊ณ  ์žฅ์‹ ๋ ˆ์ด์–ด๊ฐ€ ๊ทธ ์˜์—ญ ์ „์ฒด(`absolute`, inset 0)๋ฅผ ๋ฎ๋Š”๋‹ค. ๋„˜์น˜๋Š” ์žฅ์‹์€ `radius` ๋ชจ์„œ๋ฆฌ ์•ˆ์—์„œ ์ž˜๋ฆฐ๋‹ค(`overflow: hidden`). ์•ˆ์— ๋‘” Surface์™€ ๊ฐ™์€ ๊ธฐ๋ณธ radius๋ผ ๋‘ฅ๊ทผ ์นด๋“œ ๋ชจ์„œ๋ฆฌ ๋ฐ–์œผ๋กœ ์žฅ์‹์ด ๋น„์น˜์ง€ ์•Š๋Š”๋‹ค. ๋ฐฐ๊ฒฝ์€ ํ…Œ๋งˆ `bg`๋‹ค. ๋†’์ด๋ฅผ ๋Š˜๋ฆฌ๋ ค๋ฉด children ๋†’์ด, Web `layoutStyle`ยทNative `style`์˜ ๋†’์ด๋กœ ์ •ํ•œ๋‹ค. ์žฅ์‹ ๋ ˆ์ด์–ด๋Š” ๋ฐฐ์น˜์— ์ฐธ์—ฌํ•˜์ง€ ์•Š๋Š”๋‹ค | `react/src/effect-surface.tsx`, `react-native/src/effect-surface.tsx` |
87
87
  | ๊ฐ„๊ฒฉ | ์•ˆ์ชฝ ์—ฌ๋ฐฑ์€ `padding`(์˜ˆ: `lg` 20), ๋‚ด์šฉ ์‚ฌ์ด ๊ฐ„๊ฒฉ์€ children ์ชฝ [Stack](stack.md)์œผ๋กœ ์ค€๋‹ค. raw ์š”์†Œ์— padding์„ ์ง์ ‘ ์ฃผ์ง€ ์•Š๋Š”๋‹ค | `react/src/effect-surface.tsx` |
88
- | ์ˆœ์„œยท์ •๋ ฌ | children์€ ์ผ๋ฐ˜ ๋ ˆ์ด์•„์›ƒ์ด๋‹ค. [Stack](stack.md)์œผ๋กœ eyebrow โ†’ [Heading](heading.md) โ†’ ์†Œ๊ฐœ โ†’ [Button](button.md)์„ ์Œ“๋Š”๋‹ค(Showcase ๋žœ๋”ฉ ์˜ˆ๋Š” `gap="lg"` 20, Heading `level1`) | `showcase/web/src/patterns/Landing.stories.tsx` |
88
+ | ์ˆœ์„œยท์ •๋ ฌ | children์€ ์ผ๋ฐ˜ ๋ ˆ์ด์•„์›ƒ์ด๋‹ค. [Stack](stack.md)์œผ๋กœ eyebrow โ†’ [Heading](heading.md) โ†’ ์†Œ๊ฐœ โ†’ [Button](button.md)์„ ์Œ“๋Š”๋‹ค(Showcase ๋žœ๋”ฉ ์˜ˆ๋Š” `gap="lg"` 20, Heading `level3` 24ยทh1) | `showcase/web/src/patterns/Landing.stories.tsx` |
89
89
  | ๊ณ ์ •ยท์Šคํฌ๋กค | ํ™”๋ฉด ์œ„์ชฝ ํžˆ์–ด๋กœ ํ•˜๋‚˜์—๋งŒ ๋‘”๋‹ค. ๊ฐ™์€ ํ™”๋ฉด์— ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ๊ฒน์น˜๊ฑฐ๋‚˜ ๋ชฉ๋ก ํ–‰๋งˆ๋‹ค ๋‘์ง€ ์•Š๋Š”๋‹ค | โ€” |
90
90
  | ์ข์€ ํญยทํฐ ๊ธ€์ž | โ€” | โ€” |
91
91
 
92
92
  ```text
93
93
  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ† EffectSurface(๋ฐฐ๊ฒฝ bg + mesh/glow/grain, ํ„ฐ์น˜ ์—†์Œ)
94
94
  โ”‚ eyebrow โ”‚
95
- โ”‚ ํฐ ์ œ๋ชฉ(Heading level1) โ”‚ โ† children: ์ผ๋ฐ˜ ๋ ˆ์ด์•„์›ƒ(Stack gap lg 20)
95
+ โ”‚ ์ œ๋ชฉ(Heading level3, 24) โ”‚ โ† children: ์ผ๋ฐ˜ ๋ ˆ์ด์•„์›ƒ(Stack gap lg 20)
96
96
  โ”‚ ์†Œ๊ฐœ ๋ฌธ์žฅ โ”‚
97
97
  โ”‚ [์‹œ์ž‘ํ•˜๊ธฐ] primary โ”‚
98
98
  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
@@ -10,9 +10,9 @@
10
10
 
11
11
  ## ์–ธ์ œ ์“ฐ๋‚˜
12
12
 
13
- ์ž๋ฆฌ๋ฅผ ๋ชจ๋ฅด๋Š” ํฐ ์ œ๋ชฉ ๊ธ€์ž ํ•˜๋‚˜๊ฐ€ ํ•„์š”ํ•  ๋•Œ ์“ด๋‹ค. ๋žœ๋”ฉ ํžˆ์–ด๋กœ, ๊ฒฐ๊ณผ ํ™”๋ฉด์˜ ํฐ ์ œ๋ชฉ,
14
- ์นด๋“œยทํ‘œยท๋นˆ ์ƒํƒœ ์•ˆ์˜ ์ œ๋ชฉ์ฒ˜๋Ÿผ `Text`์˜ ์ตœ๋Œ€ ํฌ๊ธฐ(24px)๋กœ๋Š” ๋ชจ์ž๋ผ๊ฑฐ๋‚˜ ๋ฌธ์„œ ์ œ๋ชฉ ๋‹จ๊ณ„๋ฅผ
15
- ์‹ค์ œ๋กœ ๋‚ด์•ผ ํ•˜๋Š” ์ž๋ฆฌ๋‹ค. ์ฃผ๋ณ€ ์—ฌ๋ฐฑ์€ ๊ฐ–์ง€ ์•Š๋Š”๋‹ค. ๋‹ด๋Š” ๋ธ”๋ก์ด ์ •ํ•œ๋‹ค.
13
+ ์ž๋ฆฌ๋ฅผ ๋ชจ๋ฅด๋Š” ์ œ๋ชฉ ๊ธ€์ž ํ•˜๋‚˜๊ฐ€ ํ•„์š”ํ•  ๋•Œ ์“ด๋‹ค. ๋žœ๋”ฉ ๋Œ€ํ‘œ ์ œ๋ชฉ, ๊ฒฐ๊ณผ ํ™”๋ฉด์˜ ์ œ๋ชฉ,
14
+ ์นด๋“œยทํ‘œยท๋นˆ ์ƒํƒœ ์•ˆ์˜ ์ œ๋ชฉ์ฒ˜๋Ÿผ ๋ฌธ์„œ ์ œ๋ชฉ ๋‹จ๊ณ„๋ฅผ ์‹ค์ œ๋กœ ๋‚ด์•ผ ํ•˜๋Š” ์ž๋ฆฌ๋‹ค. ํฌ๊ธฐ๋Š” `Text`์™€ ๊ฐ™์€
15
+ ๋‹จ๊ณ„(์ตœ๋Œ€ 24px)๋ฅผ ์“ด๋‹ค. ์ฃผ๋ณ€ ์—ฌ๋ฐฑ์€ ๊ฐ–์ง€ ์•Š๋Š”๋‹ค. ๋‹ด๋Š” ๋ธ”๋ก์ด ์ •ํ•œ๋‹ค.
16
16
 
17
17
  ## ์“ฐ์ง€ ์•Š์„ ๋•Œ
18
18
 
@@ -34,7 +34,7 @@
34
34
  // Web
35
35
  import { Heading } from "@hjmds/react/heading";
36
36
 
37
- <Heading level="level2">{t("result.title")}</Heading>
37
+ <Heading level="level3" semanticLevel={2}>{t("result.title")}</Heading>
38
38
  ```
39
39
 
40
40
  ```tsx
@@ -48,23 +48,23 @@ import { Heading } from "@hjmds/react-native/heading";
48
48
 
49
49
  | prop | ๊ฐ’ | ๊ธฐ๋ณธ๊ฐ’ | ์„ค๋ช… |
50
50
  | --- | --- | --- | --- |
51
- | `level`(ํ•„์ˆ˜) | `level1` 40px/700 ยท `level2` 32px/700 ยท `level3` 24px/600 ยท `level4` 20px/600 ยท `level5` 18px/600 | โ€” | recipe ๊ธฐ๋ณธ์€ `level3`์ด์ง€๋งŒ ๋‘ renderer ๋ชจ๋‘ prop์„ ํ•„์ˆ˜๋กœ ๋ฐ›๋Š”๋‹ค |
51
+ | `level`(ํ•„์ˆ˜) | `level3` 24px/500 ยท `level4` 20px/500 ยท `level5` 18px/500. `level1`ยท`level2`๋Š” ์‚ฌ์šฉ ์ค‘๋‹จ๋œ ์ด๋ฆ„์œผ๋กœ `level3`๊ณผ ๊ฐ™์€ 24px/500์ด๋‹ค | โ€” | recipe ๊ธฐ๋ณธ์€ `level3`์ด์ง€๋งŒ ๋‘ renderer ๋ชจ๋‘ prop์„ ํ•„์ˆ˜๋กœ ๋ฐ›๋Š”๋‹ค. ๊ฐ€์žฅ ํฐ ๋‹จ๊ณ„๋Š” 24px๋‹ค |
52
52
  | `semanticLevel` | 1~6 | `level`์˜ ์ˆซ์ž | ํฌ๊ฒŒ ๋ณด์ด์ง€๋งŒ ๊ตฌ์กฐ์ƒ h4์ธ ์นด๋“œ ์ œ๋ชฉ์ฒ˜๋Ÿผ ์‹œ๊ฐ ํฌ๊ธฐ์™€ ๋ฌธ์„œ ๋‹จ๊ณ„๊ฐ€ ๋‹ค๋ฅด๋ฉด ๋‘˜์„ ๋”ฐ๋กœ ์ ๋Š”๋‹ค |
53
53
  | `layoutStyle` | ๋ฐฐ์น˜ key(marginยทํญยท์ •๋ ฌ ๋“ฑ) | โ€” | ๋ฐ”๊นฅ ๋ฐฐ์น˜๋งŒ. ํฌ๊ธฐยท์ค„ ๋†’์ดยท๊ตต๊ธฐยท์ƒ‰์€ ๋ฐ›์ง€ ์•Š๋Š”๋‹ค |
54
54
 
55
55
  - ๋ฒ”์œ„ ๋ฐ– ๊ฐ’์€ `TypeError`๋กœ ๊ฑฐ๋ถ€๋œ๋‹ค.
56
56
  - ์œ„ ํฌ๊ธฐ๋Š” ํ”„๋กœํ•„ ์—†๋Š” ๊ธฐ๋ณธ๊ฐ’์ด๋‹ค. [๋””์ž์ธ ํ”„๋กœํ•„](../../design-profile.md)์˜
57
- `tokens.heading.level1`~`level5`๋กœ ๋‹ค์„ฏ ์‹œ๊ฐ ๋‹จ๊ณ„๋ฅผ ์ง€์ •ํ•˜๋ฉด ์–‘ renderer๊ฐ€ ๋”ฐ๋ฅด๋ฉฐ,
58
- `semanticLevel`์€ ๊ทธ๋Œ€๋กœ๋‹ค. ํฌ๊ธฐ๋ฅผ ๋งž์ถ”๋ ค๊ณ  ๋ฌธ์„œ ๋‹จ๊ณ„๋ฅผ ๋ฐ”๊พธ์ง€ ์•Š๋Š”๋‹ค.
59
- - `defineHjmDesignProfile`์—์„œ `tokens.typography.heading/titleLarge/title`์„ ๋ฐ”๊พธ๋ฉด ๊ธฐ์กด
60
- level3/4/5 ์—ฐ๊ฒฐ์„ ์œ ์ง€ํ•œ๋‹ค. ๊ฐ™์€ ๋‹จ๊ณ„์— `tokens.heading`๋„ ์ง€์ •ํ•˜๋ฉด ๋ช…์‹œํ•œ heading
61
- ๊ฐ’์ด ์šฐ์„ ํ•œ๋‹ค. ํฐ ์ œ๋ชฉ level1/2๋Š” ๋ณธ๋ฌธ ํฌ๊ธฐ์—์„œ ์ž๋™ ์ถ”์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค.
57
+ `tokens.heading`์œผ๋กœ ์‹œ๊ฐ ๋‹จ๊ณ„๋ฅผ ์ง€์ •ํ•˜๋ฉด ์–‘ renderer๊ฐ€ ๋”ฐ๋ฅด๋ฉฐ, `semanticLevel`์€ ๊ทธ๋Œ€๋กœ๋‹ค.
58
+ ์–ด๋А ๋‹จ๊ณ„๋„ `typography.heading` 24px๋ฅผ ๋„˜์œผ๋ฉด `RangeError`๋กœ ๊ฑฐ๋ถ€๋œ๋‹ค. ํฌ๊ธฐ๋ฅผ ๋งž์ถ”๋ ค๊ณ  ๋ฌธ์„œ ๋‹จ๊ณ„๋ฅผ ๋ฐ”๊พธ์ง€ ์•Š๋Š”๋‹ค.
59
+ - `defineHjmDesignProfile`์—์„œ `tokens.typography.heading/titleLarge/title`์„ ๋ฐ”๊พธ๋ฉด
60
+ level1~3/4/5๊ฐ€ ๊ทธ ๊ฐ’์„ ๋”ฐ๋ฅธ๋‹ค. ๊ฐ™์€ ๋‹จ๊ณ„์— `tokens.heading`๋„ ์ง€์ •ํ•˜๋ฉด ๋ช…์‹œํ•œ heading
61
+ ๊ฐ’์ด ์šฐ์„ ํ•œ๋‹ค.
62
62
 
63
63
  ## ๋ฐฐ์น˜
64
64
 
65
65
  | ํ•ญ๋ชฉ | ๊ฐ’ | ๊ทผ๊ฑฐ |
66
66
  | --- | --- | --- |
67
- | ํฌ๊ธฐ | ์ค„ ๋†’์ด: `level1` 48 ยท `level2` 40 ยท `level3` 32 ยท `level4` 28 ยท `level5` 26 | `foundations.ts` `heading`, `typography` |
67
+ | ํฌ๊ธฐ | ์ค„ ๋†’์ด: `level3` 32 ยท `level4` 28 ยท `level5` 26 (`level1`ยท`level2`๋Š” 32) | `foundations.ts` `heading`, `typography` |
68
68
  | ๊ฐ„๊ฒฉ | Heading์€ margin์ด 0์ด๋‹ค(Web `.hjm-heading`). ์œ„์•„๋ž˜ ๊ฐ„๊ฒฉ์€ ๊ฐ์‹ธ๋Š” StackยทSection์˜ `gap`์ด ์ •ํ•œ๋‹ค | `styles.css` `.hjm-heading` |
69
69
  | ์ˆœ์„œยท์ •๋ ฌ | ํ•œ ๋ธ”๋ก์— Heading์€ ํ•˜๋‚˜๋ฅผ ๋งจ ์œ„์— ๋‘”๋‹ค | โ€” |
70
70
  | ๊ณ ์ •ยท์Šคํฌ๋กค | โ€” | โ€” |
@@ -88,7 +88,9 @@ import { Heading } from "@hjmds/react-native/heading";
88
88
 
89
89
  ## ๊ทผ๊ฑฐ
90
90
 
91
- 2026-10-17 ์‚ฌ์šฉ์ž ๊ฒฐ์ •: `level1`ยท`level2`๋Š” Pretendard 800์ด ํฐ ํฌ๊ธฐ์—์„œ ๋ฌด๊ฒ๊ณ  ๊ฑฐ์น ์–ด 700(bold)์œผ๋กœ ๋‚ฎ์ท„๋‹ค. ๊ฐ™์€ ๋‚  600์œผ๋กœ ๋‚ฎ์ถ˜ `level3`~`level5`๋ณด๋‹ค ํ•œ ๋‹จ๊ณ„ ๊ตต๊ฒŒ ์œ ์ง€ํ•œ๋‹ค. Native๋Š” `fonts="pretendard"`์ผ ๋•Œ `Pretendard-Bold` face๋กœ ๊ทธ๋ฆฐ๋‹ค. `Top size="large"` ์ œ๋ชฉ๋„ `heading.level2`๋ผ ํ•จ๊ป˜ 700์ด ๋œ๋‹ค. ๋ธŒ๋ฃจํƒˆ๋ฆฌ์ฆ˜ ํ”„๋ฆฌ์…‹์€ level1ยท2๋ฅผ 800์œผ๋กœ ๋ช…์‹œํ•œ๋‹ค.
91
+ 2026-10-17 ์‚ฌ์šฉ์ž ๊ฒฐ์ •("๊ธ€์ž ๋„ˆ๋ฌด ์ปค", "ํฐ ๊ธ€์ž ์ •์ฑ…์€ ์—†์• "): ํฐ ๊ธ€์ž ๋‹จ๊ณ„๋ฅผ ํ์ง€ํ–ˆ๋‹ค. Native Storybook ์„œ๋น„์Šค ์†Œ๊ฐœ ํ™”๋ฉด์˜ ํžˆ์–ด๋กœ ์ œ๋ชฉ(level1 40px)๊ณผ ๊ตฌํš ์ œ๋ชฉ(level2 32px)์ด ์ง€๋‚˜์น˜๊ฒŒ ์ปธ๋˜ ๊ฒƒ์ด ๊ณ„๊ธฐ๋‹ค. `level1`ยท`level2`๋Š” ๊ธฐ์กด ์†Œ๋น„ ์ฝ”๋“œ๊ฐ€ ๊นจ์ง€์ง€ ์•Š๋„๋ก ์ด๋ฆ„๋งŒ ๋‚จ๊ธฐ๊ณ  `level3`๊ณผ ๊ฐ™์€ 24/32/500์œผ๋กœ ๊ณ ์ •ํ–ˆ์œผ๋ฉฐ ์ƒˆ ์ฝ”๋“œ์—์„œ ์“ฐ์ง€ ์•Š๋Š”๋‹ค. ์œ„๊ณ„๋Š” `level3`(24) โ†’ `level4`(20) โ†’ `level5`(18)๋กœ ๋งŒ๋“ค๊ณ , ๋ฌธ์„œ ๊ตฌ์กฐ๋Š” `semanticLevel`๋กœ ์ ๋Š”๋‹ค. `Top size="large"` ์ œ๋ชฉ๋„ `heading.level3` 24px๋‹ค. ๋ธŒ๋ฃจํƒˆ๋ฆฌ์ฆ˜ ํ”„๋ฆฌ์…‹์€ ๊ตต๊ธฐ๋งŒ 800์œผ๋กœ ๋ช…์‹œํ•˜๊ณ  ํฌ๊ธฐ๋Š” ๊ณตํ†ต ๋‹จ๊ณ„๋ฅผ ๋”ฐ๋ฅธ๋‹ค.
92
+
93
+ ๊ฐ™์€ ๋‚  ์•ž์„  ๊ตต๊ธฐ ๊ฒฐ์ •: ์ œ๋ชฉ ๋‹จ๊ณ„(`level3`~`level5`)๋Š” 500(medium)์ด๋ฉฐ Native๋Š” `fonts="pretendard"`์ผ ๋•Œ `Pretendard-Medium` face๋กœ ๊ทธ๋ฆฐ๋‹ค. ์ด์ „์˜ ํฐ ์ œ๋ชฉ 600(semibold) ๋‹จ๊ณ„๋Š” ํฐ ๊ธ€์ž ๋‹จ๊ณ„์™€ ํ•จ๊ป˜ ์—†์–ด์กŒ๋‹ค.
92
94
 
93
95
  ## ํ•จ์ •
94
96
 
@@ -86,7 +86,7 @@ Native ์›ํ˜• leading์˜ `full`์€ Provider token์—์„œ ์ฝ์ง€๋งŒ ๊ณ ์ • ์›ํ˜•
86
86
  | --- | --- | --- |
87
87
  | ํฌ๊ธฐ | ํ–‰ ํ‘œ๋ฉด(๋ˆ„๋ฆ„ยทhoverยท์„ ํƒ ๋ฐฐ๊ฒฝ, ํฌ์ปค์Šค ๋ง, ๋ˆ„๋ฅผ ์ˆ˜ ์žˆ๋Š” ์˜์—ญ)์€ ๋ถ€๋ชจ ์ฝ˜ํ…์ธ  ํญ๋ณด๋‹ค ์–‘์ชฝ์œผ๋กœ `listRowRecipe.surfaceBleed`(= density `paddingHorizontal`, `spacing.xs` 8)์”ฉ ๋„“๋‹ค(Web `inline-size: calc(100% + 16)` + `margin-inline: -8`, Native `marginHorizontal: -8`). ๊ธ€์žยทleadingยทtrailing์€ ๋ถ€๋ชจ ์ฝ˜ํ…์ธ  ๊ฐ€์žฅ์ž๋ฆฌ์— ๋†“์ธ๋‹ค. leading ํ”„๋ ˆ์ž„์€ 40ร—40(`leadingSize`), `circle`์ด๋ฉด `radius.full`. trailing ์•„์ด์ฝ˜์€ `glyph.sm` 20. ์ตœ์†Œ ๋†’์ด๋Š” ์•„๋ž˜ density ํ‘œ | `design-contracts/src/component-recipes.ts`(`listRowRecipe`), `design-contracts/src/foundations.ts`(`layout.rowHeight`) |
88
88
  | ๊ฐ„๊ฒฉ | leadingยทcontentยทtrailing ์‚ฌ์ด `spacing.sm` 12(`listRowRecipe.gap`). ํ–‰ ์•ˆ ์ขŒ์šฐ ์—ฌ๋ฐฑ 8์€ ํ‘œ๋ฉด์ด ๋ฐ”๊นฅ์œผ๋กœ ๋„“์–ด์ง„ ๋งŒํผ์ด๋ผ ๊ธ€์ž๋Š” ๋ถ€๋ชจ ์ฝ˜ํ…์ธ  ๊ฐ€์žฅ์ž๋ฆฌ(๊ธฐ๋ณธ ํ™”๋ฉด์ด๋ฉด ์—ฌ๋ฐฑ ์„  16)์—์„œ ์‹œ์ž‘ํ•œ๋‹ค. ์œ„์•„๋ž˜ ์—ฌ๋ฐฑ์€ ์•„๋ž˜ density ํ‘œ. Native์˜ ํˆฌ๋ช… ์„ ํƒ ํ…Œ๋‘๋ฆฌ 1์€ ์ด ์—ฌ๋ฐฑ ์•ˆ์— ํฌํ•จ๋œ๋‹ค(ํ…Œ๋‘๋ฆฌ + padding = 8). ์ œํ’ˆ์€ ํ–‰์— margin์„ ์ฃผ์ง€ ์•Š๋Š”๋‹ค | `design-contracts/src/component-recipes.ts`(`listRowRecipe`), `react/src/styles.css`(`.hjm-list-row`) |
89
- | ์ˆœ์„œยท์ •๋ ฌ | leading โ†’ content(์ œ๋ชฉยท์„ค๋ช…) โ†’ trailing. trailing ๋‚ด์šฉ(์•„์ด์ฝ˜ยทSwitchยท๋ฌธ๊ตฌ)์€ ํ–‰์˜ ์„ธ๋กœ ๊ฐ€์šด๋ฐ์— ๋‘”๋‹ค(Web `.hjm-list-row__trailing` flex ๊ฐ€์šด๋ฐ, Native ํ–‰ ๊ฐ€์šด๋ฐ ์ •๋ ฌ View). `trailingAction`(๋‘ ํ”Œ๋žซํผ)์€ ํ–‰ ๋ช…๋ น ๋ฐ”๊นฅ ๋์— `listRowRecipe.gap` 12 ๋–จ์–ด์ ธ ๋†“์ด๊ณ , ๋ช…๋ น๊ณผ ํ•จ๊ป˜ ํ•˜๋‚˜์˜ ํ‘œ๋ฉด(์„ ํƒ ๋ฐฐ๊ฒฝยทํ…Œ๋‘๋ฆฌ)์„ ์“ด๋‹ค. ํ–‰๋™ ์ƒ์ž์˜ ๋์€ ๋ถ€๋ชจ ์ฝ˜ํ…์ธ  ๊ฐ€์žฅ์ž๋ฆฌ์— ๋งž์œผ๋ฏ€๋กœ ghost IconButton์— `edge="end"`๋ฅผ ์ฃผ๋ฉด glyph ์นธ ๋์ด ์—ฌ๋ฐฑ ์„  16์— ์˜จ๋‹ค. ํ–‰ ์‚ฌ์ด ๊ตฌ๋ถ„์„ ยท๋ฐ”๊นฅ ๋‘ฅ๊ทผ ๋ฐฐ๊ฒฝ์€ [List](list.md)๊ฐ€ ๊ทธ๋ฆฐ๋‹ค | `react-native/src/data-display.tsx`(ListRow), `react/src/styles.css`(`.hjm-list-row__trailing`) |
89
+ | ์ˆœ์„œยท์ •๋ ฌ | leading โ†’ content(์ œ๋ชฉยท์„ค๋ช…) โ†’ trailing. trailing ๋‚ด์šฉ(์•„์ด์ฝ˜ยทSwitchยท๋ฌธ๊ตฌ)์€ ํ–‰์˜ ์„ธ๋กœ ๊ฐ€์šด๋ฐ์— ๋‘”๋‹ค(Web `.hjm-list-row__trailing` flex ๊ฐ€์šด๋ฐ, Native ํ–‰ ๊ฐ€์šด๋ฐ ์ •๋ ฌ View). `trailingAction`(๋‘ ํ”Œ๋žซํผ)์€ ํ–‰ ๋ช…๋ น ๋ฐ”๊นฅ ๋์— `listRowRecipe.gap` 12 ๋–จ์–ด์ ธ ๋†“์ด๊ณ , ๋ช…๋ น๊ณผ ํ•จ๊ป˜ ํ•˜๋‚˜์˜ ํ‘œ๋ฉด(์„ ํƒ ๋ฐฐ๊ฒฝยทํ…Œ๋‘๋ฆฌ)์„ ์“ด๋‹ค. ํ–‰๋™ ์ƒ์ž์˜ ๋์€ ๋ถ€๋ชจ ์ฝ˜ํ…์ธ  ๊ฐ€์žฅ์ž๋ฆฌ์— ๋งž์œผ๋ฏ€๋กœ ghost IconButton์— `edge="end"`๋ฅผ ์ฃผ๋ฉด glyph ์นธ ๋์ด ์—ฌ๋ฐฑ ์„  16์— ์˜จ๋‹ค. ํ–‰ ์‚ฌ์ด ๊ตฌ๋ถ„์„ ยท๋ฐ”๊นฅ ๋‘ฅ๊ทผ ๋ฐฐ๊ฒฝ์€ [List](list.md)๊ฐ€ ๊ทธ๋ฆฐ๋‹ค. ํ–‰์€ leading ์—ฌ๋ถ€๋ฅผ List์— ์•Œ๋ ค(Web ๋ฃจํŠธ `data-leading`, Native List ํ•ญ๋ชฉ context) ์ž๊ธฐ ์•„๋ž˜ `indented` ๊ตฌ๋ถ„์„ ์ด ๊ธ€์ž ์—ด(leading ์žˆ์œผ๋ฉด 52, ์—†์œผ๋ฉด 0)์—์„œ ์‹œ์ž‘ํ•˜๊ฒŒ ํ•œ๋‹ค | `react-native/src/data-display.tsx`(ListRow), `react/src/styles.css`(`.hjm-list-row__trailing`) |
90
90
  | ๊ณ ์ •ยท์Šคํฌ๋กค | โ€” | โ€” |
91
91
  | ์ข์€ ํญยทํฐ ๊ธ€์ž | ๊ธด ์ œ๋ชฉยท์„ค๋ช…์€ ์ค„๋ฐ”๊ฟˆ๋˜๊ณ (`overflow-wrap: anywhere`) ํ–‰ ๋†’์ด๊ฐ€ ๋Š˜์–ด๋‚œ๋‹ค. ํฐ ๊ธ€์ž์—์„œ๋„ ์ž๋ฅด์ง€ ์•Š๋Š”๋‹ค | `react/src/styles.css`(`.hjm-list-row`) |
92
92
 
@@ -100,7 +100,7 @@ Native ์›ํ˜• leading์˜ `full`์€ Provider token์—์„œ ์ฝ์ง€๋งŒ ๊ณ ์ • ์›ํ˜•
100
100
  ```text
101
101
  ํ™”๋ฉด ๋ โ†“ ์—ฌ๋ฐฑ ์„  16 โ†“ โ†“ ์—ฌ๋ฐฑ ์„  16
102
102
  โ”Œโ”€8โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€8โ”€โ” โ† ํ–‰ ํ‘œ๋ฉด(๋ˆ„๋ฆ„ยท์„ ํƒ ๋ฐฐ๊ฒฝ), 8์”ฉ ๋ฐ”๊นฅ์œผ๋กœ
103
- โ”‚ โ”‚[40ร—40]โ”‚12โ”‚ ์ œ๋ชฉ(bodyLarge bold) โ”‚12โ”‚ ๊ฐ’ โ€บโ”‚ โ”‚
103
+ โ”‚ โ”‚[40ร—40]โ”‚12โ”‚ ์ œ๋ชฉ(bodyLarge 500) โ”‚12โ”‚ ๊ฐ’ โ€บโ”‚ โ”‚
104
104
  โ”‚ โ”‚leadingโ”‚ โ”‚ ์„ค๋ช…(body, secondary) โ”‚ โ”‚trailโ”‚ โ”‚
105
105
  โ””โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”˜
106
106
  ์„น์…˜ ์ œ๋ชฉยท๊ฒฐ๊ณผ ๊ฐœ์ˆ˜(16)์™€ ํ–‰ ๊ธ€์žยทleading(16)์ด ๊ฐ™์€ ์„ ์—์„œ ์‹œ์ž‘ํ•œ๋‹ค
@@ -113,7 +113,7 @@ Native ์›ํ˜• leading์˜ `full`์€ Provider token์—์„œ ์ฝ์ง€๋งŒ ๊ณ ์ • ์›ํ˜•
113
113
 
114
114
  - ์ œ๋ชฉยท์„ค๋ช…์€ i18n ํ‚ค๋กœ ๋„ฃ๋Š”๋‹ค. leading์˜ ์‚ฌ์ง„ยท์•„์ด์ฝ˜์€ ์žฅ์‹์œผ๋กœ ๋‘๊ณ  ์˜๋ฏธ๋Š” ์ œ๋ชฉ์ด ๋งํ•œ๋‹ค.
115
115
  - ํ–‰ ์•ˆ์— ๋‹ค๋ฅธ ๋ฒ„ํŠผ์„ ๋„ฃ์ง€ ์•Š๋Š”๋‹ค. ๋ณ„๋„ target์€ `trailingAction`์— ๋‘”๋‹ค(ํ–‰ ๋ช…๋ น ์˜†์— ๋”ฐ๋กœ ๊ทธ๋ฆฐ๋‹ค).
116
- - ํ–‰์€ ๋ถ€๋ชจ๊ฐ€ ์ขŒ์šฐ๋กœ 8 ์ด์ƒ์˜ ์—ฌ๋ฐฑ์„ ๊ฐ€์ง„ ๊ณณ์— ๋‘”๋‹ค(ํ™”๋ฉด ๋ณธ๋ฌธ 16, CardยทSheetยทSidePanel ๋ณธ๋ฌธ, `grouped` List). ์—ฌ๋ฐฑ์ด 0์ธ ์ƒ์ž(์˜ˆ: ์—ฌ๋ฐฑ ์—†๋Š” ๋ถ„ํ•  ํŒจ๋„, ์ œํ’ˆ์˜ ๊ฝ‰ ์ฐฌ div)์— ๋ฐ”๋กœ ๋‘๋ฉด ํ‘œ๋ฉด์ด ์ž˜๋ฆฌ๊ณ  Web์€ ๊ฐ€๋กœ ์Šคํฌ๋กค์ด ์ƒ๊ธด๋‹ค. ๊ทธ ์ƒ์ž์— ์ฝ˜ํ…์ธ  ์—ฌ๋ฐฑ์„ ์ค€๋‹ค. `ScreenLayout contentInset="body-edge"` ๋ณธ๋ฌธ์€ ์ž๊ธฐ ์—ฌ๋ฐฑ 16์„ ๊ฐ€์ง„ ์ „์ฒด ํญ ํ–‰(ConversationRowยทNotificationRow) ์ „์šฉ์ด๋‹ค. ListRowยทNotificationItem์€ `default` ๋ณธ๋ฌธ์— ๋‘”๋‹ค(๊ทธ๋ž˜์•ผ ๊ธ€์ž๊ฐ€ ์—ฌ๋ฐฑ ์„  16์— ์˜จ๋‹ค).
116
+ - ํ–‰์€ ๋ถ€๋ชจ๊ฐ€ ์ขŒ์šฐ๋กœ 8 ์ด์ƒ์˜ ์—ฌ๋ฐฑ์„ ๊ฐ€์ง„ ๊ณณ์— ๋‘”๋‹ค(ํ™”๋ฉด ๋ณธ๋ฌธ 16, CardยทSheetยทSidePanel ๋ณธ๋ฌธ, `grouped` List). ์—ฌ๋ฐฑ์ด 0์ธ ์ƒ์ž(์˜ˆ: ์—ฌ๋ฐฑ ์—†๋Š” ๋ถ„ํ•  ํŒจ๋„, ์ œํ’ˆ์˜ ๊ฝ‰ ์ฐฌ div)์— ๋ฐ”๋กœ ๋‘๋ฉด ํ‘œ๋ฉด์ด ์ž˜๋ฆฌ๊ณ  Web์€ ๊ฐ€๋กœ ์Šคํฌ๋กค์ด ์ƒ๊ธด๋‹ค. ๊ทธ ์ƒ์ž์— ์ฝ˜ํ…์ธ  ์—ฌ๋ฐฑ์„ ์ค€๋‹ค. HJM์˜ ์Šคํฌ๋กค ์ƒ์ž๋Š” ์ด ์—ฌ์œ ๋ฅผ ์Šค์Šค๋กœ ๋งŒ๋“ ๋‹ค: VirtualList๋Š” ๋ฐ”๊นฅ์œผ๋กœ 8 ๋„“ํžˆ๊ณ  ์•ˆ์ชฝ 8์„ ๋‘๋ฉฐ, ์Šคํฌ๋กค Sheet ๋ณธ๋ฌธ์€ ์‹œํŠธ ์—ฌ๋ฐฑ ๋๊นŒ์ง€ ๋„“๊ณ  ์—ฌ๋ฐฑ์„ ์•ˆ์ชฝ์— ๋‘”๋‹ค(๋‚ด๋ถ€ `listRowScrollRoom`). ์ฝ˜ํ…์ธ  ์œ„์น˜๋Š” ๊ทธ๋Œ€๋กœ๋‹ค. ํ™”๋ฉด์„ ๋ฐ”๊นฅ Container ์—ฌ๋ฐฑ + `contentInset="none"`์œผ๋กœ ๊ฐ์‹ธ๋Š” ๊ตฌ์„ฑ์€ ์ง€์›ํ•˜์ง€ ์•Š๋Š”๋‹ค([ScreenLayout](screen-layout.md#๊ผญ-์ง€ํ‚ฌ-๊ฒƒ)). `ScreenLayout contentInset="body-edge"` ๋ณธ๋ฌธ์€ ์ž๊ธฐ ์—ฌ๋ฐฑ 16์„ ๊ฐ€์ง„ ์ „์ฒด ํญ ํ–‰(ConversationRowยทNotificationRow) ์ „์šฉ์ด๋‹ค. ListRowยทNotificationItem์€ `default` ๋ณธ๋ฌธ์— ๋‘”๋‹ค(๊ทธ๋ž˜์•ผ ๊ธ€์ž๊ฐ€ ์—ฌ๋ฐฑ ์„  16์— ์˜จ๋‹ค).
117
117
  - ๋ฐฐ์น˜๋Š” `layoutStyle`๋กœ ํ•œ๋‹ค. ๋†’์ดยท์—ฌ๋ฐฑยท๋ฐฐ๊ฒฝ์„ ๋ฎ์ง€ ์•Š๋Š”๋‹ค. ๋ฐ€๋„๋Š” `density`๋กœ ๋ฐ”๊พผ๋‹ค.
118
118
  - ์•„๋ฐ”ํƒ€ ํ”„๋ ˆ์ž„์„ ์ œํ’ˆ์ด ๋‹ค์‹œ ๊ทธ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค. `leadingShape`๋ฅผ ์“ด๋‹ค.
119
119
 
@@ -148,5 +148,9 @@ Web๋„ Native์™€ ๊ฐ™์ด `trailingAction`์„ ์ง€์›ํ•œ๋‹ค. ์ด ์Šฌ๋กฏ์€ ํ–‰์˜ l
148
148
 
149
149
  ## ๊ทผ๊ฑฐ
150
150
 
151
+ 2026-10-17 ์‚ฌ์šฉ์ž ๊ฒฐ์ •("๊ตต๊ธฐ ์ข€๋” ์ค„์—ฌ"): ๋ชจ๋“  ๊ธ€์ž ๊ตต๊ธฐ๋ฅผ ํ•œ ๋‹จ๊ณ„ ๋‚ฎ์ท„๋‹ค. ํฐ ์ˆซ์žยท์„ ํƒ ์ƒํƒœ 600(ํฐ ์ œ๋ชฉ ๋‹จ๊ณ„๋Š” ๊ฐ™์€ ๋‚  ํ์ง€), ์ œ๋ชฉยท๊ฐ•์กฐ 500, label 500, ๋ณธ๋ฌธ 400์ด๋ฉฐ ์ •๋ณธ์€ [ํƒ€์ดํฌ๊ทธ๋ž˜ํ”ผ](../tokens/typography.md)๋‹ค.
152
+
153
+ - ์Šคํฌ๋กค ์ƒ์ž์˜ ํ‘œ๋ฉด ์—ฌ์œ : 2026-10-17 1.27.2 ์ฑ„ํƒ ์ ๊ฒ€. Native ์Šคํฌ๋กค Sheet๋Š” ์—ฌ๋ฐฑ 20์ด ScrollView ๋ฐ”๊นฅ์— ์žˆ์–ด ํ–‰ ํ‘œ๋ฉด์ด ์‹œํŠธ ์ฝ˜ํ…์ธ  ๋(21pt)์—์„œ ์ž˜๋ ธ๋‹ค(3x ์ธก์ •: ์„ ํƒ ํ…Œ๋‘๋ฆฌ ์œ„ ์„  21โ€“381, ์˜† ์„  ์—†์Œ โ†’ ์ˆ˜์ • ํ›„ ์˜† ์„  13ยท๋ 13, ์ œ๋ชฉ ์œ„์น˜ ๊ทธ๋Œ€๋กœ). VirtualList์™€ ๊ฐ™์€ ๊ทœ์น™์ด๋ผ ๋‚ด๋ถ€ helper ํ•˜๋‚˜๋กœ ๋ฌถ์—ˆ๋‹ค.
151
154
  - trailing ์„ธ๋กœ ๊ฐ€์šด๋ฐ: 2026-10-17 ์ •๋ ฌ ์‹ค์ธก(Web 402). trailing span์ด block์ด๋ผ ์•ˆ์˜ inline svg๊ฐ€ ๊ธ€์ž ๊ธฐ์ค€์„ ์— ๋†“์—ฌ ํ–‰ ๊ฐ€์šด๋ฐ๋ณด๋‹ค 2~2.5px ์œ„์˜€๋‹ค(์„ค์ • 334/331.5, ์ปฌ๋ ‰์…˜ 184/181.5). Native๋Š” ํ–‰ ๊ฐ€์šด๋ฐ(388/388)์˜€๋‹ค. trailing์„ flex ๊ฐ€์šด๋ฐ ์ƒ์ž๋กœ ๋ฐ”๊พผ ๋’ค Web๋„ 334/334, 184/184๋กœ ์ธก์ •๋๋‹ค.
152
155
  - ๊ธ€์ž๋ฅผ ์—ฌ๋ฐฑ ์„ ์—, ํ‘œ๋ฉด์€ ๋ฐ”๊นฅ์œผ๋กœ: 2026-10-17 ์‚ฌ์šฉ์ž ๊ฒฐ์ •. ํ–‰์ด ๋ˆ„๋ฆ„ ๋ฐฐ๊ฒฝ์šฉ ์ขŒ์šฐ ์—ฌ๋ฐฑ 8์„ ์ฝ˜ํ…์ธ  ์•ˆ์— ๋‘์–ด ๊ธฐ๋ณธ ํ™”๋ฉด์—์„œ ํ–‰ ๊ธ€์ž๊ฐ€ 16 + 8 = 24์—์„œ ์‹œ์ž‘ํ–ˆ๊ณ , ๊ฐ™์€ ํ™”๋ฉด์˜ ์„น์…˜ ์ œ๋ชฉยท๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ๋จธ๋ฆฌ("๊ฒฐ๊ณผ N๊ฐœ")ยท์„ค์ • ๋ฌถ์Œ ์ œ๋ชฉ์€ 16์—์„œ ์‹œ์ž‘ํ–ˆ๋‹ค(Web 402 ์‹ค์ธก: ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ํ–‰ 24 / ๋จธ๋ฆฌ 16, ์„ค์ • leading 24 / ๋ฌถ์Œ ์ œ๋ชฉ 16, ์•Œ๋ฆผ leading 24 / "์˜ค๋Š˜" 16. Native 3x ํ™”๋ฉด ์ž‰ํฌ: ๊ฒฐ๊ณผ ํ–‰ ์ œ๋ชฉ 25 / ๊ฐœ์ˆ˜ 16.7 โ€” Native๋Š” ํˆฌ๋ช… ์„ ํƒ ํ…Œ๋‘๋ฆฌ 1๊นŒ์ง€ ๋”ํ•ด์กŒ๋‹ค). ํ‘œ๋ฉด์„ ๋ฐ”๊นฅ์œผ๋กœ 8 ๋„“ํžˆ๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ฐ”๊พผ ๋’ค Web 402ยท1280, LTRยทRTL ๋ชจ๋‘ ํ–‰ ๊ธ€์žยทleading ์‹œ์ž‘๊ณผ trailing ๋์ด 16(1280์€ ํ™”๋ฉด ์—ด ๊ธฐ์ค€ 296)์œผ๋กœ, Native๋Š” ๊ฒฐ๊ณผ ํ–‰ ์ œ๋ชฉ ์ž‰ํฌ 16, ์„ค์ • leading ์•„์ด์ฝ˜ ์ž‰ํฌ 36 โ†’ 27, ์•Œ๋ฆผ 42.3 โ†’ 33(ํ”„๋ ˆ์ž„ 16 + ์•„์ด์ฝ˜ ์•ˆ์ชฝ ์—ฌ๋ฐฑ)์œผ๋กœ ์ธก์ •๋๋‹ค. ๊ตฌ๋ถ„์„  ์‹œ์ž‘๋„ ๊ธ€์ž ์œ„์น˜(52)๋กœ ์˜ฎ๊ฒผ๋‹ค.
156
+ - ๊ตฌ๋ถ„์„ ์ด ํ–‰์˜ ๊ธ€์ž ์—ด์„ ๋”ฐ๋ฆ„: 2026-10-17 ์‚ฌ์šฉ์ž ๋ณด๊ณ (leading ์—†๋Š” ํ–‰์—์„œ ๊ตฌ๋ถ„์„ ์ด ์ค‘๊ฐ„์—์„œ ์ž˜๋ฆผ). ์œ„ 52๋Š” leading ์žˆ๋Š” ํ–‰์˜ ๊ธ€์ž ์œ„์น˜์ผ ๋ฟ์ด๋ผ leading ์—†๋Š” ํ–‰(๊ธ€์ž 16)์—์„œ๋Š” ๊ตฌ๋ถ„์„ ์ด 68์—์„œ ์‹œ์ž‘ํ–ˆ๋‹ค. ํ–‰์ด leading ์—ฌ๋ถ€๋ฅผ List์— ์•Œ๋ฆฌ๋„๋ก ๋ฐ”๊ฟ” ๊ตฌ๋ถ„์„  ์‹œ์ž‘์ด ๊ฐ ํ–‰์˜ ๊ธ€์ž ์—ด๊ณผ ๊ฐ™์•„์กŒ๋‹ค([List ๊ทผ๊ฑฐ](list.md#๊ทผ๊ฑฐ)).
@@ -73,7 +73,7 @@ import { Text } from "@hjmds/react-native/primitives";
73
73
  | prop | ๊ฐ’ | ๊ธฐ๋ณธ๊ฐ’ | ์„ค๋ช… |
74
74
  | --- | --- | --- | --- |
75
75
  | `label` | ํ˜„์ง€ํ™” ๋ฌธ์ž์—ด(ํ•„์ˆ˜) | โ€” | ๋ชฉ๋ก์˜ ์ ‘๊ทผ์„ฑ ์ด๋ฆ„. ๋น„๋ฉด `TypeError` |
76
- | `separator` | `indented` ยท `full` ยท `none` | `indented` | `indented`๋Š” leading ์Šฌ๋กฏ ํญ๋งŒํผ ๋“ค์—ฌ์”€ |
76
+ | `separator` | `indented` ยท `full` ยท `none` | `indented` | `indented`๋Š” ์œ„ ํ–‰์˜ ๊ธ€์ž ์—ด์—์„œ ์‹œ์ž‘(leading์ด ์žˆ์œผ๋ฉด 52, ์—†์œผ๋ฉด 0) |
77
77
  | `appearance` | `plain` ยท `grouped` | `plain` | `grouped`๋Š” ๋ฐฐ๊ฒฝ๊ณผ ๋‘ฅ๊ทผ ๋ชจ์„œ๋ฆฌ๋กœ ํ•œ ๋ฉ์–ด๋ฆฌ |
78
78
  | `layoutStyle` | ๋ฐฐ์น˜ key๋งŒ | โ€” | ๋ชฉ๋ก ๋ฃจํŠธ ๋ฐฐ์น˜. Native `style`์€ ์ œ๊ฑฐ๋œ ์†์„ฑ โ€” `layoutStyle`, ๋ชจ์–‘์€ `appearance`ยท`separator` |
79
79
  | TaskList `items` | `readonly TaskItem[]` โ€” `{ id, label, completed, description?, disabled? }` | โ€” | `id`ยท`label`์ด ๋น„๊ฑฐ๋‚˜ `id`๊ฐ€ ์ค‘๋ณต๋˜๊ฑฐ๋‚˜ `completed`๊ฐ€ boolean์ด ์•„๋‹ˆ๋ฉด `TypeError` |
@@ -93,7 +93,7 @@ Native `grouped` ํ”„๋ ˆ์ž„์€ Provider์˜ `tokens.radius.lg`๋ฅผ ์ฝ๋Š”๋‹ค. plain
93
93
  | ํ•ญ๋ชฉ | ๊ฐ’ | ๊ทผ๊ฑฐ |
94
94
  | --- | --- | --- |
95
95
  | ํฌ๊ธฐ | ํ™”๋ฉด ๋ณธ๋ฌธ ํญ์„ ์ฑ„์šฐ๋Š” ์„ธ๋กœ ๋ฌถ์Œ์ด๋‹ค. `plain`์€ ์ž๋ฅด์ง€ ์•Š์œผ๋ฏ€๋กœ ํ–‰ ํ‘œ๋ฉด์ด ๋ถ€๋ชจ ์—ฌ๋ฐฑ ์ชฝ์œผ๋กœ 8์”ฉ ๋„“์–ด์ง„๋‹ค(ํ–‰ ๊ธ€์ž๋Š” ๋ชฉ๋ก ์ฝ˜ํ…์ธ  ๊ฐ€์žฅ์ž๋ฆฌ). `grouped`๋Š” ๋ฐฐ๊ฒฝ `--hjm-color-bg`์™€ ๋ชจ์„œ๋ฆฌ `radius.lg` 16์œผ๋กœ ํ•œ ๋ฉ์–ด๋ฆฌ๊ฐ€ ๋˜๊ณ  ๊ทธ ๋ชจ์–‘์œผ๋กœ ์ž๋ฅด๋ฏ€๋กœ, ์ขŒ์šฐ ์•ˆ์ชฝ ์—ฌ๋ฐฑ `listRecipe.grouped.paddingInline`(= `listRowRecipe.surfaceBleed` 8)์„ ๋‘์–ด ํ–‰ ํ‘œ๋ฉด์ด ์ž˜๋ฆฌ์ง€ ์•Š๊ณ  ํ–‰ ๊ธ€์ž๋Š” ์ด์ „์ฒ˜๋Ÿผ ๋ฉ์–ด๋ฆฌ ๋์—์„œ 8 ์•ˆ์ชฝ์— ์˜จ๋‹ค | `design-contracts/src/component-recipes.ts`(`listRecipe`), `react/src/styles.css`(`.hjm-list`), `react-native/src/data-display.tsx`(List) |
96
- | ๊ฐ„๊ฒฉ | ํ–‰ ์‚ฌ์ด ๊ฐ„๊ฒฉ์€ ์—†๊ณ  ๊ตฌ๋ถ„์„  1px(`--hjm-color-border`)๋งŒ ๋“ค์–ด๊ฐ„๋‹ค. ๊ตฌ๋ถ„์„  ์œ„์น˜๋Š” ๋ชฉ๋ก ์ฝ˜ํ…์ธ  ๊ฐ€์žฅ์ž๋ฆฌ(= ํ–‰ ๊ธ€์ž ์‹œ์ž‘) ๊ธฐ์ค€์ด๋‹ค: `indented`๋Š” ์‹œ์ž‘ 52(leading 40 + `spacing.sm` 12, ๊ธ€์ž ์‹œ์ž‘๊ณผ ๊ฐ™์€ ์œ„์น˜), ๋ โˆ’8(ํ–‰ ํ‘œ๋ฉด ๋๊นŒ์ง€). `full`์€ ์‹œ์ž‘ยท๋ ๋ชจ๋‘ โˆ’8๋กœ ํ–‰ ํ‘œ๋ฉด ํญ๊ณผ ๊ฐ™๋‹ค(`listRecipe.separators`, ๋‘ ํ”Œ๋žซํผ, Web `--hjm-list-separator-*`). ๋ฉ์–ด๋ฆฌ ๋ฐ”๊นฅ ์—ฌ๋ฐฑยท์„น์…˜ ์‚ฌ์ด ๊ฐ„๊ฒฉ์€ ๊ฐ์‹ธ๋Š” Stack์ด ์ค€๋‹ค(ํŽ˜์ด์ง€ ์ขŒ์šฐ ์—ฌ๋ฐฑ์€ `layout.pagePadding`, ์„น์…˜ ๊ฐ„๊ฒฉ์€ `layout.sectionGap` = `spacing.xl` 24) | `design-contracts/src/component-recipes.ts`(`listRecipe`), `design-contracts/src/foundations.ts`(`layout`), `react/src/styles.css`(`.hjm-list`), `react-native/src/data-display.tsx`(List) |
96
+ | ๊ฐ„๊ฒฉ | ํ–‰ ์‚ฌ์ด ๊ฐ„๊ฒฉ์€ ์—†๊ณ  ๊ตฌ๋ถ„์„  1px(`--hjm-color-border`)๋งŒ ๋“ค์–ด๊ฐ„๋‹ค. ๊ตฌ๋ถ„์„  ์œ„์น˜๋Š” ๋ชฉ๋ก ์ฝ˜ํ…์ธ  ๊ฐ€์žฅ์ž๋ฆฌ(= leading ์—†๋Š” ํ–‰์˜ ๊ธ€์ž ์‹œ์ž‘) ๊ธฐ์ค€์ด๊ณ , ๊ฐ ๊ตฌ๋ถ„์„ ์€ ๋ฐ”๋กœ ์œ„ ํ–‰์— ์†ํ•œ๋‹ค(iOS ์…€ ๊ตฌ๋ถ„์„ ๊ณผ ๊ฐ™๋‹ค). `indented`๋Š” ์œ„ ํ–‰์˜ ๊ธ€์ž ์—ด์—์„œ ์‹œ์ž‘ํ•œ๋‹ค: leading์ด ์žˆ์œผ๋ฉด `leadingInsetStart` 52(leading 40 + `spacing.sm` 12), ์—†์œผ๋ฉด `insetStart` 0. ๋์€ ํ–‰์˜ trailing ๋๊ณผ ๊ฐ™์€ ์ฝ˜ํ…์ธ  ๊ฐ€์žฅ์ž๋ฆฌ 0์ด๋‹ค. `full`์€ ์œ„ ํ–‰๊ณผ ๋ฌด๊ด€ํ•˜๊ฒŒ ์‹œ์ž‘ยท๋ ๋ชจ๋‘ โˆ’8๋กœ ํ–‰ ํ‘œ๋ฉด ํญ๊ณผ ๊ฐ™๋‹ค(`listRecipe.separators`, ๋‘ ํ”Œ๋žซํผ, Web `--hjm-list-separator-*`). ์œ„ ํ–‰์˜ leading ์—ฌ๋ถ€๋Š” ListRow๊ฐ€ ์•Œ๋ฆฐ๋‹ค: Web์€ ํ–‰ ๋ฃจํŠธ์˜ `data-leading`, Native๋Š” List ํ•ญ๋ชฉ context. ๋ฉ์–ด๋ฆฌ ๋ฐ”๊นฅ ์—ฌ๋ฐฑยท์„น์…˜ ์‚ฌ์ด ๊ฐ„๊ฒฉ์€ ๊ฐ์‹ธ๋Š” Stack์ด ์ค€๋‹ค(ํŽ˜์ด์ง€ ์ขŒ์šฐ ์—ฌ๋ฐฑ์€ `layout.pagePadding`, ์„น์…˜ ๊ฐ„๊ฒฉ์€ `layout.sectionGap` = `spacing.xl` 24) | `design-contracts/src/component-recipes.ts`(`listRecipe`), `design-contracts/src/foundations.ts`(`layout`), `react/src/styles.css`(`.hjm-list`), `react-native/src/data-display.tsx`(List) |
97
97
  | ์ˆœ์„œยท์ •๋ ฌ | ๋‹ค์Œ ํŽ˜์ด์ง€ ์š”์ฒญ์€ ๋ชฉ๋ก ๋ฐ”๋กœ ์•„๋ž˜์— [LoadMore](load-more.md)๋ฅผ ๋‘”๋‹ค | โ€” |
98
98
  | ๊ณ ์ •ยท์Šคํฌ๋กค | List ์ž์ฒด๋Š” ์Šคํฌ๋กคํ•˜์ง€ ์•Š๋Š”๋‹ค. ํ™”๋ฉด ์Šคํฌ๋กค ์•ˆ์— ๋‘”๋‹ค | `react-native/src/data-display.tsx`(List) |
99
99
  | ์ข์€ ํญยทํฐ ๊ธ€์ž | โ€” | โ€” |
@@ -101,7 +101,7 @@ Native `grouped` ํ”„๋ ˆ์ž„์€ Provider์˜ `tokens.radius.lg`๋ฅผ ์ฝ๋Š”๋‹ค. plain
101
101
  ```text
102
102
  โ”Œโ”€ List grouped (radius.lg 16, --hjm-color-bg) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
103
103
  โ”‚ ListRow โ”‚
104
- โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ โ† indented ๊ตฌ๋ถ„์„ (์‹œ์ž‘ ๋“ค์—ฌ์”€)
104
+ โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ โ† indented ๊ตฌ๋ถ„์„ (์œ„ ํ–‰์— leading์ด ์žˆ์œผ๋ฉด ๊ธ€์ž ์—ด 52, ์—†์œผ๋ฉด 0)
105
105
  โ”‚ ListRow โ”‚
106
106
  โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚
107
107
  โ”‚ ListRow โ”‚
@@ -197,7 +197,7 @@ import { CollectionRail } from "@hjmds/react/collection-rail";
197
197
  | ํ•ญ๋ชฉ | Web | Native |
198
198
  | --- | --- | --- |
199
199
  | ๊ตฌ์กฐ | `role="list"` + ์ž์‹๋งˆ๋‹ค `role="listitem"` | `accessibilityRole="list"` |
200
- | ๊ตฌ๋ถ„์„  | CSS(`data-separator`) | ํ–‰ ์‚ฌ์ด 1px `View` |
200
+ | ๊ตฌ๋ถ„์„  | CSS(`data-separator`, ๋‹ค์Œ ํ•ญ๋ชฉ `::before`, ์œ„ ํ–‰ `data-leading`์€ `:has()`๋กœ ์ฝ์Œ) | ํ–‰ ์‚ฌ์ด 1px `View`(์œ„ ํ–‰ ListRow๊ฐ€ context๋กœ leading ์—ฌ๋ถ€๋ฅผ ์•Œ๋ฆผ) |
201
201
  | ๋ฐฐ์น˜ | `layoutStyle`(+ `className`) | `layoutStyle`(`style`์€ ์ œ๊ฑฐ๋œ ์†์„ฑ) |
202
202
 
203
203
  2026-10-07 Utilverse ํ•ญ๋ชฉ ์‚ญ์ œ ์ฑ„ํƒ์„ ์œ„ํ•ด `renderItemAction`์„ ์ถ”๊ฐ€ํ–ˆ๋‹ค. ์ฒดํฌ์™€ ์‚ญ์ œ์˜ ์ดˆ์ ยท๋ˆ„๋ฆ„์„ ๋ถ„๋ฆฌํ•˜๊ณ  ํฐ ๊ธ€์ž ๋ผ๋ฒจ ํญ์„ ๋ณด์กดํ•˜๋„๋ก ํ–‰๋™์„ ๋‹ค์Œ ์ค„์— ๋‘”๋‹ค. `renderCollection`์˜ `renderItem`์—๋„ ํฌํ•จ๋œ๋‹ค. ์‚ญ์ œ ์ €์žฅยท์‹คํŒจยท๋˜๋Œ๋ฆฌ๊ธฐ๋Š” ์ œํ’ˆ์ด ์ฒ˜๋ฆฌํ•œ๋‹ค.
@@ -205,4 +205,5 @@ import { CollectionRail } from "@hjmds/react/collection-rail";
205
205
  ํ•ญ๋ชฉ ์‚ญ์ œ ๋’ค์—๋Š” ์ œํ’ˆ์ด ๋‹ค์Œ ํ•ญ๋ชฉ์˜ ๋…๋ฆฝ ํ–‰๋™(์—†์œผ๋ฉด ์ด์ „ ํ•ญ๋ชฉ, ๋ชฉ๋ก์ด ๋น„๋ฉด ํ›„์† ํ–‰๋™)์œผ๋กœ ์ดˆ์ ์„ ๋ณต๊ตฌํ•œ๋‹ค. Web Showcase๋Š” ref์™€ ์ปค๋ฐ‹ ํ›„ focus ์˜ˆ์‹œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค. Native ์ ‘๊ทผ์„ฑ ์ดˆ์  ๊ฒ€์ฆ์€ ์•„์ง ๋‚จ์•„ ์žˆ๋‹ค.
206
206
 
207
207
  ## ๊ทผ๊ฑฐ
208
+ - ๊ตฌ๋ถ„์„  ์‹œ์ž‘์€ ์œ„ ํ–‰์˜ ๊ธ€์ž ์—ด: 2026-10-17 ์‚ฌ์šฉ์ž ๋ณด๊ณ (leading ์—†๋Š” ํ–‰์—์„œ ๊ตฌ๋ถ„์„ ์ด ์ค‘๊ฐ„์—์„œ ์ž˜๋ฆฐ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž„). ๊ณ ์ • ์‹œ์ž‘ 52๊ฐ€ leading ์—†๋Š” ํ–‰์—๋„ ์ ์šฉ๋ผ Web 402 ๋Œ€์‹œ๋ณด๋“œ ๊ธฐ๋ก ๋ชฉ๋ก์—์„œ ํ–‰ ๊ธ€์ž 16 / ๊ตฌ๋ถ„์„  68~394(์ฝ˜ํ…์ธ  ๋ 386๋ณด๋‹ค 8 ๋” ๋‚˜๊ฐ)์˜€๋‹ค. ์œ„ ํ–‰์˜ leading ์—ฌ๋ถ€๋กœ ์‹œ์ž‘์„ ์ •ํ•˜๊ณ  ๋์„ ์ฝ˜ํ…์ธ  ๊ฐ€์žฅ์ž๋ฆฌ๋กœ ๋งž์ถ˜ ๋’ค ๊ธ€์ž 16 / ๊ตฌ๋ถ„์„  16~386, leading ์žˆ๋Š” ๋ชฉ๋ก์€ ๊ธ€์ž 85 / ๊ตฌ๋ถ„์„  85~369(์ฝ˜ํ…์ธ  ๋ 369), RTL๋„ ๋Œ€์นญ์œผ๋กœ ์ธก์ •๋๋‹ค.
208
209
  - ๊ตฌ๋ถ„์„ ยทgrouped ์—ฌ๋ฐฑ: 2026-10-17 ์‚ฌ์šฉ์ž ๊ฒฐ์ •(ํ–‰ ๊ธ€์ž๋Š” ์—ฌ๋ฐฑ ์„  16, ํ‘œ๋ฉด๋งŒ ๋ฐ”๊นฅ์œผ๋กœ 8). ํ–‰ ์ฝ˜ํ…์ธ  ์ƒ์ž๊ฐ€ ๋ชฉ๋ก ์ฝ˜ํ…์ธ  ๊ฐ€์žฅ์ž๋ฆฌ๋กœ ์˜ฎ๊ฒจ์ ธ `indented` ์‹œ์ž‘์ด 60 โ†’ 52๊ฐ€ ๋˜์–ด๋„ ํ™”๋ฉด์—์„œ ๋ณด์ด๋Š” ์œ„์น˜(๊ธ€์ž ์‹œ์ž‘)๋Š” ๊ฐ™๋‹ค. ๊ธฐ๋ณธ ํ™”๋ฉด์—์„œ ํ–‰ ๊ธ€์ž๊ฐ€ 24, ์„น์…˜ ์ œ๋ชฉ์ด 16์ด๋˜ ์‹ค์ธก์€ [ListRow ๊ทผ๊ฑฐ](list-row.md#๊ทผ๊ฑฐ)์— ์žˆ๋‹ค. ์ด์ „ plain ๋ชฉ๋ก์˜ `overflow: hidden`์€ grouped ๋ชจ์„œ๋ฆฌ๋งŒ์„ ์œ„ํ•œ ๊ฒƒ์ด๋ผ grouped๋กœ ์˜ฎ๊ฒผ๋‹ค.
@@ -95,4 +95,8 @@ import { NotificationItem } from "@hjmds/react-native/screens";
95
95
  | ์ƒํƒœยท์‹œ๊ฐ ์ค„ | ์„ค๋ช… ์•„๋ž˜ caption `Text` | `description`๊ณผ ์ค„๋ฐ”๊ฟˆ(`\n`)์œผ๋กœ ํ•ฉ์นœ ํ•œ ๋ฌธ์ž์—ด |
96
96
  | ์ด๋™ | `href`, `onClick` | `onPress` |
97
97
  | ์ถ”๊ฐ€ ์Šฌ๋กฏ | `className`, `layoutStyle` | `titleMetadata`, `trailingAction`, `trailingText`, `layoutStyle` |
98
- | ์ œ๋ชฉ ๊ตต๊ธฐ ์กฐ์ • | `Text emphasis` | ๋ Œ๋”๋Ÿฌ ๋น„๊ณต๊ฐœ ์ž…๋ ฅ(`hjmTitleEmphasis`)์œผ๋กœ ์•ˆ ์ฝ์Œ 700(`fontWeight.bold`)ยท์ฝ์Œ 400(`fontWeight.regular`). ์ œ๊ฑฐ๋œ `ListRow.titleStyle`์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. `NotificationItemProps`์—๋Š” `titleStyle`์ด ์—†๋‹ค(1.13.0 ๋ณ€๊ฒฝ) |
98
+ | ์ œ๋ชฉ ๊ตต๊ธฐ ์กฐ์ • | `Text emphasis` | ๋ Œ๋”๋Ÿฌ ๋น„๊ณต๊ฐœ ์ž…๋ ฅ(`hjmTitleEmphasis`)์œผ๋กœ ์•ˆ ์ฝ์Œ `strong` 500(์ œ๋ชฉ ๊ตต๊ธฐ)ยท์ฝ์Œ `regular` 400. ์ œ๊ฑฐ๋œ `ListRow.titleStyle`์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. `NotificationItemProps`์—๋Š” `titleStyle`์ด ์—†๋‹ค(1.13.0 ๋ณ€๊ฒฝ) |
99
+
100
+ ## ๊ทผ๊ฑฐ
101
+
102
+ 2026-10-17 ์‚ฌ์šฉ์ž ๊ฒฐ์ •("๊ตต๊ธฐ ์ข€๋” ์ค„์—ฌ"): ๋ชจ๋“  ๊ธ€์ž ๊ตต๊ธฐ๋ฅผ ํ•œ ๋‹จ๊ณ„ ๋‚ฎ์ท„๋‹ค. ํฐ ์ˆซ์žยท์„ ํƒ ์ƒํƒœ 600(ํฐ ์ œ๋ชฉ ๋‹จ๊ณ„๋Š” ๊ฐ™์€ ๋‚  ํ์ง€), ์ œ๋ชฉยท๊ฐ•์กฐ 500, label 500, ๋ณธ๋ฌธ 400์ด๋ฉฐ ์ •๋ณธ์€ [ํƒ€์ดํฌ๊ทธ๋ž˜ํ”ผ](../tokens/typography.md)๋‹ค.
@@ -95,7 +95,7 @@ import { PhotoSourceSheet } from "@hjmds/react-native/screen-flows";
95
95
  | --- | --- | --- |
96
96
  | ํฌ๊ธฐ | Sheet ๊ธฐ๋ณธ `placement="bottom"`ยท`size="auto"`(๋‚ด์šฉ ๋†’์ด, ํ™”๋ฉด ๋†’์ด 0.9 ์ƒํ•œ), Web ์ตœ๋Œ€ ํญ 640; ์„ ํƒ ๋ฒ„ํŠผ์€ `tone="secondary"` `Button` ๋‘ ๊ฐœ | `sheetRecipe`, `screen-flows.tsx` |
97
97
  | ๊ฐ„๊ฒฉ | ์‹œํŠธ ์•ˆ ์—ฌ๋ฐฑ์€ Sheet ์†Œ์œ (๋‘ ํ”Œ๋žซํผ ์ขŒ์šฐ `spacing.lg` 20 ยท ์œ„์•„๋ž˜ `spacing.sm` 12 + ํ•˜๋‹จ safe area); ๋‘ ๋ฒ„ํŠผ ์‚ฌ์ด `spacing.xs` 8(์„ธ๋กœ๋กœ ์Œ“์€ ๋ฒ„ํŠผ, `actionGroupRecipe.stackedGap`); ๋ฐ”๊นฅ์— padding์„ ๋”ํ•˜์ง€ ์•Š๋Š”๋‹ค | Web `.hjm-sheet__body`, Native `sheetRecipe.content`, `Stack gap="xs"` |
98
- | ์ˆœ์„œยท์ •๋ ฌ | Sheet ์ œ๋ชฉยท๋‹ซ๊ธฐ โ†’ ์•จ๋ฒ” โ†’ ์ดฌ์˜(`cameraAvailable`์ผ ๋•Œ๋งŒ) | Web `screen-flows.tsx` 59โ€“60ํ–‰, Native 50โ€“51ํ–‰ |
98
+ | ์ˆœ์„œยท์ •๋ ฌ | Sheet ์†์žก์ด โ†’ ์•จ๋ฒ” โ†’ ์ดฌ์˜(`cameraAvailable`์ผ ๋•Œ๋งŒ). `labels.title`์€ ๋ณด์ด์ง€ ์•Š๋Š” ์‹œํŠธ ์ด๋ฆ„(2026-10-17 ์‚ฌ์šฉ์ž ๊ฒฐ์ •: ์‹œํŠธ๋Š” ๋ณด์ด๋Š” ์ œ๋ชฉ ์—†์ด `title`์„ ์ ‘๊ทผ์„ฑ ์ด๋ฆ„์œผ๋กœ๋งŒ ์“ด๋‹ค) | Web `screen-flows.tsx` 59โ€“60ํ–‰, Native 50โ€“51ํ–‰ |
99
99
  | ๊ณ ์ •ยท์Šคํฌ๋กค | ํ™”๋ฉด ํ•˜๋‹จ์— ๋œจ๋Š” ์˜ค๋ฒ„๋ ˆ์ด(๋ฐฐ๊ฒฝ ๋ง‰) โ€” ์„ ํƒ ๋’ค picker ํ˜ธ์ถœ ์‹œ์ ์€ ํ”Œ๋žซํผ ์ฐจ์ด ์ฐธ๊ณ  | `Sheet` |
100
100
  | ์ข์€ ํญยทํฐ ๊ธ€์ž | ๋ฒ„ํŠผ ๋ฌธ๊ตฌ๋Š” ์ค„๋ฐ”๊ฟˆ๋˜๊ณ  Sheet ๋†’์ด๊ฐ€ ๋Š˜์–ด๋‚œ๋‹ค(0.9 ์ƒํ•œ์„ ๋„˜์œผ๋ฉด ๋ณธ๋ฌธ ์Šคํฌ๋กค); ์นด๋ฉ”๋ผ๊ฐ€ ์—†์œผ๋ฉด ๋ฒ„ํŠผ ํ•˜๋‚˜๋งŒ ๋‚จ๋Š”๋‹ค | `sheetRecipe.content.maxHeightRatio` |
101
101
 
@@ -85,6 +85,7 @@ import { ScreenLayout } from "@hjmds/react-native/screens";
85
85
  | `contentInset` | `"default"` ยท `"none"` ยท `"body-edge"` | `"default"` | `none`์€ ํ—ค๋”ยทnoticeยท๋ณธ๋ฌธยทfooter padding์„ 0์œผ๋กœ(Native๋Š” footer ์œ„ ํ…Œ๋‘๋ฆฌ๋„ ๋บ€๋‹ค). host๊ฐ€ ๋ชจ๋“  ์—ฌ๋ฐฑ์„ ์ด๋ฏธ ์ค„ ๋•Œ ์“ด๋‹ค. `body-edge`๋Š” ํ—ค๋”ยทnoticeยทfooter ์—ฌ๋ฐฑ(16)๊ณผ footer ํ…Œ๋‘๋ฆฌ๋ฅผ ์œ ์ง€ํ•˜๊ณ  **๋ณธ๋ฌธ ์ขŒ์šฐ padding๋งŒ 0**์œผ๋กœ ํ•œ๋‹ค. ์ž๊ธฐ ์ขŒ์šฐ ์—ฌ๋ฐฑ์„ ๊ฐ€์ง„ ์ „์ฒด ํญ ๋ชฉ๋ก ํ–‰(ConversationRowยทNotificationRow ๋“ฑ ํ–‰ padding 16)์„ ๋ณธ๋ฌธ์— ๋ฐ”๋กœ ๋‘˜ ๋•Œ ์“ด๋‹ค(๋ฏธ๊ฒŒ์‹œ). ListRowยทNotificationItem์€ `default`์— ๋‘”๋‹ค. ๊ฐ’ ๋ชฉ๋ก์€ ๊ณ„์•ฝ `ScreenContentInset`ยท`screenContentInsets` |
86
86
  | `presentation` | `"dashboard"` ยท `"editorial"` ยท `"landscape"` | ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด profile.screens.overview / ์—†์œผ๋ฉด ๊ธฐ์กด ๊ณจ๊ฒฉ | [๋””์ž์ธ ํ”„๋กœํ•„](../../design-profile.md)์˜ ์ œ๊ณต ๋ฒ”์œ„๋ฅผ ๋”ฐ๋ฅธ๋‹ค. ๋ช…์‹œ๊ฐ’์ด ํ”„๋กœํ•„์„ ์ด๊ธด๋‹ค. ํ—ค๋” ๋ฐฐ์น˜ยท์ฝ๊ธฐ ํญ๋งŒ ๋ฐ”๊พธ๊ณ  ์ƒํƒœยท์ž…๋ ฅยทํ–‰๋™ ์Šฌ๋กฏ์€ ์œ ์ง€ํ•œ๋‹ค |
87
87
  | `as` (Web) | `"main"` ยท `"section"` | `"main"` | ์ œํ’ˆ ์…ธ์— ์ด๋ฏธ `<main>`์ด ์žˆ์œผ๋ฉด `section` |
88
+ | `safeAreaBottom` (Native) | 0 ์ด์ƒ์˜ ์œ ํ•œ์ˆ˜ | `0`(๋ฏธ๊ฒŒ์‹œ) | ํ™”๋ฉด์ด ๋‹ฟ๋Š” ์ฐฝ ์•„๋ž˜ ๊ฐ€์žฅ์ž๋ฆฌ์˜ safe area(`useSafeAreaInsets().bottom`, ํƒญ๋ฐ” ์œ„ยท์ด๋ฏธ ์•„๋ž˜๋ฅผ ๋“ค์ธ host ์•ˆ์ด๋ฉด 0). ๋งˆ์ง€๋ง‰ ์˜์—ญ(footer, ์—†์œผ๋ฉด ๋ณธ๋ฌธ)์ด ์•„๋ž˜ ์—ฌ๋ฐฑ์„ `max(16, inset)`์œผ๋กœ ํ•œ ๋ฒˆ๋งŒ ์ค€๋‹ค. ๋„˜๊ธธ ๋•Œ๋Š” host์˜ ์•„๋ž˜ SafeAreaView edge๋ฅผ ๋นผ๊ณ , ๋‘˜์„ ๊ฐ™์ด ์“ฐ์ง€ ์•Š๋Š”๋‹ค. ์Œ์ˆ˜ยท๋ฌดํ•œ๋Œ€๋Š” `RangeError` |
88
89
  | `layoutStyle` | `HjmCompositionStyleProp` | ์—†์Œ | ํ™”๋ฉด ๋ฃจํŠธ ๋ฐฐ์น˜ ์ „์šฉ(์˜ˆ: ๋ถ„ํ•  ํ™”๋ฉด์˜ `flex`ยท`width`). ScreenLayout ์œ„์— ๋งŒ๋“  ํ™”๋ฉด์€ ๋ชจ๋‘ ์ด prop์„ ๋ฃจํŠธ๊นŒ์ง€ ๋„˜๊ธด๋‹ค |
89
90
  | `className` (Web) | `string` | ์—†์Œ | ์‹๋ณ„ยท๋ฐฐ์น˜ ๋ณด์กฐ. ์ƒ‰ยท์—ฌ๋ฐฑ์„ ๋ฎ์ง€ ์•Š๋Š”๋‹ค |
90
91
  | `testID` ยท `scrollRef` ยท `scrollProps` (Native) | `string` ยท `Ref<ScrollView>` ยท `refreshControl`ยท`keyboardDismissMode`ยท์Šคํฌ๋กค ๋ง‰๋Œ€ ํ‘œ์‹œยท`onScroll`ยท`onScrollBeginDrag`ยท`onScrollEndDrag`ยท`scrollEventThrottle`ยท`alwaysBounceVertical`ยท`automaticallyAdjustKeyboardInsets` | ์—†์Œ | ScrollView๊ฐ€ ์žˆ์„ ๋•Œ(`scroll="screen"` ๋˜๋Š” ์ƒํƒœ ๊ต์ฒด ์ค‘)๋งŒ `scrollRef`ยท`scrollProps`๊ฐ€ ์—ฐ๊ฒฐ๋œ๋‹ค |
@@ -97,8 +98,8 @@ import { ScreenLayout } from "@hjmds/react-native/screens";
97
98
  | ๊ฐ„๊ฒฉ | ๋ฐ”๊นฅ padding `screenPatternRecipe.padding`(`spacing.md` 16)์„ ํ—ค๋” ์‚ฌ๋ฐฉยทnotice ์ขŒ์šฐยท๋ณธ๋ฌธ ์‚ฌ๋ฐฉยทfooter ์‚ฌ๋ฐฉ์— ์ค€๋‹ค(`contentInset="none"`์ด๋ฉด 0, `"body-edge"`๋ฉด ๋ณธ๋ฌธ ์ขŒ์šฐ๋งŒ 0); ํ—ค๋” ์•ˆ `exit`ยท์ œ๋ชฉยท`actions` ๊ฐ„๊ฒฉ `itemGap`(`spacing.sm`) 12(๋‘ ํ”Œ๋žซํผ, `contentInset="none"`์ด์–ด๋„ ์œ ์ง€); ์ƒํƒœ ์•ˆ๋‚ด๋Š” ์œ„์•„๋ž˜ `sectionGap`(`spacing.xl`) 24, ์•ˆ๋‚ดโ€“`stateAction` `stateGap`(`spacing.md`) 16 | Web `src/screens.tsx`(`--hjm-screen-item-gap`ยท`--hjm-screen-state-gap`)ยท`.hjm-screen__*`, Native `ScreenLayout` |
98
99
  | ์ œ๋ชฉ | ๊ธฐ๋ณธ ๊ฐ€์šด๋ฐ `Heading` `screenHeaderRecipe.centeredTitleLevel`(level5), `headerAlignment="start"`๋ฉด `titleLevel`(level3). ์ถ”๊ฐ€ ๊ธฐ๋Šฅ ๋ฒ„ํŠผ(`actions`)์€ ๋(์˜ค๋ฅธ์ชฝ) ์œ„, ๋‚˜๊ฐ€๊ธฐ(`exit`)๋Š” ์‹œ์ž‘(์™ผ์ชฝ) ์œ„. ํ—ค๋” ๋†’์ด๋Š” ๋‘ ํ”Œ๋žซํผ ๋ชจ๋‘ `screenHeaderRecipe`์˜ ๊ณ ์ • ๋  | `screenHeaderRecipe` |
99
100
  | ์ˆœ์„œยท์ •๋ ฌ | ํ—ค๋”(`exit` โ†’ ์ œ๋ชฉยท์„ค๋ช… โ†’ `actions`) โ†’ notice โ†’ ๋ณธ๋ฌธ โ†’ footer; ์ƒํƒœ ์•ˆ๋‚ด๋Š” ๋ณธ๋ฌธ ์„ธ๋กœ ๊ฐ€์šด๋ฐ `exit`๋Š” HJM์ด `edge="start"`๋กœ ๊ทธ๋ ค ์•„์ด์ฝ˜ ์นธ์ด ํ—ค๋” ์—ฌ๋ฐฑ ์„  16์— ์˜จ๋‹ค(WebยทNative 31 โ†’ 16, ๊ฐ€์šด๋ฐ ํ—ค๋”์˜ ๊ฐ™์€ ํญ ์–‘์ชฝ ์—ดยท์ œ๋ชฉ ์ค‘์•™์€ ๊ทธ๋Œ€๋กœ). ๋ `actions`์˜ ๋งˆ์ง€๋ง‰ ghost IconButton์€ ์ œํ’ˆ์ด `edge="end"`๋ฅผ ์ค€๋‹ค(2026-10-17 ์‹ค์ธก ๊ฐ์‚ฌ, [IconButton `edge`](icon-button.md#๋ฐฐ์น˜)) | ๋ Œ๋” ์ˆœ์„œ |
100
- | ๊ณ ์ •ยท์Šคํฌ๋กค | ํ—ค๋”ยทnoticeยทfooter ๊ณ ์ •, `scroll="screen"`์€ ๋ณธ๋ฌธ์ด ์Šคํฌ๋กค, `"content"`๋Š” ์ž์‹์ด ์Šคํฌ๋กค; footer ์œ„ ํ…Œ๋‘๋ฆฌ 1, Web์€ ํ•˜๋‹จ safe area๋งŒํผ padding์„ ๋Š˜๋ฆฐ๋‹ค | Web `data-scroll`ยท`.hjm-screen__footer`, Native `ScrollView` |
101
- | ์ข์€ ํญยทํฐ ๊ธ€์ž | ์ œ๋ชฉ ์—ด ์ตœ์†Œ ํญ `headerMinWidth` 120 ร— ๊ธ€์ž ๋ฐฐ์œจ, ๋ชจ์ž๋ผ๋ฉด `actions`๊ฐ€ ๋‹ค์Œ ์ค„๋กœ ๋‚ด๋ ค๊ฐ„๋‹ค; ์ œ๋ชฉ์€ ์ค„๋ฐ”๊ฟˆ(`overflow-wrap: anywhere`)๋˜๊ณ  ์ž๋ฅด์ง€ ์•Š๋Š”๋‹ค; Native safe areaยทํƒญ๋ฐ” inset์€ host | `screenPatternRecipe.headerMinWidth`, Web `.hjm-screen__heading` |
101
+ | ๊ณ ์ •ยท์Šคํฌ๋กค | ํ—ค๋”ยทnoticeยทfooter ๊ณ ์ •, `scroll="screen"`์€ ๋ณธ๋ฌธ์ด ์Šคํฌ๋กค, `"content"`๋Š” ์ž์‹์ด ์Šคํฌ๋กค; footer ์œ„ ํ…Œ๋‘๋ฆฌ 1. ๋งˆ์ง€๋ง‰ ์˜์—ญ(footer, ์—†์œผ๋ฉด ๋ณธ๋ฌธ)์˜ ์•„๋ž˜ ์—ฌ๋ฐฑ์€ `max(16, ํ•˜๋‹จ inset)`์ด๋‹ค โ€” Web์€ `env(safe-area-inset-bottom)`, Native๋Š” `safeAreaBottom`. 16 + inset์œผ๋กœ ๋”ํ•˜์ง€ ์•Š์œผ๋ฉฐ, ํ‚ค๋ณด๋“œ๊ฐ€ ์—ด๋ ค ์žˆ์œผ๋ฉด ํ‚ค๋ณด๋“œ๊ฐ€ ํ™ˆ ์ธ๋””์ผ€์ดํ„ฐ๋ฅผ ๋ฎ์œผ๋ฏ€๋กœ 16๋งŒ ๋‘”๋‹ค | Web `data-scroll`ยท`.hjm-screen__footer`, Native `ScrollView` |
102
+ | ์ข์€ ํญยทํฐ ๊ธ€์ž | ์ œ๋ชฉ ์—ด ์ตœ์†Œ ํญ `headerMinWidth` 120 ร— ๊ธ€์ž ๋ฐฐ์œจ, ๋ชจ์ž๋ผ๋ฉด `actions`๊ฐ€ ๋‹ค์Œ ์ค„๋กœ ๋‚ด๋ ค๊ฐ„๋‹ค; ์ œ๋ชฉ์€ ์ค„๋ฐ”๊ฟˆ(`overflow-wrap: anywhere`)๋˜๊ณ  ์ž๋ฅด์ง€ ์•Š๋Š”๋‹ค; Native ์œ„ยท์˜† safe areaยทํƒญ๋ฐ” inset์€ host, ์•„๋ž˜ inset์€ `safeAreaBottom` | `screenPatternRecipe.headerMinWidth`, Web `.hjm-screen__heading` |
102
103
 
103
104
  ## ๊ผญ ์ง€ํ‚ฌ ๊ฒƒ
104
105
 
@@ -109,11 +110,12 @@ import { ScreenLayout } from "@hjmds/react-native/screens";
109
110
 
110
111
  - Web์˜ ํ™”๋ฉด ์Šคํฌ๋กค ๋ณธ๋ฌธ์€ Tab์œผ๋กœ ์ง„์ž…ํ•  ์ˆ˜ ์žˆ๋‹ค. `scroll="content"`์˜ ์ •์ƒ ๋ณธ๋ฌธ์€ ์ž์‹์ด ํ‚ค๋ณด๋“œ ์Šคํฌ๋กค์„ ์†Œ์œ ํ•˜์ง€๋งŒ, ์˜ค๋ฅ˜ยท๋นˆ ์ƒํƒœ ๋“ฑ ๋Œ€์ฒด ์•ˆ๋‚ด๋Š” ํ™”๋ฉด ์Šคํฌ๋กค๋กœ ๋ฐ”๋€Œ๋ฉฐ Tab ์ง„์ž…๋„ ํ•จ๊ป˜ ๋ณต์›๋œ๋‹ค.
111
112
  - Web์—์„œ ๋ณธ๋ฌธ์— ์ดˆ์ ์„ ๊ฐ€์ง„ ์ž…๋ ฅยท์žฌ์‹œ๋„ ๋ฒ„ํŠผ์ด ์ƒํƒœ ์ „ํ™˜์œผ๋กœ ์ œ๊ฑฐ๋˜๋ฉด ๊ฐ™์€ ๋ณธ๋ฌธ์œผ๋กœ ์ดˆ์ ์„ ๋ณต๊ตฌํ•œ๋‹ค. `scroll="content"`์˜ ๋ณธ๋ฌธ์€ ์ด ๋ณต๊ตฌ๋งŒ์„ ์œ„ํ•œ `tabIndex=-1`์„ ๊ฐ€์ง€๋ฉฐ ์ผ๋ฐ˜ Tab ์ˆœ์„œ์—๋Š” ์ถ”๊ฐ€๋˜์ง€ ์•Š๋Š”๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ๋‹ค๋ฅธ ์ปจํŠธ๋กค์ด๋‚˜ ๋ฐ”๊นฅ ์˜์—ญ์œผ๋กœ ์ดˆ์ ์„ ์˜ฎ๊ธด ๊ฒฝ์šฐ์—๋Š” ์ด๋™์‹œํ‚ค์ง€ ์•Š๋Š”๋‹ค. 2026-10-13 ์žฌ์‹œ๋„ยท๊ถŒํ•œ ์ œํ•œ ์ „ํ™˜์—์„œ ์ดˆ์ ์ด body๋กœ ์œ ์‹ค๋œ ๊ฒฝ๋กœ๋ฅผ ์ˆ˜์ •ํ–ˆ๋‹ค.
113
+ - **ํ™”๋ฉด ์—ฌ๋ฐฑ์€ ScreenLayout์ด ์†Œ์œ ํ•œ๋‹ค(๊ธฐ๋ณธ `contentInset`).** ํ™”๋ฉด์„ ๋ฐ”๊นฅ `Container gutter`๋กœ ๊ฐ์‹ธ๊ณ  `contentInset="none"`์„ ์ฃผ๋Š” ๊ตฌ์„ฑ์€ ์ง€์›ํ•˜์ง€ ์•Š๋Š”๋‹ค. ํ–‰์˜ ํ‘œ๋ฉด bleed, footerยทBottomCTA ๋ฐ”, ๋ ์ปจํŠธ๋กค์˜ `edge`๋Š” ๋ชจ๋‘ ScreenLayout์ด ์—ฌ๋ฐฑ์„ ๊ฐ€์ง„๋‹ค๋Š” ์ „์ œ๋กœ ๋งž์ถฐ์ ธ ์žˆ์–ด, ๊ทธ ๊ตฌ์„ฑ์—์„œ๋Š” ํ–‰ ํ‘œ๋ฉด์ด ๋ณธ๋ฌธ ๋์—์„œ ์ž˜๋ฆฌ๊ณ  footer๊ฐ€ ์—ฌ๋ฐฑ ์•ˆ์— ๋–  ์žˆ๋Š” ์ƒ์ž๊ฐ€ ๋œ๋‹ค. `none`์€ host๊ฐ€ ๋ชจ๋“  inset์„ ์†Œ์œ ํ•˜๋Š” ๊ธฐ์กด ์˜๋ฏธ ๊ทธ๋Œ€๋กœ๋‹ค(์ƒˆ ๋™์ž‘ ์—†์Œ).
112
114
  - ๊ฐ€์ƒํ™” ๋ชฉ๋ก(FlatList, VirtualList)์„ ๋„ฃ์œผ๋ฉด `scroll="content"`๋กœ ๋‘”๋‹ค. ์Šคํฌ๋กค์„ ์ด์ค‘์œผ๋กœ ์ค‘์ฒฉํ•˜์ง€ ์•Š๋Š”๋‹ค.
113
115
  - ์ƒˆ๋กœ๊ณ ์นจ ์‹คํŒจยท์ €์žฅ ์˜ค๋ฅ˜๋Š” `state`๋ฅผ ๋ฐ”๊พธ์ง€ ๋ง๊ณ  `ready` + `notice`๋กœ ์•Œ๋ฆฐ๋‹ค. `loading`์œผ๋กœ ๋ฐ”๊พธ๋ฉด ๋ณธ๋ฌธ์ด
114
116
  unmount๋˜์–ด ์ž…๋ ฅ ์ดˆ์•ˆ์ด ์‚ฌ๋ผ์ง„๋‹ค.
115
117
  - `state.title`ยท๋ฌธ๊ตฌ๋Š” i18n ํ‚ค๋กœ ๋„ฃ๋Š”๋‹ค. ready ์™ธ ์ƒํƒœ์˜ ๋นˆ `title`์€ `TypeError`๋‹ค.
116
- - Web host๋Š” ์‹ค์ œ ๋‚จ์€ ๋†’์ด(`height:100%` ๋“ฑ)๋ฅผ, Native host๋Š” safe areaยทํƒญ๋ฐ” inset์„ ๋จผ์ € ์ฒ˜๋ฆฌํ•œ๋‹ค.
118
+ - Web host๋Š” ์‹ค์ œ ๋‚จ์€ ๋†’์ด(`height:100%` ๋“ฑ)๋ฅผ, Native host๋Š” ์œ„ยท์˜† safe area์™€ ํƒญ๋ฐ” inset์„ ๋จผ์ € ์ฒ˜๋ฆฌํ•œ๋‹ค. ์•„๋ž˜ ํ™ˆ ์ธ๋””์ผ€์ดํ„ฐ๋Š” host๊ฐ€ SafeAreaView๋กœ ๋“ค์ด์ง€ ๋ง๊ณ  `safeAreaBottom`์œผ๋กœ ๋„˜๊ธด๋‹ค(๋“ค์ธ ๋’ค footer 16์„ ๋”ํ•˜๋ฉด ๋ฒ„ํŠผ ์•„๋ž˜๊ฐ€ 50์ด ๋œ๋‹ค).
117
119
  HJM์€ ๊ธฐ์ข…๋ณ„ ๋†’์ด๋ฅผ ์ถ”์ธกํ•˜์ง€ ์•Š๋Š”๋‹ค.
118
120
  - ๋ฐฐ์น˜๋Š” WebยทNative ๋ชจ๋‘ `layoutStyle`๋กœ ํ•œ๋‹ค(Web์€ `className`๋„ ์žˆ๋‹ค). ์ƒ‰ยท์—ฌ๋ฐฑ์„ ๋ฎ์ง€ ์•Š๋Š”๋‹ค.
119
121
 
@@ -141,4 +143,6 @@ dashboard๋Š” ๊ฐ€๋กœ ํ—ค๋”/1200 ๋ชฉ๋ก ํญ, editorial์€ ์„ธ๋กœ ํ—ค๋”/720 ์ฝ
141
143
 
142
144
  ## ๊ทผ๊ฑฐ
143
145
 
146
+ - ํ•˜๋‹จ ์—ฌ๋ฐฑ `max(16, inset)`(Native `safeAreaBottom`): 2026-10-17 ์‚ฌ์šฉ์ž ๋ณด๊ณ  "์ „์ฒด์ ์œผ๋กœ ๋ฒ„ํŠผ ์•„๋ž˜ ์—ฌ๋ฐฑ์ด ๋งŽ์•„". Native Storybook์˜ ์‚ฌ์ง„ ์„ ํƒ๊ณผ ์—…๋กœ๋“œ ํ™”๋ฉด์—์„œ ๋ฒ„ํŠผ ์•„๋ž˜๊ฐ€ ์•ฝ 33pt์˜€๋‹ค. ์›์ธ์€ ๋‘˜์ด์—ˆ๋‹ค. ํ™”๋ฉด ์Šคํ† ๋ฆฌ์˜ route host๊ฐ€ ๊ณ ์ • ๋†’์ด 720์ด๋ผ iPhone 17 Pro ์Šคํ† ๋ฆฌ ์˜์—ญ 737๋ณด๋‹ค 17 ์งง์•˜๊ณ (footer 16 + ๋นˆ ์นธ 17), ์ปดํฌ๋„ŒํŠธ๋Š” Native footer๊ฐ€ safe area๋ฅผ ๋‹ค๋ฃจ์ง€ ์•Š์•„ host์˜ ์•„๋ž˜ inset ์œ„์— 16์„, footer ์•ˆ BottomCTA์˜ `safeAreaBottom`๋„ 16 ์œ„์— ๋”ํ–ˆ๋‹ค(16 + 34 = 50). Web footer๋Š” ์ด๋ฏธ `max(16, env())`์˜€์ง€๋งŒ footer ์•ˆ BottomCTA์˜ `safeAreaBottom`์€ ๊ทธ ์œ„์— ๋”ํ–ˆ๋‹ค. ํ‘œ์ค€์„ "๋งˆ์ง€๋ง‰ ์ปจํŠธ๋กค ์•„๋ž˜ = footer ์œ„ ์—ฌ๋ฐฑ 16, ํ™ˆ ์ธ๋””์ผ€์ดํ„ฐ ๊ธฐ๊ธฐ์—์„œ๋Š” max(16, inset)"์œผ๋กœ ์ •ํ•˜๊ณ  footer๊ฐ€ ํ•œ ๋ฒˆ๋งŒ ์†Œ์œ ํ•˜๊ฒŒ ํ–ˆ๋‹ค.
147
+ - ํ™”๋ฉด ์—ฌ๋ฐฑ์€ ScreenLayout ์†Œ์œ , ๋ฐ”๊นฅ ์—ฌ๋ฐฑ + `none` ๋ฏธ์ง€์›: 2026-10-17 ๋ฐ”๊นฅ ์—ฌ๋ฐฑ ํ˜ธ์ŠคํŠธ ์˜ˆ์ œ ์‚ฌ์šฉ์ž ๊ฒ€ํ† . utilverse์‹(`Container gutter="regular"` 20 + `contentInset="none"`)์„ HJM์—์„œ ์ง€์›ํ•˜๋ ค๊ณ  ๋ณธ๋ฌธ ํ™•์žฅยทfooter ๋ฐ” ์†Œ์œ ๋ฅผ ๋ถ™์ธ ์˜ˆ์ œ๊ฐ€ ์–ด์ƒ‰ํ•˜๋‹ค๋Š” ํŒ๋‹จ์œผ๋กœ ์ง€์›์„ ์ ‘์—ˆ๋‹ค(2026-10-15 ๊ณตํ†ต ๊ตฌ์กฐ๋Š” HJM ์†Œ์œ  ์›์น™). ์ธก์ •์ƒ ๊ทธ ๊ตฌ์„ฑ์—์„œ๋Š” Web 402ยท1280์—์„œ ํ–‰ ํ‘œ๋ฉด์ด ์–‘์ชฝ 8 ์ž˜๋ฆฌ๊ณ  ๋ณธ๋ฌธ์ด ์˜†์œผ๋กœ 8 ์Šคํฌ๋กค๋˜๋ฉฐ, Native 3x์—์„œ ์„ ํƒ ํ…Œ๋‘๋ฆฌ ์˜† ์„ ์ด ๊ทธ๋ ค์ง€์ง€ ์•Š์•˜๋‹ค. ์ œํ’ˆ์€ ๋ฐ”๊นฅ ์—ฌ๋ฐฑ์„ ๊ฑท๊ณ  ๊ธฐ๋ณธ inset์„ ์“ด๋‹ค.
144
148
  - `contentInset="body-edge"`: 2026-10-17 ์‚ฌ์šฉ์ž ๊ฒฐ์ •. ํ™”๋ฉด ๊ฒ€ํ†  S5#9์—์„œ ๋Œ€ํ™” ๋ชฉ๋ก ์•„๋ฐ”ํƒ€๊ฐ€ ํ™”๋ฉด ๋์—์„œ ์•ฝ 32pt ์•ˆ์ชฝ์—์„œ ์‹œ์ž‘ํ–ˆ๋‹ค. ๋ณธ๋ฌธ padding 16๊ณผ ConversationRow ์ž์ฒด padding 16์ด ๊ฒน์ณค๋‹ค(์ธ์Šคํƒ€๊ทธ๋žจ DM์€ ์•ฝ 16). ์•ฑ ์•ฝ 45๊ณณ์ด "host๊ฐ€ ๋ชจ๋“  ์—ฌ๋ฐฑ์„ ์†Œ์œ ํ•œ๋‹ค"๋Š” ๋œป์œผ๋กœ `none`์„ ์“ฐ๊ณ  ์žˆ์–ด `none`์˜ ์˜๋ฏธ๋ฅผ ๋ฐ”๊ฟ€ ์ˆ˜ ์—†์—ˆ์œผ๋ฏ€๋กœ ๊ฐ’์„ ์ƒˆ๋กœ ์ถ”๊ฐ€ํ–ˆ๋‹ค. ChatScreen์˜ 10 ํƒ€์ž„๋ผ์ธ ์—ฌ๋ฐฑ์€ `default`์ผ ๋•Œ๋งŒ ๊ณตํ†ต ์—ฌ๋ฐฑ์„ ๋Œ€์‹ ํ•œ๋‹ค.
@@ -157,7 +157,7 @@ import { SearchScreen } from "@hjmds/react-native/screen-flows";
157
157
  | `resultSummary.countVisibility` | `visible` ยท `hidden` | `visible` | `hidden`์€ ์‹œ๊ฐ์  ๊ฐœ์ˆ˜ยท๊ฐœ์ˆ˜ Skeleton๋งŒ ์ˆจ๊ธฐ๋ฉฐ ์ •๋ ฌยท๋กœ๋”ฉ ํ–‰ยท๋นˆ ์ƒํƒœยท์ ‘๊ทผ์„ฑ ๊ฐœ์ˆ˜ ์•Œ๋ฆผ์€ ์œ ์ง€ํ•œ๋‹ค. 2026-10-14 ์•ผ์ž˜์•Œ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ์—์„œ ๊ฐœ์ˆ˜ ์—†๋Š” ๋ชฉ๋ก์„ ์š”์ฒญํ•ด ์ถ”๊ฐ€ํ•œ ์„ ํƒํ˜• ์ถ•(๋ฏธ๊ฒŒ์‹œ)์ด๋‹ค |
158
158
  | `resultSummary.sort` | `{ label, triggerLabel, value, options: { id, label }[], onChange(id), icon? }` (Native๋Š” `dismissLabel` ์ถ”๊ฐ€) | ์—†์Œ | ๊ฒฐ๊ณผ ๋จธ๋ฆฌ ๋ Menu(single). ๋ฐ”๊พธ๋ฉด ๋ณธ๋ฌธ์„ ๋งจ ์œ„๋กœ |
159
159
  | `appliedFilters` | `{ items: { key, label }[], removeLabel(label), onRemove(key), clearAllLabel, onClearAll(), removeIcon? }` | ์—†์Œ | ๊ฒฐ๊ณผ ๋จธ๋ฆฌ ์•„๋ž˜ ร— ์นฉ + `๋ชจ๋‘ ํ•ด์ œ`. ๊ฐœ์ˆ˜๋Š” trigger ์ด๋ฆ„๊ณผ 0๊ฑด ์›์ธ ํŒ์ •์—๋„ ์“ด๋‹ค |
160
- | `filterSheet` | `{ open, onOpenChange(open), title, value, onApply(next), count(draft): number \| null, reset(draft), isDefault(draft), renderContent(draft, setDraft), labels: { close, reset, apply(count) }, size?, trigger? }` | ์—†์Œ | ์—ด ๋•Œ `value`๋ฅผ ์ดˆ์•ˆ์œผ๋กœ ๋ณต์‚ฌ, ๋‹ซํžˆ๋ฉด ์ดˆ์•ˆ์„ ๋ฒ„๋ฆผ, ์ฃผ ํ–‰๋™์—์„œ๋งŒ `onApply`. `count = 0`์ด๋ฉด ์ฃผ ํ–‰๋™ ๋น„ํ™œ์„ฑ, `isDefault`๋ฉด ์ดˆ๊ธฐํ™” ๋น„ํ™œ์„ฑ. `trigger`๋ฅผ ์ฃผ๋ฉด ์นฉ ์ค„ ๋งจ ์•ž์— `label(์ ์šฉ ๊ฐœ์ˆ˜)` Chip |
160
+ | `filterSheet` | `{ open, onOpenChange(open), title, value, onApply(next), count(draft): number \| null, reset(draft), isDefault(draft), renderContent(draft, setDraft), labels: { close, reset, apply(count) }, size?, trigger? }` | ์—†์Œ | ์—ด ๋•Œ `value`๋ฅผ ์ดˆ์•ˆ์œผ๋กœ ๋ณต์‚ฌ, ๋‹ซํžˆ๋ฉด ์ดˆ์•ˆ์„ ๋ฒ„๋ฆผ, ์ฃผ ํ–‰๋™์—์„œ๋งŒ `onApply`. `count = 0`์ด๋ฉด ์ฃผ ํ–‰๋™ ๋น„ํ™œ์„ฑ, `isDefault`๋ฉด ์ดˆ๊ธฐํ™” ๋น„ํ™œ์„ฑ. `trigger`๋ฅผ ์ฃผ๋ฉด ์นฉ ์ค„ ๋งจ ์•ž์— `label(์ ์šฉ ๊ฐœ์ˆ˜)` Chip. `title`์€ ํ•„ํ„ฐ ์‹œํŠธ์˜ ๋ณด์ด์ง€ ์•Š๋Š” ์ ‘๊ทผ์„ฑ ์ด๋ฆ„์ด๋‹ค(2026-10-17 ์‚ฌ์šฉ์ž ๊ฒฐ์ •: ์‹œํŠธ ์ œ๋ชฉ ์ค„ ์—†์Œ). ๊ฐ€๋ฆผ๋ง‰์„ ๋ˆ„๋ฅด๋ฉด ๋‹ซํžˆ๊ณ  ์ดˆ์•ˆ์„ ๋ฒ„๋ฆฐ๋‹ค |
161
161
  | `filtersOverflow` | `wrap` ยท `scroll` | `wrap` | `scroll`์ด๋ฉด `filters`๋ฅผ ํ•œ ์ค„ ๊ฐ€๋กœ ์Šคํฌ๋กค ์˜์—ญ์— ๋„ฃ๊ณ  ํ™”๋ฉด ์ขŒ์šฐ ์—ฌ๋ฐฑ(`spacing.md` 16, `contentInset="none"`์ด๋ฉด 0)์— `hostGutter`๋ฅผ ๋”ํ•œ ๋งŒํผ ๊ฐ€์žฅ์ž๋ฆฌ๊นŒ์ง€ ๋„“ํžŒ๋‹ค. ์ฒซ ์นฉ์€ ๊ฒ€์ƒ‰ ์ž…๋ ฅ๊ณผ ๊ฐ™์€ ์‹œ์ž‘์„ ์— ๋†“์ธ๋‹ค |
162
162
  | `hostGutter` | `none` ยท `compact` ยท `regular` ยท `spacious` | `none` | 1.13.1 ๋ณ€๊ฒฝ. ์ด ํ™”๋ฉด์„ ๊ฐ์‹ผ host๊ฐ€ ์ด๋ฏธ ์ค€ ์ขŒ์šฐ ์—ฌ๋ฐฑ ์ด๋ฆ„(`containerRecipe.gutters`: 0 ยท `spacing.md` 16 ยท `spacing.lg` 20 ยท `spacing.xl` 24). Container ์•ˆ์ด๋ฉด ๊ทธ `gutter`, Sheet ๋ณธ๋ฌธ ์•ˆ์ด๋ฉด `regular`(`sheetRecipe.content.paddingHorizontal`๊ณผ ๊ฐ™์€ `spacing.lg`). `scroll` ์ค„๋งŒ ์ด ๊ฐ’์„ ์“ด๋‹ค |
163
163
  | `recentSearches` | `ReactNode` | ์—†์Œ | `query`๊ฐ€ ๊ณต๋ฐฑ์ผ ๋•Œ๋งŒ ๋ณธ๋ฌธ ๋งจ ์œ„์— ๋ณด์ธ๋‹ค |
@@ -78,7 +78,7 @@ import { Section } from "@hjmds/react-native/primitives";
78
78
  | ํ•ญ๋ชฉ | ๊ฐ’ | ๊ทผ๊ฑฐ |
79
79
  | --- | --- | --- |
80
80
  | ํฌ๊ธฐ | ์ž์ฒด ๋ฐฐ๊ฒฝยทํ…Œ๋‘๋ฆฌยท์—ฌ๋ฐฑ์ด ์—†๋‹ค. ํญ์€ ๋ถ€๋ชจ๋ฅผ ๋”ฐ๋ฅธ๋‹ค | `.hjm-section` |
81
- | ๊ธ€์ž | ์ œ๋ชฉ `title` 18/26 bold, ์„ค๋ช… `caption` 11/16(๋‘ ํ”Œ๋žซํผ). 2026-10-06๊นŒ์ง€ Web์€ ๋‘˜ ๋‹ค ๋ณธ๋ฌธ 14๋ฅผ ๋ฌผ๋ ค๋ฐ›์•˜๋‹ค(1.13.0 ๋ณ€๊ฒฝ) | `sectionRecipe.title`ยท`description`, `.hjm-section__title`ยท`__description` |
81
+ | ๊ธ€์ž | ์ œ๋ชฉ `title` 18/26 500(์ œ๋ชฉ ๊ตต๊ธฐ), ์„ค๋ช… `caption` 11/16(๋‘ ํ”Œ๋žซํผ). 2026-10-06๊นŒ์ง€ Web์€ ๋‘˜ ๋‹ค ๋ณธ๋ฌธ 14๋ฅผ ๋ฌผ๋ ค๋ฐ›์•˜๋‹ค(1.13.0 ๋ณ€๊ฒฝ) | `sectionRecipe.title`ยท`description`, `.hjm-section__title`ยท`__description` |
82
82
  | ๊ฐ„๊ฒฉ | ๋จธ๋ฆฌ์™€ ๋ณธ๋ฌธ ์‚ฌ์ด `spacing.xs` 8, ๊ธ€์ž ๋ฌถ์Œ๊ณผ ํ–‰๋™ ์‚ฌ์ด `spacing.sm` 12, ์ œ๋ชฉ๊ณผ ์„ค๋ช… ์‚ฌ์ด `spacing.xxs` 4. Section๋ผ๋ฆฌ์˜ ๊ฐ„๊ฒฉ์€ Section์ด ์ฃผ์ง€ ์•Š๋Š”๋‹ค. ๊ฐ์‹ธ๋Š” [Stack](stack.md)์ด๋‚˜ `layoutStyle`๋กœ `layout.sectionGap`(`spacing.xl` 24)์„ ๋‘”๋‹ค | `sectionRecipe.gap`ยท`headerGap`ยท`copyGap`, `layout.sectionGap` |
83
83
  | ์ˆœ์„œยท์ •๋ ฌ | ๋จธ๋ฆฌ ํ–‰๋™์€ ๋(LTR ์˜ค๋ฅธ์ชฝ)์— ํ•˜๋‚˜, ๊ธ€์ž ๋ฌถ์Œ๊ณผ ์„ธ๋กœ ๊ฐ€์šด๋ฐ ์ •๋ ฌ. ๋ณดํ†ต [Link](link.md) ๋˜๋Š” `tone="link"` [Button](button.md) | `.hjm-section__header`, Native `Section` |
84
84
  | ๊ณ ์ •ยท์Šคํฌ๋กค | ๊ณ ์ •๋˜์ง€ ์•Š๋Š”๋‹ค. ํ™”๋ฉด ๋ณธ๋ฌธ ์Šคํฌ๋กค ์•ˆ์— ๋‘”๋‹ค | โ€” |
@@ -109,3 +109,7 @@ import { Section } from "@hjmds/react-native/primitives";
109
109
  | heading ์ˆ˜์ค€ | `headingLevel` | ์—†์Œ(header role ๊ณ ์ •) |
110
110
  | ๋ฃจํŠธ | `<section>` | `View` |
111
111
  | ๋ฐฐ์น˜ | `className`, `layoutStyle`(HTML `style`๋„ ๋ฐ›์Œ) | `layoutStyle`, slot `*Style`(`style`์€ ์ œ๊ฑฐ๋œ ์†์„ฑ) |
112
+
113
+ ## ๊ทผ๊ฑฐ
114
+
115
+ 2026-10-17 ์‚ฌ์šฉ์ž ๊ฒฐ์ •("๊ตต๊ธฐ ์ข€๋” ์ค„์—ฌ"): ๋ชจ๋“  ๊ธ€์ž ๊ตต๊ธฐ๋ฅผ ํ•œ ๋‹จ๊ณ„ ๋‚ฎ์ท„๋‹ค. ํฐ ์ˆซ์žยท์„ ํƒ ์ƒํƒœ 600(ํฐ ์ œ๋ชฉ ๋‹จ๊ณ„๋Š” ๊ฐ™์€ ๋‚  ํ์ง€), ์ œ๋ชฉยท๊ฐ•์กฐ 500, label 500, ๋ณธ๋ฌธ 400์ด๋ฉฐ ์ •๋ณธ์€ [ํƒ€์ดํฌ๊ทธ๋ž˜ํ”ผ](../tokens/typography.md)๋‹ค.
@@ -80,7 +80,7 @@ import { SegmentedControl } from "@hjmds/react-native/inputs";
80
80
 
81
81
  | ํ•ญ๋ชฉ | ๊ฐ’ | ๊ทผ๊ฑฐ |
82
82
  | --- | --- | --- |
83
- | ํฌ๊ธฐ | ํ•ญ๋ชฉ ์ตœ์†Œ ๋†’์ด `medium` 44 ยท `small` 36 + hitSlop 4. ํ•ญ๋ชฉ ์ขŒ์šฐ ์—ฌ๋ฐฑ `medium` `spacing.md` 16 ยท `small` `spacing.sm` 12(๋‘ ํ”Œ๋žซํผ. Web `small`์€ `::after`๋กœ ์œ„์•„๋ž˜ 4๋ฅผ ๋„“ํžŒ๋‹ค) | `segmentedControlRecipe.sizes`, `.hjm-segmented__item` |
83
+ | ํฌ๊ธฐ | ๋ฐ”๊นฅ ๋†’์ด(ํŠธ๋ž™ ํ…Œ๋‘๋ฆฌยท์•ˆ์ชฝ ์—ฌ๋ฐฑ ํฌํ•จ) `height`๋Š” ๊ฐ™์€ ํฌ๊ธฐ์˜ ButtonยทIconButtonยทChip๊ณผ ๊ฐ™๋‹ค: `medium` 44 ยท `small` 36. ํ•ญ๋ชฉ ์ตœ์†Œ ๋†’์ด๋Š” ๊ทธ๋ณด๋‹ค ํŠธ๋ž™ ์•ˆ์ชฝ ์—ฌ๋ฐฑ 4์™€ ํ…Œ๋‘๋ฆฌ 1์„ ์œ„์•„๋ž˜๋กœ ๋บ€ `medium` 34 ยท `small` 26์ด๊ณ , ์œ„์•„๋ž˜๋กœ๋งŒ ๋„“ํžŒ ํ„ฐ์น˜ ์˜์—ญ(`hitSlop` 5 ยท 9, Web `::after`)์œผ๋กœ 44๋ฅผ ์ฑ„์šด๋‹ค. ์ž‘์€ ํŠธ๋ž™์€ ๋ฐ”๊นฅ์œผ๋กœ 4 ๋” ๋„“์–ด์ง€๋˜ ๋ ˆ์ด์•„์›ƒ ๋†’์ด๋Š” ๋Š˜์ง€ ์•Š๋Š”๋‹ค. ํฐ ๊ธ€์ž์—์„œ ์„ธ๋กœ๋กœ ์Œ“์ด๋ฉด ํ•ญ๋ชฉ๋งˆ๋‹ค 44. ํ•ญ๋ชฉ ์ขŒ์šฐ ์—ฌ๋ฐฑ `medium` `spacing.md` 16 ยท `small` `spacing.sm` 12. 2026-10-17 ์‚ฌ์šฉ์ž ์š”์ฒญ("๋†’์ด ๋งž์ถฐ")์œผ๋กœ ๊ฐ™์€ ์ค„์˜ ์นฉ๊ณผ ๋†’์ด๋ฅผ ๋งž์ท„๋‹ค(์ด์ „์—๋Š” ํ•ญ๋ชฉ ๋†’์ด ๊ธฐ์ค€์ด๋ผ ํŠธ๋ž™์ด 46ยท54์˜€๋‹ค) | `segmentedControlRecipe.sizes`, `.hjm-segmented__scroller`, `.hjm-segmented__item` |
84
84
  | ๊ฐ„๊ฒฉ | ํŠธ๋ž™ ์•ˆ์ชฝ ์—ฌ๋ฐฑยทํ•ญ๋ชฉ ๊ฐ„๊ฒฉ `container.padding`ยท`gap` `spacing.xxs` 4. ํŠธ๋ž™ ๋ชจ์„œ๋ฆฌ `radius.lg` 16(ํ…Œ๋‘๋ฆฌ 1). ์„ ํƒ ํ•ญ๋ชฉ ๋ชจ์„œ๋ฆฌ `radius.md` 12, ์„ ํƒ ํ…Œ๋‘๋ฆฌ 2(`stroke.strong`). ์•„๋ž˜ ๋‚ด์šฉ๊ณผ `layout.contentGap` 16 | `segmentedControlRecipe.container`ยท`item`, `.hjm-segmented__items` |
85
85
  | ์ˆœ์„œยท์ •๋ ฌ | ํ•ญ๋ชฉ์€ ๊ฐ™์€ ํญ์œผ๋กœ ๋‚˜๋‰˜๊ณ (Native `flex: 1`, Web `flex: 1 1 0`) ํŠธ๋ž™์€ ๋ถ€๋ชจ ํญ์„ ์ฑ„์šด๋‹ค. ์ „ํ™˜ํ•  ๋‚ด์šฉ ๋ฐ”๋กœ ์œ„, ํ™”๋ฉด ์ขŒ์šฐ ์—ฌ๋ฐฑ(`layout.pagePadding`) ์•ˆ | Native `SegmentedControl`, `.hjm-segmented__item` |
86
86
  | ๊ณ ์ •ยท์Šคํฌ๋กค | ๊ณ ์ •๋˜์ง€ ์•Š๋Š”๋‹ค. Web ํ•ญ๋ชฉ์€ ๊ธ€์ž๋ณด๋‹ค ์ข์•„์ง€์ง€ ์•Š์•„(`min-inline-size: max-content`) ๋„˜์น˜๋ฉด ํŠธ๋ž™์ด ๊ฐ€๋กœ ์Šคํฌ๋กค๋œ๋‹ค. Native๋Š” ์Šคํฌ๋กคํ•˜์ง€ ์•Š๋Š”๋‹ค | `.hjm-segmented__items`(overflow-x) |