@hjmds/design-contracts 0.8.2

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 (353) hide show
  1. package/README.md +208 -0
  2. package/dist/alert-dialog.d.ts +102 -0
  3. package/dist/alert-dialog.d.ts.map +1 -0
  4. package/dist/alert-dialog.js +136 -0
  5. package/dist/alert-dialog.js.map +1 -0
  6. package/dist/base-recipes.d.ts +184 -0
  7. package/dist/base-recipes.d.ts.map +1 -0
  8. package/dist/base-recipes.js +129 -0
  9. package/dist/base-recipes.js.map +1 -0
  10. package/dist/behaviors.d.ts +1254 -0
  11. package/dist/behaviors.d.ts.map +1 -0
  12. package/dist/behaviors.js +972 -0
  13. package/dist/behaviors.js.map +1 -0
  14. package/dist/bottom-navigation-defaults.d.ts +13 -0
  15. package/dist/bottom-navigation-defaults.d.ts.map +1 -0
  16. package/dist/bottom-navigation-defaults.js +10 -0
  17. package/dist/bottom-navigation-defaults.js.map +1 -0
  18. package/dist/bottom-navigation.d.ts +114 -0
  19. package/dist/bottom-navigation.d.ts.map +1 -0
  20. package/dist/bottom-navigation.js +223 -0
  21. package/dist/bottom-navigation.js.map +1 -0
  22. package/dist/breadcrumb.d.ts +97 -0
  23. package/dist/breadcrumb.d.ts.map +1 -0
  24. package/dist/breadcrumb.js +99 -0
  25. package/dist/breadcrumb.js.map +1 -0
  26. package/dist/calendar.d.ts +285 -0
  27. package/dist/calendar.d.ts.map +1 -0
  28. package/dist/calendar.js +297 -0
  29. package/dist/calendar.js.map +1 -0
  30. package/dist/card.d.ts +39 -0
  31. package/dist/card.d.ts.map +1 -0
  32. package/dist/card.js +50 -0
  33. package/dist/card.js.map +1 -0
  34. package/dist/carousel.d.ts +180 -0
  35. package/dist/carousel.d.ts.map +1 -0
  36. package/dist/carousel.js +172 -0
  37. package/dist/carousel.js.map +1 -0
  38. package/dist/catalog.d.ts +7158 -0
  39. package/dist/catalog.d.ts.map +1 -0
  40. package/dist/catalog.js +220 -0
  41. package/dist/catalog.js.map +1 -0
  42. package/dist/collection.d.ts +123 -0
  43. package/dist/collection.d.ts.map +1 -0
  44. package/dist/collection.js +211 -0
  45. package/dist/collection.js.map +1 -0
  46. package/dist/color-references.d.ts +46 -0
  47. package/dist/color-references.d.ts.map +1 -0
  48. package/dist/color-references.js +39 -0
  49. package/dist/color-references.js.map +1 -0
  50. package/dist/colors.d.ts +56 -0
  51. package/dist/colors.d.ts.map +1 -0
  52. package/dist/colors.js +90 -0
  53. package/dist/colors.js.map +1 -0
  54. package/dist/command-palette.d.ts +240 -0
  55. package/dist/command-palette.d.ts.map +1 -0
  56. package/dist/command-palette.js +97 -0
  57. package/dist/command-palette.js.map +1 -0
  58. package/dist/component-contracts.d.ts +137 -0
  59. package/dist/component-contracts.d.ts.map +1 -0
  60. package/dist/component-contracts.js +53 -0
  61. package/dist/component-contracts.js.map +1 -0
  62. package/dist/component-definitions.d.ts +135 -0
  63. package/dist/component-definitions.d.ts.map +1 -0
  64. package/dist/component-definitions.js +142 -0
  65. package/dist/component-definitions.js.map +1 -0
  66. package/dist/component-recipes.d.ts +3583 -0
  67. package/dist/component-recipes.d.ts.map +1 -0
  68. package/dist/component-recipes.js +1503 -0
  69. package/dist/component-recipes.js.map +1 -0
  70. package/dist/component-references.d.ts +416 -0
  71. package/dist/component-references.d.ts.map +1 -0
  72. package/dist/component-references.js +140 -0
  73. package/dist/component-references.js.map +1 -0
  74. package/dist/content-state.d.ts +104 -0
  75. package/dist/content-state.d.ts.map +1 -0
  76. package/dist/content-state.js +116 -0
  77. package/dist/content-state.js.map +1 -0
  78. package/dist/counter-badge-recipe.d.ts +80 -0
  79. package/dist/counter-badge-recipe.d.ts.map +1 -0
  80. package/dist/counter-badge-recipe.js +44 -0
  81. package/dist/counter-badge-recipe.js.map +1 -0
  82. package/dist/counter-badge.d.ts +12 -0
  83. package/dist/counter-badge.d.ts.map +1 -0
  84. package/dist/counter-badge.js +21 -0
  85. package/dist/counter-badge.js.map +1 -0
  86. package/dist/data-table.d.ts +203 -0
  87. package/dist/data-table.d.ts.map +1 -0
  88. package/dist/data-table.js +182 -0
  89. package/dist/data-table.js.map +1 -0
  90. package/dist/date-picker.d.ts +268 -0
  91. package/dist/date-picker.d.ts.map +1 -0
  92. package/dist/date-picker.js +168 -0
  93. package/dist/date-picker.js.map +1 -0
  94. package/dist/description-list.d.ts +68 -0
  95. package/dist/description-list.d.ts.map +1 -0
  96. package/dist/description-list.js +85 -0
  97. package/dist/description-list.js.map +1 -0
  98. package/dist/design-system-provider.d.ts +80 -0
  99. package/dist/design-system-provider.d.ts.map +1 -0
  100. package/dist/design-system-provider.js +147 -0
  101. package/dist/design-system-provider.js.map +1 -0
  102. package/dist/evidence.d.ts +49 -0
  103. package/dist/evidence.d.ts.map +1 -0
  104. package/dist/evidence.js +133 -0
  105. package/dist/evidence.js.map +1 -0
  106. package/dist/file-picker.d.ts +183 -0
  107. package/dist/file-picker.d.ts.map +1 -0
  108. package/dist/file-picker.js +224 -0
  109. package/dist/file-picker.js.map +1 -0
  110. package/dist/floating-action-button.d.ts +143 -0
  111. package/dist/floating-action-button.d.ts.map +1 -0
  112. package/dist/floating-action-button.js +149 -0
  113. package/dist/floating-action-button.js.map +1 -0
  114. package/dist/form.d.ts +143 -0
  115. package/dist/form.d.ts.map +1 -0
  116. package/dist/form.js +206 -0
  117. package/dist/form.js.map +1 -0
  118. package/dist/foundations.d.ts +300 -0
  119. package/dist/foundations.d.ts.map +1 -0
  120. package/dist/foundations.js +238 -0
  121. package/dist/foundations.js.map +1 -0
  122. package/dist/grid.d.ts +75 -0
  123. package/dist/grid.d.ts.map +1 -0
  124. package/dist/grid.js +133 -0
  125. package/dist/grid.js.map +1 -0
  126. package/dist/icon-button-recipe.d.ts +99 -0
  127. package/dist/icon-button-recipe.d.ts.map +1 -0
  128. package/dist/icon-button-recipe.js +53 -0
  129. package/dist/icon-button-recipe.js.map +1 -0
  130. package/dist/icon.d.ts +41 -0
  131. package/dist/icon.d.ts.map +1 -0
  132. package/dist/icon.js +147 -0
  133. package/dist/icon.js.map +1 -0
  134. package/dist/image.d.ts +82 -0
  135. package/dist/image.d.ts.map +1 -0
  136. package/dist/image.js +100 -0
  137. package/dist/image.js.map +1 -0
  138. package/dist/index.d.ts +58 -0
  139. package/dist/index.d.ts.map +1 -0
  140. package/dist/index.js +66 -0
  141. package/dist/index.js.map +1 -0
  142. package/dist/layout.d.ts +118 -0
  143. package/dist/layout.d.ts.map +1 -0
  144. package/dist/layout.js +118 -0
  145. package/dist/layout.js.map +1 -0
  146. package/dist/link.d.ts +57 -0
  147. package/dist/link.d.ts.map +1 -0
  148. package/dist/link.js +142 -0
  149. package/dist/link.js.map +1 -0
  150. package/dist/load-more.d.ts +64 -0
  151. package/dist/load-more.d.ts.map +1 -0
  152. package/dist/load-more.js +124 -0
  153. package/dist/load-more.js.map +1 -0
  154. package/dist/mentions.d.ts +67 -0
  155. package/dist/mentions.d.ts.map +1 -0
  156. package/dist/mentions.js +107 -0
  157. package/dist/mentions.js.map +1 -0
  158. package/dist/number-field.d.ts +208 -0
  159. package/dist/number-field.d.ts.map +1 -0
  160. package/dist/number-field.js +247 -0
  161. package/dist/number-field.js.map +1 -0
  162. package/dist/otp-field.d.ts +152 -0
  163. package/dist/otp-field.d.ts.map +1 -0
  164. package/dist/otp-field.js +117 -0
  165. package/dist/otp-field.js.map +1 -0
  166. package/dist/pagination.d.ts +181 -0
  167. package/dist/pagination.d.ts.map +1 -0
  168. package/dist/pagination.js +226 -0
  169. package/dist/pagination.js.map +1 -0
  170. package/dist/password-field.d.ts +187 -0
  171. package/dist/password-field.d.ts.map +1 -0
  172. package/dist/password-field.js +120 -0
  173. package/dist/password-field.js.map +1 -0
  174. package/dist/popover.d.ts +152 -0
  175. package/dist/popover.d.ts.map +1 -0
  176. package/dist/popover.js +137 -0
  177. package/dist/popover.js.map +1 -0
  178. package/dist/progress-recipe.d.ts +43 -0
  179. package/dist/progress-recipe.d.ts.map +1 -0
  180. package/dist/progress-recipe.js +16 -0
  181. package/dist/progress-recipe.js.map +1 -0
  182. package/dist/recipes.d.ts +31 -0
  183. package/dist/recipes.d.ts.map +1 -0
  184. package/dist/recipes.js +46 -0
  185. package/dist/recipes.js.map +1 -0
  186. package/dist/responsive.d.ts +27 -0
  187. package/dist/responsive.d.ts.map +1 -0
  188. package/dist/responsive.js +66 -0
  189. package/dist/responsive.js.map +1 -0
  190. package/dist/result.d.ts +111 -0
  191. package/dist/result.d.ts.map +1 -0
  192. package/dist/result.js +97 -0
  193. package/dist/result.js.map +1 -0
  194. package/dist/selection-helpers.d.ts +16 -0
  195. package/dist/selection-helpers.d.ts.map +1 -0
  196. package/dist/selection-helpers.js +52 -0
  197. package/dist/selection-helpers.js.map +1 -0
  198. package/dist/semantic-colors.d.ts +275 -0
  199. package/dist/semantic-colors.d.ts.map +1 -0
  200. package/dist/semantic-colors.js +84 -0
  201. package/dist/semantic-colors.js.map +1 -0
  202. package/dist/sheet.d.ts +51 -0
  203. package/dist/sheet.d.ts.map +1 -0
  204. package/dist/sheet.js +69 -0
  205. package/dist/sheet.js.map +1 -0
  206. package/dist/showcase.d.ts +153 -0
  207. package/dist/showcase.d.ts.map +1 -0
  208. package/dist/showcase.js +210 -0
  209. package/dist/showcase.js.map +1 -0
  210. package/dist/side-panel.d.ts +199 -0
  211. package/dist/side-panel.d.ts.map +1 -0
  212. package/dist/side-panel.js +111 -0
  213. package/dist/side-panel.js.map +1 -0
  214. package/dist/slider.d.ts +138 -0
  215. package/dist/slider.d.ts.map +1 -0
  216. package/dist/slider.js +150 -0
  217. package/dist/slider.js.map +1 -0
  218. package/dist/splitter.d.ts +113 -0
  219. package/dist/splitter.d.ts.map +1 -0
  220. package/dist/splitter.js +99 -0
  221. package/dist/splitter.js.map +1 -0
  222. package/dist/statistic.d.ts +41 -0
  223. package/dist/statistic.d.ts.map +1 -0
  224. package/dist/statistic.js +76 -0
  225. package/dist/statistic.js.map +1 -0
  226. package/dist/steps.d.ts +196 -0
  227. package/dist/steps.d.ts.map +1 -0
  228. package/dist/steps.js +160 -0
  229. package/dist/steps.js.map +1 -0
  230. package/dist/tag.d.ts +128 -0
  231. package/dist/tag.d.ts.map +1 -0
  232. package/dist/tag.js +93 -0
  233. package/dist/tag.js.map +1 -0
  234. package/dist/timeline.d.ts +147 -0
  235. package/dist/timeline.d.ts.map +1 -0
  236. package/dist/timeline.js +127 -0
  237. package/dist/timeline.js.map +1 -0
  238. package/dist/toast.d.ts +164 -0
  239. package/dist/toast.d.ts.map +1 -0
  240. package/dist/toast.js +529 -0
  241. package/dist/toast.js.map +1 -0
  242. package/dist/tokens.d.ts +9 -0
  243. package/dist/tokens.d.ts.map +1 -0
  244. package/dist/tokens.js +9 -0
  245. package/dist/tokens.js.map +1 -0
  246. package/dist/tooltip.d.ts +44 -0
  247. package/dist/tooltip.d.ts.map +1 -0
  248. package/dist/tooltip.js +88 -0
  249. package/dist/tooltip.js.map +1 -0
  250. package/dist/tour.d.ts +218 -0
  251. package/dist/tour.d.ts.map +1 -0
  252. package/dist/tour.js +211 -0
  253. package/dist/tour.js.map +1 -0
  254. package/dist/transfer-list.d.ts +207 -0
  255. package/dist/transfer-list.d.ts.map +1 -0
  256. package/dist/transfer-list.js +193 -0
  257. package/dist/transfer-list.js.map +1 -0
  258. package/dist/tree-select.d.ts +78 -0
  259. package/dist/tree-select.d.ts.map +1 -0
  260. package/dist/tree-select.js +132 -0
  261. package/dist/tree-select.js.map +1 -0
  262. package/dist/tree.d.ts +206 -0
  263. package/dist/tree.d.ts.map +1 -0
  264. package/dist/tree.js +223 -0
  265. package/dist/tree.js.map +1 -0
  266. package/dist/upload-item.d.ts +173 -0
  267. package/dist/upload-item.d.ts.map +1 -0
  268. package/dist/upload-item.js +156 -0
  269. package/dist/upload-item.js.map +1 -0
  270. package/dist/version.d.ts +3 -0
  271. package/dist/version.d.ts.map +1 -0
  272. package/dist/version.js +3 -0
  273. package/dist/version.js.map +1 -0
  274. package/docs/affix.md +63 -0
  275. package/docs/anchor.md +59 -0
  276. package/docs/ant-design-coverage.md +119 -0
  277. package/docs/app-provider.md +50 -0
  278. package/docs/app-rn-adoption.md +227 -0
  279. package/docs/architecture.md +320 -0
  280. package/docs/authoring-brief.md +87 -0
  281. package/docs/border-beam.md +66 -0
  282. package/docs/bottom-navigation.md +127 -0
  283. package/docs/breadcrumb.md +82 -0
  284. package/docs/calendar.md +154 -0
  285. package/docs/carousel.md +130 -0
  286. package/docs/cascader.md +93 -0
  287. package/docs/catalog-decision-status.md +306 -0
  288. package/docs/color-picker.md +72 -0
  289. package/docs/command-palette.md +116 -0
  290. package/docs/confirm-popover.md +93 -0
  291. package/docs/consistency-audit.md +383 -0
  292. package/docs/consumer-release-gate.md +90 -0
  293. package/docs/content-state.md +156 -0
  294. package/docs/context-panel.md +88 -0
  295. package/docs/cross-platform-core-normalization.md +118 -0
  296. package/docs/data-table.md +79 -0
  297. package/docs/date-picker.md +84 -0
  298. package/docs/description-list.md +75 -0
  299. package/docs/design-system-provider.md +139 -0
  300. package/docs/dropdown.md +78 -0
  301. package/docs/expansion-roadmap.md +285 -0
  302. package/docs/file-picker.md +59 -0
  303. package/docs/floating-action-button.md +111 -0
  304. package/docs/form.md +134 -0
  305. package/docs/generated/component-maturity.md +103 -0
  306. package/docs/generated/renderer-evidence.json +5597 -0
  307. package/docs/generated/renderer-evidence.md +132 -0
  308. package/docs/generated/showcase-manifest.json +3732 -0
  309. package/docs/icon.md +22 -0
  310. package/docs/identity.md +121 -0
  311. package/docs/image.md +84 -0
  312. package/docs/implementation-0.5.md +85 -0
  313. package/docs/layout-primitives.md +107 -0
  314. package/docs/layout.md +83 -0
  315. package/docs/library-reference-decisions.md +123 -0
  316. package/docs/link.md +67 -0
  317. package/docs/load-more.md +31 -0
  318. package/docs/mentions.md +82 -0
  319. package/docs/migration-0.2.md +108 -0
  320. package/docs/migration-0.3.md +72 -0
  321. package/docs/migration-0.5.md +82 -0
  322. package/docs/migration-0.6.md +197 -0
  323. package/docs/notification.md +54 -0
  324. package/docs/number-field.md +82 -0
  325. package/docs/otp-field.md +103 -0
  326. package/docs/pagination.md +139 -0
  327. package/docs/password-field.md +98 -0
  328. package/docs/popover.md +124 -0
  329. package/docs/promotion-candidates.md +169 -0
  330. package/docs/qr-code.md +69 -0
  331. package/docs/rating.md +58 -0
  332. package/docs/responsive-grid.md +90 -0
  333. package/docs/result.md +96 -0
  334. package/docs/showcase.md +97 -0
  335. package/docs/side-panel.md +71 -0
  336. package/docs/slider.md +79 -0
  337. package/docs/splitter.md +55 -0
  338. package/docs/statistic.md +16 -0
  339. package/docs/steps.md +115 -0
  340. package/docs/tag.md +57 -0
  341. package/docs/time-picker.md +88 -0
  342. package/docs/timeline.md +146 -0
  343. package/docs/toast.md +127 -0
  344. package/docs/tooltip.md +58 -0
  345. package/docs/tour.md +136 -0
  346. package/docs/transfer-list.md +94 -0
  347. package/docs/tree-select.md +101 -0
  348. package/docs/tree.md +123 -0
  349. package/docs/upload-item.md +68 -0
  350. package/docs/utility.md +53 -0
  351. package/docs/virtual-list.md +70 -0
  352. package/docs/watermark.md +58 -0
  353. package/package.json +402 -0
@@ -0,0 +1,75 @@
1
+ # DescriptionList contract
2
+
3
+ **๋ฌธ์ œ.** ๋ผ๋ฒจ-๊ฐ’ ์Œ์˜ ๋ฌถ์Œ โ€” FA ๋“ฑ๊ธ‰ ๊ทœ์ •, ์„ ์ˆ˜ ํ”„๋กœํ•„, ๊ณ„์•ฝ ์กฐ๊ฑด โ€” ์„ ์ผ๊ด€๋œ ์œ„๊ณ„์™€
4
+ ๋ฐ˜์‘ํ˜• ์—ด ๋ฐฐ์น˜๋กœ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ์•ผ์ž˜์•Œ์˜ FA ๋“ฑ๊ธ‰ ์‹œํŠธ์™€ ํ†ต์‚ฐ ํ™”๋ฉด์ด ์ง€๊ธˆ ๊ฐ์ž์˜ ์ž์ฒด
5
+ ๊ตฌํ˜„์œผ๋กœ ์ด ๋ฌธ์ œ๋ฅผ ํ’€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
6
+
7
+ **์ผ๋ฐ˜ํ™”ํ•œ ๊ณ„์•ฝ.** Statistic๊ณผ ๊ฐ™์€ ์›์น™์ž…๋‹ˆ๋‹ค โ€” ๊ฐ’์€ ์ œํ’ˆ์ด ์ด๋ฏธ ํฌ๋งทํ•œ ๋ฌธ์ž์—ด์ด๊ณ ,
8
+ HJM์€ stable `id`, `label`, `value`์˜ ๋ฐ˜๋ณต๋˜๋Š” ์ฝ๊ธฐ ์ˆœ์„œ๋งŒ ์†Œ์œ ํ•ฉ๋‹ˆ๋‹ค.
9
+
10
+ ```ts
11
+ const gradeSheet = {
12
+ items: [
13
+ { id: "grade", label: "FA ๋“ฑ๊ธ‰", value: "A๋“ฑ๊ธ‰" },
14
+ { id: "years", label: "๊ทœ์ • ์ถœ์žฅ ์‹œ์ฆŒ", value: "6์‹œ์ฆŒ" },
15
+ ],
16
+ } satisfies DescriptionListDescriptor;
17
+ ```
18
+
19
+ - ๊ฐ ์Œ์€ ๋…๋ฆฝ๋œ ์ ‘๊ทผ์„ฑ ๋…ธ๋“œ์ž…๋‹ˆ๋‹ค. Statistic ๊ทธ๋ฃน๊ณผ ๊ฐ™์€ ์›์น™์œผ๋กœ, renderer๋Š” ์—ฌ๋Ÿฌ
20
+ ์Œ์„ ํ•˜๋‚˜์˜ ์ถ•์•ฝ๋œ ๋…ธ๋“œ๋กœ ํ•ฉ์น˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
21
+ - `columns`๋Š” 1 ๋˜๋Š” 2๋งŒ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค(Statistic์˜ 1โ€“4๋ณด๋‹ค ์ข์Šต๋‹ˆ๋‹ค โ€” ๋ผ๋ฒจ-๊ฐ’ ์Œ์€ ํ†ต๊ณ„
22
+ ์นด๋“œ๋ณด๋‹ค ํ•œ ์ค„์ด ๊ธธ์–ด 3โ€“4์—ด์—์„œ ๊ฐ’์ด ์‰ฝ๊ฒŒ ์ž˜๋ฆฝ๋‹ˆ๋‹ค).
23
+
24
+ **HJM ๊ธฐ๋ณธ๊ฐ’.** ๊ธฐ๋ณธ `columns`๋Š” 2.
25
+
26
+ ## ํฐ ๊ธ€์ž์—์„œ์˜ ์ „ํ™˜ โ€” resolver๊ฐ€ ์†Œ์œ 
27
+
28
+ ์ด๋ฒˆ ๊ฒ€์ˆ˜์—์„œ ์•ผ์ž˜์•Œ ์†Œ๋น„ ์ฝ”๋“œ๊ฐ€ ยง5 ใ€Œํฐ ๊ธ€์ž์—์„œ์˜ ์ „ํ™˜ใ€ ๊ทœ์น™์„ ๋‹ค์„ฏ ๋ฒˆ ์–ด๊ฒผ์Šต๋‹ˆ๋‹ค.
29
+ ๋งค๋ฒˆ ํ™”๋ฉด์ด `fontScale >= 1.6`์ด๋ฉด `columns={1}`์„ ๋„˜๊ธฐ๋Š” ์‹์œผ๋กœ ์ง์ ‘ ๋ง‰์•˜๊ณ , ๊ทธ ์™„ํ™”๋ฅผ
30
+ ๋น ๋œจ๋ฆฐ ํ™”๋ฉด์€ ์กฐ์šฉํžˆ ๊นจ์กŒ์Šต๋‹ˆ๋‹ค. ์•ผ์ž˜์•Œ `src/components/ui/statistic-renderer-contract.ts`์˜
31
+ `resolveStatisticColumnCount`๊ฐ€ ์ด๋ฏธ ๊ฐ™์€ ๋ฌธ์ œ๋ฅผ "ํ™”๋ฉด์ด ๋ฐฐ์œจ์„ ํŒ์ •ํ•˜์ง€ ์•Š๊ณ , ์ตœ์†Œ ์นธ
32
+ ํญ์„ ๋ฐฐ์œจ๋งŒํผ ํ‚ค์›Œ์„œ ์ข์€ ํญ๊ณผ ํฐ ๊ธ€์ž๋ฅผ ๊ฐ™์€ ๊ณ„์‚ฐ์œผ๋กœ ํก์ˆ˜ํ•œ๋‹ค"๋Š” ํ˜•ํƒœ๋กœ ํ’€์—ˆ์Šต๋‹ˆ๋‹ค.
33
+
34
+ DescriptionList๋Š” ์ด ํ˜•ํƒœ๋ฅผ **์ฝ”์–ด ๊ณ„์•ฝ ์•ˆ์œผ๋กœ** ๊ฐ€์ ธ์™€ `resolveDescriptionListColumnCount`๋กœ
35
+ ๊ณต๊ฐœํ•ฉ๋‹ˆ๋‹ค โ€” Statistic์ฒ˜๋Ÿผ ์†Œ๋น„ ์•ฑ์ด ๊ฐ์ž ์žฌ๊ตฌํ˜„ํ•˜์ง€ ์•Š๊ณ , ์ด ํŒจํ‚ค์ง€๊ฐ€ ํญยท๋ฐฐ์œจ ํŒ์ •์„
36
+ ์†Œ์œ ํ•ฉ๋‹ˆ๋‹ค.
37
+
38
+ ```ts
39
+ resolveDescriptionListColumnCount(availableWidth, requestedColumns, textScale);
40
+ ```
41
+
42
+ - `availableWidth`๊ฐ€ ์œ ํšจํ•˜์ง€ ์•Š์œผ๋ฉด(0 ์ดํ•˜, NaN) `requestedColumns`๋ฅผ ๊ทธ๋Œ€๋กœ ๋Œ๋ ค์ค๋‹ˆ๋‹ค โ€”
43
+ renderer๊ฐ€ ์•„์ง ๋ ˆ์ด์•„์›ƒ์„ ์ธก์ •ํ•˜์ง€ ๋ชปํ•œ ์ฒซ ํ”„๋ ˆ์ž„์„ ์œ„ํ•œ ์•ˆ์ „ํ•œ ํด๋ฐฑ์ž…๋‹ˆ๋‹ค.
44
+ - `textScale`์€ `DesignSystemProvider`์˜ ์—ฐ์†๊ฐ’์„ ๊ทธ๋Œ€๋กœ ๋ฐ›์œผ๋ฉฐ ์ตœ์†Œ 1๋กœ clampํ•ฉ๋‹ˆ๋‹ค.
45
+ ๋ฐฐ์œจ์ด 1๋ณด๋‹ค ์ž‘๋‹ค๊ณ  ์นธ์„ ๋” ์ขํžˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค(ยง5๊ฐ€
46
+ ๋ง‰์€ ๋ฐฉํ–ฅ).
47
+ - ๊ฐ™์€ `availableWidth`์—์„œ `textScale`์ด ์ปค์ง€๋ฉด `minItemWidth`๊ฐ€ ํ•จ๊ป˜ ์ปค์ง€๋ฏ€๋กœ 2์—ด์ด
48
+ ์ž์—ฐํžˆ 1์—ด๋กœ ์ค„์–ด๋“ญ๋‹ˆ๋‹ค โ€” ํ™”๋ฉด๋งˆ๋‹ค ๋ฐ˜๋ณตํ•ด์•ผ ํ–ˆ๋˜ ์ž„๊ณ„๊ฐ’ ๋ถ„๊ธฐ๊ฐ€ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค.
49
+
50
+ ## Statistic๊ณผ์˜ ๊ฒฝ๊ณ„
51
+
52
+ DescriptionList๋Š” Statistic์˜ "์ œํ’ˆ์ด ํฌ๋งทํ•œ ๋ฌธ์ž์—ด, ๋…๋ฆฝ ์ ‘๊ทผ์„ฑ ๋…ธ๋“œ" ์›์น™์„ ๊ทธ๋Œ€๋กœ
53
+ ๋”ฐ๋ฅด์ง€๋งŒ ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ๋Š” ์•„๋‹™๋‹ˆ๋‹ค. Statistic์€ ์ˆซ์ž ์ค‘์‹ฌ ์ง€ํ‘œ(๊ฐ’์ด tabular, ์งง๊ณ ,
54
+ trend๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Œ)์ด๊ณ  DescriptionList๋Š” ์ž„์˜ ๊ธธ์ด ํ…์ŠคํŠธ ๊ฐ’์˜ ๋ผ๋ฒจ-๊ฐ’ ์Œ์ž…๋‹ˆ๋‹ค.
55
+ ๊ทธ๋ž˜์„œ `value`์— `trend`๊ฐ€ ์—†๊ณ , `columns` ์ƒํ•œ์ด 2๋กœ ๋” ์ข์œผ๋ฉฐ, `resolveDescriptionListColumnCount`์˜
56
+ `minItemWidth`(160)๋Š” Statistic์˜ `minItemWidth`(120)์™€ ๋‹ค๋ฅธ ๊ฐ’์ž…๋‹ˆ๋‹ค โ€” ํ†ต๊ณ„ ์นด๋“œ๋ณด๋‹ค
57
+ ๋ผ๋ฒจ-๊ฐ’ ํ•œ ์ค„์ด ๋„“๊ฒŒ ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
58
+
59
+ ## ํ”Œ๋žซํผ ๋ฒˆ์—ญ
60
+
61
+ Web/Native ๋ชจ๋‘ `resolveDescriptionListColumnCount`๊ฐ€ ๋Œ๋ ค์ค€ ์—ด ์ˆ˜๋กœ CSS grid ๋˜๋Š”
62
+ flex wrap ๋ ˆ์ด์•„์›ƒ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์‹ค์ œ ์ธก์ •๋œ ์ปจํ…Œ์ด๋„ˆ ํญ๊ณผ ์‹œ์Šคํ…œ ํฐํŠธ ๋ฐฐ์œจ์€ renderer๊ฐ€
63
+ ๊ณต๊ธ‰ํ•˜๊ณ , ์ด ๊ณ„์•ฝ์€ ๊ทธ ๋‘ ์ž…๋ ฅ์„ ๋ฐ›์•„ ์—ด ์ˆ˜๋งŒ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
64
+
65
+ ## ํ˜„์žฌ ๊ฒ€์ฆ๊ณผ ๋‚จ์€ ์ฆ๊ฑฐ
66
+
67
+ first-party Web/RN renderer๊ฐ€ ๊ณตํ†ต descriptor์™€
68
+ `resolveDescriptionListColumnCount`๋ฅผ ์ง์ ‘ ์†Œ๋น„ํ•˜๋ฏ€๋กœ contract์™€ ๋‘ surface๋ฅผ `beta`๋กœ
69
+ ์Šน๊ฒฉํ–ˆ๋‹ค. Web์€ `<dl>/<dt>/<dd>` ๊ตฌ์กฐ์™€ ์ธก์ • ํญ ๊ธฐ๋ฐ˜ ์—ด ์ „ํ™˜์„, Native๋Š” ๋…๋ฆฝ๋œ ๋ผ๋ฒจ-๊ฐ’
70
+ ์ ‘๊ทผ์„ฑ ๋…ธ๋“œ์™€ window/text-scale ๊ธฐ๋ฐ˜ flex ์—ด ์ „ํ™˜์„ ๊ธฐ๋ณธ ์‹คํ–‰ test๋กœ ๊ฒ€์ฆํ•œ๋‹ค.
71
+
72
+ ์ด์ „ ํŒ์ •์ด ํ›„๋ณด๋กœ ๋“  ์•ผ์ž˜์•Œ ํ™”๋ฉด์€ ์—ฌ์ „ํžˆ ์Šน๊ฒฉ์˜ ์ œํ’ˆ ๊ทผ๊ฑฐ๋กœ ์„ธ์ง€ ์•Š๋Š”๋‹ค. ํ•ด๋‹น ํ™”๋ฉด์€
73
+ ๋‹จ์ผ ์—ด `List`/`ListRow` ์กฐํ•ฉ์ด๋ฉฐ DescriptionList์˜ 1/2์—ด ๋ฌธ์ œ์™€ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์‹ค์ œ ์†Œ๋น„
74
+ ์•ฑ์—์„œ ์ด renderer๋ฅผ ์“ฐ๋Š” 1/2์—ด ํ™”๋ฉด๊ณผ 200% ๊ธ€์ž ํฌ๊ธฐ ์‹ค๊ธฐ๊ธฐ ์ฆ๊ฑฐ๋Š” stable ์Šน๊ฒฉ ์ „๊นŒ์ง€
75
+ ๋ช…์‹œ์ ์ธ debt๋กœ ๋‚จ๋Š”๋‹ค.
@@ -0,0 +1,139 @@
1
+ # DesignSystemProvider contract
2
+
3
+ ## ๋ฌธ์ œ
4
+
5
+ antd `ConfigProvider`๋Š” ํ…Œ๋งˆยท๋ฐฉํ–ฅ(RTL)ยท๊ธ€์ž ๋ฐฐ์œจยทlocale ๊ฐ™์€ ์ „์—ญ ์„ค์ •์„ React Context๋กœ
6
+ ์•„๋ž˜ ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ์— ๋‚ด๋ ค์ค€๋‹ค. ์ด ํŒจํ‚ค์ง€๋Š” React๋„ RN๋„ importํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ "Context๋กœ
7
+ ๋‚ด๋ ค์ค€๋‹ค"๋Š” ๋ถ€๋ถ„(๊ทธ ์ž์ฒด๊ฐ€ antd `ConfigProvider`์˜ ๋ณธ์ฒด)์€ ์• ์ดˆ์— ์ด ์ €์žฅ์†Œ์˜ ๋ฌผ๊ฑด์ด ๋ 
8
+ ์ˆ˜ ์—†๋‹ค. ๊ทธ๋ž˜์„œ ๋จผ์ € ๋ฌผ์–ด์•ผ ํ–ˆ๋‹ค: **๋Ÿฐํƒ€์ž„(Context ์ „ํŒŒ)์„ ๊ฑท์–ด๋‚ด๊ณ  ๋‚˜๋ฉด ๊ณ„์•ฝํ•  ๊ฒƒ์ด
9
+ ๋‚จ๋Š”๊ฐ€?**
10
+
11
+ **๋‚จ๋Š”๋‹ค โ€” ๋‹ค๋งŒ "provider ์ปดํฌ๋„ŒํŠธ"๊ฐ€ ์•„๋‹ˆ๋ผ "ํ™˜๊ฒฝ ๊ฐ’์˜ ํƒ€์ž… + ๊ธฐ๋ณธ๊ฐ’ + ๋ณ‘ํ•ฉ ๊ทœ์น™ +
12
+ ํ•ด์„๋œ ์ƒ‰ ํŒ”๋ ˆํŠธ"๋‹ค.**
13
+ `showcaseEnvironmentMatrix`(`src/showcase.ts`)๊ฐ€ ์ด๋ฏธ theme/direction/textScale/motion
14
+ ๋„ค ์ถ•์„ ์ •ํ™•ํžˆ ์—ด๊ฑฐํ•˜๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์ด ๊ทธ ์ฆ๊ฑฐ์˜€๋‹ค โ€” ๋‹ค๋งŒ ๊ทธ๊ฑด Showcase ๋ฌธ์„œ ๋„๊ตฌ๊ฐ€ ์“ฐ๋Š”
15
+ **๋‹ซํžŒ 5๊ฐœ fixture ์‹œ๋‚˜๋ฆฌ์˜ค**(`id: "default"|"dark"|"large-text"|"rtl"|"reduced-motion"`)
16
+ ์ด์ง€, ์‹ค์ œ ์ œํ’ˆ์ด ๋Ÿฐํƒ€์ž„์— ๊ตฌ๋…ํ•  **์—ด๋ฆฐ ๊ฐ’ ํƒ€์ž…**์ด ์•„๋‹ˆ๋‹ค. ์ด ๊ณ„์•ฝ์ด ๊ทธ ์—ด๋ฆฐ ๋ฒ„์ „์ด๋‹ค.
17
+
18
+ ## ์ด๋ฏธ ์žˆ๋Š” ๊ฒƒ๊ณผ ๊ฒน์น˜์ง€ ์•Š๋Š”์ง€ ๋จผ์ € ํ™•์ธํ–ˆ๋‹ค
19
+
20
+ - **theme ์ถ•์€ ์ด๋ฏธ ์™„๊ฒฐ๋ผ ์žˆ๋‹ค.** `colors.ts`๊ฐ€ ์ด๋ฏธ `ThemePreference =
21
+ "system"|"light"|"dark"`, `ResolvedTheme`, `isThemePreference()`๋ฅผ ๊ฐ–๊ณ  ์žˆ๋‹ค. ์ด
22
+ ๋ชจ๋“ˆ์€ ๊ทธ๊ฒƒ์„ **์žฌ์„ ์–ธํ•˜์ง€ ์•Š๊ณ  ๊ทธ๋Œ€๋กœ import**ํ•œ๋‹ค โ€” "์ด๋ฏธ ์žˆ๋Š” ๊ฒƒ๊ณผ ๊ฒน์น˜๋ฉด ๋งŒ๋“ค์ง€
23
+ ๋งˆ๋ผ"๋Š” ์ง€์‹œ๋ฅผ theme ์ถ•์—๋Š” ๊ทธ๋Œ€๋กœ ์ ์šฉํ•ด ์•„๋ฌด๊ฒƒ๋„ ์ƒˆ๋กœ ๋งŒ๋“ค์ง€ ์•Š์•˜๋‹ค.
24
+ - **direction ์ถ•์€ ๊ฒน์น˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ ํฉ์–ด์ ธ ์žˆ์—ˆ๋‹ค.** `"ltr" | "rtl"`๊ฐ€
25
+ `BottomNavigationDirection`, `TabsDirection`, `SelectionDirection`, `IconDirection`,
26
+ `ShowcaseDirection`, ๊ทธ๋ฆฌ๊ณ  `calendar.ts`์˜ ์ธ๋ผ์ธ ํŒŒ๋ผ๋ฏธํ„ฐ๊นŒ์ง€ **์ตœ์†Œ 6๊ณณ์—์„œ ๊ฐ์ž ๋‹ค์‹œ
27
+ ์„ ์–ธ**๋ผ ์žˆ์—ˆ๋‹ค. ๊ณต๊ฐœ ์ด๋ฆ„์€ ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•ด ์œ ์ง€ํ•˜๋˜ ๋ชจ๋‘
28
+ `DesignSystemDirection`์˜ type alias๋กœ ์ด๊ด€ํ–ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ธฐ์กด import๋Š” ๊นจ์ง€์ง€ ์•Š๊ณ ,
29
+ ํ—ˆ์šฉ ๊ฐ’์˜ ๋‹จ์ผ ์ถœ์ฒ˜๋งŒ Provider ๊ณ„์•ฝ์œผ๋กœ ๋ชจ์˜€๋‹ค.
30
+ - **textScale์€ ์ด๋ฆ„๋„ ๋ชจ์–‘๋„ ์ด๋ฏธ ๋‘ ๊ฐˆ๋ž˜์˜€๋‹ค.** `description-list.ts`๋Š” `fontScale`
31
+ (์—ฐ์†๊ฐ’, `Math.max(fontScale, 1)`๋กœ ์ž์ฒด clamp), `showcase.ts`๋Š” `textScale`(๋‹ซํžŒ
32
+ `1|1.5|2`)์„ ๊ฐ์ž ์“ฐ๊ณ  ์žˆ์—ˆ๋‹ค. `DesignSystemTextScale = number`(์—ฐ์†๊ฐ’)๋ฅผ ์ƒ๋ฅ˜
33
+ ์‹ ํ˜ธ๋กœ ์—ด์—ˆ๊ณ  DescriptionList์˜ ์„ธ ๋ฒˆ์งธ ์ธ์ˆ˜์™€ Showcase fixture ๋ณ€ํ™˜ ํ•จ์ˆ˜๊ฐ€ ์ด ํƒ€์ž…์„
34
+ ์‚ฌ์šฉํ•œ๋‹ค. Showcase์˜ ๋‹ซํžŒ union๊ณผ ๊ธฐ์กด `motion` ํ•„๋“œ๋Š” fixture API ํ˜ธํ™˜์„ ์œ„ํ•ด ์œ ์ง€ํ•œ๋‹ค.
35
+ - **reducedMotion์€ "์„ ํ˜ธ"์™€ "์ „๋žต"์ด ์ด๋ฏธ ๋ถ„๋ฆฌ๋ผ ์žˆ์—ˆ๋‹ค.** `foundations.ts`์˜
36
+ `ReducedMotionBehavior`("instant"/"opacity"/"static")๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ Reduce Motion์ผ
37
+ **๋•Œ ๋ฌด์—‡์„ ํ•˜๋Š”์ง€**(์ „๋žต)์ด๊ณ , `carousel.ts`์˜ `inputs: ["reducedMotion", ...]`๋Š” ๊ทธ
38
+ ํ˜„์žฌ **์„ ํ˜ธ๊ฐ’**(boolean) ํ•˜๋‚˜๋ฅผ ์ด๋ฏธ ์ปดํฌ๋„ŒํŠธ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›๊ณ  ์žˆ์—ˆ๋‹ค. ์ด ๋ชจ๋“ˆ์€ ๊ทธ
39
+ boolean ์„ ํ˜ธ๊ฐ’์˜ ๋‹จ์ผ ์ถœ์ฒ˜๋ฅผ ๊ณ„์•ฝํ•  ๋ฟ, ๊ฐ ์ปดํฌ๋„ŒํŠธ์˜ ์ „๋žต(motionPreset)์„ ๋Œ€์ฒดํ•˜์ง€
40
+ ์•Š๋Š”๋‹ค โ€” ๋‘˜์€ ๊ณ„์† ๋ถ„๋ฆฌ๋œ ์ฑ„๋กœ ๋‘”๋‹ค.
41
+
42
+ ## ์ผ๋ฐ˜ํ™”ํ•œ ๊ณ„์•ฝ
43
+
44
+ - `DesignSystemEnvironmentInput`์€ ๋„ค ํ•„๋“œ ๋ชจ๋‘ **์„ ํƒ**์ด๋‹ค โ€” ๋ Œ๋”๋Ÿฌ๊ฐ€ ์•„์ง ์ผ๋ถ€
45
+ ์‹ ํ˜ธ๋งŒ ์•Œ๊ณ  ์žˆ์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค(RN์˜ `AccessibilityInfo.isReduceMotionEnabled()`๋Š”
46
+ ๋น„๋™๊ธฐ๋ผ ์ฒซ ๋ Œ๋”์—๋Š” ๊ฐ’์ด ์—†์„ ์ˆ˜ ์žˆ๋‹ค).
47
+ - `resolveDesignSystemEnvironment(input, options)`์˜ ์šฐ์„ ์ˆœ์œ„๋Š” ์ถ•๋งˆ๋‹ค
48
+ **๋ช…์‹œ input โ†’ ํ•ด์„๋œ parent โ†’ renderer์˜ system signal โ†’ HJM default**๋‹ค. ๊ธฐ์กด ํ˜ธ์ถœ์˜
49
+ ํ•„์ˆ˜ `systemTheme`์€ ๊ทธ๋Œ€๋กœ์ด๋ฉฐ `systemDirection`, `systemTextScale`,
50
+ `systemReducedMotion`, `parent`๋งŒ ์„ ํƒ์ ์œผ๋กœ ์ถ”๊ฐ€๋๋‹ค. `theme: "system"`์„ ๋ช…์‹œํ•˜๋ฉด
51
+ parent๋ณด๋‹ค ํ˜„์žฌ `systemTheme`์„ ์šฐ์„ ํ•œ๋‹ค.
52
+ - `resolveDesignSystemProviderValue()`๋Š” ์ด ํ™˜๊ฒฝ๊ณผ `THEMES`, `ACCENTS`, `accentFill`์„ ๋ฌถ์–ด
53
+ `{ environment, palette }`๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. renderer๋Š” `palette`๋ฅผ
54
+ `resolveColorReference()`์— ๊ทธ๋Œ€๋กœ ์ „๋‹ฌํ•œ๋‹ค.
55
+ - `validateDesignSystemProviderValue()`๋Š” renderer์— ์ง์ ‘ ์ฃผ์ž…๋˜๋Š” ์™„์ „ํ•œ ์ œํ’ˆ palette๋„
56
+ ๊ฐ™์€ ๋Ÿฐํƒ€์ž„ ๊ฒฝ๊ณ„์—์„œ ๊ฒ€์‚ฌํ•œ๋‹ค. ๋ชจ๋“  semantic theme/accent role๊ณผ alpha ํ•ฉ์„ฑ ๊ฐ€๋Šฅํ•œ
57
+ 6์ž๋ฆฌ hex ๊ฐ’์ด ํ•„์š”ํ•˜๋ฉฐ, ์ผ๋ถ€ token๋งŒ ๋ฎ๋Š” partial override๋Š” ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ œํ’ˆ
58
+ palette์˜ ๋Œ€๋น„ fixture์™€ ์Šน์ธ ์ฑ…์ž„์€ ๊ทธ ์™„์ „ํ•œ palette๋ฅผ ์ œ๊ณตํ•˜๋Š” ์ œํ’ˆ adapter๊ฐ€ ๊ฐ€์ง„๋‹ค.
59
+ - `validateDesignSystemEnvironmentInput()`์€ ์„ ํƒํ˜• input์„ ๊ฒ€์‚ฌํ•˜๊ณ ,
60
+ `validateResolvedDesignSystemEnvironment()`๋Š” parent ์ „์šฉ invariant๋ฅผ ๊ฒ€์‚ฌํ•œ๋‹ค. ํ›„์ž๋Š”
61
+ `theme: "system"`, ๋ˆ„๋ฝ๋œ ์ถ•, ์ž˜๋ชป๋œ direction, 0 ์ดํ•˜/non-finite textScale, boolean์ด
62
+ ์•„๋‹Œ reducedMotion์„ ๋ชจ๋‘ ๊ฑฐ๋ถ€ํ•œ๋‹ค. ์ด๋ฏธ resolved๋ผ๋Š” ํƒ€์ž… ์ด๋ฆ„์„ ๋Ÿฐํƒ€์ž„์—์„œ๋„ ์ง€ํ‚จ๋‹ค.
63
+ - **OS ์กฐํšŒ ์ž์ฒด๋Š” ํ•˜์ง€ ์•Š๋Š”๋‹ค.** `Appearance`, `AccessibilityInfo`, `I18nManager`,
64
+ `PixelRatio`, `matchMedia`๋Š” renderer ๋ชซ์ด๊ณ  ์ฝ”์–ด๋Š” ๊ณ„์† React/RN/DOM ์˜์กด์„ฑ์ด ์—†๋‹ค.
65
+
66
+ ## HJM ๊ธฐ๋ณธ๊ฐ’
67
+
68
+ `designSystemEnvironmentDefaults`: `theme: "system"`, `direction: "ltr"`,
69
+ `textScale: 1`, `reducedMotion: false` โ€” ๊ธฐ์กด ํ˜ธ์ถœ์˜ fallback๊ณผ ํ˜ธํ™˜๋˜๋Š” ๊ฐ’์ด๋‹ค. ์‹ค์ œ
70
+ renderer๋Š” ์ด fallback์„ OS ๊ฐ์ง€ ๊ฒฐ๊ณผ๋กœ ์˜คํ•ดํ•˜๋ฉด ์•ˆ ๋˜๊ณ , root์—์„œ ๋ฐ˜๋“œ์‹œ
71
+ `systemReducedMotion`์„ ๊ณต๊ธ‰ํ•ด์•ผ ํ•œ๋‹ค. RN์˜ ๋น„๋™๊ธฐ ์‹ ํ˜ธ๋ฅผ ์•„์ง ๋ชจ๋ฅด๋Š” ์ฒซ ํ”„๋ ˆ์ž„์—๋Š” adapter๊ฐ€
72
+ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์‹œ์ž‘ํ•˜์ง€ ์•Š๋Š” ์ •์ฑ…์„ ๋ณ„๋„๋กœ ์ ์šฉํ•œ๋‹ค.
73
+
74
+ ## ํ”Œ๋žซํผ ๋ฒˆ์—ญ
75
+
76
+ ์ด ๋ชจ๋“ˆ ์ž์ฒด๋Š” ํ”Œ๋žซํผ์„ ๋ถ„๊ธฐํ•˜์ง€ ์•Š๋Š”๋‹ค โ€” ๊ฐ™์€ Provider value๋ฅผ Web๊ณผ Native๊ฐ€
77
+ ๊ตฌ๋…ํ•œ๋‹ค. ๋‹ค๋ฅธ ๊ฒƒ์€ **system signal์„ ์–ด๋–ป๊ฒŒ ์–ป๊ณ , ๊ฐ’์„ ์–ด๋–ป๊ฒŒ ์ „ํŒŒํ•˜๊ณ , palette๋ฅผ
78
+ ์–ด๋–ค style API๋กœ ๋ฒˆ์—ญํ•˜๋Š”๊ฐ€**๋ฟ์ด๋‹ค:
79
+
80
+ - Web: `matchMedia`(์ƒ‰ ๊ตฌ์„ฑํ‘œยทprefers-reduced-motion), CSS `dir` ์†์„ฑ(direction),
81
+ `document.documentElement`์˜ root font-size ๋ฐฐ์œจ. ์ „ํŒŒ๋Š” React Context.
82
+ - Native: `Appearance`/`useColorScheme()`, `AccessibilityInfo`, `PixelRatio.getFontScale()`
83
+ ๋˜๋Š” `useWindowDimensions().fontScale`, `I18nManager.isRTL`. ์ „ํŒŒ๋Š” RN Context ๋˜๋Š”
84
+ ๋™๋“ฑํ•œ ์ƒํƒœ ์ €์žฅ์†Œ.
85
+
86
+ catalog์˜ `platform: "shared"`๊ฐ€ ๋งž๋‹ค. ์˜ค๋ฒ„๋ ˆ์ด(Web popup vs Native Sheet)์ฒ˜๋Ÿผ ํ‘œ๋ฉด์„
87
+ ๋ฐ”๊พธ๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์•„๋‹ˆ๋ผ, ๊ฐ™์€ ๊ฐ’ ํƒ€์ž…์„ ๋‘ ํ”Œ๋žซํผ์ด ๊ฐ์ž์˜ OS API๋กœ ์ฑ„์›Œ ๋„ฃ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
88
+
89
+ ์ค‘์ฒฉ Provider๋Š” `parent.environment`๋ฅผ options์— ๋„˜๊ธด๋‹ค. ์ผ๋ถ€ ์ถ•๋งŒ ๋ช…์‹œํ•˜๋ฉด ๋‚˜๋จธ์ง€๋Š”
90
+ parent์—์„œ ์ƒ์†ํ•˜๊ณ , root Provider๋Š” system signal๋กœ ์ฑ„์šด๋‹ค. ์ด ๊ทœ์น™ ๋•๋ถ„์— ๊ฐ React/RN
91
+ adapter๊ฐ€ ์ž์ฒด ๋ณ‘ํ•ฉ ๋กœ์ง์„ ๋‹ค์‹œ ๋งŒ๋“ค ํ•„์š”๊ฐ€ ์—†๋‹ค. `parent`์—๋Š” ๋ฐ˜๋“œ์‹œ
92
+ `resolveDesignSystemEnvironment()` ๋˜๋Š” `resolveDesignSystemProviderValue().environment`์˜
93
+ ๊ฒฐ๊ณผ๋ฅผ ๋„˜๊ธด๋‹ค. `theme: "system"`์ธ input ๊ฐ์ฒด๋ฅผ ํƒ€์ž… ๋‹จ์–ธ์œผ๋กœ parent์— ๋„ฃ์–ด๋„ resolver๊ฐ€
94
+ ๋‹ค์‹œ ํ•ด์„ํ•˜์ง€ ์•Š๊ณ  ์ฆ‰์‹œ ์‹คํŒจํ•œ๋‹ค.
95
+
96
+ ## ๊ณต๊ฐœํ•œ ์ถ• / ๋ฐฐ์ œํ•œ ์ถ•
97
+
98
+ | ์ถ• | ์ƒํƒœ |
99
+ | --- | --- |
100
+ | `theme`(system/light/dark) | ๊ณต๊ฐœ โ€” `colors.ts` ์žฌ์‚ฌ์šฉ |
101
+ | `direction`(ltr/rtl) | ๊ณต๊ฐœ โ€” ์ƒˆ๋กœ ์ •์‹ํ™” |
102
+ | `textScale`(์—ฐ์†๊ฐ’) | ๊ณต๊ฐœ |
103
+ | `reducedMotion`(boolean ์„ ํ˜ธ) | ๊ณต๊ฐœ |
104
+ | `locale`(์–ธ์–ด ์ฝ”๋“œ) | **๋ฐฐ์ œ** โ€” RTL ์—ฌ๋ถ€๋Š” `direction`์œผ๋กœ ์ด๋ฏธ ํ‘œํ˜„๋˜๊ณ , ์ˆซ์žยท๋‚ ์งœยท๋ณต์ˆ˜ํ˜•
105
+ ํฌ๋งท์€ "์ œํ’ˆ์ด ํฌ๋งทํ•œ ๋ฌธ์ž์—ด์„ ๋ฐ›๋Š”๋‹ค" ์›์น™์ƒ ์ด ํŒจํ‚ค์ง€๊ฐ€ ๋ชฐ๋ผ๋„ ๋œ๋‹ค. locale ์ž์ฒด๊ฐ€
106
+ ํ•„์š”ํ•œ ์ œํ’ˆ์€ ๊ทธ ๊ฐ’์„ ์ง์ ‘ ๋“ค๊ณ  ์žˆ๋‹ค๊ฐ€ ํ•„์š”ํ•œ ๊ณณ(์˜ˆ: `Intl.DateTimeFormat`)์— ์“ด๋‹ค. |
107
+ | React/RN Context, `<Provider>` ์ปดํฌ๋„ŒํŠธ, `useDesignSystem()` ํ›… | **๋ฐฐ์ œ** โ€” ์ด ํŒจํ‚ค์ง€๋Š”
108
+ ๋Ÿฐํƒ€์ž„ ์˜์กด์„ฑ์„ ๊ฐ–์ง€ ์•Š๋Š”๋‹ค. ๊ฐ ์ œํ’ˆ์˜ renderer๊ฐ€ ์ด ๊ฐ’ ํƒ€์ž…์„ ์ž์‹ ์˜ Context์— ๋‹ด์•„
109
+ ์ „ํŒŒํ•œ๋‹ค. |
110
+ | `size`(antd ConfigProvider์˜ ์ปดํฌ๋„ŒํŠธ ์ „์—ญ ์‚ฌ์ด์ฆˆ ํ”„๋ฆฌ์…‹) | **๋ฐฐ์ œ** โ€” ์ธก์ •๋œ ์š”๊ตฌ๊ฐ€
111
+ ์—†๊ณ , ์žˆ๋‹ค ํ•ด๋„ ๊ทธ๊ฑด ๊ฐ recipe์˜ `sizes`(์˜ˆ: `selectRecipe.sizes`)๊ฐ€ ์ด๋ฏธ ์ปดํฌ๋„ŒํŠธ๋ณ„๋กœ
112
+ ๊ฐ–๊ณ  ์žˆ๋Š” ์ถ•์ด๋ผ ์ „์—ญ ์˜ค๋ฒ„๋ผ์ด๋“œ๋ฅผ ์–น์œผ๋ฉด ๋‘ ๊ณณ์ด ๊ฐ™์€ ์ถ•์„ ๋‹ค์‹œ ์†Œ์œ ํ•˜๊ฒŒ ๋œ๋‹ค. |
113
+ | ์ž„์˜ theme/component token override | **partial override๋Š” ๋ฐฐ์ œ** โ€” HJM light/dark๋Š” ๋Œ€๋น„
114
+ ํ…Œ์ŠคํŠธ๋ฅผ ํ•จ๊ป˜ ํ†ต๊ณผํ•˜๋Š” ๊ณ ์ • ๊ณ„์•ฝ์ด๋‹ค. ๋ณ„๋„ ๋ธŒ๋žœ๋“œ ์ œํ’ˆ์€ ๋ชจ๋“  semantic role์„ ๊ฐ€์ง„
115
+ ์™„์ „ํ•œ `DesignSystemProviderValue`๋งŒ renderer์˜ `value` ๊ฒฝ๊ณ„๋กœ ์ฃผ์ž…ํ•˜๋ฉฐ, ๋Ÿฐํƒ€์ž„ shape ๊ฒ€์‚ฌ์™€
116
+ ์ œํ’ˆ๋ณ„ ์ „์ฒด ๋Œ€๋น„ fixture๋ฅผ ํ•จ๊ป˜ ๋‘”๋‹ค. |
117
+
118
+ ## ์ œํ’ˆ adapter ์ฆ๊ฑฐ
119
+
120
+ Showcase fixture๋งŒ์œผ๋กœ ์„ฑ์ˆ™๋„๋ฅผ ์˜ฌ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค. ํ˜„์žฌ๋Š” ๋‹ค์Œ ์‹ค์ œ ์ œํ’ˆ ๊ฒฝ๊ณ„๊ฐ€
121
+ `resolveDesignSystemProviderValue()`์˜ `environment + palette`๋ฅผ Context์— ์ €์žฅํ•˜๊ณ  renderer์—
122
+ ๋‚ด๋ ค์ค€๋‹ค.
123
+
124
+ | ์ œํ’ˆ ํ‘œ๋ฉด | ์‹ค์ œ adapter ์ฆ๊ฑฐ | ๊ฒ€์ฆ ๊ฒฝ๊ณ„ |
125
+ | --- | --- | --- |
126
+ | BurnTok Web | `../BurnTok/apps/web/src/components/ThemeProvider.tsx` | `matchMedia`, root `dir`, ์ €์žฅ๋œ theme preference๋ฅผ resolver์— ๋„ฃ๊ณ  Context๊ฐ€ `providerValue`, `environment`, `palette`๋ฅผ ๊ณต๊ฐœํ•œ๋‹ค. OS ์ถ•์€ system option์œผ๋กœ ์ „๋‹ฌํ•˜๋ฏ€๋กœ nested `parentEnvironment`๊ฐ€ omitted axis๋ณด๋‹ค ๋จผ์ € ์ ์šฉ๋œ๋‹ค. `palette.theme.bg`๋Š” ๋ธŒ๋ผ์šฐ์ € theme color์— ์‹ค์ œ ์ ์šฉ๋œ๋‹ค. `ThemeProvider.test.tsx`๊ฐ€ ์ด ๊ฒฝ๊ณ„๋ฅผ ๊ฒ€์ฆํ•œ๋‹ค. |
127
+ | BurnTok RN | `../BurnTok/apps/mobile/src/components/ThemeProvider.tsx` | `useColorScheme`, `I18nManager`, `useWindowDimensions().fontScale`, `AccessibilityInfo`์˜ ์‹ ํ˜ธ๋ฅผ system option์œผ๋กœ ํ•ด์„ํ•˜๊ณ  `parentEnvironment` ์ƒ์† ๋ฐ ๋ช…์‹œ fixture๋ฅผ ์ง€์›ํ•˜๋ฉฐ `palette.theme`์„ Native style renderer์˜ `colors`๋กœ ์ œ๊ณตํ•œ๋‹ค. |
128
+ | Yajalal RN | `../yajalal/modules/app-rn/src/lib/theme/provider-adapter.ts`, `ThemeProvider.tsx` | HJM resolver๋กœ ํ™˜๊ฒฝ ์šฐ์„ ์ˆœ์œ„์™€ `parentEnvironment`์˜ omitted axis ์ƒ์†์„ ํ•ด์„ํ•˜๊ณ  `validateResolvedDesignSystemEnvironment()`๋กœ ๊ฒ€์ฆํ•œ ๋’ค, ๊ธฐ์กด ์ œํ’ˆ ํŒ”๋ ˆํŠธ๋งŒ ๊ฒ€ํ† ๋œ adapter๋กœ ๋ฐ”๊พผ๋‹ค. `ThemeProvider.test.ts`๊ฐ€ ํ•ด์„๋œ ํ™˜๊ฒฝ๊ณผ ํŒ”๋ ˆํŠธ๋ฅผ ๊ฒ€์ฆํ•œ๋‹ค. |
129
+
130
+ Showcase์˜ `DesignSystemProvider` Web reference๋Š” ์ด ์ฆ๊ฑฐ๋ฅผ ๋Œ€์‹ ํ•˜๋Š” ๊ฐ€์ƒ UI๊ฐ€ ์•„๋‹ˆ๋‹ค.
131
+ ๋™์ผํ•œ provider value์˜ theme, direction, textScale, reducedMotion๊ณผ ํ•ด์„๋œ palette๋ฅผ
132
+ ์ง์ ‘ ํ‘œ์‹œํ•˜๋Š” ๋น„์‹œ๊ฐ adapter presentation์ด๋‹ค.
133
+
134
+ ## ํ˜„์žฌ ์„ฑ์ˆ™๋„
135
+
136
+ catalog ์ƒํƒœ๋Š” `beta`๋‹ค. Web๊ณผ RN, ๋‘ ์ œํ’ˆ์—์„œ ๊ฐ’ ํ•ด์„ยทContext ์ „ํŒŒยทpalette ์†Œ๋น„,
137
+ ์ค‘์ฒฉ Provider์˜ omitted axis ์ƒ์† ๊ฒฝ๊ณ„๊นŒ์ง€ ํ™•์ธ๋๋‹ค. ๋‹ค๋งŒ ์ด ์ƒ์† adapter๊ฐ€ ํฌํ•จ๋œ
138
+ ์ถ”๊ฐ€ ์ œํ’ˆ ๋ฆด๋ฆฌ์Šค ์ฆ๊ฑฐ๋Š” ์•„์ง ์—†์œผ๋ฏ€๋กœ roadmap์€ ๋‹ค์Œ ์Šน๊ฒฉ ์กฐ๊ฑด์„
139
+ `evidence-needed`๋กœ ๊ธฐ๋กํ•˜๊ณ  `stable`์„ ๊ณผ์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค.
@@ -0,0 +1,78 @@
1
+ # Dropdown โ€” ๋ณ„๋„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค
2
+
3
+ ## ํŒ์ •
4
+
5
+ Ant Design์—์„œ `Dropdown`์€ "ํŠธ๋ฆฌ๊ฑฐ์— ๋ถ™๋Š” ์˜ค๋ฒ„๋ ˆ์ด"์ด๊ณ  ๊ทธ ์•ˆ์˜ ํ•ญ๋ชฉ ๋ชฉ๋ก์€ ๋ณ„๋„
6
+ ์ปดํฌ๋„ŒํŠธ `Menu`๊ฐ€ ์ฑ„์šด๋‹ค. ๋‘ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋‚˜๋‰œ ์ด์œ ๋Š” Ant Design์˜ Dropdown์ด ์ž„์˜
7
+ ์ฝ˜ํ…์ธ (`dropdownRender`)๋„ ๋‹ด์„ ์ˆ˜ ์žˆ๋Š” ๋ฒ”์šฉ ์˜ค๋ฒ„๋ ˆ์ด ์…ธ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
8
+
9
+ HJM์—๋Š” ์ด ๋ถ„๋ฆฌ๊ฐ€ ์—†๋‹ค. `menuRecipe`(`src/component-recipes.ts:628`)์˜ anatomy๋Š” ์ด๋ฏธ
10
+ `trigger, content, viewport, section, sectionLabel, item, ...`์ด๊ณ , `behaviorRegistry.menu`
11
+ (`src/behaviors.ts:815`)๋Š” `open`/`defaultOpen`/`onOpenChange`/`selection`/`asyncState`๋ฅผ
12
+ ์ง์ ‘ controlled ์ถ•์œผ๋กœ ๊ฐ€์ง„๋‹ค. ์ฆ‰ HJM์˜ `Menu`๋Š” ์ด๋ฏธ **ํŠธ๋ฆฌ๊ฑฐ + ๋–  ์žˆ๋Š” ํ‘œ๋ฉด + ํ•ญ๋ชฉ
13
+ ๋ชฉ๋ก**์„ ํ•œ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋๊นŒ์ง€ ์†Œ์œ ํ•œ๋‹ค. `expansion-roadmap.md`๋„ Menu๋ฅผ "Web anchored
14
+ surface์™€ RN Sheet๊ฐ€ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ๋งŒ๋“œ๋Š” adaptive ์Šฌ๋ผ์ด์Šค"๋กœ ์ด๋ฏธ beta ๊ฒ€์ฆํ–ˆ๋‹ค๊ณ 
15
+ ๊ธฐ๋กํ•œ๋‹ค.
16
+
17
+ ๊ทธ๋ž˜์„œ Ant Design ๊ธฐ์ค€ "Dropdown"์ด ์‹ค์ œ๋กœ ํ’€๋˜ ๋ฌธ์ œ โ€” ํŠธ๋ฆฌ๊ฑฐ๋ฅผ ๋ˆ„๋ฅด๋ฉด ๋œจ๋Š” action
18
+ ๋ชฉ๋ก โ€” ๋Š” HJM์—์„œ ์ด๋ฏธ `Menu` ํ•˜๋‚˜๋กœ ์™„๊ฒฐ๋œ ๋ฌธ์ œ๋‹ค. ์—ฌ๊ธฐ์— ์ด๋ฆ„๋งŒ ๋‹ค๋ฅธ `Dropdown`์„
19
+ ์ƒˆ๋กœ ๋งŒ๋“ค๋ฉด:
20
+
21
+ - `menuRecipe`์™€ ๊ฑฐ์˜ ๊ฐ™์€ `trigger`/`content`/`viewport` anatomy๋ฅผ ๋‹ค์‹œ ์„ ์–ธํ•˜๊ฒŒ ๋˜๊ณ ,
22
+ - `behaviorRegistry.menu`์™€ ๊ฑฐ์˜ ๊ฐ™์€ `open`/`dismiss`/`selection` ์ถ•์„ ๋‹ค์‹œ ๊ณ„์•ฝํ•˜๊ฒŒ
23
+ ๋˜์–ด, ๋‘ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ฐ™์€ ์ƒํƒœ๋ฅผ ์„œ๋กœ ๋‹ค๋ฅธ ์ด๋ฆ„์œผ๋กœ ์†Œ์œ ํ•˜๋Š” ์ •ํ™•ํžˆ ๊ทธ ์‹ค์ˆ˜(Tag๊ฐ€
24
+ `docs/tag.md`์—์„œ Chip์˜ `selected`์™€ ๋ณ„๋„ `closable` ์ถ•์„ ๋งŒ๋“ค์ง€ ์•Š๊ธฐ๋กœ ํ•œ ๊ฒƒ๊ณผ ๊ฐ™์€
25
+ ์ข…๋ฅ˜์˜ ์‹ค์ˆ˜)๋ฅผ ๋ฐ˜๋ณตํ•œ๋‹ค.
26
+
27
+ ## ์ž„์˜ ์ฝ˜ํ…์ธ  ์˜ค๋ฒ„๋ ˆ์ด๋Š” ์ด๋ฏธ ๋‹ค๋ฅธ ๊ณณ์— ์žˆ๋‹ค
28
+
29
+ **์…‹ ์ค‘ 2๋ฒˆ ์„ ํƒ์ง€ ๊ฒ€ํ† .** "Menu๋Š” ํ•ญ๋ชฉ collection๋งŒ ๋‹ค๋ฃจ๊ณ  Dropdown์€ ์ž„์˜ ์ฝ˜ํ…์ธ ๋ฅผ
30
+ ๋‹ด๋Š” ํ‘œ๋ฉด"์ด๋ผ๋Š” ๋ถ„๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•œ์ง€ ๊ฒ€ํ† ํ–ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ "ํŠธ๋ฆฌ๊ฑฐ์— ๋ถ™์–ด ์ž„์˜ ์ฝ˜ํ…์ธ ๋ฅผ ๋ณด์—ฌ
31
+ ์ฃผ๋Š” Web ์˜ค๋ฒ„๋ ˆ์ด"๋Š” ์ด๋ฏธ catalog์— `Popover`(`category: overlay`, `platform: web`,
32
+ `status: planned`)๋กœ ์ž๋ฆฌ๋ฅผ ์˜ˆ์•ฝํ•ด ๋‘์—ˆ๋‹ค. Ant Design์˜ crosswalk๋„ `Popover`๋ฅผ
33
+ `category: "data-display"`, `relationship: "direct"`๋กœ ์ด๋ฏธ ๋ณ„๋„ target์— ์—ฐ๊ฒฐํ•ด ๋‘์—ˆ๋‹ค
34
+ (`src/component-references.ts:102`). ์ฆ‰ "์ž„์˜ ์ฝ˜ํ…์ธ  ๋‹ด๋Š” ํŠธ๋ฆฌ๊ฑฐ ์˜ค๋ฒ„๋ ˆ์ด"๋ผ๋Š” ๋ฌธ์ œ๋Š”
35
+ HJM ์•ˆ์—์„œ ์ด๋ฏธ `Popover`์˜ ์ด๋ฆ„ํ‘œ๋ฅผ ๋‹ฌ๊ณ  ๋Œ€๊ธฐ ์ค‘์ด๋‹ค.
36
+
37
+ ์—ฌ๊ธฐ์„œ `Dropdown`์„ "์ž„์˜ ์ฝ˜ํ…์ธ "์šฉ์œผ๋กœ ๋‹ค์‹œ ์ •์˜ํ•˜๋ฉด `Popover`์™€ ์™„์ „ํžˆ ๊ฐ™์€ ๋ฌธ์ œ๋ฅผ
38
+ ๋‘ ์ด๋ฆ„์œผ๋กœ ๊ณ„์•ฝํ•˜๊ฒŒ ๋œ๋‹ค. ๋ธŒ๋ฆฌํ”„๊ฐ€ ๋ช…์‹œํ•œ ๋Œ€๋กœ Popover์™€ Dropdown์„ ๋™์‹œ์— ๋งŒ๋“ค์ง€
39
+ ์•Š๊ธฐ๋กœ ํ•˜๊ณ , ๋‘ planned ํ•ญ๋ชฉ ์ค‘ ์‹ค์ œ ์ œํ’ˆ์—์„œ ๋จผ์ € ์š”๊ตฌ๊ฐ€ ๋‚˜์˜ค๋Š” ์ชฝ๋งŒ ๊ณ„์•ฝํ•œ๋‹ค. ์ง€๊ธˆ์€
40
+ ์–ด๋А ์ชฝ๋„ vertical slice ๊ทผ๊ฑฐ๊ฐ€ ์—†์œผ๋ฏ€๋กœ **์•„๋ฌด๊ฒƒ๋„ ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค.**
41
+
42
+ ## ๊ฒฐ๋ก 
43
+
44
+ 1. Menu๊ฐ€ ์ด๋ฏธ ํŠธ๋ฆฌ๊ฑฐ+ํ‘œ๋ฉด+ํ•ญ๋ชฉ ๋ชฉ๋ก์˜ ๋ฌธ์ œ๋ฅผ ์™„๊ฒฐํ•œ๋‹ค โ€” antd Dropdown์˜ ์••๋„์  ๋‹ค์ˆ˜
45
+ ์‚ฌ์šฉ๋ฒ•("Dropdown + Menu" ์กฐํ•ฉ)์ด ์ •ํ™•ํžˆ ์ด ๋ฌธ์ œ๋‹ค.
46
+ 2. Dropdown์ด ํ•ญ๋ชฉ ๋ชฉ๋ก์ด ์•„๋‹Œ ์ž„์˜ ์ฝ˜ํ…์ธ ๋ฅผ ์œ„ํ•œ ๊ฒƒ์ด๋ผ๋Š” ๋Œ€์•ˆ์€ ์ด๋ฏธ `Popover`๊ฐ€
47
+ ์ ์œ ํ•œ ๋ฌธ์ œ์™€ ๊ตฌ๋ถ„๋˜์ง€ ์•Š๋Š”๋‹ค.
48
+ 3. ์ธก์ •๋œ ์ œํ’ˆ ์ˆ˜์š” ์—†์ด ๊ฒน์น˜๋Š” ๋‘ ํ‘œ๋ฉด์„ ๋งŒ๋“ค์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ด ์ €์žฅ์†Œ์˜ ์›์น™์ด๋‹ค
49
+ (`docs/authoring-brief.md`: "์—†๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ๋ณด๋‹ค ์•ˆ ๋งŒ๋“œ๋Š” ์ด์œ ๋ฅผ ๋‚จ๊ธฐ๋Š”
50
+ ๊ฒƒ์ด ์ด ์ €์žฅ์†Œ์— ๋” ๊ฐ’์ง€๋‹ค").
51
+
52
+ `src/dropdown.ts`, `test/dropdown.test.ts`๋Š” ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค. `antDesignReferenceComponents`์˜
53
+ `Dropdown โ†’ Dropdown` crosswalk(`relationship: "direct"`)๋„ ๋ฐ”๊ฟ€ ํ•„์š”๊ฐ€ ์—†๋‹ค โ€” target
54
+ `ComponentId`๋Š” ์œ ์ง€ํ•˜๋˜, catalog์˜ ์‹ค์ œ ๊ตฌํ˜„ ๊ฒฐ์ •๋งŒ ์•„๋ž˜๋กœ ์˜ฎ๊ธด๋‹ค.
55
+
56
+ ## ๋ฐฐ์„  ๋ช…์„ธ ์ œ์•ˆ (๋ฆฌ๋“œ ์ ์šฉ)
57
+
58
+ ๋‘ ๊ฐ€์ง€ ์ค‘ ํ•˜๋‚˜๋ฅผ ๋ฆฌ๋“œ๊ฐ€ ๊ณ ๋ฅธ๋‹ค. ์ด ์ €์ž‘์ž์˜ ๊ถŒ๊ณ ๋Š” (a)๋‹ค.
59
+
60
+ **(a) ๊ถŒ๊ณ : Menu์˜ alias๋กœ ํก์ˆ˜.**
61
+
62
+ ```ts
63
+ { name: "Menu", category: "navigation", platform: "adaptive", status: "beta",
64
+ recipe: "menuRecipe", behavior: "menu", aliases: ["Dropdown"] }
65
+ ```
66
+
67
+ ๊ธฐ์กด `{ name: "Dropdown", ... status: "planned" }` catalog row๋Š” ์ œ๊ฑฐํ•œ๋‹ค. Ant Design
68
+ crosswalk์˜ `Dropdown` source entry๋Š” ๊ทธ๋Œ€๋กœ ๋‘๋˜(๊ฐ™์€ `Menu` target์„ ์ด๋ฏธ ๊ฐ€๋ฆฌํ‚ค๊ณ 
69
+ ์žˆ์–ด ๋ณ€๊ฒฝ์ด ํ•„์š” ์—†๋‹ค), Component Explorer์˜ "Dropdown" ๊ฒ€์ƒ‰์€ `aliases`๋ฅผ ํ†ตํ•ด Menu๋กœ
70
+ ์•ˆ๋‚ด๋œ๋‹ค.
71
+
72
+ **(b) ๋Œ€์•ˆ: planned ์œ ์ง€ + ์ด์œ ๋งŒ ๊ธฐ๋ก.** catalog row๋ฅผ ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š๊ณ  ์ด ๋ฌธ์„œ๋งŒ ๋งํฌํ•œ๋‹ค.
73
+ alias ํก์ˆ˜๊ฐ€ Component Explorer ํ‘œ์‹œ ๋ฐฉ์‹๊ณผ ์ถฉ๋Œํ•˜๊ฑฐ๋‚˜ ์ถ”ํ›„ Menu๊ฐ€ collection ์ „์šฉ์œผ๋กœ
74
+ ์ข์•„์งˆ ๊ณ„ํš์ด ์žˆ๋‹ค๋ฉด ์ด ๋Œ€์•ˆ์„ ์“ด๋‹ค.
75
+
76
+ ์ด ์ €์ž‘์ž ํŒ๋‹จ์œผ๋กœ๋Š” (a)๊ฐ€ ๋งž๋‹ค โ€” `aliases`๋Š” ์ด๋ฏธ `FloatingActionButton: aliases:
77
+ ["FloatButton", "FAB"]`์ฒ˜๋Ÿผ "๋‹ค๋ฅธ ์ƒํƒœ๊ณ„ ์ด๋ฆ„์œผ๋กœ ์ฐพ์•„์™€๋„ ๊ฐ™์€ HJM ์ปดํฌ๋„ŒํŠธ๋กœ
78
+ ์•ˆ๋‚ดํ•œ๋‹ค"๋Š” ์ •ํ™•ํžˆ ์ด ์šฉ๋„๋กœ ์“ฐ์ด๊ณ  ์žˆ๋‹ค.
@@ -0,0 +1,285 @@
1
+ # HJM Design System Expansion Roadmap
2
+
3
+ ## ๋ฌด์—‡์„ ํก์ˆ˜ํ•˜๋Š”๊ฐ€
4
+
5
+ HJM์€ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์™ธํ˜•์ด๋‚˜ public prop ์ด๋ฆ„์„ ๋ณต์‚ฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ฐ ์‹œ์Šคํ…œ์—์„œ
6
+ ์ž˜ ๊ฒ€์ฆ๋œ ๋ฌธ์ œ ๋ถ„ํ•ด ๋ฐฉ์‹๋งŒ ๊ฐ€์ ธ์™€ HJM์˜ ๋ฌธ์žฅ์ธ **โ€œ์กฐ์šฉํ•œ ํ™”๋ฉด ์œ„์— ์ค‘์š”ํ•œ ์ˆœ๊ฐ„๋งŒ
7
+ ์„ ๋ช…ํ•˜๊ฒŒโ€**์— ๋งž๊ฒŒ ๋‹ค์‹œ ์„ค๊ณ„ํ•ฉ๋‹ˆ๋‹ค.
8
+
9
+ | ์ฐธ๊ณ  ์‹œ์Šคํ…œ | ํก์ˆ˜ํ•  ๊ฒƒ | ๊ทธ๋Œ€๋กœ ๊ฐ€์ ธ์˜ค์ง€ ์•Š์„ ๊ฒƒ |
10
+ | --- | --- | --- |
11
+ | Ant Design | ๋„“์€ ์ปดํฌ๋„ŒํŠธ ๋ฒ”์œ„, Form/Field ์—ญํ•  ๋ถ„๋ฆฌ, async ์ƒํƒœ | ์‹œ๊ฐ ์Šคํƒ€์ผ, variant ์ด๋ฆ„, runtime dependency |
12
+ | Radix Primitives | compound anatomy, focusยทdismissยทkeyboard acceptance table | DOM primitive๋ฅผ RN๊นŒ์ง€ ๊ฐ•์ œํ•˜๋Š” ๊ตฌ์กฐ |
13
+ | React Aria | stable key ๊ธฐ๋ฐ˜ collection, selection mode, ๊ตญ์ œํ™”ยทํ‚ค๋ณด๋“œ ๋ชจ๋ธ | React hook๊ณผ DOM ๊ตฌํ˜„ |
14
+ | Material | ์ƒํƒœ ์ถ• ์กฐํ•ฉ, adaptive layout, non-text contrast | Material shapeยทmotionยทcomponent appearance |
15
+ | TDS | ๋ชจ๋ฐ”์ผ ์ •๋ณด ์œ„๊ณ„, ์ž‘์€ ํ•ต์‹ฌ ์„ธํŠธ, ListRow ์ค‘์‹ฌ ์กฐํ•ฉ | ์ „์šฉ ์ž์‚ฐยทํฐํŠธยท์ปดํฌ๋„ŒํŠธยท์ด๋ฆ„์˜ ๋ณต์ œ |
16
+ | Polaris | component lifecycle, page/pattern catalog | Shopify ๋„๋ฉ”์ธ ์–ดํœ˜ |
17
+ | Tamagui | typed variant, Web popup/Native sheet์˜ adaptive intent | ์Šคํƒ€์ผ ์—”์ง„๊ณผ package dependency |
18
+
19
+ ๊ณต์‹ ์ฐธ๊ณ  ๋งํฌ๋Š” `docs/identity.md`์˜ ์ฐธ๊ณ  ์›์น™์— ๊ณ ์ •ํ•ฉ๋‹ˆ๋‹ค. ์ƒˆ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ฐธ๊ณ ํ•  ๋•Œ๋„
20
+ `๋ฌธ์ œ โ†’ ์ผ๋ฐ˜ํ™”ํ•œ ๊ณ„์•ฝ โ†’ HJM ๊ธฐ๋ณธ๊ฐ’ โ†’ ํ”Œ๋žซํผ ๋ฒˆ์—ญ โ†’ ๊ฒ€์ฆ ํ™”๋ฉด`์„ ๊ธฐ๋กํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
21
+
22
+ ### ใ€Œ๊ฒ€์ฆ ํ™”๋ฉดใ€์— ํ›„๋ณด๋ฅผ ์ ์„ ๋•Œ
23
+
24
+ **๊ตฌ์ฒด์ ์ธ ํ™”๋ฉดยท์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„์€ ์‹ค์ œ ์ฝ”๋“œ์—์„œ ํ™•์ธํ•œ ๋’ค์—๋งŒ ์ ์Šต๋‹ˆ๋‹ค.** ํ™•์ธํ•˜์ง€ ์•Š์•˜์œผ๋ฉด
25
+ `์•„์ง ์—†์Œ`์ด ์ •ํ™•ํ•œ ๊ฐ’์ด๊ณ , ๊ทธ๊ฒƒ๋งŒ ์ ๋Š” ๊ฒƒ์ด ์ •์งํ•œ ๋ฌธ์„œ์ž…๋‹ˆ๋‹ค.
26
+
27
+ ์ด ๊ทœ์น™์ด ํ•„์š”ํ•œ ์ด์œ ๋Š” **๊ฒŒ์ดํŠธ๊ฐ€ ์—ฌ๊ธฐ๋ฅผ ๋ชป ๋ณด๊ธฐ ๋•Œ๋ฌธ**์ž…๋‹ˆ๋‹ค. `pnpm typecheck && pnpm test`๋Š”
28
+ ์ด ์ €์žฅ์†Œ ์•ˆ๋งŒ ๊ฒ€์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ "๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค" ํŒ์ •์€ ๊ทผ๊ฑฐ๊ฐ€ ์ €์žฅ์†Œ ์•ˆ(๋‹ค๋ฅธ ๋ชจ๋“ˆ์˜ ๊ณ„์•ฝ)์—
29
+ ์žˆ์–ด ์–ด๊ธ‹๋‚˜๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ์žก์ง€๋งŒ, ใ€Œ๊ฒ€์ฆ ํ™”๋ฉดใ€์€ ๊ทผ๊ฑฐ๊ฐ€ **์ €์žฅ์†Œ ๋ฐ–**(์ œํ’ˆ ์ฝ”๋“œ)์— ์žˆ์–ด ๊ฐ™์€
30
+ ์‹ค์ˆ˜๋ผ๋„ ๊ฑธ๋ฆฌ๋Š” ๊ทธ๋ฌผ์ด ์—†์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ๋„ค ๋ฌธ์„œ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ™”๋ฉด์„ ํ›„๋ณด๋กœ ์ ์–ด ๋‘์—ˆ๊ณ ,
31
+ ์Šน๊ฒฉ์„ ์‹ค์ธกํ•˜๊ธฐ ์ „๊นŒ์ง€ ์•„๋ฌด๋„ ๋ชฐ๋ž์Šต๋‹ˆ๋‹ค(`docs/consistency-audit.md` 3์ฐจ).
32
+
33
+ ๊ทธ๋ž˜์„œ ํ›„๋ณด๋ฅผ ์ ์„ ๋•Œ๋Š” **`ํŒŒ์ผ:์ค„` ํ˜•ํƒœ๋กœ ์ธ์šฉํ•ฉ๋‹ˆ๋‹ค.** ์ธ์šฉ์ด ๊ทธ ์ž์ฒด๋กœ ์ฆ๋ช…์€ ์•„๋‹ˆ์ง€๋งŒ,
34
+ ์ ๋Š” ์‚ฌ๋žŒ์ด ํŒŒ์ผ์„ ์—ด๊ฒŒ ํ•˜๊ณ  ์ฝ๋Š” ์‚ฌ๋žŒ์ด ๋ฐ˜์ฆํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ์ธ์šฉํ•  ์ˆ˜ ์—†์œผ๋ฉด ๊ทธ๊ฒƒ์€
35
+ ํ›„๋ณด๊ฐ€ ์•„๋‹ˆ๋ผ ์ง์ž‘์ด๊ณ , ์ง์ž‘์€ ์ ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
36
+
37
+ Ant Design์˜ ํ˜„์žฌ ์ „์ฒด ๋ฒ”์œ„๋Š” [`ant-design-coverage.md`](./ant-design-coverage.md)์™€
38
+ `antDesignReferenceComponents`์— 6.6.1 core 73๊ฐœ๋กœ ๊ณ ์ •ํ•ฉ๋‹ˆ๋‹ค. 73/73์€ scope tracking์ด๋ฉฐ
39
+ renderer ์™„๋ฃŒ๋ฅผ ๋œปํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ™ˆ๊ณผ Showcase๋Š” Web reference, contract-only, Native-only
40
+ ์ฆ๊ฑฐ๋ฅผ ํ‘œ์‹œํ•˜๊ณ , reference crosswalk์˜ fully mature, partial maturity, planned-only ์ˆ˜์น˜์™€
41
+ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
42
+
43
+ ## ํ™•์žฅ ๊ตฌ์กฐ
44
+
45
+ ```text
46
+ Foundations โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
47
+ Semantic color references โ”œโ”€ Component fragments โ”€ Visual recipes โ”€โ”
48
+ โ”‚ โ”œโ”€ Web renderer
49
+ Behavior contracts โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”œโ”€ RN renderer
50
+ Collection contracts โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€ Product adapter
51
+ ```
52
+
53
+ - `component-contracts.ts`: focus, field frame, floating surface, collection item์ฒ˜๋Ÿผ ์—ฌ๋Ÿฌ
54
+ recipe๊ฐ€ ๊ณต์œ ํ•˜๋Š” ๋‚ด๋ถ€ ๋ฌธ๋ฒ•
55
+ - `component-recipes.ts`: anatomy, size, tone, visual state
56
+ - `behaviors.ts`: controlled state ์ด๋ฆ„, ์œ ํšจํ•œ state axis, Web keyboard/focus, RN
57
+ accessibilityState, ๊ณตํ†ต acceptance scenario
58
+ - `catalog.ts`: ๊ตฌํ˜„ ๋ฒ”์œ„, ํ”Œ๋žซํผ ๋ถ„๋ฅ˜, maturity์™€ recipe/behavior ์—ฐ๊ฒฐ
59
+
60
+ ์‹œ๊ฐ recipe๋งŒ์œผ๋กœ ๊ตฌํ˜„ ์™„๋ฃŒ๋ฅผ ์ฃผ์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Menu, Tabs, Dialog์ฒ˜๋Ÿผ ํ–‰๋™์ด ์ค‘์š”ํ•œ
61
+ ์ปดํฌ๋„ŒํŠธ๋Š” behavior scenario๊นŒ์ง€ renderer ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
62
+
63
+ ## ๊ณตํ†ต ์ƒํƒœ ์ถ•
64
+
65
+ | ์ถ• | ๊ฐ’ |
66
+ | --- | --- |
67
+ | interaction | idle, hover, focusVisible, pressed, dragged |
68
+ | availability | enabled, disabled, readOnly, busy |
69
+ | value | empty, filled, checked, mixed, selected, open, expanded |
70
+ | validation | valid, invalid |
71
+ | content | idle, loading, loadingMore, empty, error |
72
+
73
+ ์ปดํฌ๋„ŒํŠธ๋Š” ํ•„์š”ํ•œ ์ถ•๋งŒ ๊ณต๊ฐœํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด Link๋Š” disabled๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š๊ณ , AlertDialog๋Š”
74
+ outside dismiss๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ฐ˜๋“œ์‹œ ๋ณ„๋„ fixture๋กœ ๊ฒ€์ฆํ•  ์กฐํ•ฉ์€
75
+ `selected + focusVisible`, `invalid + focusVisible`, `busy + focusVisible`,
76
+ `open + selected item`์ž…๋‹ˆ๋‹ค.
77
+
78
+ ## Collection ๊ธฐ๋ณธ ๊ณ„์•ฝ
79
+
80
+ Menu, Select, Combobox, DataTable, Tree๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ์„ ๋งŒ๋“ค์ง€ ์•Š๋„๋ก ๋‹ค์Œ์„
81
+ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค.
82
+
83
+ - stable string `id`
84
+ - ๋ณด์ด๋Š” `label`๊ณผ typeahead/๊ฒ€์ƒ‰์šฉ `textValue`
85
+ - ์„ ํƒ์  `description`, `disabled`; ์œ„ํ—˜ `tone`๊ณผ `shortcut`์€ Menu descriptor์—๋งŒ ์ถ”๊ฐ€
86
+ - section์˜ ๋ณด์ด๋Š” label ๋˜๋Š” accessibility label
87
+ - `none | single | multiple` selection mode
88
+ - `idle | loading | loadingMore | empty | error` async state
89
+ - interactive item ์•ˆ์— ๋˜ ๋‹ค๋ฅธ button/link ๊ธˆ์ง€
90
+
91
+ ์ œํ’ˆ ๊ฐ์ฒด๋ฅผ recipe์— ์ง์ ‘ ๋„˜๊ธฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ œํ’ˆ adapter๊ฐ€ ๋ชฉ์ ์— ๋งž๋Š” descriptor๋กœ ๋ณ€ํ™˜ํ•˜๋ฉฐ
92
+ ๋„๋ฉ”์ธ ID๋ฅผ ์œ ์ง€ํ•˜๊ณ , semantic tone์€ ๊ทธ ์˜๋ฏธ๋ฅผ ์ง€์›ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์—๋งŒ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
93
+
94
+ ## ๊ณต๊ฐœ ๋ฐฐ์น˜
95
+
96
+ ### ํ˜„์žฌ ์‹ค์ œ ์•ฑ์—์„œ ๊ฒ€์ฆ ์ค‘
97
+
98
+ - Button, Field, Surface
99
+ - IconButton, Badge, CounterBadge
100
+ - SegmentedControl, Tabs, SearchField
101
+ - Checkbox, CheckboxGroup, RadioGroup
102
+ - List, ListRow, Divider, Section
103
+ - Notice, EmptyState, Skeleton
104
+ - Sheet, Dialog, Toast, BottomCTA, TopBar
105
+ - Select, Combobox
106
+
107
+ ### Batch 1 โ€” ๊ธฐ๋ฐ˜๊ณผ ํ–‰๋™ ๊ฒ€์ฆ (beta ์ ์šฉ ์ค‘)
108
+
109
+ - shared: Icon, Stack, Checkbox/CheckboxGroup/RadioGroup, Accordion
110
+ - adaptive: Link, Menu, AlertDialog
111
+ - web: Tooltip
112
+
113
+ Accordion์€ disclosure behavior์˜ ์ฒซ shared ์„ธ๋กœ ์Šฌ๋ผ์ด์Šค, Menu๋Š” Web anchored surface์™€ RN
114
+ Sheet๊ฐ€ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ๋งŒ๋“œ๋Š” adaptive ์Šฌ๋ผ์ด์Šค, AlertDialog๋Š” focus/back/async confirm์„
115
+ ๊ฒ€์ฆํ•˜๋Š” overlay ์Šฌ๋ผ์ด์Šค๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
116
+
117
+ Tooltip์€ ํ˜„์ง€ํ™”๋œ plain text ๋ณด์ถฉ ์„ค๋ช…๋งŒ ํ—ˆ์šฉํ•˜๋Š” Web ์ „์šฉ overlay์ž…๋‹ˆ๋‹ค. focus๋Š” ์ฆ‰์‹œ,
118
+ pointer๋Š” ์ง€์—ฐ ํ›„ ์—ด๊ณ  trigger/content hoverยทpointer corridorยทEscapeยทskip delayยทํ•œ ๋ฒˆ์— ํ•˜๋‚˜๋งŒ
119
+ ์—ด๋ฆผ์„ provider๊ฐ€ ์กฐ์ •ํ•ฉ๋‹ˆ๋‹ค. portal/flip/shift/RTL/visual viewport๋Š” ์ œํ’ˆ Web renderer์˜
120
+ ๋น„๊ณต๊ฐœ AnchoredOverlay์— ๋‘๊ณ  interactive Popover๋กœ ํ™•์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ƒ์„ธ๋Š”
121
+ `docs/tooltip.md`์— ๋‘ก๋‹ˆ๋‹ค.
122
+
123
+ BurnTok ์•Œ๋ฆผ ๋ฒ„ํŠผ vertical slice์—์„œ ์‹ค์ œ anchor clone, ๊ธฐ์กด `aria-describedby`, focus์™€
124
+ pointer ์ˆ˜๋ช…์ฃผ๊ธฐ, controlled close ๊ฑฐ๋ถ€, sibling FIFO, detached anchor, portal RTL๊ณผ viewport
125
+ collision์„ ๊ฒ€์ฆํ–ˆ์Šต๋‹ˆ๋‹ค. Tooltip surface๋Š” interaction์„ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š๊ณ  plain copy๋งŒ
126
+ ์ œ๊ณตํ•˜๋ฉฐ Reduce Motion exit๋„ ๊ฐ™์€ ์™„๋ฃŒ ๊ฒฝ๊ณ„๋ฅผ ์ง€๋‚˜๋ฏ€๋กœ Tooltip์„ Web beta๋กœ ์Šน๊ฒฉํ•ฉ๋‹ˆ๋‹ค.
127
+
128
+ Icon์€ ์™ธ๋ถ€ package component๋ฅผ ํ™”๋ฉด์—์„œ ์ง์ ‘ ๊ณ ๋ฅด๋Š” ๋ฐฉ์‹ ๋Œ€์‹  HJM semantic name์„ ์ œํ’ˆ
129
+ adapter๊ฐ€ tree-shakeable glyph๋กœ ๋ฒˆ์—ญํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์€ decorative์ด๋ฉฐ ์ •๋ณด icon๋งŒ ํ˜„์ง€ํ™”๋œ
130
+ ์ ‘๊ทผ์„ฑ ์ด๋ฆ„์„ ์š”๊ตฌํ•˜๊ณ , ๋…ผ๋ฆฌ ๋ฐฉํ–ฅ icon๋งŒ RTL์—์„œ mirrorํ•ฉ๋‹ˆ๋‹ค. ์ƒ์„ธ๋Š” `docs/icon.md`์— ๋‘ก๋‹ˆ๋‹ค.
131
+
132
+ Link๋Š” Button callback์ด ์•„๋‹ˆ๋ผ ํ•„์ˆ˜ `href`๊ฐ€ ์žˆ๋Š” ๋ชฉ์ ์ง€์ž…๋‹ˆ๋‹ค. Web์€ ์‹ค์ œ anchor/Next Link๋กœ
133
+ modifier clickยทcontext menuยท์ƒˆ ํƒญ์„ ๋ณด์กดํ•˜๊ณ , Native๋Š” internal Expo Router Link์™€ external
134
+ Linking adapter๋กœ ์ ์‘ํ•ฉ๋‹ˆ๋‹ค. disabledยทvisited application stateยทdownload๋Š” ๊ณตํ†ต API์— ๋„ฃ์ง€
135
+ ์•Š์Šต๋‹ˆ๋‹ค. BurnTok ๋ฉ”์‹œ์ง€ ๋ชฉ๋ก์˜ ๊ณ ์ • conversation-row adapter์—์„œ Web anchor์™€ Native
136
+ `Link asChild`, unread ์ ‘๊ทผ์„ฑ ์ด๋ฆ„, modifier/context navigation, pressed feedback์„
137
+ ๊ฒ€์ฆํ–ˆ์œผ๋ฏ€๋กœ Link๋ฅผ adaptive beta๋กœ ์Šน๊ฒฉํ•ฉ๋‹ˆ๋‹ค.
138
+ Stack์€ ๋ฐ˜๋ณต๋˜๋Š” ๋‚ด๋ถ€ flex๋ฅผ ๊ฐ์‹ธ๋Š” ๊ฒƒ๋งŒ์œผ๋กœ ์ œํ’ˆ ์˜๋ฏธ๋‚˜ ์ ‘๊ทผ์„ฑ ๊ณ„์•ฝ์ด ์ƒ๊ธฐ์ง€ ์•Š์œผ๋ฏ€๋กœ ์‹ค์ œ
139
+ paired layout ์š”๊ตฌ๊ฐ€ ๋‚˜ํƒ€๋‚  ๋•Œ๊นŒ์ง€ planned recipe ์ด์ƒ์œผ๋กœ ๊ณต๊ฐœํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
140
+
141
+ BurnTok Web/RN๊ณผ Yajalal RN์˜ Toast tone mark, Yajalal Statistic trend mark์—์„œ ๊ฐ™์€ semantic
142
+ registryยทtoneยทsizeยทstrokeยทRTL ๊ณ„์•ฝ์„ ์‹ค์ œ renderer๋กœ ๊ฒ€์ฆํ–ˆ์Šต๋‹ˆ๋‹ค. ์ œํ’ˆ ์ „์šฉ ์•ผ๊ตฌ icon์€
143
+ ๋ณ„๋„ adapter์— ๋‚จ๊ธฐ๊ณ  raw colorยท์ˆซ์ž sizeยทstroke override๊ฐ€ ๊ณต์šฉ API๋กœ ์ƒˆ์ง€ ์•Š๊ฒŒ ํ–ˆ์œผ๋ฏ€๋กœ
144
+ Icon์„ beta๋กœ ์Šน๊ฒฉํ•ฉ๋‹ˆ๋‹ค.
145
+
146
+ AlertDialog๋Š” `idle โ†’ busy โ†’ error/closing โ†’ closed` session์„ ๊ณตํ†ต ๊ธฐ๋ฐ˜์œผ๋กœ ์‚ผ์Šต๋‹ˆ๋‹ค.
147
+ confirm side effect์™€ ๊ฒฐ๊ณผ ์ •์‚ฐ์„ ๋ณ„๋„ once guard๋กœ ๋‚˜๋ˆ„์ง€ ์•Š๊ณ  ํ•œ session์ด ์†Œ์œ ํ•˜๋ฉฐ,
148
+ outside dismiss๋Š” ์˜๊ตฌ ๊ธˆ์ง€ํ•ฉ๋‹ˆ๋‹ค. Web์˜ exit ์™„๋ฃŒ์™€ Native Modal dismissal ์ดํ›„์—๋งŒ ๊ฒฐ๊ณผ๋ฅผ
149
+ ์ •์‚ฐํ•˜๋ฏ€๋กœ ์ค‘์ฒฉ ํ™•์ธ๋„ ๋™์‹œ์— ๋‘ ๊ฐœ๊ฐ€ ์—ด๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
150
+
151
+ Sheet๋Š” beta ๋‹จ๊ณ„์—์„œ `SheetOpenState`, concrete dismiss reason, `SheetDismissPolicy`์™€
152
+ `canDismissSheet`๋ฅผ ๊ณตํ†ต ๊ณ„์•ฝ์œผ๋กœ ๊ณ ์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ close/outside/Escapeยทback ํ—ˆ์šฉ,
153
+ busy dismiss์™€ swipe ๊ธˆ์ง€์ž…๋‹ˆ๋‹ค. controlled owner์˜ programmatic close๋Š” ํ•ญ์ƒ ํ—ˆ์šฉํ•˜๊ณ ,
154
+ ํ›„์† overlay๋Š” exit/onDismiss๊ฐ€ ๋๋‚œ ๋’ค ์—ฝ๋‹ˆ๋‹ค. drag handle์€ swipe gesture capability์™€
155
+ ๋ช…์‹œ์  policy๊ฐ€ ๋ชจ๋‘ ์ผœ์ง„ renderer์—์„œ๋งŒ ๋ณด์—ฌ ๋™์ž‘ํ•˜์ง€ ์•Š๋Š” affordance๋ฅผ ๋งŒ๋“ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
156
+ visual recipe๋Š” border/shadow, ์ฝ˜ํ…์ธ  typography rhythm, Web max-width, safe-area, Reduce Motion๋งŒ
157
+ ๋‹ด๊ณ  dismiss behavior๋Š” ํฌํ•จํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
158
+
159
+ Toast๋Š” root provider์˜ bounded FIFO์™€ stable-id update๋ฅผ ๊ณตํ†ตํ™”ํ•ฉ๋‹ˆ๋‹ค. queued ํ•ญ๋ชฉ์—๋Š” timer๋ฅผ
160
+ ์‹œ์ž‘ํ•˜์ง€ ์•Š๊ณ  visible ๋™์•ˆ pointer/focus/window/gesture pause๋ฅผ ํ•ฉ์„ฑํ•˜๋ฉฐ, action๊ณผ dismiss๋Š”
161
+ ํ•œ revision์—์„œ ์ •ํ™•ํžˆ ํ•œ ๋ฒˆ๋งŒ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์™ธํ˜• tone๊ณผ announcement priority๋ฅผ ๋ถ„๋ฆฌํ•˜๊ณ  ๋ชจ๋“ 
162
+ tone์„ ๊ณ ์œ  icon mark์™€ ํ•จ๊ป˜ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ์ƒ์„ธ ๊ณ„์•ฝ์€ `docs/toast.md`์— ๋‘ก๋‹ˆ๋‹ค.
163
+
164
+ ์„ ํƒ ์ž…๋ ฅ์€ ๋‹จ์ผ mode prop์œผ๋กœ ํ•ฉ์น˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Checkbox, CheckboxGroup, RadioGroup์ด
165
+ ์‹œ๊ฐ recipe๋งŒ ๊ณต์œ ํ•˜๊ณ , Checkbox๋Š” ๊ฐ native tab stop, RadioGroup์€ roving focus๋ฅผ ๊ฐ–์Šต๋‹ˆ๋‹ค.
166
+ ๊ทธ๋ฃน ๊ฐ’์€ stable string id์™€ `ReadonlySet` ๋˜๋Š” nullable single key๋งŒ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
167
+
168
+ ### Batch 2 โ€” ์ž…๋ ฅ๊ณผ ํƒ์ƒ‰ (beta ์ ์šฉ ์ค‘)
169
+
170
+ - shared: Steps, Statistic, Slider, NumberField, LoadMore
171
+ - adaptive: Select, Combobox, BottomNavigation
172
+ - `ContextPanel`์€ ์ด ๋ชฉ๋ก์—์„œ ๋บ๋‹ค. ์„ ํƒ ๋Œ€์ƒ์˜ ์ƒ์„ธ๋ฅผ ์˜†์— ๋ณด์—ฌ ์ฃผ๋Š” ๋ฌธ์ œ๋Š”
173
+ `Drawer`๋ฅผ ๋ถ„ํ•ดํ•  ๋•Œ ์ด๋ฏธ **Web `SidePanel`(+`modal: false`) / Native `Sheet`**๋กœ
174
+ ๋‹ต์ด ๋‚˜์™€ ์žˆ์—ˆ๋‹ค. ๋กœ๋“œ๋งต์ด ์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„์„ ๋จผ์ € ์ ์–ด ๋‘๊ณ  ๋ฌธ์ œ ์ •์˜๋ฅผ ๋‚˜์ค‘์œผ๋กœ
175
+ ๋ฏธ๋ฃจ๋ฉด ์ด๋Ÿฐ ์ค‘๋ณต์ด ์ƒ๊ธด๋‹ค โ€” ๊ทผ๊ฑฐ๋Š” `docs/context-panel.md`.
176
+ - web: Pagination, Breadcrumb
177
+
178
+ Statistic์€ ์ œํ’ˆ์ด ํฌ๋งทํ•œ ๋ฌธ์ž์—ด์„ ๋ฐ›์•„ label/value/hint/trend ์œ„๊ณ„๋งŒ ํ†ต์ผํ•ฉ๋‹ˆ๋‹ค. trend ๋ฐฉํ–ฅ๊ณผ
179
+ semantic tone์€ ๋…๋ฆฝ์ด๊ณ  arrow/minus์™€ visible copy๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฃน์€ ๊ฐ ๊ฐ’์„ ํ•˜๋‚˜์˜
180
+ ์ถ•์•ฝ๋œ ์ ‘๊ทผ์„ฑ ๋…ธ๋“œ๋กœ ํ•ฉ์น˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
181
+
182
+ Yajalal์˜ ์„ ์ˆ˜ยทFA ๊ธฐ๋ก vertical slice์—์„œ ๊ธฐ์กด StatGrid ํ˜ธํ™˜ adapter์™€ ์ƒˆ Statistic renderer๋ฅผ
183
+ ํ•จ๊ป˜ ๊ฒ€์ฆํ–ˆ์Šต๋‹ˆ๋‹ค. ์ข์€ ํญ์—์„œ๋Š” 1์—ด๊นŒ์ง€ reflowํ•˜๊ณ  ํฐ ๊ธ€์ž์—์„œ๋„ ๊ฐ’์„ ์ค„ ์ˆ˜๋กœ ์ž๋ฅด์ง€ ์•Š์œผ๋ฉฐ,
184
+ ๊ฐ ํ†ต๊ณ„์˜ label/value/hint/trend๋ฅผ ๋…๋ฆฝ๋œ ์ ‘๊ทผ์„ฑ ์ด๋ฆ„์œผ๋กœ ์œ ์ง€ํ•˜๋ฏ€๋กœ Statistic์„ beta๋กœ
185
+ ์Šน๊ฒฉํ•ฉ๋‹ˆ๋‹ค.
186
+
187
+ Select/Combobox๋Š” Menu์˜ collection contract๋ฅผ ๊ณต์œ ํ•˜์ง€๋งŒ role๊ณผ dismiss behavior๋Š” ๋ณ„๋„์ž…๋‹ˆ๋‹ค.
188
+ Web์€ listbox popup, Native๋Š” Sheet๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. Native ๊ธด ๋ชฉ๋ก์—๋Š” ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ๋ณด๋‹ค
189
+ LoadMore/infinite loading์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
190
+
191
+ LoadMore๋Š” `ready | loading | error | complete` footer state์™€ stable `requestKey`๋งŒ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค.
192
+ Web IntersectionObserver์™€ Native onEndReached๋Š” ํ”Œ๋žซํผ renderer๊ฐ€ ์†Œ์œ ํ•˜๊ณ , ๊ณตํ†ต controller๋Š”
193
+ ์š”์ฒญ ํ•˜๋‚˜๋งŒ ํ†ต๊ณผ์‹œ์ผœ ๋ฐ˜๋ณต viewport event์™€ retry ์ค‘๋ณต์„ ๋ง‰์Šต๋‹ˆ๋‹ค. automatic mode๋„ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ
194
+ manual fallback์„ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.
195
+
196
+ BurnTok ํ™ˆ ํ”ผ๋“œ vertical slice์—์„œ Web IntersectionObserver์™€ ํ•ญ์ƒ ๋ณด์ด๋Š” manual fallback,
197
+ Native FlatList onEndReached์™€ footer fallback์„ ๊ฐ™์€ controller์— ์—ฐ๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‘ renderer ๋ชจ๋‘
198
+ ํƒญ๊ณผ ๋‹ค์Œ offset์œผ๋กœ requestKey๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ค์ œ ํŽ˜์ด์ง€ ์š”์ฒญ Promise๊ฐ€ ๋๋‚  ๋•Œ๊นŒ์ง€ ์ค‘๋ณต ํ˜ธ์ถœ์„
199
+ ์ฐจ๋‹จํ•˜๋ฉฐ loading/error/complete ์ ‘๊ทผ์„ฑ ์ƒํƒœ๋ฅผ ๊ฒ€์ฆํ–ˆ์œผ๋ฏ€๋กœ LoadMore๋ฅผ beta๋กœ ์Šน๊ฒฉํ•ฉ๋‹ˆ๋‹ค.
200
+
201
+ BottomNavigation์€ route source-of-truth๋ฅผ ๋ณต์ œํ•˜์ง€ ์•Š๊ณ  `selectedKey`๋ฅผ input์œผ๋กœ๋งŒ ๋ฐ›์Šต๋‹ˆ๋‹ค.
202
+ Web renderer๋Š” ์‹ค์ œ link์™€ `aria-current`, Native renderer๋Š” navigator์˜ preventable tabPress์™€
203
+ long press๋ฅผ ๋ณด์กดํ•ฉ๋‹ˆ๋‹ค. ์ˆซ์ž badge๋Š” visual subtree๋ฅผ ์ ‘๊ทผ์„ฑ์—์„œ ์ˆจ๊ธฐ๊ณ  item root์— ํ•ฉ์„ฑ๋œ
204
+ ์ด๋ฆ„์„ ํ•œ ๋ฒˆ๋งŒ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. BurnTok ์ค‘์•™ ์ƒ์„ฑ action์€ `center-gap`์— ๋†“์ด๋Š” sibling primary
205
+ action์ด๋ฉฐ destination collection์—๋Š” ๋“ค์–ด๊ฐ€์ง€ ์•Š์Šต๋‹ˆ๋‹ค. BurnTok Web/RN๊ณผ Yajalal RN ์‹ค์ œ
206
+ navigation์— ์ ์šฉํ•ด route stateยทdisabled/reselectยท๊ธด ๊ธ€์žยทsafe areaยทRTL ๊ณ„์•ฝ์„ ๊ฒ€์ฆํ–ˆ์œผ๋ฏ€๋กœ
207
+ BottomNavigation์„ beta๋กœ ์Šน๊ฒฉํ•ฉ๋‹ˆ๋‹ค.
208
+
209
+ ์„ ํ–‰ ํƒ€์ž…์€ Select์˜ nullable stable key์™€ Combobox์˜ `selectedKey`/`inputValue` ๋ถ„๋ฆฌ๋ฅผ
210
+ ๊ณ ์ •ํ•ฉ๋‹ˆ๋‹ค. local filtering๊ณผ server-driven external filtering๋„ ๊ตฌ๋ถ„ํ•ด ์„ ํƒ ์ƒํƒœ์™€ ๋น„๋™๊ธฐ
211
+ ๊ฒ€์ƒ‰ ์ƒํƒœ๊ฐ€ ์„œ๋กœ ๋ฎ์–ด์“ฐ์ง€ ์•Š๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ์‹ค์ œ ์ œํ’ˆ ํ๋ฆ„์—์„œ ํ™•์ธ๋œ stable key, stale result,
212
+ committed item snapshot๋งŒ ๊ณต๊ฐœํ•˜๊ณ  ์ž„์˜ ๊ฐ’ ์ƒ์„ฑ์ด๋‚˜ option ๋‚ด๋ถ€ action์€ ์•„์ง ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
213
+
214
+ `validateCollection`, `flattenCollectionItems`, `resolveCollectionItem`,
215
+ `reconcileSelectSelection`์€ ๋จผ์ € ๊ณต๊ฐœํ•ฉ๋‹ˆ๋‹ค. item ID๋Š” section ์ „์ฒด์—์„œ ์œ ์ผํ•˜๊ณ  ๋ณด์ด๋Š”
216
+ labelยทtypeahead์šฉ textValueยทsection accessible name์€ ๋น„์–ด ์žˆ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. Select์˜ open
217
+ state๋„ selection state์™€ ๋ณ„๋„ controlled/uncontrolled ์ถ•์œผ๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.
218
+
219
+ ### vertical slice๊ฐ€ ์—†๋Š” ๊ณ„์•ฝ โ€” ์ฑ„ํƒ ์ „ ํ™•์ธํ•  ๊ฒƒ
220
+
221
+ surface๋ณ„ `planned โ†’ beta` gate๋Š” public renderer export์™€ package CI๊ฐ€ ์‹คํ–‰ํ•˜๋Š” canonical
222
+ `default` proof๋ฅผ ์š”๊ตฌํ•ฉ๋‹ˆ๋‹ค. ์‹ค์ œ ์ œํ’ˆ vertical slice๋Š” ๋ณ„๋„์˜ adoption evidence์ด๋ฉฐ,
223
+ ์—†๋‹ค๋ฉด beta์˜ ํ™˜๊ฒฝ debt์™€ ํ•จ๊ป˜ ๊ณต๊ฐœ๋˜๊ณ  stable ์Šน๊ฒฉ์„ ๋ง‰์Šต๋‹ˆ๋‹ค. ์ œํ’ˆ ์ฑ„ํƒ์„ ๊ฒ€ํ† ํ•˜๋Š”
224
+ ๊ณผ์ •์—์„œ **์ „์ œ๊ฐ€ ์ด๋ฏธ ๋ฐ”๋€Œ์–ด ์žˆ๋˜ ์‚ฌ๋ก€**๋„ ๋‚˜์™”์Šต๋‹ˆ๋‹ค.
225
+
226
+ `Calendar`ยท`DatePicker`๋ฅผ ์œ„์ž„ํ•  ๋•Œ "์•ผ์ž˜์•Œ ์ผ์ • ์ฐพ๊ธฐ๊ฐ€ ์›” ๋‹ฌ๋ ฅ ๊ฒฉ์ž๋ฅผ ์ž์ฒด ๊ตฌํ˜„ ์ค‘"์ด๋ผ๋Š”
227
+ ์ „์ œ๋ฅผ ์คฌ๋Š”๋ฐ, ์ €์ž‘์ž๊ฐ€ ์†Œ์Šค๋ฅผ ์ง์ ‘ ํ™•์ธํ•ด ๊ทธ ์ „์ œ๊ฐ€ **์ปค๋ฐ‹ `0f4887c`(ใ€Œ์ผ์ • ํƒ์ƒ‰๊ธฐ ์›”
228
+ ๊ทธ๋ฆฌ๋“œ๋ฅผ ๋‚ ์งœ ๋ ˆ์ผ๋กœ ๊ต์ฒดใ€)์—์„œ ์ด๋ฏธ ๊นจ์กŒ๋‹ค**๋Š” ๊ฒƒ์„ ์ฐพ์•„๋ƒˆ๋‹ค. `buildCalendarCells`๋Š”
229
+ ๋‚จ์•„ ์žˆ์ง€๋งŒ ๋ Œ๋”๋˜์ง€ ์•Š๊ณ  ์›” ๋ฒ”์œ„ ์ฟผ๋ฆฌ์˜ ๋‚ด๋ถ€ ๊ณ„์‚ฐ์ผ ๋ฟ์ด๋ฉฐ, ํ™”๋ฉด์€ ์›” ํ—ค๋” + 7์ผ
230
+ ๋‚ ์งœ ๋ ˆ์ผ์ด๋‹ค. ์•ฑ ์ „์ฒด์— ๊ฐ’ ํ•˜๋‚˜๋ฅผ ๊ณ ๋ฅด๋Š” ์••์ถ• ํŠธ๋ฆฌ๊ฑฐ UI๋„ ์—†๋‹ค.
231
+
232
+ ์ดํ›„ DatePicker์—๋Š” first-party WebยทNative renderer์™€ canonical ํ™˜๊ฒฝ ์ฆ๊ฑฐ๊ฐ€ ์ถ”๊ฐ€๋˜์–ด
233
+ `beta`๋กœ ์Šน๊ฒฉ๋๋‹ค. ๋‹ค๋งŒ ์œ„ ์‹ค์ธก์€ ์—ฌ์ „ํžˆ ์œ ํšจํ•˜๋‹ค. **์ œํ’ˆ adoption evidence๋Š” ์—†๊ณ **,
234
+ Yajalal์˜ ๋‚ ์งœ ๋ ˆ์ผ์„ DatePicker ์ฑ„ํƒ์œผ๋กœ ์„ธ์ง€ ์•Š๋Š”๋‹ค. ๋”ฐ๋ผ์„œ `stable` ์Šน๊ฒฉ ๊ทผ๊ฑฐ๋Š” ์—†๋‹ค.
235
+
236
+ **๊ตํ›ˆ**: ์œ„์ž„ํ•  ๋•Œ ์ค€ ์‹ค์‚ฌ์šฉ์ฒ˜ ์ „์ œ๋ฅผ ์ €์ž‘์ž๊ฐ€ **ํ™•์ธํ•˜๊ฒŒ** ํ•ด์•ผ ํ•œ๋‹ค. ๋ฆฌ๋“œ์˜ ๊ธฐ์–ต์€
237
+ ์ปค๋ฐ‹ ํ•˜๋‚˜๋กœ ๋‚ก๋Š”๋‹ค.
238
+
239
+ ### Batch 3 โ€” ๋ณตํ•ฉ ๋ฐ์ดํ„ฐ์™€ ํŒŒ์ผ
240
+
241
+ - beta: Timeline, UploadItem, DatePicker, FilePicker
242
+ - planned: TimePicker
243
+ - web: DataTable, Tree, ColorPicker, CommandPalette, SidePanel, Popover
244
+
245
+ FilePicker๋Š” ํŒŒ์ผ ์„ ํƒ ์˜๋„๋งŒ ์†Œ์œ ํ•ฉ๋‹ˆ๋‹ค. ์—…๋กœ๋“œ ์š”์ฒญยท์žฌ์‹œ๋„ยท์„œ๋ฒ„ ์ƒํƒœ๋Š” ์ œํ’ˆ์ด ์†Œ์œ ํ•˜๊ณ ,
246
+ ๊ณต์œ  UI์—๋Š” UploadItem์˜ progress/success/error/cancel ํ‘œํ˜„๋งŒ ๋‘ก๋‹ˆ๋‹ค.
247
+
248
+ ## ์ œํ’ˆ ์ ์šฉ ์ˆœ์„œ
249
+
250
+ ### BurnTok
251
+
252
+ 1. SearchField, CounterBadge, ShareSheet/ListRow
253
+ 2. messages/notifications metadata row์™€ unread state
254
+ 3. Sheet์˜ ์‹œ๊ฐ recipe ์—ฐ๊ฒฐ โ€” ๊ธฐ์กด focus trapยทscroll lock์€ ๋ณด์กด
255
+ 4. action Menu๋ฅผ ๊ณต์œ /ํ”ผ๋“œ์—์„œ ๊ฒ€์ฆ
256
+ 5. Dialog์™€ AlertDialog๋ฅผ ๋ถ„๋ฆฌ
257
+
258
+ ### Yajalal
259
+
260
+ 1. SearchField, BottomCTA, Notice, CounterBadge
261
+ 2. Chip์„ action/radio/checkbox๋กœ ์˜๋ฏธ ๋ถ„๋ฆฌ
262
+ 3. List/ListRow/Section/Skeleton์„ ๊ณต์šฉ recipe์— ์—ฐ๊ฒฐ
263
+ 4. Accordion์„ ๊ธฐ๋ก ์ƒ์„ธ์—์„œ ๊ฒ€์ฆ
264
+ 5. Menu/Select๋ฅผ ์„ ์ˆ˜ยท์‹œ์ฆŒ ์„ ํƒ ํ๋ฆ„์— ์ ์šฉ
265
+
266
+ ์ œํ’ˆ ์ „์šฉ `ai` accent, `built`, `live`, `win`, ๊ตฌ๋‹จ ์ƒ‰์€ adapter์— ๋‚จ๊ณ  recipe์—๋Š”
267
+ `info`, `success`, `attention`, `brand` ๊ฐ™์€ ๊ณต์šฉ ์˜๋ฏธ๋งŒ ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด
268
+ `SemanticIconName`์˜ `ai`๋Š” ํŠน์ • ๋ชจ๋ธ์ด๋‚˜ ์ œํ’ˆ ์ƒ‰์„ ๋œปํ•˜์ง€ ์•Š๋Š” ์ผ๋ฐ˜ โ€œAI ๊ธฐ๋Šฅโ€
269
+ ์•„์ด์ฝ˜ ์—ญํ• ์ด๋ฏ€๋กœ ๊ณต์šฉ registry์— ๋‘ก๋‹ˆ๋‹ค.
270
+
271
+ ## maturity gate
272
+
273
+ - surface `planned โ†’ beta`: public renderer export + package CI์˜ canonical default proof
274
+ - `beta โ†’ stable(shared)`: Web/RN renderer, ๊ณตํ†ต scenario parity, Web keyboard,
275
+ iOS VoiceOver, Android TalkBack, Reduce Motion + consumer adoption evidence
276
+ - `beta โ†’ stable(adaptive)`: ํ”ฝ์…€ parity ๋Œ€์‹  ๊ฐ™์€ action/result/announcement, dismiss/back
277
+ scenario ํ†ต๊ณผ
278
+ - Web/Native ์ „์šฉ: ํ•ด๋‹น ํ”Œ๋žซํผ์˜ keyboard ๋˜๋Š” screen reader evidence
279
+
280
+ ๋ชจ๋“  ๋‹จ๊ณ„์—์„œ light/dark, 200% text ๋˜๋Š” ํฐ ๊ธ€์ž, RTL ๊ฐ€๋Šฅํ•œ API, ํ•„์ˆ˜ ํ…์ŠคํŠธ 4.5:1,
281
+ ๊ฒฝ๊ณ„ยทfocusยทindicator 3:1, 44-unit target์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
282
+
283
+ Sheet stable ์Šน๊ฒฉ์—๋Š” ์œ„ gate์™€ ํ•จ๊ป˜ ๋ชจ๋“  dismiss reason์˜ ๋‹จ์ผ callback, busy ์ฐจ๋‹จ,
284
+ Web focus/scroll lock, Native safe-area/back, Reduce Motion exit ์™„๋ฃŒ, Sheet ์ข…๋ฃŒ ๋’ค ํ›„์† surface
285
+ ์ˆœ์„œ, opt-in swipe gesture์˜ ์‹ค์ œ ๊ธฐ๊ธฐ ๊ฒ€์ฆ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
@@ -0,0 +1,59 @@
1
+ # FilePicker contract
2
+
3
+ **๋ฌธ์ œ.** ์‚ฌ์šฉ์ž๊ฐ€ ์—…๋กœ๋“œํ•  ๋กœ์ปฌ ํŒŒ์ผ์„ ๊ณ ๋ฅธ๋‹ค โ€” ์–ด๋–ค ํ˜•์‹์„ ๋ฐ›๋Š”์ง€, ๋ช‡ ๊ฐœ๊นŒ์ง€
4
+ ๊ณ ๋ฅผ ์ˆ˜ ์žˆ๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  ๋ฌด์—‡์„ ๊ณจ๋ž๋Š”์ง€. ์—…๋กœ๋“œ ์š”์ฒญยท์žฌ์‹œ๋„ยท์„œ๋ฒ„ ์‘๋‹ต์€ ์ด ๊ณ„์•ฝ
5
+ ๋ฐ–์ด๋‹ค. `docs/expansion-roadmap.md`์˜ Batch 3 ์ ˆ์ด ์ด๋ฏธ ๊ทธ ๊ฒฝ๊ณ„๋ฅผ ๊ทธ์–ด ๋’€๋‹ค:
6
+ FilePicker๋Š” ํŒŒ์ผ ์„ ํƒ ์˜๋„๋งŒ ์†Œ์œ ํ•˜๊ณ , ์ง„ํ–‰ยท์„ฑ๊ณตยท์‹คํŒจ ํ‘œํ˜„์€ [[upload-item]]์ด
7
+ ๋”ฐ๋กœ ์†Œ์œ ํ•œ๋‹ค. antd `Upload`๋Š” ์ด ๋‘˜๋กœ decompose๋œ๋‹ค
8
+ (`src/component-references.ts`์˜ crosswalk).
9
+
10
+ **์ผ๋ฐ˜ํ™”ํ•œ ๊ณ„์•ฝ.**
11
+
12
+ - `mode`(`single` ๊ธฐ๋ณธ๊ฐ’ ๋˜๋Š” `multiple`), `accept?`(MIME ํŒจํ„ด ๋˜๋Š” ํ™•์žฅ์ž ๋ชฉ๋ก),
13
+ `maxSizeBytes?`, `maxCount?`(multiple ์ „์šฉ)๋งŒ ๊ณต๊ฐœํ•œ๋‹ค. `maxCount`๋ฅผ single
14
+ ๋ชจ๋“œ์— ์ฃผ๋ฉด ์กฐ์šฉํžˆ ๋ฌด์‹œํ•˜์ง€ ์•Š๊ณ  ๋˜์ง„๋‹ค โ€” ๋‘ ์ถ•์ด ๊ฐ™์€ ๊ฒƒ์„ ๋‹ค๋ฅด๊ฒŒ ๋‘ ๋ฒˆ
15
+ ๋งํ•˜๊ฒŒ ๋‘์ง€ ์•Š๋Š”๋‹ค.
16
+ - ๊ณ ๋ฅธ ๊ฒฐ๊ณผ๋Š” `{ accepted, rejected }`๋กœ ํ•จ๊ป˜ ๋Œ์•„์˜จ๋‹ค. `rejected`์˜ ๊ฐ ํ•ญ๋ชฉ์€
17
+ `reason`(`unsupported-type`, `too-large`, `count-exceeded` ์ค‘ ํ•˜๋‚˜)๊ณผ ๊ทธ ํŒ์ •์— ์“ด
18
+ ํ•œ๊ณ„๊ฐ’์„ ํ•จ๊ป˜ ๋“ค๊ณ  ์žˆ์–ด ์ œํ’ˆ์ด ์™œ ๋ง‰ํ˜”๋Š”์ง€ ๋‹ค์‹œ ๊ณ„์‚ฐํ•˜์ง€ ์•Š๊ณ  ๋ฌธ์žฅ์„ ๋งŒ๋“ ๋‹ค.
19
+ ๋‚˜๋จธ์ง€ accepted ํŒŒ์ผ์€ ๊ทธ๋Œ€๋กœ ์„ ํƒ๋œ ์ฑ„๋กœ ๋‚จ๋Š”๋‹ค โ€” identity.md์˜ "๋ฌด์—‡์ด
20
+ ๊นจ์กŒ๋Š”์ง€ + ๋ฌด์—‡์ด ๋ฌด์‚ฌํ•œ์ง€"๋ฅผ ํ•œ ๊ฒฐ๊ณผ ๊ฐ’ ์•ˆ์—์„œ ๋งŒ์กฑํ•œ๋‹ค.
21
+ - ํฌ๊ธฐยทํ˜•์‹ ๊ฑฐ๋ถ€๋Š” **์„ ํƒ ์‹œ์ **์˜ ํŒ์ •์ด๋‹ค. ๋ธŒ๋ผ์šฐ์ € `accept` ์†์„ฑ์ด๋‚˜ ๋„ค์ดํ‹ฐ๋ธŒ
22
+ ํ”ผ์ปค์˜ ํ•„ํ„ฐ๋Š” ์ฐธ๊ณ  ํžŒํŠธ์ผ ๋ฟ ๊ฐ•์ œ๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ(์‚ฌ์šฉ์ž๊ฐ€ "๋ชจ๋“  ํŒŒ์ผ"์„ ๊ณ ๋ฅด๋ฉด
23
+ ํ†ต๊ณผํ•œ๋‹ค), `resolveFilePickerSelection`์ด ์‹ค์ œ ์„ ํƒ ๊ฒฐ๊ณผ๋ฅผ ๋‹ค์‹œ ๊ฒ€์ฆํ•œ๋‹ค.
24
+ - `mode: "single"`์€ ๋ณ„๋„ ๋ถ„๊ธฐ๊ฐ€ ์•„๋‹ˆ๋ผ `maxCount = 1`์ธ ์ผ๋ฐ˜ ๊ทœ์น™์˜ ํŠน์ˆ˜
25
+ ๊ฒฝ์šฐ๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค โ€” Web dropzone์— ํŒŒ์ผ ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ํ•œ ๋ฒˆ์— ๋Œ์–ด๋‹ค ๋†“์•„๋„(๋‹จ์ผ
26
+ ๋ชจ๋“œ๋ผ๋„ ๋“œ๋กญ ์ด๋ฒคํŠธ ์ž์ฒด๋Š” ์—ฌ๋Ÿฌ ํŒŒ์ผ์„ ์ค„ ์ˆ˜ ์žˆ๋‹ค) ์ฒซ ํŒŒ์ผ๋งŒ accepted, ๋‚˜๋จธ์ง€๋Š”
27
+ `count-exceeded`๋กœ ๋–จ์–ด์ง„๋‹ค.
28
+ - `existingCount`๋Š” FilePicker๊ฐ€ ์†Œ์œ ํ•˜์ง€ ์•Š๋Š” ์ž…๋ ฅ์ด๋‹ค(Select์˜ `selectedItem`๊ณผ
29
+ ๊ฐ™์€ ์ž๋ฆฌ). ์—ฌ๋Ÿฌ ๋ฒˆ ๋‚˜๋ˆ  ๊ณ ๋ฅด๋Š” ์ œํ’ˆ ํ๋ฆ„์—์„œ ์ด๋ฏธ ๊ณ ๋ฅธ ๊ฐœ์ˆ˜๋ฅผ ๋„˜๊ฒจ์ฃผ๋ฉด
30
+ `maxCount`๊ฐ€ ๋ˆ„์  ๊ธฐ์ค€์œผ๋กœ ํŒ๋‹จ๋œ๋‹ค โ€” FilePicker๋Š” ์„ ํƒ ๋ชฉ๋ก ์ž์ฒด๋ฅผ ์Œ“์•„๋‘์ง€
31
+ ์•Š๋Š”๋‹ค.
32
+ - ๋„ฃ์ง€ ์•Š์€ ๊ฒƒ: ํŒŒ์ผ ๋‚ด์šฉ ์ฝ๊ธฐ/๋ฏธ๋ฆฌ๋ณด๊ธฐ, ์—…๋กœ๋“œ ์ง„ํ–‰ยท์žฌ์‹œ๋„ยท์„œ๋ฒ„ ์ƒํƒœ(โ†’
33
+ [[upload-item]]๊ณผ ์ œํ’ˆ), ๋””๋ ‰ํ„ฐ๋ฆฌ ์—…๋กœ๋“œ, ์ž๋™ ์ •๋ ฌ. antd `Upload`์˜ ๋„“์€ ํ‘œ๋ฉด ์ค‘
34
+ "๋ฌด์—‡์„ ๊ณ ๋ฅผ ๊ฒƒ์ธ๊ฐ€"๋งŒ ๊ฐ€์ ธ์˜จ๋‹ค.
35
+
36
+ **HJM ๊ธฐ๋ณธ๊ฐ’.** `mode` ๊ธฐ๋ณธ๊ฐ’์€ `single`(๋” ์ข๊ณ  ์•ˆ์ „ํ•œ ์ชฝ). trigger ๋ฒ„ํŠผ์€
37
+ `control.minTouchTarget`(44) ์ด์ƒ์„ ์œ ์ง€ํ•˜๊ณ , dropzone์€ `radius.lg`์˜ ์ ์„ 
38
+ ํ…Œ๋‘๋ฆฌ๋กœ ํ‘œํ˜„ํ•˜๋ฉฐ hover/drag ์‹œ `border.focus` ์ƒ‰๊ณผ `interaction.focus`
39
+ ๋ฐฐ๊ฒฝ์œผ๋กœ ๊ฐ•์กฐํ•œ๋‹ค โ€” ์ด ๊ฐ•์กฐ๋Š” ์žฅ์‹์ด ์•„๋‹ˆ๋ผ "์—ฌ๊ธฐ ๋†“์œผ๋ฉด ๋œ๋‹ค"๋Š” ์‹ ํ˜ธ๋‹ค.
40
+
41
+ **ํ”Œ๋žซํผ ๋ฒˆ์—ญ.**
42
+
43
+ - Web: `<input type="file">` ๋˜๋Š” ๋™๋“ฑ ์œ„์ ฏ์ด `role="button"`์œผ๋กœ trigger๋ฅผ
44
+ ๋“œ๋Ÿฌ๋‚ธ๋‹ค. ๋“œ๋ž˜๊ทธ ์•ค ๋“œ๋กญ์€ **Web ์ „์šฉ ๋ณด๊ฐ•**์ด๋ฉฐ ํ•ญ์ƒ ๋ฒ„ํŠผ trigger์™€ ํ•จ๊ป˜
45
+ ์žˆ์–ด์•ผ ํ•œ๋‹ค โ€” `validateFilePickerTriggers`๊ฐ€ ์ด ์กฐํ•ฉ์„ ๊ฐ•์ œํ•œ๋‹ค. Native๊ฐ€
46
+ dropzone trigger๋ฅผ ์š”์ฒญํ•˜๋ฉด ๋˜์ง„๋‹ค.
47
+ - Native: ์‹œ์Šคํ…œ document/์ด๋ฏธ์ง€ ํ”ผ์ปค๊ฐ€ ์œ ์ผํ•œ ์ง„์ž…์ ์ด๋‹ค. ๊ฒฐ๊ณผ๊ฐ€ ๋„์ฐฉํ•˜๋Š”
48
+ ๊ฒฝ๋กœ๋Š” ๋‹ค๋ฅด์ง€๋งŒ(Web `change` ์ด๋ฒคํŠธ vs Native picker ์ฝœ๋ฐฑ), ๊ฐ™์€
49
+ `FilePickerCandidate` ๋ฐฐ์—ด๋กœ ๋“ค์–ด์™€ ๊ฐ™์€ `resolveFilePickerSelection`์„ ํ†ต๊ณผํ•˜๋ฏ€๋กœ
50
+ accept/size/count ํŒ์ •์€ ๋‘ ํ”Œ๋žซํผ์—์„œ ๋™์ผํ•˜๋‹ค โ€” ๋กœ๋“œ๋งต์˜ adaptive gate๊ฐ€
51
+ ์š”๊ตฌํ•˜๋Š” "๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ๋‚ด๋Š” ๋‹ค๋ฅธ ๊ฒฝ๋กœ"๋‹ค.
52
+ - ์—ด๋ฆผ/๋‹ซํž˜ ์ถ•์„ ๊ณต๊ฐœํ•˜์ง€ ์•Š๋Š”๋‹ค. ํ”Œ๋žซํผ ํ”ผ์ปค ์‹œํŠธ๋Š” OS๊ฐ€ ์†Œ์œ ํ•˜๋Š” ์ผ์‹œ์ 
53
+ chrome์ด๋ผ Sheet/Select์ฒ˜๋Ÿผ `open` controlled state๋ฅผ ๋ชจ๋ธ๋งํ•˜์ง€ ์•Š๋Š”๋‹ค.
54
+ - ๊ฑฐ๋ถ€ ๋ฐœํ‘œ๋Š” ์ƒ‰์— ์˜์กดํ•˜์ง€ ์•Š๋Š”๋‹ค โ€” `reason`๊ณผ ํ•œ๊ณ„๊ฐ’์œผ๋กœ ์ œํ’ˆ์ด ๋งŒ๋“  ๋ฌธ์žฅ์„
55
+ live ์˜์—ญ/์—๋Ÿฌ ์นดํ”ผ๋กœ ๋ณด์—ฌ์ค€๋‹ค.
56
+
57
+ **๊ฒ€์ฆ ํ™”๋ฉด.** first-party Web input/dropzone๊ณผ Native picker-adapter renderer, ์„ ํƒ ํŒ์ •
58
+ ์ƒํ˜ธ์ž‘์šฉ ํ…Œ์ŠคํŠธ๋Š” ์—ฐ๊ฒฐ๋˜์–ด surface๋Š” `beta`๋‹ค. ์‹ค์ œ ์ œํ’ˆ vertical slice์™€ ํ”Œ๋žซํผ picker
59
+ ์‹ค๊ธฐ๊ธฐ ์ฆ๊ฑฐ๋Š” ์•„์ง ์—†์œผ๋ฏ€๋กœ `stable` ์Šน๊ฒฉ gate๋Š” ๋‹ซํ˜€ ์žˆ๋‹ค.