zdp-design-system 0.43.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/CHANGELOG.md +449 -0
  2. package/LICENSE +21 -0
  3. package/README.md +568 -0
  4. package/THIRD_PARTY_NOTICES.md +34 -0
  5. package/dist/code.ts +2 -0
  6. package/dist/combobox.ts +9 -0
  7. package/dist/command.ts +1 -0
  8. package/dist/components/Accordion.svelte +97 -0
  9. package/dist/components/Avatar.svelte +90 -0
  10. package/dist/components/Badge.svelte +61 -0
  11. package/dist/components/Breadcrumb.svelte +97 -0
  12. package/dist/components/Button.svelte +163 -0
  13. package/dist/components/Callout.svelte +81 -0
  14. package/dist/components/Card.svelte +151 -0
  15. package/dist/components/CardHeader.svelte +58 -0
  16. package/dist/components/Checkbox.svelte +135 -0
  17. package/dist/components/CodeBlock.svelte +247 -0
  18. package/dist/components/Combobox.svelte +552 -0
  19. package/dist/components/CommandField.svelte +230 -0
  20. package/dist/components/ConfirmAction.svelte +307 -0
  21. package/dist/components/Container.svelte +63 -0
  22. package/dist/components/Dialog.svelte +303 -0
  23. package/dist/components/Disclosure.svelte +176 -0
  24. package/dist/components/Divider.svelte +41 -0
  25. package/dist/components/EmptyState.svelte +79 -0
  26. package/dist/components/ErrorText.svelte +18 -0
  27. package/dist/components/Field.svelte +38 -0
  28. package/dist/components/Grid.svelte +76 -0
  29. package/dist/components/HelpText.svelte +17 -0
  30. package/dist/components/Icon.svelte +45 -0
  31. package/dist/components/IconButton.svelte +162 -0
  32. package/dist/components/IdentityChip.svelte +130 -0
  33. package/dist/components/Inline.svelte +85 -0
  34. package/dist/components/InlineCode.svelte +27 -0
  35. package/dist/components/Input.svelte +109 -0
  36. package/dist/components/Kbd.svelte +63 -0
  37. package/dist/components/KeyValue.svelte +73 -0
  38. package/dist/components/Label.svelte +43 -0
  39. package/dist/components/Link.svelte +70 -0
  40. package/dist/components/LocaleSwitcher.svelte +209 -0
  41. package/dist/components/Menu.svelte +491 -0
  42. package/dist/components/Page.svelte +36 -0
  43. package/dist/components/PageHeader.svelte +93 -0
  44. package/dist/components/Pagination.svelte +297 -0
  45. package/dist/components/Popover.svelte +208 -0
  46. package/dist/components/Progress.svelte +111 -0
  47. package/dist/components/Radio.svelte +132 -0
  48. package/dist/components/Section.svelte +52 -0
  49. package/dist/components/SegmentedControl.svelte +190 -0
  50. package/dist/components/Select.svelte +88 -0
  51. package/dist/components/ShareDock.svelte +304 -0
  52. package/dist/components/Sheet.svelte +332 -0
  53. package/dist/components/ShortcutHint.svelte +52 -0
  54. package/dist/components/Skeleton.svelte +82 -0
  55. package/dist/components/SkipLink.svelte +40 -0
  56. package/dist/components/SortHeader.svelte +138 -0
  57. package/dist/components/Spinner.svelte +82 -0
  58. package/dist/components/Stack.svelte +62 -0
  59. package/dist/components/StatusToast.svelte +133 -0
  60. package/dist/components/Surface.svelte +53 -0
  61. package/dist/components/Switch.svelte +152 -0
  62. package/dist/components/Table.svelte +94 -0
  63. package/dist/components/TableToolbar.svelte +195 -0
  64. package/dist/components/Tabs.svelte +205 -0
  65. package/dist/components/TermSheet.svelte +392 -0
  66. package/dist/components/TermTrigger.svelte +70 -0
  67. package/dist/components/TextScaleControl.svelte +219 -0
  68. package/dist/components/Textarea.svelte +106 -0
  69. package/dist/components/ThemeToggle.svelte +148 -0
  70. package/dist/components/Toast.svelte +180 -0
  71. package/dist/components/Toolbar.svelte +83 -0
  72. package/dist/components/Tooltip.svelte +199 -0
  73. package/dist/components/VisuallyHidden.svelte +18 -0
  74. package/dist/disclosure.ts +11 -0
  75. package/dist/focusable.ts +36 -0
  76. package/dist/identity.ts +5 -0
  77. package/dist/index.d.ts +106 -0
  78. package/dist/index.js +76 -0
  79. package/dist/index.ts +106 -0
  80. package/dist/menu.ts +12 -0
  81. package/dist/modal-layer.ts +108 -0
  82. package/dist/pagination.ts +10 -0
  83. package/dist/preferences.js +14 -0
  84. package/dist/preferences.ts +36 -0
  85. package/dist/progress.ts +4 -0
  86. package/dist/schemas/design-tokens.schema.json +119 -0
  87. package/dist/segmented.ts +8 -0
  88. package/dist/share.d.ts +48 -0
  89. package/dist/share.js +115 -0
  90. package/dist/share.ts +99 -0
  91. package/dist/sheet.ts +3 -0
  92. package/dist/shortcuts.js +125 -0
  93. package/dist/shortcuts.ts +153 -0
  94. package/dist/styles/brand-fonts.css +10 -0
  95. package/dist/styles/components.css +4686 -0
  96. package/dist/styles/expressive-fonts.css +2 -0
  97. package/dist/styles/index.css +2 -0
  98. package/dist/styles/locale-fonts.css +4 -0
  99. package/dist/styles/tokens.css +413 -0
  100. package/dist/table-tools.ts +10 -0
  101. package/dist/term.ts +16 -0
  102. package/dist/theme.ts +2 -0
  103. package/dist/toast.ts +14 -0
  104. package/dist/tokens/zdp.tokens.json +241 -0
  105. package/dist/tokens.js +122 -0
  106. package/dist/tokens.ts +123 -0
  107. package/docs/CONSUMER_CONTRACT.md +482 -0
  108. package/docs/EXTERNAL_UI_ADOPTION.md +141 -0
  109. package/docs/INTERACTIVE_PRIMITIVE_AUDIT.md +127 -0
  110. package/package.json +78 -0
@@ -0,0 +1,482 @@
1
+ # Consumer Contract
2
+
3
+ ์ด ๋ฌธ์„œ๋Š” `zdp-design-system`์„ ๋‹ค๋ฅธ ZDP ์ €์žฅ์†Œ์—์„œ ์†Œ๋น„ํ•  ๋•Œ์˜ ๊ธฐ์ค€์ด๋‹ค.
4
+ ๋ชฉํ‘œ๋Š” public web, app shell, product lab, game surface๊ฐ€ ๊ฐ™์€ ํ† ํฐ๊ณผ ๊ฐ™์€ ์ ‘๊ทผ์„ฑ ๊ธฐ๋ณธ๊ฐ’์„ ๊ณต์œ ํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด๋‹ค.
5
+ Default component text is English. ์†Œ๋น„ ์•ฑ์€ ํ™”๋ฉด locale์— ๋งž์ถฐ user-facing label, placeholder, aria-label, empty text, toast dismissal text๋ฅผ prop์œผ๋กœ overrideํ•œ๋‹ค.
6
+
7
+ ## ๊ณตํ†ต ์›์น™
8
+
9
+ - ์†Œ๋น„ ์ €์žฅ์†Œ๋Š” ์ œํ’ˆ ๋ฌธ๊ตฌ, ๋ผ์šฐํŒ…, SEO, ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ, ์ธ์ฆ, ๊ฒฐ์ œ, ๊ถŒํ•œ ํŒ๋‹จ์„ ์ง์ ‘ ์†Œ์œ ํ•œ๋‹ค.
10
+ - ๋””์ž์ธ ์‹œ์Šคํ…œ์€ ์ƒ‰์ƒ, ํƒ€์ž…, ๊ฐ„๊ฒฉ, radius, focus, i18n, control metric, shared component API๋งŒ ์ œ๊ณตํ•œ๋‹ค.
11
+ - ์†Œ๋น„ ์ €์žฅ์†Œ๋Š” `zdp-design-system`์˜ public export๋งŒ ์‚ฌ์šฉํ•˜๊ณ  ๋‚ด๋ถ€ `src/` deep import๋ฅผ ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค.
12
+ - package export๋Š” `dist/` ์‚ฐ์ถœ๋ฌผ์„ ํ†ตํ•ด ์†Œ๋น„ํ•œ๋‹ค. root runtime entry๋Š” `dist/index.js`, type entry๋Š” `dist/index.d.ts`๋‹ค. ์›์ฒœ์€ `src/lib`, `src/styles`, `tokens/zdp.tokens.json`, `src/lib/share.ts`์ด๊ณ  `dist/`๋Š” release ์ „ `bun run package:build`๋กœ ๋‹ค์‹œ ๋งŒ๋“ ๋‹ค.
13
+ - `zdpTokenNames`, `share.js`, `share.d.ts`๋Š” ์†์œผ๋กœ ๋งž์ถ”์ง€ ์•Š๊ณ  `tokens:generate`, `share-icons:generate` ์‚ฐ์ถœ๋ฌผ๋กœ ์œ ์ง€ํ•œ๋‹ค.
14
+ - ์ƒˆ ๋ฒ„์ „์€ ์†Œ๋น„ ์ €์žฅ์†Œ๊ฐ€ opt-in์œผ๋กœ ์ฑ„ํƒํ•œ๋‹ค. broad adoption ์ „์—๋Š” ๋Œ€ํ‘œ ์†Œ๋น„์ฒ˜์—์„œ ์‹œ๊ฐ๊ณผ build๋ฅผ ํ™•์ธํ•œ๋‹ค.
15
+ - keyboard focus, flat UI, framed control, Pretendard-first font stack์€ ์†Œ๋น„์ฒ˜์—์„œ ์ž„์˜๋กœ ๋‚ฎ์ถ”์ง€ ์•Š๋Š”๋‹ค.
16
+ - ๋ธŒ๋žœ๋“œ ์›Œ๋“œ๋งˆํฌ๋Š” `font.family.brand`์™€ `brand-fonts.css`๋ฅผ ์“ฐ๋˜, ๋ณธ๋ฌธ๊ณผ ์ œํ’ˆ UI heading์€ Pretendard-first sans/display stack์„ ์œ ์ง€ํ•œ๋‹ค.
17
+ - ์†Œ๋น„ ์ €์žฅ์†Œ๋Š” `zdp-design-system`์„ ์“ฐ๊ธฐ ์œ„ํ•ด Tailwind, UnoCSS, shadcn registry, daisyUI theme, Skeleton preset, Flowbite theme, external `cn()` helper๋ฅผ ์•Œ ํ•„์š”๊ฐ€ ์—†์–ด์•ผ ํ•œ๋‹ค.
18
+ - ์™ธ๋ถ€ headless primitive๊ฐ€ ๋‚ด๋ถ€ ๊ตฌํ˜„์— ์“ฐ์ด๋”๋ผ๋„ public API, CSS class, token, dist export๋Š” ZDP ๊ณ„์•ฝ์œผ๋กœ๋งŒ ๋…ธ์ถœํ•œ๋‹ค.
19
+
20
+ ## Astro ์†Œ๋น„ ํ‘œ๋ฉด
21
+
22
+ Astro ์ •์  ์‚ฌ์ดํŠธ๋Š” ์ „์—ญ ์Šคํƒ€์ผ๋กœ ๊ธฐ๋ณธ CSS๋ฅผ ๋จผ์ € ๋ถˆ๋Ÿฌ์˜จ๋‹ค.
23
+
24
+ ```ts
25
+ import 'zdp-design-system/styles.css';
26
+ ```
27
+
28
+ ๋‹ค๊ตญ์–ด ํŽ˜์ด์ง€๊ฐ€ ๋ผํ‹ด, ์ค‘๊ตญ์–ด, ๋ฐ๋ฐ”๋‚˜๊ฐ€๋ฆฌ, ์ผ๋ณธ์–ด ์›นํฐํŠธ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์จ์•ผ ํ•˜๋ฉด ์„ ํƒํ˜• locale font entry๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.
29
+
30
+ ```ts
31
+ import 'zdp-design-system/styles.css';
32
+ import 'zdp-design-system/locale-fonts.css';
33
+ ```
34
+
35
+ `8ailors` ๊ฐ™์€ ๋ธŒ๋žœ๋“œ ์›Œ๋“œ๋งˆํฌ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ํ‘œ๋ฉด์€ ์„ ํƒํ˜• brand font entry๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.
36
+
37
+ ```ts
38
+ import 'zdp-design-system/styles.css';
39
+ import 'zdp-design-system/brand-fonts.css';
40
+ ```
41
+
42
+ ์บ ํŽ˜์ธํ˜• ์„น์…˜ ์ œ๋ชฉ, ์งง์€ ๋งˆ์ผ€ํŒ… ๋ฌธ๊ตฌ, ์žฅ์‹์  ์•ˆ๋‚ด์ฒ˜๋Ÿผ ํ‘œํ˜„๋ ฅ์ด ํ•„์š”ํ•œ ํ‘œ๋ฉด์€ ์„ ํƒํ˜• expressive font entry๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค. ์ด entry๋Š” ๊ธฐ๋ณธ UI ํฐํŠธ๋ฅผ ๋ฐ”๊พธ์ง€ ์•Š๋Š”๋‹ค.
43
+
44
+ ```ts
45
+ import 'zdp-design-system/styles.css';
46
+ import 'zdp-design-system/expressive-fonts.css';
47
+ ```
48
+
49
+ ํŽ˜์ด์ง€ ๋ฃจํŠธ ๋˜๋Š” ์ฃผ์š” section์—๋Š” `.zdp-surface-reset`์„ ๋ถ™์—ฌ font, link, input, focus ๊ธฐ๋ณธ๊ฐ’์„ ๋ฐ›๋Š”๋‹ค.
50
+ Svelte island ์—†์ด ์ •์  HTML๋งŒ ์“ฐ๋Š” ๊ณณ์€ ์Šคํฌ๋ฆฐ๋ฆฌ๋” ์ „์šฉ ๋ณด์กฐ ํ…์ŠคํŠธ์— `.zdp-visually-hidden` utility๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
51
+ ํŽ˜์ด์ง€ root๋Š” `.zdp-page`, ๋ณธ๋ฌธ ํญ์€ `.zdp-container`์™€ `.zdp-container--lg`, ์„น์…˜ ๊ฐ„๊ฒฉ์€ `.zdp-section`๊ณผ `.zdp-section--spacing-*`, ์ƒ๋‹จ ์ œ๋ชฉ๊ณผ ์•ก์…˜ ํ๋ฆ„์€ `.zdp-page-header` utility๋กœ ๋งž์ถ˜๋‹ค.
52
+ ๋ธŒ๋žœ๋“œ ํ—ค๋”๋‚˜ ๋กœ๊ณ  ์˜† ์›Œ๋“œ๋งˆํฌ๋Š” `.zdp-brand-lockup`, `.zdp-brand-lockup__mark`, `.zdp-brand-wordmark` utility๋กœ ๋งž์ถ”๋˜ ์ œํ’ˆ ๊ธฐ๋Šฅ ์ œ๋ชฉ, CTA, ํ‘œ ๋ฐ์ดํ„ฐ, ๋ณธ๋ฌธ์—๋Š” ๋ธŒ๋žœ๋“œ ํฐํŠธ๋ฅผ ์“ฐ์ง€ ์•Š๋Š”๋‹ค. `lang="ko"` ๊ฐ™์€ locale surface ์•ˆ์—์„œ๋„ ์‹ค์ œ ์›Œ๋“œ๋งˆํฌ ํ…์ŠคํŠธ์—๋Š” `.zdp-brand-wordmark`๋ฅผ ์ง์ ‘ ๋ถ™์—ฌ์•ผ ํ•˜๋ฉฐ `.zdp-surface-reset .zdp-brand-wordmark`๊ฐ€ locale font override๋ณด๋‹ค ๋’ค์—์„œ ๋ธŒ๋žœ๋“œ ์Šคํƒ, `font-size: calc(var(--zdp-type-page-title-size) - 0.8rem)`, `font-size: calc(var(--zdp-type-page-title-compact-size) - 0.5rem)`, `font-weight: var(--zdp-font-weight-semibold)`์„ ์œ ์ง€ํ•œ๋‹ค.
53
+ ๊ฐ€๊นŒ์šด ์š”์†Œ์˜ ์„ธ๋กœ ํ๋ฆ„์€ `.zdp-stack`๊ณผ `.zdp-stack--gap-*` utility๋กœ ๋งž์ถ˜๋‹ค.
54
+ ๊ฐ€๊นŒ์šด ๋ฒ„ํŠผ, ๋ฐฐ์ง€, ์ž‘์€ ๋งํฌ ๋ฌถ์Œ์˜ ๊ฐ€๋กœ ํ๋ฆ„์€ `.zdp-inline`๊ณผ `.zdp-inline--gap-*` utility๋กœ ๋งž์ถ˜๋‹ค.
55
+ ๊ฐ€๊นŒ์šด ๋‚ด์šฉ ์‚ฌ์ด์˜ ์–‡์€ ๊ตฌ๋ถ„์„ ์€ `.zdp-divider`์™€ `.zdp-divider--horizontal` utility๋กœ ๋งž์ถ”๋˜, section spacing์€ ์†Œ๋น„์ฒ˜๊ฐ€ ์†Œ์œ ํ•œ๋‹ค.
56
+ ๋ฐ˜๋ณต ์นด๋“œ๋‚˜ ์š”์•ฝ ๋ฌถ์Œ์€ `.zdp-grid`, ๊ฐ€๊นŒ์šด ํ™”๋ฉด ๋„๊ตฌ์™€ ์•ก์…˜ ๋ฌถ์Œ์€ `.zdp-toolbar` utility๋กœ ๋งž์ถ˜๋‹ค.
57
+ CommandField๋Š” ๊ฒ€์ƒ‰, ๋น ๋ฅธ ์ด๋™, ๋ช…๋ น ํŒ”๋ ˆํŠธ ์ง„์ž…์ฒ˜๋Ÿผ ์งง์€ keyboard affordance๊ฐ€ ํ•„์š”ํ•œ ์ž…๋ ฅ์— `CommandField` ๋˜๋Š” `.zdp-command-field-shell`, `.zdp-command-field`, `.zdp-command-field__input`, `.zdp-command-field__shortcut`, `.zdp-kbd`, `.zdp-shortcut-hint` utility๋กœ ๋งž์ถ˜๋‹ค.
58
+ Combobox๋Š” ๊ฒ€์ƒ‰ ๊ฐ€๋Šฅํ•œ ๋‹จ์ผ ์„ ํƒ์— `Combobox` ๋˜๋Š” `.zdp-combobox`, `.zdp-combobox__control`, `.zdp-combobox__input`, `.zdp-combobox__listbox`, `.zdp-combobox__option` utility๋กœ ๋งž์ถ˜๋‹ค. option source, filtering, async loading, command ์‹คํ–‰, ๊ถŒํ•œ ํŒ๋‹จ์€ ์†Œ๋น„์ฒ˜๊ฐ€ ์†Œ์œ ํ•œ๋‹ค.
59
+ ๋ฌธ์„œ, ๋ณด์•ˆ, ์•„ํ‚คํ…์ฒ˜ ํŽ˜์ด์ง€์˜ ์ฝ”๋“œ ์กฐ๊ฐ์€ `InlineCode`, `CodeBlock`, `.zdp-inline-code`, `.zdp-code-block`, `.zdp-code-block__copy` utility๋กœ ๋งž์ถ˜๋‹ค.
60
+ ์‚ฌ๋žŒ, ํŒ€, ์กฐ์ง์˜ ์งง์€ ํ‘œ๊ธฐ๋Š” `.zdp-avatar`, `.zdp-avatar__initials`, `.zdp-identity-chip`, `.zdp-identity-chip__label` utility๋กœ ๋งž์ถ”๋˜ ์‹ค์ œ ๊ณ„์ • ์‹๋ณ„, ํ”„๋กœํ•„ ๋ผ์šฐํŒ…, ์˜จ๋ผ์ธ ์ƒํƒœ, ๊ถŒํ•œ, ์ดˆ๋Œ€ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ํŒ๋‹จ์€ ์†Œ๋น„์ฒ˜๊ฐ€ ์†Œ์œ ํ•œ๋‹ค.
61
+ ํ…Œ๋งˆ ์ „ํ™˜ ๋ฒ„ํŠผ์€ `.zdp-theme-toggle`, `.zdp-theme-toggle__icon`, `data-zdp-theme-state` utility๋กœ ๋งž์ถ”๋˜ ์ดˆ๊ธฐ ํ…Œ๋งˆ ๊ฒฐ์ •, ์‚ฌ์šฉ์ž ์ €์žฅ์†Œ, ์‹œ์Šคํ…œ ์„ ํ˜ธ๋„, SSR/์ดˆ๊ธฐ paint ์ฒ˜๋ฆฌ๋Š” ์†Œ๋น„์ฒ˜๊ฐ€ ์†Œ์œ ํ•œ๋‹ค.
62
+ ์–ธ์–ด ์„ ํƒ์€ `.zdp-locale-switcher`, `.zdp-locale-switcher__item`, `data-zdp-locale-value` utility๋กœ ๋งž์ถ”๋˜ ์‹ค์ œ message catalog, URL routing, fallback locale, storage key, `<html lang>` ๋ฐ˜์˜, ์‚ฌ์šฉ์ž ์„ ํ˜ธ๋„ ํŒ๋‹จ์€ ์†Œ๋น„์ฒ˜๊ฐ€ ์†Œ์œ ํ•œ๋‹ค.
63
+ ๊ธ€์ž ํฌ๊ธฐ ์„ ํƒ์€ `.zdp-text-scale-control`, `.zdp-text-scale-control__item`, `data-zdp-text-scale-value` utility๋กœ ๋งž์ถ”๋˜ ์‹ค์ œ ๋ฌธ์„œ ํฌ๊ธฐ ๋ฐ˜์˜, ์ €์žฅ์†Œ, ์‚ฌ์šฉ์ž ์„ ํ˜ธ๋„ ํŒ๋‹จ์€ ์†Œ๋น„์ฒ˜๊ฐ€ ์†Œ์œ ํ•œ๋‹ค.
64
+ ์งง์€ ๋ณด์กฐ ์„ค๋ช…์€ `.zdp-tooltip`, `.zdp-tooltip__trigger`, `.zdp-tooltip__content` utility๋กœ ๋ฐฐ์น˜ํ•˜๋˜ ๊ธด ๋„์›€๋ง, popover, validation, tour๋Š” ์†Œ๋น„์ฒ˜๊ฐ€ ๋ณ„๋„ ํ๋ฆ„์œผ๋กœ ์†Œ์œ ํ•œ๋‹ค.
65
+ ์ ‘ํžŒ ์•ˆ๋‚ด์™€ ๋ฐ˜๋ณต๋˜๋Š” ํŽผ์นจ ๋ชฉ๋ก์€ `.zdp-disclosure`, `.zdp-disclosure__trigger`, `.zdp-disclosure__panel`, `.zdp-accordion`, `.zdp-accordion__item` utility๋กœ ๋งž์ถ”๋˜ ์‹ค์ œ FAQ ๋ฌธ๊ตฌ, ์„ค์ • ๊ฐ’, ํ•ญ๋ชฉ ๋…ธ์ถœ, ๊ถŒํ•œ, ๋ฐ์ดํ„ฐ fetch ํŒ๋‹จ์€ ์†Œ๋น„์ฒ˜๊ฐ€ ์†Œ์œ ํ•œ๋‹ค.
66
+ ๋ณด๊ธฐ ๋ฐฉ์‹, ๋ฐ€๋„, ๊ธฐ๊ฐ„์ฒ˜๋Ÿผ ๊ฐ€๊นŒ์šด ๋‹จ์ผ ์„ ํƒ์€ `.zdp-segmented-control`, `.zdp-segmented-control__item` utility๋กœ ๋งž์ถ”๋˜ ์‹ค์ œ ํ•„ํ„ฐ ์˜๋ฏธ, URL state, ์ •๋ ฌ, ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ, ๊ถŒํ•œ ํŒ๋‹จ์€ ์†Œ๋น„์ฒ˜๊ฐ€ ์†Œ์œ ํ•œ๋‹ค.
67
+ ์„ค์ •, ๋”๋ณด๊ธฐ, ํ•„ํ„ฐ, ๊ณ„์ • ๋ฉ”๋‰ด์ฒ˜๋Ÿผ ๊ฐ€๊นŒ์šด ํŠธ๋ฆฌ๊ฑฐ์—์„œ ์งง๊ฒŒ ํŽผ์น˜๋Š” ํ‘œ๋ฉด์€ `.zdp-popover`, `.zdp-popover__trigger`, `.zdp-popover__panel`, `.zdp-menu`, `.zdp-menu__trigger`, `.zdp-menu__panel`, `.zdp-menu__item` utility๋กœ ๋งž์ถ”๋˜ ํ•ญ๋ชฉ ๋…ธ์ถœ, ๊ถŒํ•œ, ๋ผ์šฐํŒ…, ํ•„ํ„ฐ ์˜๋ฏธ, ๊ณ„์ • ์ƒํƒœ ํŒ๋‹จ์€ ์†Œ๋น„์ฒ˜๊ฐ€ ์†Œ์œ ํ•œ๋‹ค.
68
+ ์„ค์ •, ํ•„ํ„ฐ, ๋ณด์กฐ ํ๋ฆ„์ฒ˜๋Ÿผ ํ˜„์žฌ ํ™”๋ฉด ๊ฐ€์žฅ์ž๋ฆฌ์—์„œ ํ™•์ธํ•˜๋Š” modal edge panel์€ `.zdp-sheet`, `.zdp-sheet__backdrop`, `.zdp-sheet__header`, `.zdp-sheet__body`, `.zdp-sheet__footer` utility๋กœ ๋งž์ถ”๋˜ ์ €์žฅ, ๊ถŒํ•œ, ๋ฐ์ดํ„ฐ fetch, ๋ผ์šฐํŒ… ํŒ๋‹จ์€ ์†Œ๋น„์ฒ˜๊ฐ€ ์†Œ์œ ํ•œ๋‹ค.
69
+ ์ €์žฅ, ๋™๊ธฐํ™”, ์‹คํŒจ ๊ฐ™์€ ์งง์€ ์ƒํƒœ ์•Œ๋ฆผ์€ `.zdp-toast`, `.zdp-toast__body`, `.zdp-toast__close`, `.zdp-status-toast`, `.zdp-status-toast--inline|top-start|top-end|bottom-start|bottom-end` utility๋กœ ๋งž์ถ”๋˜ ์•Œ๋ฆผ ๋ฐœ์ƒ ์กฐ๊ฑด, ํ ์ˆœ์„œ, ์ž๋™ ๋‹ซํž˜ ํƒ€์ด๋จธ, ์ค‘๋ณต ์ œ๊ฑฐ, ์žฌ์‹œ๋„ ์ •์ฑ…, ๊ถŒํ•œ, ์„œ๋ฒ„ ์ƒํƒœ ํŒ๋‹จ์€ ์†Œ๋น„์ฒ˜๊ฐ€ ์†Œ์œ ํ•œ๋‹ค.
70
+ ์ž‘์—… ์ง„ํ–‰, ์‘๋‹ต ๋Œ€๊ธฐ, ์ฝ˜ํ…์ธ  ์ž๋ฆฌ ์˜ˆ์•ฝ์€ `.zdp-progress`, `.zdp-spinner`, `.zdp-skeleton`, `.zdp-skeleton__line` utility๋กœ ๋งž์ถ”๋˜ ๋กœ๋”ฉ ์กฐ๊ฑด, ์ง„ํ–‰๋ฅ  ๊ณ„์‚ฐ, ์™„๋ฃŒ/์‹คํŒจ ์ „ํ™˜, ๋ฐ์ดํ„ฐ fetch, ์žฌ์‹œ๋„, ๊ถŒํ•œ, ์„œ๋ฒ„ ์ƒํƒœ ํŒ๋‹จ์€ ์†Œ๋น„์ฒ˜๊ฐ€ ์†Œ์œ ํ•œ๋‹ค.
71
+ ์ž‘์€ glyph๋Š” `.zdp-icon`๊ณผ `.zdp-icon--sm|md` utility๋กœ ์ค‘์•™์ •๋ ฌํ•˜๋˜ ์˜๋ฏธ์™€ ๋ผ๋ฒจ ๋ฌธ๊ตฌ๋Š” ์†Œ๋น„์ฒ˜๊ฐ€ ์†Œ์œ ํ•œ๋‹ค.
72
+ ์ •๋ ฌ ๊ฐ€๋Šฅํ•œ ํ‘œ ํ—ค๋”์™€ ํ‘œ ์ฃผ๋ณ€ ๋„๊ตฌ๋Š” `.zdp-sort-header`, `.zdp-sort-header__label`, `.zdp-sort-header__mark`, `.zdp-table-toolbar`, `.zdp-table-toolbar__controls`, `.zdp-table-toolbar__actions` utility๋กœ ๋งž์ถ”๋˜ `aria-sort`, ์‹ค์ œ ์ •๋ ฌ, ์„ ํƒ ํ–‰ ์ƒํƒœ, ๋ฐ€๋„ ์ €์žฅ, ํ•„ํ„ฐ, ๊ถŒํ•œ ํŒ๋‹จ์€ ์†Œ๋น„์ฒ˜๊ฐ€ ์†Œ์œ ํ•œ๋‹ค.
73
+ ๋ชฉ๋ก ํŽ˜์ด์ง€ ์ด๋™์€ `.zdp-pagination`, `.zdp-pagination__list`, `.zdp-pagination__link`, `.zdp-pagination__ellipsis` utility๋กœ ๋งž์ถ”๋˜ ์ „์ฒด ๊ฐœ์ˆ˜, ํ˜„์žฌ ํŽ˜์ด์ง€ ์ƒํƒœ, ํŽ˜์ด์ง€ ํฌ๊ธฐ, ์ฟผ๋ฆฌ ๋ผ์šฐํŒ…, ํ•„ํ„ฐ, ์ •๋ ฌ, ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ ํŒ๋‹จ์€ ์†Œ๋น„์ฒ˜๊ฐ€ ์†Œ์œ ํ•œ๋‹ค.
74
+ ๊ณต์œ  ๋„ํฌ๋Š” `.zdp-share-dock`, `.zdp-share-dock--side|rail|bottom|inline`, `.zdp-share-action`, `.zdp-share-icon`, `.zdp-share-action__tooltip` utility๋กœ ๋ฐฐ์น˜ํ•˜๋˜ URL ์ƒ์„ฑ, clipboard, navigator.share, ํ”Œ๋žซํผ๋ณ„ ๊ณต์œ  ๋งํฌ๋Š” ์†Œ๋น„์ฒ˜๊ฐ€ ์†Œ์œ ํ•œ๋‹ค.
75
+ Svelte island ์—†์ด Astro์—์„œ ๊ณต์œ  ์•„์ด์ฝ˜ shape๋งŒ ํ•„์š”ํ•˜๋ฉด `zdp-design-system/share`์—์„œ `zdpShareIcons`์™€ `ZdpShareIconName`์„ ๊ฐ€์ ธ์˜จ๋‹ค.
76
+ ํ”Œ๋žซํผ ๋ธŒ๋žœ๋“œ ๊ณต์œ  ์•„์ด์ฝ˜์€ Simple Icons path ๊ธฐ์ค€์„ ์œ ์ง€ํ•˜๊ณ  ์ž„์˜ outline glyph๋กœ ๋Œ€์ฒดํ•˜์ง€ ์•Š๋Š”๋‹ค.
77
+ Astro ํŽ˜์ด์ง€๋Š” Svelte island๊ฐ€ ํ•„์š”ํ•œ ๋ถ€๋ถ„์—์„œ๋งŒ Svelte ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
78
+
79
+ ## Svelte์™€ Tauri ์†Œ๋น„ ํ‘œ๋ฉด
80
+
81
+ Svelte, SvelteKit, Tauri Svelte WebView๋Š” package root์—์„œ shared component๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
82
+
83
+ ```svelte
84
+ <script lang="ts">
85
+ import {
86
+ Accordion,
87
+ Avatar,
88
+ Breadcrumb,
89
+ Button,
90
+ CodeBlock,
91
+ Combobox,
92
+ CommandField,
93
+ ConfirmAction,
94
+ Container,
95
+ Divider,
96
+ Dialog,
97
+ Disclosure,
98
+ EmptyState,
99
+ Field,
100
+ Grid,
101
+ HelpText,
102
+ Icon,
103
+ Input,
104
+ IdentityChip,
105
+ Inline,
106
+ InlineCode,
107
+ Kbd,
108
+ KeyValue,
109
+ Label,
110
+ Link,
111
+ LocaleSwitcher,
112
+ Menu,
113
+ Page,
114
+ PageHeader,
115
+ Pagination,
116
+ Popover,
117
+ Progress,
118
+ Section,
119
+ SegmentedControl,
120
+ ShareDock,
121
+ Sheet,
122
+ ShortcutHint,
123
+ Skeleton,
124
+ SkipLink,
125
+ SortHeader,
126
+ Stack,
127
+ StatusToast,
128
+ Spinner,
129
+ Surface,
130
+ Tabs,
131
+ Table,
132
+ TableToolbar,
133
+ TermSheet,
134
+ TermTrigger,
135
+ TextScaleControl,
136
+ ThemeToggle,
137
+ Tooltip,
138
+ Toast,
139
+ Toolbar,
140
+ VisuallyHidden
141
+ } from 'zdp-design-system';
142
+
143
+ let dialogOpen = false;
144
+ </script>
145
+
146
+ <Page labelledBy="consumer-contract-title">
147
+ <SkipLink href="#content">๋ณธ๋ฌธ์œผ๋กœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ</SkipLink>
148
+ <Section spacing="lg">
149
+ <Container size="lg" padding="lg">
150
+ <PageHeader labelledBy="consumer-contract-title">
151
+ <span slot="eyebrow">ํ”Œ๋žซํผ</span>
152
+ <h1 id="consumer-contract-title">๋””์ž์ธ ์‹œ์Šคํ…œ</h1>
153
+ <p slot="summary">๊ณต๊ฐœ ํ™”๋ฉด๊ณผ ์ž‘์—… ํ™”๋ฉด์ด ๊ฐ™์€ ๊ธฐ์ค€ ์œ„์—์„œ ์›€์ง์ž…๋‹ˆ๋‹ค.</p>
154
+ </PageHeader>
155
+ </Container>
156
+ </Section>
157
+ <Container as="section" id="content" size="lg" padding="lg">
158
+ <Stack gap="md">
159
+ <Breadcrumb
160
+ ariaLabel="ํ˜„์žฌ ์œ„์น˜"
161
+ items={[
162
+ { label: 'ํ™ˆ ํ™”๋ฉด', href: '/' },
163
+ { label: 'ํ”Œ๋žซํผ', href: '/platform' },
164
+ { label: '๋””์ž์ธ ์‹œ์Šคํ…œ' }
165
+ ]}
166
+ />
167
+ <Link href="/design">์ž์„ธํžˆ ๋ณด๊ธฐ</Link>
168
+ <IdentityChip
169
+ label="ํ™๊ธธ๋™"
170
+ description="๊ฒ€ํ†  ๋‹ด๋‹น"
171
+ initials="ํ™"
172
+ href="/people/hong"
173
+ />
174
+ <Avatar label="ํ”Œ๋žซํผ ํŒ€" initials="ํ”Œ" tone="primary" />
175
+ <ShareDock
176
+ placement="inline"
177
+ ariaLabel="๊ณต์œ "
178
+ items={[
179
+ { id: 'copy', label: '๋งํฌ ๋ณต์‚ฌ', icon: 'copy' },
180
+ { id: 'telegram', label: 'ํ…”๋ ˆ๊ทธ๋žจ', icon: 'telegram', href: '/share' },
181
+ { id: 'x', label: 'X', icon: 'x', href: '/share' }
182
+ ]}
183
+ />
184
+ <Button
185
+ variant="secondary"
186
+ onclick={() => (dialogOpen = true)}
187
+ ariaControls="project-dialog"
188
+ ariaExpanded={dialogOpen}
189
+ >
190
+ <Icon size="sm">+</Icon>
191
+ <VisuallyHidden>์ƒˆ ํ•ญ๋ชฉ </VisuallyHidden>์ถ”๊ฐ€
192
+ </Button>
193
+ <Divider />
194
+ <Disclosure title="๊ฒ€ํ†  ๊ธฐ์ค€" open headingLevel={2}>
195
+ <p>ํ•„์š”ํ•œ ๊ธฐ์ค€๋งŒ ํŽผ์ณ์„œ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.</p>
196
+ </Disclosure>
197
+ <Accordion
198
+ ariaLabel="์ ‘ํžŒ ์•ˆ๋‚ด"
199
+ items={[
200
+ {
201
+ id: 'scope',
202
+ title: '๋ฒ”์œ„',
203
+ content: 'ํ™”๋ฉด ํ๋ฆ„๊ณผ ๋ฐ์ดํ„ฐ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์—์„œ ์ •ํ•ฉ๋‹ˆ๋‹ค.',
204
+ open: true
205
+ },
206
+ {
207
+ id: 'owner',
208
+ title: '์†Œ์œ ์ž',
209
+ content: 'ํ‘œ์‹œํ•  ํ•ญ๋ชฉ๊ณผ ๊ถŒํ•œ ํŒ๋‹จ์€ ์ œํ’ˆ ์ €์žฅ์†Œ๊ฐ€ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.'
210
+ }
211
+ ]}
212
+ />
213
+ <SegmentedControl
214
+ ariaLabel="๋ณด๊ธฐ ๋ฐฉ์‹"
215
+ items={[
216
+ { id: 'list', label: '๋ชฉ๋ก' },
217
+ { id: 'cards', label: '์นด๋“œ' },
218
+ { id: 'summary', label: '์š”์•ฝ' }
219
+ ]}
220
+ selectedId="list"
221
+ />
222
+ <CommandField
223
+ label="๋น ๋ฅธ ์ด๋™"
224
+ labelVisible
225
+ placeholder="ํ”„๋กœ์ ํŠธ, ๋ฌธ์„œ, ์„ค์ • ๊ฒ€์ƒ‰"
226
+ describedBy="command-field-help"
227
+ />
228
+ <HelpText id="command-field-help">์ด ํ™”๋ฉด์—์„œ ์ฐพ์„ ํ•ญ๋ชฉ์„ ์ž…๋ ฅํ•˜์„ธ์š”.</HelpText>
229
+ <Combobox
230
+ name="owner"
231
+ label="๋‹ด๋‹น"
232
+ labelVisible
233
+ placeholder="๋‹ด๋‹น ํŒ€ ์ฐพ๊ธฐ"
234
+ options={[
235
+ { id: 'platform', value: 'platform', label: 'ํ”Œ๋žซํผ ์šด์˜' },
236
+ { id: 'security', value: 'security', label: '๋ณด์•ˆ ๊ฒ€ํ† ' }
237
+ ]}
238
+ />
239
+ <p>๋ฐฐํฌ ๊ฐ’์€ <InlineCode text="readonly" /> ์ƒํƒœ๋กœ ๋‚จ๊น๋‹ˆ๋‹ค.</p>
240
+ <CodeBlock
241
+ label="๊ฒ€ํ†  ๊ทœ์น™"
242
+ language="ts"
243
+ code={"const requiredEvidence = ['owner', 'budget', 'audit-log'];\nconst ready = requiredEvidence.every((item) => status[item] === 'ready');"}
244
+ />
245
+ <Divider />
246
+ <Grid columns="two" gap="md">
247
+ <Surface padding="lg">
248
+ <strong>๊ณต๊ฐœ ํ‘œ๋ฉด</strong>
249
+ <p>๋ธŒ๋žœ๋“œ, ๋ฌธ์„œ, ๋กœ๋“œ๋งต์ฒ˜๋Ÿผ ๋ฐ˜๋ณต ํ™•์ธํ•˜๋Š” ํ™”๋ฉด์„ ์ฐจ๋ถ„ํ•˜๊ฒŒ ๋ฌถ์Šต๋‹ˆ๋‹ค.</p>
250
+ </Surface>
251
+ <Surface padding="lg">
252
+ <strong>์ž‘์—… ํ‘œ๋ฉด</strong>
253
+ <p>์„ค์ •, ์ž…๋ ฅ, ๊ฒ€ํ†  ํ๋ฆ„์€ ๊ฐ™์€ ์—ฌ๋ฐฑ๊ณผ focus ๊ทœ์น™ ์œ„์— ๋†“์ž…๋‹ˆ๋‹ค.</p>
254
+ </Surface>
255
+ </Grid>
256
+ <Toolbar labelledBy="consumer-contract-toolbar-title">
257
+ <strong id="consumer-contract-toolbar-title">๊ฒ€ํ†  ํ๋ฆ„</strong>
258
+ <svelte:fragment slot="actions">
259
+ <Button variant="secondary">์ดˆ์•ˆ</Button>
260
+ <Button>๊ฒ€ํ†  ์š”์ฒญ</Button>
261
+ </svelte:fragment>
262
+ </Toolbar>
263
+ <TableToolbar
264
+ title="์ ๊ฒ€ ๋ชฉ๋ก"
265
+ summary="๊ถŒํ•œ๊ณผ ๊ฐ์‚ฌ ํ•ญ๋ชฉ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค."
266
+ selectedCount={2}
267
+ density="compact"
268
+ ariaLabel="์ ๊ฒ€ ๋ชฉ๋ก ๋„๊ตฌ"
269
+ >
270
+ <svelte:fragment slot="selection-actions">
271
+ <Button variant="secondary">์„ ํƒ ํ•ด์ œ</Button>
272
+ </svelte:fragment>
273
+ <svelte:fragment slot="actions">
274
+ <Button>์ƒˆ๋กœ ๊ณ ์นจ</Button>
275
+ </svelte:fragment>
276
+ </TableToolbar>
277
+ <Table caption="๋ณด์•ˆ ์ ๊ฒ€ ๋ชฉ๋ก" density="compact">
278
+ <thead>
279
+ <tr>
280
+ <th scope="col" aria-sort="ascending">
281
+ <SortHeader label="ํ•ญ๋ชฉ" direction="ascending" />
282
+ </th>
283
+ <th scope="col">
284
+ <SortHeader label="์ƒํƒœ" direction="none" />
285
+ </th>
286
+ <th scope="col">๋‹ค์Œ ํ™•์ธ</th>
287
+ </tr>
288
+ </thead>
289
+ <tbody>
290
+ <tr>
291
+ <th scope="row">๊ถŒํ•œ ๋ถ„๋ฆฌ</th>
292
+ <td>ํ†ต๊ณผ</td>
293
+ <td>๋ถ„๊ธฐ ๋ฆฌ๋ทฐ</td>
294
+ </tr>
295
+ </tbody>
296
+ </Table>
297
+ <Pagination
298
+ currentPage={2}
299
+ totalPages={8}
300
+ ariaLabel="์ ๊ฒ€ ๋ชฉ๋ก ํŽ˜์ด์ง€"
301
+ hrefForPage={(page) => `?page=${page}`}
302
+ />
303
+ <KeyValue columns="two">
304
+ <dt>์†Œ์œ  ์ €์žฅ์†Œ</dt>
305
+ <dd>zdp-money-platform</dd>
306
+ <dt>์Šน๊ฒฉ ์กฐ๊ฑด</dt>
307
+ <dd>์˜ˆ์‚ฐ, ์†Œ์œ ์ž, ์šด์˜ ์ฆ๊ฑฐ ํ™•์ธ</dd>
308
+ </KeyValue>
309
+ <EmptyState labelledBy="contract-empty-title">
310
+ <h2 id="contract-empty-title">์•„์ง ๊ณต๊ฐœํ•  ๋ณ€๊ฒฝ์ด ์—†์Šต๋‹ˆ๋‹ค.</h2>
311
+ <p>๊ฒ€ํ† ๊ฐ€ ๋๋‚œ ํ•ญ๋ชฉ๋งŒ ๊ณต๊ฐœ ๋กœ๋“œ๋งต์— ์˜ฌ๋ผ๊ฐ‘๋‹ˆ๋‹ค.</p>
312
+ </EmptyState>
313
+ <Field required>
314
+ <Label forId="project-name">ํ”„๋กœ์ ํŠธ</Label>
315
+ <Input id="project-name" name="project-name" describedBy="project-name-help" />
316
+ <HelpText id="project-name-help">๊ณต๊ฐœ ํ‘œ๊ธฐ์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.</HelpText>
317
+ </Field>
318
+ <Field readonly>
319
+ <Label forId="project-id">๊ณ ์ • ID</Label>
320
+ <Input id="project-id" name="project-id" value="ZDP-2401" describedBy="project-id-help" readonly />
321
+ <HelpText id="project-id-help">์ด๋ฏธ ๋ฐœ๊ธ‰๋œ ๊ฐ’์€ ๊ทธ๋Œ€๋กœ ๋‘ก๋‹ˆ๋‹ค.</HelpText>
322
+ </Field>
323
+ <Field invalid>
324
+ <Label forId="project-status">์ƒํƒœ</Label>
325
+ <Input
326
+ id="project-status"
327
+ name="project-status"
328
+ describedBy={['project-status-help', 'project-status-error']}
329
+ errorMessageId="project-status-error"
330
+ invalid
331
+ />
332
+ <HelpText id="project-status-help">ํ˜„์žฌ ์ž‘์—… ์ƒํƒœ๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”.</HelpText>
333
+ <ErrorText id="project-status-error">๋‹ค์Œ ๋‹จ๊ณ„ ์ „์— ๊ธฐ์ค€์„ ํ™•์ธํ•˜์„ธ์š”.</ErrorText>
334
+ </Field>
335
+ <Inline gap="sm">
336
+ <Button>์ €์žฅ</Button>
337
+ </Inline>
338
+ <Dialog
339
+ open={dialogOpen}
340
+ id="project-dialog"
341
+ labelledBy="project-dialog-title"
342
+ describedBy="project-dialog-desc"
343
+ onClose={() => (dialogOpen = false)}
344
+ >
345
+ <h2 slot="title" id="project-dialog-title">๋ณ€๊ฒฝ ๋‚ด์šฉ์„ ์ €์žฅํ• ๊นŒ์š”?</h2>
346
+ <p id="project-dialog-desc">์ €์žฅํ•˜๋ฉด ๊ณต๊ฐœ ํ‘œ๊ธฐ์— ๋ฐ”๋กœ ๋ฐ˜์˜๋ฉ๋‹ˆ๋‹ค.</p>
347
+ <svelte:fragment slot="footer">
348
+ <Button variant="secondary" onclick={() => (dialogOpen = false)}>์ทจ์†Œ</Button>
349
+ <Button onclick={() => (dialogOpen = false)}>์ €์žฅ</Button>
350
+ </svelte:fragment>
351
+ </Dialog>
352
+ </Stack>
353
+ </Container>
354
+ </Page>
355
+ ```
356
+
357
+ Tauri shell์€ native window, permission, update, file access ๊ฒฐ์ •์„ ์ด ํŒจํ‚ค์ง€์— ๋„˜๊ธฐ์ง€ ์•Š๋Š”๋‹ค.
358
+ ์ด ํŒจํ‚ค์ง€๋Š” WebView ์•ˆ์˜ UI ํ† ํฐ๊ณผ ์ปดํฌ๋„ŒํŠธ๋งŒ ๋‹ด๋‹นํ•œ๋‹ค.
359
+ Breadcrumb๋Š” page-location trail, link, separator, current-page aria ๊ตฌ์กฐ๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ๋ผ์šฐํŒ…, SEO, ์ธ์ฆ, ๊ฒฐ์ œ, ๊ถŒํ•œ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
360
+ Button๊ณผ IconButton์€ native button ์œ„์˜ framed control ํ‘œ๋ฉด์ด๋ฉฐ `onclick`, `ariaLabel`, `ariaControls`, `ariaExpanded`, `ariaPressed`, `ariaDescribedBy`, `ariaKeyShortcuts` ๊ฐ™์€ ์•ก์…˜ ์—ฐ๊ฒฐ props๋ฅผ ์ „๋‹ฌํ•œ๋‹ค. ์ €์žฅ, ์‚ญ์ œ, ๊ถŒํ•œ, ๊ฒฐ์ œ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
361
+ ConfirmAction์€ ์ค‘์š”ํ•œ ์•ก์…˜์„ ๋ฐ€๊ธฐ ๋˜๋Š” ๊ธธ๊ฒŒ ๋ˆ„๋ฅด๊ธฐ๋กœ ํ™•์ธํ•˜๋Š” ํ‘œ๋ฉด์ด๋ฉฐ `onconfirm` ์ฝœ๋ฐฑ๋งŒ ์ „๋‹ฌํ•œ๋‹ค. ๊ฒฐ์ œ, ์‚ญ์ œ, ๊ถŒํ•œ, ํ™˜๋ถˆ ํŒ๋‹จ๊ณผ ์„œ๋ฒ„ ์š”์ฒญ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
362
+ Avatar์™€ IdentityChip์€ ์‚ฌ๋žŒ, ํŒ€, ์กฐ์ง์˜ visual identity, ์ด๋‹ˆ์…œ, ์ด๋ฆ„, ๋ณด์กฐ ํ…์ŠคํŠธ, ์„ ํƒ์  ๋งํฌ ํ‘œ๋ฉด๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ์‹ค์ œ ๊ณ„์ • ์‹๋ณ„, ํ”„๋กœํ•„ ๋ผ์šฐํŒ…, ์˜จ๋ผ์ธ ์ƒํƒœ, ๊ถŒํ•œ, ์ดˆ๋Œ€ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
363
+ Icon์€ ์žฅ์‹์šฉ glyph ๋˜๋Š” ์งง์€ ๋ณด์กฐ ๊ธฐํ˜ธ์˜ ๋ฐ•์Šค, ํฌ๊ธฐ, ์ค‘์•™์ •๋ ฌ๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ์˜๋ฏธ, ๋ผ๋ฒจ ๋ฌธ๊ตฌ, ์ƒํƒœ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
364
+ Link๋Š” ์ผ๋ฐ˜ ํ…์ŠคํŠธ ์ด๋™, hover ์ƒ‰์ƒ ๋ณ€ํ™”, keyboard focus highlight๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ๋ผ์šฐํŒ…, SEO, ์ธ์ฆ, ๊ฒฐ์ œ, ๊ถŒํ•œ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค. ์‹ค์ œ ๋‹จ์ถ•ํ‚ค๊ฐ€ ๊ตฌํ˜„๋œ ๋งํฌ๋งŒ `ariaKeyShortcuts`๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.
365
+ SkipLink๋Š” ๋ฐ˜๋ณต ํƒ์ƒ‰์„ ๊ฑด๋„ˆ๋›ฐ๋Š” keyboard-first link ๊ตฌ์กฐ์™€ focus-visible ํ‘œ์‹œ๋งŒ ์ œ๊ณตํ•˜๋ฉฐ target id, ํŽ˜์ด์ง€ ๋ ˆ์ด์•„์›ƒ, ๋ผ์šฐํŒ… ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
366
+ VisuallyHidden์€ screen-reader-only ๋ณด์กฐ ํ…์ŠคํŠธ ์ˆจ๊น€๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ๋ผ๋ฒจ ๋ฌธ๊ตฌ, ๋ฒˆ์—ญ, ๊ถŒํ•œ, ๋ฐ์ดํ„ฐ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
367
+ ShareDock์€ ๊ณต์œ  ๋„ํฌ์˜ ์œ„์น˜, ์•„์ด์ฝ˜, tooltip, focus-visible ํ‘œ๋ฉด๋งŒ ์ œ๊ณตํ•˜๋ฉฐ URL ์ƒ์„ฑ, clipboard, navigator.share, ํ”Œ๋žซํผ๋ณ„ ๊ณต์œ  ๋งํฌ, ๊ถŒํ•œ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค. ๋ฌธ์„œ ๋ณธ๋ฌธ ์˜†์— ๋ถ™๋Š” sticky ๊ณต์œ  ๋ ˆ์ผ์€ `rail` placement๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
368
+ `zdpShareIcons`๋Š” ๊ณต์œ  ์•„์ด์ฝ˜ shape ๋ฐ์ดํ„ฐ๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ํ”Œ๋žซํผ๋ณ„ ๊ณต์œ  URL, target, rel, ํด๋ฆญ ๊ฐ€๋Šฅ ์—ฌ๋ถ€๋Š” ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค. Telegram, LINE, WhatsApp, X, Reddit ๊ฐ™์€ ํ”Œ๋žซํผ ๋ธŒ๋žœ๋“œ glyph๋Š” Simple Icons path ๊ธฐ์ค€์„ ์œ ์ง€ํ•œ๋‹ค.
369
+ ThemeToggle์€ light/dark ์ „ํ™˜ ๋ฒ„ํŠผ์˜ pressed ์ƒํƒœ, glyph, ์ ‘๊ทผ์„ฑ ์ด๋ฆ„, focus-visible ํ‘œ๋ฉด๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ์ดˆ๊ธฐ ํ…Œ๋งˆ ๊ฒฐ์ •, storage key, system preference, SSR/์ดˆ๊ธฐ paint ์ฒ˜๋ฆฌ๋Š” ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
370
+
371
+ LocaleSwitcher๋Š” locale ์„ ํƒ์„ ์œ„ํ•œ radiogroup, ์„ ํƒ ์ƒํƒœ, focus-visible, keyboard ์ด๋™ ํ‘œ๋ฉด๋งŒ ์ œ๊ณตํ•œ๋‹ค. ์‹ค์ œ message catalog ๋กœ๋”ฉ, URL routing, fallback locale, root `lang`, storage key, ์‚ฌ์šฉ์ž preference ์ €์žฅ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
372
+
373
+ TextScaleControl์€ ๊ธ€์ž ํฌ๊ธฐ ์„ ํƒ์„ ์œ„ํ•œ radiogroup, ์„ ํƒ ์ƒํƒœ, focus-visible, keyboard ์ด๋™ ํ‘œ๋ฉด๋งŒ ์ œ๊ณตํ•œ๋‹ค. ์‹ค์ œ document root ๋ฐฐ์œจ, media query, storage key, locale๋ณ„ ๊ธ€์ž ํฌ๊ธฐ ๋ณด์ •, ์‚ฌ์šฉ์ž preference ์ €์žฅ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
374
+ Tooltip์€ ์งง์€ ๋ณด์กฐ ์„ค๋ช… ํ‘œ๋ฉด๋งŒ ์ œ๊ณตํ•˜๋ฉฐ Escape dismiss๋ฅผ ์œ ์ง€ํ•˜๊ณ , ๊ธด ๋„์›€๋ง, validation message, popover, tour, ๊ถŒํ•œ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค. ์„ค๋ช…์ด ์ ‘๊ทผ์„ฑ ์ด๋ฆ„์„ ๋ณด๊ฐ•ํ•ด์•ผ ํ•  ๋•Œ๋งŒ Tooltip `id`๋ฅผ ๋„˜๊ธฐ๊ณ  trigger์— `aria-describedby`๋ฅผ ์—ฐ๊ฒฐํ•œ๋‹ค.
375
+ Accordion๊ณผ Disclosure๋Š” ์ ‘ํžŒ ์•ˆ๋‚ด, ์„ค์ • ๋ฌถ์Œ, FAQํ˜• ์„ค๋ช…์˜ trigger/panel/`aria-expanded`/`aria-controls` ๊ตฌ์กฐ๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ์‹ค์ œ FAQ ๋ฌธ๊ตฌ, ์„ค์ • ๊ฐ’, ํ•ญ๋ชฉ ๋…ธ์ถœ, ๊ถŒํ•œ, ๋ฐ์ดํ„ฐ fetch ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค. Accordion์€ ๋‹จ์ผ ๋˜๋Š” ๋ณต์ˆ˜ ์—ด๋ฆฐ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜์ง€๋งŒ ํ•ญ๋ชฉ visibility, ํ•„ํ„ฐ ์˜๋ฏธ, ์„œ๋ฒ„ ์ƒํƒœ ํŒ๋‹จ์œผ๋กœ ํ™•์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค.
376
+ SegmentedControl์€ ๋ณด๊ธฐ ๋ฐฉ์‹, ๋ฐ€๋„, ๊ธฐ๊ฐ„์ฒ˜๋Ÿผ ๊ฐ€๊นŒ์šด ๋‹จ์ผ ์„ ํƒ์˜ `radiogroup`/`radio`/`aria-checked` ๊ตฌ์กฐ๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ์‹ค์ œ ํ•„ํ„ฐ ์˜๋ฏธ, URL state, ์ •๋ ฌ, ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ, ๊ถŒํ•œ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
377
+ Popover์™€ Menu๋Š” ์„ค์ •, ๋”๋ณด๊ธฐ, ํ•„ํ„ฐ, ๊ณ„์ • ๋ฉ”๋‰ด์ฒ˜๋Ÿผ ๊ฐ€๊นŒ์šด ํŠธ๋ฆฌ๊ฑฐ์—์„œ ์งง๊ฒŒ ํŽผ์น˜๋Š” ํ‘œ๋ฉด๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ํ•ญ๋ชฉ ๋…ธ์ถœ, ๊ถŒํ•œ, ๋ผ์šฐํŒ…, ํ•„ํ„ฐ ์˜๋ฏธ, ๊ณ„์ • ์ƒํƒœ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค. Popover์™€ Menu๋Š” Escape ๋‹ซ๊ธฐ, outside click, focus ๋ณต๊ท€, menu keyboard movement ๊ฐ™์€ ๊ธฐ๋ณธ ์ƒํ˜ธ์ž‘์šฉ๋งŒ ์œ ์ง€ํ•˜๊ณ  tour, validation, modal decision, floating collision engine ์—ญํ• ๋กœ ํ™•์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค.
378
+ Sheet๋Š” right, left, bottom edge panel๋กœ ์„ค์ •, ํ•„ํ„ฐ, ๋ณด์กฐ ํ๋ฆ„์„ ์—ฌ๋Š” modal surface๋งŒ ์ œ๊ณตํ•œ๋‹ค. Escape ๋‹ซ๊ธฐ, backdrop ๋‹ซ๊ธฐ, Tab ์ˆœํ™˜, scroll lock, ์ด์ „ focus ๋ณต๊ท€, `role="dialog"`, `aria-modal` ๊ตฌ์กฐ๋Š” Sheet ํ‘œ๋ฉด์˜ ๊ธฐ๋ณธ ๋™์ž‘์œผ๋กœ ์œ ์ง€ํ•œ๋‹ค. Drawer๋Š” ๋ณ„๋„ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ณต์ œํ•˜์ง€ ์•Š๊ณ  Sheet placement/use case๋กœ ๋จผ์ € ๋‹ค๋ฃฌ๋‹ค. ์ €์žฅ, ๊ถŒํ•œ, ๋ฐ์ดํ„ฐ fetch, ๋ผ์šฐํŒ… ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
379
+ Sheet root๋Š” `data-zdp-sheet-placement`, `data-zdp-sheet-size`, `data-zdp-sheet-surface="sheet"`๋ฅผ ๋‚จ๊ฒจ QA์™€ ์†Œ๋น„ ์•ฑ์ด surface identity๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค.
380
+ Toast์™€ StatusToast๋Š” ์ €์žฅ, ๋™๊ธฐํ™”, ์‹คํŒจ, ๊ฒฝ๊ณ ์ฒ˜๋Ÿผ ์งง์€ ์ƒํƒœ ์•Œ๋ฆผ ํ‘œ๋ฉด๊ณผ dismiss/action/live-region ์—ฐ๊ฒฐ๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ์•Œ๋ฆผ ๋ฐœ์ƒ ์กฐ๊ฑด, ํ ์ˆœ์„œ, ์ž๋™ ๋‹ซํž˜ ํƒ€์ด๋จธ, ์ค‘๋ณต ์ œ๊ฑฐ, ์žฌ์‹œ๋„ ์ •์ฑ…, ๊ถŒํ•œ, ์„œ๋ฒ„ ์ƒํƒœ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค. Toast์™€ StatusToast๋Š” ํŽ˜์ด์ง€ ์•ˆ ํ”ผ๋“œ๋ฐฑ์ด๋‚˜ modal decision์„ ๋Œ€์ฒดํ•˜์ง€ ์•Š๊ณ , ์˜ค๋ž˜ ์ฝ์–ด์•ผ ํ•˜๋Š” ์•ˆ๋‚ด๋Š” Callout ๋˜๋Š” ์†Œ๋น„ ์•ฑ์˜ ๋ณ„๋„ ํ๋ฆ„์œผ๋กœ ๋‚จ๊ธด๋‹ค.
381
+ Progress, Spinner, Skeleton์€ ์ž‘์—… ์ง„ํ–‰, ์‘๋‹ต ๋Œ€๊ธฐ, ์ฝ˜ํ…์ธ  ์ž๋ฆฌ ์˜ˆ์•ฝ ํ‘œ๋ฉด๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ๋กœ๋”ฉ ์กฐ๊ฑด, ์ง„ํ–‰๋ฅ  ๊ณ„์‚ฐ, ์™„๋ฃŒ/์‹คํŒจ ์ „ํ™˜, ๋ฐ์ดํ„ฐ fetch, ์žฌ์‹œ๋„, ๊ถŒํ•œ, ์„œ๋ฒ„ ์ƒํƒœ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค. Skeleton์€ ์ตœ์ข… ๋ ˆ์ด์•„์›ƒ ํฌ๊ธฐ๋ฅผ ์˜ˆ์•ฝํ•˜๋Š” ์šฉ๋„๋กœ ์“ฐ๊ณ , ์‹ค์ œ ํ…์ŠคํŠธ ์˜๋ฏธ๋‚˜ ๋นˆ ์ƒํƒœ ํŒ๋‹จ์€ EmptyState ๋˜๋Š” ์†Œ๋น„ ์•ฑ์˜ ์ƒํƒœ ํ๋ฆ„์— ๋‚จ๊ธด๋‹ค.
382
+ Page๋Š” shared page root, surface reset, theme tone๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ๋ผ์šฐํŒ…, SEO, ๋ฐ์ดํ„ฐ, ๊ถŒํ•œ, ์ œํ’ˆ๋ณ„ visibility ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
383
+ Container๋Š” ํŽ˜์ด์ง€ ํญ, inline padding, centered width๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ๊ทธ๋ฆฌ๋“œ ์˜๋ฏธ, ๋ผ์šฐํŒ…, ๋ฐ์ดํ„ฐ, ๊ถŒํ•œ, ์ œํ’ˆ๋ณ„ visibility ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
384
+ Section์€ block rhythm๊ณผ optional full-width band๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ์นด๋“œ, ๋ผ์šฐํŒ…, ๋ฐ์ดํ„ฐ, ๊ถŒํ•œ, ์ œํ’ˆ๋ณ„ visibility ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
385
+ PageHeader๋Š” ์ œ๋ชฉ, ์š”์•ฝ, ์•ก์…˜ ๋ฐฐ์น˜๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ๋ฌธ๊ตฌ, SEO heading hierarchy, ๋ผ์šฐํŒ…, ๋ฐ์ดํ„ฐ, ๊ถŒํ•œ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค. ์ผ๋ฐ˜ ๋ฌธ์„œ์™€ ์•ฑ ํŽ˜์ด์ง€ ์ œ๋ชฉ์€ `type.pageTitleSize`์™€ `type.pageTitleCompactSize` ๋ฒ”์œ„์—์„œ ์‹œ์ž‘ํ•˜๊ณ , ๋ธŒ๋žœ๋“œ ํžˆ์–ด๋กœ๋‚˜ ์บ ํŽ˜์ธ ํ‘œ๋ฉด๋งŒ ์†Œ๋น„ ์•ฑ์˜ ๋ณ„๋„ ๋Œ€ํ˜• ์ œ๋ชฉ ์˜ˆ์™ธ๋ฅผ ๋‘˜ ์ˆ˜ ์žˆ๋‹ค.
386
+ Stack์€ ๊ฐ€๊นŒ์šด ์š”์†Œ์˜ ์„ธ๋กœ ํ๋ฆ„, gap, align๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ํŽ˜์ด์ง€ ๊ทธ๋ฆฌ๋“œ, ๋ผ์šฐํŒ…, ๋ฐ์ดํ„ฐ, ๊ถŒํ•œ, ์ œํ’ˆ๋ณ„ visibility ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
387
+ Inline์€ ๊ฐ€๊นŒ์šด ๋ฒ„ํŠผ, ๋ฐฐ์ง€, ์ž‘์€ ๋งํฌ ๋ฌถ์Œ์˜ ๊ฐ€๋กœ ํ๋ฆ„, gap, align, justify๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ํŽ˜์ด์ง€ ๊ทธ๋ฆฌ๋“œ, ๋ผ์šฐํŒ…, ๋ฐ์ดํ„ฐ, ๊ถŒํ•œ, ์ œํ’ˆ๋ณ„ visibility ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
388
+ Divider๋Š” ๊ฐ€๊นŒ์šด ๋‚ด์šฉ ์‚ฌ์ด์˜ ๊ตฌ๋ถ„์„ , line tone, semantic separator ์—ญํ• ๋งŒ ์ œ๊ณตํ•˜๋ฉฐ section layout, page rhythm, ๋ผ์šฐํŒ…, ๋ฐ์ดํ„ฐ, ๊ถŒํ•œ, ์ œํ’ˆ๋ณ„ visibility ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
389
+ Grid๋Š” ๋ฐ˜๋ณต๋˜๋Š” ์นด๋“œ, ์š”์•ฝ, ์„ ํƒ์ง€ ๋ฌถ์Œ์˜ responsive columns์™€ gap๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ๊ฐ ํ•ญ๋ชฉ์˜ ์˜๋ฏธ, ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ, ๊ถŒํ•œ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
390
+ Toolbar๋Š” ๊ฐ€๊นŒ์šด ํ™”๋ฉด ๋„๊ตฌ์™€ ์•ก์…˜ ๋ฌถ์Œ์˜ wrapping, main/action ๋ฐฐ์น˜๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ์ €์žฅ, ์‚ญ์ œ, ํ•„ํ„ฐ, ๊ถŒํ•œ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
391
+ CommandField๋Š” ๊ฒ€์ƒ‰ ์ž…๋ ฅ์˜ label, frame, focus-within, shortcut keycap, help/error id, `ariaKeyShortcuts`, `ariaAutocomplete`, result id ์—ฐ๊ฒฐ, ์ž…๋ ฅ keydown callback๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ๊ฒ€์ƒ‰ ์ธ๋ฑ์Šค, ๊ฒฐ๊ณผ ์ •๋ ฌ, command palette, ๋ผ์šฐํŒ…, ๊ถŒํ•œ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค. ๊ฒฐ๊ณผ ๋ชฉ๋ก, keyboard dispatcher, command ์‹คํ–‰ ์ƒํƒœ๋Š” ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
392
+ Combobox๋Š” ๊ฒ€์ƒ‰ ๊ฐ€๋Šฅํ•œ ๋‹จ์ผ ์„ ํƒ์˜ label, input frame, listbox, active option, disabled option skip, hidden submitted value๋งŒ ์ œ๊ณตํ•œ๋‹ค. ์‹ค์ œ ํ•„ํ„ฐ๋ง, async search, command ์‹คํ–‰, ๊ถŒํ•œ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค. ๋‹จ์ˆœ ์ƒํƒœ ์„ ํƒ์€ native `Select`๋ฅผ ์œ ์ง€ํ•˜๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅ์œผ๋กœ ํ›„๋ณด๋ฅผ ์ขํžˆ๋Š” ๋‹จ์ผ ์„ ํƒ์ผ ๋•Œ๋งŒ Combobox๋ฅผ ์“ด๋‹ค.
393
+ InlineCode์™€ CodeBlock์€ ๋ฌธ์„œ, ๋ณด์•ˆ, ์•„ํ‚คํ…์ฒ˜ ํŽ˜์ด์ง€์˜ ์ฝ”๋“œ ํ‘œ์‹œ, language label, horizontal overflow, ์„ ํƒ์  ๋ณต์‚ฌ ๋ฒ„ํŠผ๋งŒ ์ œ๊ณตํ•˜๋ฉฐ syntax highlighting, ์ฝ”๋“œ ์‹คํ–‰, ๋น„๋ฐ€๊ฐ’ ํƒ์ง€, ๋ณด์•ˆ ๋ถ„๋ฅ˜, command palette๋Š” ์†Œ๋น„ ์•ฑ์ด๋‚˜ ๋ฌธ์„œ ํŒŒ์ดํ”„๋ผ์ธ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค. CodeBlock์€ `code` prop์ด ์žˆ์„ ๋•Œ๋งŒ ๋ณต์‚ฌ ๋ฒ„ํŠผ์„ ๋…ธ์ถœํ•˜๋ฏ€๋กœ slot์œผ๋กœ ํ‘œ์‹œํ•œ ์ฝ”๋“œ์˜ ๋ณต์‚ฌ ๋ฌธ์ž์—ด์€ ์†Œ๋น„ ์•ฑ์ด ๋ช…์‹œ์ ์œผ๋กœ ๋„˜๊ธด๋‹ค. ๊ธด ์ฝ”๋“œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ horizontal overflow ํ‘œ๋ฉด์—์„œ ์Šคํฌ๋กค๋˜๊ณ , code body๋Š” ์„ ํƒ ๊ฐ€๋Šฅํ•ด์•ผ ํ•œ๋‹ค.
394
+
395
+ Kbd์™€ ShortcutHint๋Š” `/`, `?`, `Enter`, `Esc`, `ArrowUp`, `ArrowDown`, `Ctrl/โŒ˜+Enter` ๊ฐ™์€ ํ‚ค์บก ํžŒํŠธ๋งŒ ์ œ๊ณตํ•œ๋‹ค. ์‹ค์ œ keydown dispatcher, command palette, ๊ฒ€์ƒ‰ focus ์ด๋™, ๋‹จ์ถ•ํ‚ค ์•ˆ๋‚ด, ์„ ํƒ, ๋‹ซ๊ธฐ, ํŒŒ์ผ ์ด๋™์€ ์†Œ๋น„ ์•ฑ์ด ์†Œ์œ ํ•œ๋‹ค. `ariaKeyShortcuts`์™€ `aria-keyshortcuts`๋Š” ์‹ค์ œ ๋‹จ์ถ•ํ‚ค๊ฐ€ ๋™์ž‘ํ•˜๋Š” Button, IconButton, Link, CommandField์—๋งŒ ๋ถ™์ธ๋‹ค. ์†Œ๋น„ ์•ฑ์˜ ์ „์—ญ ๋‹จ์ถ•ํ‚ค dispatcher๋Š” `shouldZdpIgnoreShortcutEvent`, `isZdpTextEntryTarget`, `isZdpBrowserReservedShortcut`, `zdpShortcutRecommendations`, `zdpShortcutReservedExamples` ๊ฐ™์€ shortcut policy helper๋กœ ์ž…๋ ฅ์ฐฝ, IME ์กฐํ•ฉ, ๋ธŒ๋ผ์šฐ์ € ์˜ˆ์•ฝ ์กฐํ•ฉ์„ ๋จผ์ € ๊ฑธ๋Ÿฌ๋‚ธ๋‹ค. `input, textarea, select, contenteditable`, `role="textbox"`, `role="searchbox"` ์•ˆ์—์„œ๋Š” ์ „์—ญ ๋‹จ์ถ•ํ‚ค๋ฅผ ๊บผ๋‘๊ณ , `event.isComposing` ๋˜๋Š” `keyCode === 229`์ธ ํ•œ๊ตญ์–ด ์กฐํ•ฉ ์ž…๋ ฅ๋„ ๋ฌด์‹œํ•œ๋‹ค. `Ctrl+K`, `Ctrl+S`์ฒ˜๋Ÿผ Chrome๊ณผ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๊ธฐ๋ณธ ๋™์ž‘์œผ๋กœ ๊ฐ€์ ธ๊ฐ€๋Š” ์กฐํ•ฉ์€ ์†Œ๋น„ ์•ฑ์—์„œ ์‹ค์ œ๋กœ ๊ฐ€๋กœ์ฑ„๊ณ  ๊ฒ€์ฆํ•œ ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹ˆ๋ฉด ์˜ˆ์‹œ๋‚˜ UI ํžŒํŠธ๋กœ ๋ณด์—ฌ์ฃผ์ง€ ์•Š๋Š”๋‹ค.
396
+ Table์€ ํ‘œ ํ˜•์‹ ์ •๋ณด์˜ native table, caption, row/column header, horizontal overflow wrapper๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ์ •๋ ฌ, ํ•„ํ„ฐ, ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ, ๊ถŒํ•œ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค. ์ข์€ ํญ์—์„œ๋„ header์™€ cell ๋ฐ์ดํ„ฐ๊ฐ€ ํ•œ ๊ธ€์ž์”ฉ ์ชผ๊ฐœ์ง€์ง€ ์•Š๊ณ  table wrapper๊ฐ€ overflow๋ฅผ ์†Œ์œ ํ•ด์•ผ ํ•œ๋‹ค. Table wrapper๋Š” header ์˜ค๋ฅธ์ชฝ์— ๋นˆ gutter stripe๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ์ƒ์‹œ `scrollbar-gutter: stable`์„ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์“ฐ์ง€ ์•Š๋Š”๋‹ค.
397
+ SortHeader์™€ TableToolbar๋Š” sortable column affordance, ์„ ํƒ ํ–‰ ์•ก์…˜ ์ž๋ฆฌ, ๋ฐ€๋„ ์ „ํ™˜ ํ‘œ๋ฉด๋งŒ ์ œ๊ณตํ•˜๋ฉฐ `aria-sort`, ์‹ค์ œ ์ •๋ ฌ ๊ณ„์‚ฐ, ์„ ํƒ ์ƒํƒœ, ํ•„ํ„ฐ, ๊ถŒํ•œ, ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค. `aria-sort`๋Š” SortHeader ๋ฒ„ํŠผ์ด ์•„๋‹ˆ๋ผ owning `th` ๋˜๋Š” columnheader์— ๋‘”๋‹ค.
398
+ Pagination์€ ๋ชฉ๋ก ํŽ˜์ด์ง€ ์ด๋™์˜ `nav`, ordered list, link/button, ellipsis, `aria-current="page"` ๊ตฌ์กฐ๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ์ „์ฒด ๊ฐœ์ˆ˜, ํ˜„์žฌ ํŽ˜์ด์ง€ ์ƒํƒœ, ํŽ˜์ด์ง€ ํฌ๊ธฐ, ์ฟผ๋ฆฌ ๋ผ์šฐํŒ…, ํ•„ํ„ฐ, ์ •๋ ฌ, ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ, ๊ถŒํ•œ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค. ์ž‘์€ ์ปจํ…Œ์ด๋„ˆ์—์„œ๋Š” pagination nav๊ฐ€ horizontal overflow๋ฅผ ์†Œ์œ ํ•˜๊ณ  ํŽ˜์ด์ง€ ๋ฒ„ํŠผ์ด ์—ฌ๋Ÿฌ ์ค„๋กœ ๋ฌด๋„ˆ์ง€์ง€ ์•Š์•„์•ผ ํ•˜๋ฉฐ, ์Šคํฌ๋กค ํ‘œ๋ฉด ์•ˆ์—์„œ๋„ focus outline์˜ ์œ„์•„๋ž˜ edge๊ฐ€ ์ž˜๋ฆฌ์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค.
399
+ KeyValue๋Š” ์šฉ์–ด์™€ ๊ฐ’์˜ description list ๊ตฌ์กฐ์™€ responsive columns๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ์‹ค์ œ ์›์žฅ, ๋ณด์•ˆ, ๊ฒฐ์ œ, ๊ถŒํ•œ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
400
+ EmptyState๋Š” ๋น„์–ด ์žˆ๋Š” ์ƒํƒœ์˜ surface, ์ œ๋ชฉ ์—ฐ๊ฒฐ, ์•ก์…˜ ๋ฐฐ์น˜๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ๋น„์–ด ์žˆ๋Š” ์กฐ๊ฑด, ๋‹ค์Œ ์•ก์…˜ ๊ฐ€๋Šฅ ์—ฌ๋ถ€, ๋ฐ์ดํ„ฐ ์žฌ์‹œ๋„ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
401
+ TermTrigger์™€ TermSheet๋Š” ์šฉ์–ด ์„ค๋ช…์„ ํด๋ฆญ์œผ๋กœ ์—ฌ๋Š” trigger, right sheet, bottom sheet ํ‘œ๋ฉด๋งŒ ์ œ๊ณตํ•œ๋‹ค. `.zdp-term-trigger`๋Š” ๋ณธ๋ฌธ ์•ˆ ์šฉ์–ด๋ฅผ button์œผ๋กœ ์—ด๊ณ , sheet๊ฐ€ ์—ด๋ฆฐ ๋™์•ˆ์—๋งŒ `aria-controls`๋ฅผ ์—ฐ๊ฒฐํ•˜๋ฉฐ, `.zdp-term-sheet`๋Š” ์„ ํƒ๋œ ์šฉ์–ด์˜ ์งง์€ ์„ค๋ช…, ๊ธด ์„ค๋ช…, ์˜ˆ์‹œ, ๊ด€๋ จ ์šฉ์–ด, detail link ์ž๋ฆฌ๋ฅผ ๋ณด์—ฌ์ค€๋‹ค. `.zdp-term-trigger`๋Š” inline interactive text๋ผ์„œ hover์—์„œ ๊ธ€์ž์ƒ‰์„ ๋ฐ”๊พธ์ง€ ์•Š๊ณ  ๋ฐฐ๊ฒฝ๋งŒ ๊ฐ•์กฐํ•˜๋ฉฐ, ์ขŒ์šฐ ์ตœ์†Œ padding๊ณผ focus token์„ ์œ ์ง€ํ•˜๊ณ , ๋ณธ๋ฌธ ํ…์ŠคํŠธ ์„ ํƒ์„ ๋ง‰์ง€ ์•Š๋Š”๋‹ค. Escape ๋‹ซ๊ธฐ, backdrop ๋‹ซ๊ธฐ, Tab ์ˆœํ™˜, scroll lock, ์ด์ „ focus ๋ณต๊ท€๋Š” sheet ํ‘œ๋ฉด์˜ ๊ธฐ๋ณธ ๋™์ž‘์œผ๋กœ ์œ ์ง€ํ•œ๋‹ค. glossary manifest, locale fallback, ๊ณต๊ฐœ ๊ฐ€๋Šฅ ์—ฌ๋ถ€, detail page ๋ผ์šฐํŒ… ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ๊ณผ glossary pipeline์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
402
+ TermSheet root๋Š” stable `term_id`๋ฅผ `data-term-id`์™€ `data-zdp-term-id`๋กœ ๋‚จ๊ธฐ๊ณ , `data-zdp-term-placement`์™€ `data-zdp-term-surface="sheet"`๋กœ QA์™€ linter๊ฐ€ ์„ ํƒ๋œ ์šฉ์–ด surface๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค.
403
+ TermSheet์—๋Š” ๊ด‘๊ณ  slot์„ ๋„ฃ์ง€ ์•Š๋Š”๋‹ค. TermSheet root๋Š” `data-zdp-ad-exclude="true"`๋ฅผ ์œ ์ง€ํ•˜๊ณ , ๊ด‘๊ณ ๊ฐ€ ํ•„์š”ํ•œ ๊ธด ์„ค๋ช…์€ ์†Œ๋น„ ์•ฑ์˜ ๋ณ„๋„ detail page์—์„œ ๋‹ค๋ฃฌ๋‹ค.
404
+ Input, Textarea, Select๋Š” `describedBy`์— ํ•˜๋‚˜ ์ด์ƒ์˜ id๋ฅผ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๊ณ  invalid ์ƒํƒœ์—์„œ๋Š” `errorMessageId`๋กœ `aria-errormessage`๋ฅผ ์—ฐ๊ฒฐํ•œ๋‹ค. ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ๋ฌธ๊ตฌ, ๊ฒ€์ฆ ์กฐ๊ฑด, ์ œ์ถœ ์ฐจ๋‹จ ์—ฌ๋ถ€๋Š” ์†Œ๋น„ ์•ฑ์ด ๊ฒฐ์ •ํ•œ๋‹ค.
405
+ Switch๋„ `describedBy` id ๋ฐฐ์—ด๊ณผ `errorMessageId`๋ฅผ ํ†ตํ•ด invalid ์ƒํƒœ์˜ ๋ณด์กฐ ์„ค๋ช…๊ณผ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ native switch input์— ์—ฐ๊ฒฐํ•œ๋‹ค.
406
+ Input๊ณผ Textarea์˜ `readonly` ์ƒํƒœ๋Š” ์ œ์ถœ๊ณผ ํฌ์ปค์Šค๋ฅผ ์œ ์ง€ํ•˜๋Š” ์ฝ๊ธฐ ์ „์šฉ ๊ฐ’์— ์‚ฌ์šฉํ•œ๋‹ค. ๊ถŒํ•œ ๋•Œ๋ฌธ์— ๊ฐ’์„ ๋ฐ”๊พธ๋ฉด ์•ˆ ๋˜๋Š”์ง€, ๋‹จ์ˆœํžˆ ๊ณ ์ • ์‹๋ณ„์ž๋ฅผ ๋ณด์—ฌ์ฃผ๋Š”์ง€๋Š” ์†Œ๋น„ ์•ฑ์ด ๊ฒฐ์ •ํ•œ๋‹ค.
407
+ Tabs๋Š” ๊ฐ€๊นŒ์šด ์ •๋ณด ๋ฌถ์Œ ์ „ํ™˜์„ ํ‘œํ˜„ํ•˜๋˜ ๋ผ์šฐํŒ…, ๊ถŒํ•œ, ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค. ๊ฐ™์€ ํŽ˜์ด์ง€์— ์—ฌ๋Ÿฌ Tabs๊ฐ€ ์žˆ์œผ๋ฉด `idPrefix`๋ฅผ ๋„˜๊ฒจ tab/panel id๊ฐ€ ์ถฉ๋Œํ•˜์ง€ ์•Š๊ฒŒ ํ•œ๋‹ค.
408
+ Dialog๋Š” modal layer, backdrop, close, scroll lock, focus trap, aria ๊ตฌ์กฐ๋งŒ ์ œ๊ณตํ•˜๋ฉฐ ์ €์žฅ, ์‚ญ์ œ, ์ธ์ฆ, ๊ฒฐ์ œ, ๊ถŒํ•œ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์ด ๊ณ„์† ์†Œ์œ ํ•œ๋‹ค.
409
+
410
+ ## Flutter์™€ Native ์†Œ๋น„ ํ‘œ๋ฉด
411
+
412
+ Flutter์™€ native shell์€ Svelte ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ง์ ‘ ์†Œ๋น„ํ•˜์ง€ ์•Š๋Š”๋‹ค.
413
+ ๋Œ€์‹  `tokens/zdp.tokens.json`์„ theme adapter ์ž…๋ ฅ์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.
414
+
415
+ - `hex`๋Š” ๊ธฐ๋ณธ theme fallback์ด๋‹ค.
416
+ - `oklch`๋Š” ์›น ๋˜๋Š” ๋ณ€ํ™˜ ๊ฐ€๋Šฅํ•œ ๋ Œ๋”๋Ÿฌ์—์„œ ์ƒ‰ ์˜๋„๊ฐ’์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.
417
+ - `font.family.korean`, `font.family.latin`, `font.family.chinese`, `font.family.devanagari`, `font.family.japanese`, `font.family.multiscript`๋Š” locale๋ณ„ fallback ์ˆœ์„œ์˜ source of truth๋‹ค.
418
+ - `font.family.brand`๋Š” ๋ธŒ๋žœ๋“œ ์›Œ๋“œ๋งˆํฌ ์ „์šฉ source of truth๋‹ค. ์ผ๋ฐ˜ heading์˜ `font.family.display`์™€ ์„ž์ง€ ์•Š๋Š”๋‹ค.
419
+ - `font.family.expressionScript`, `font.family.expressionInscription`, `font.family.expressionSketch`, `font.family.expressionEditorial`, `font.family.expressionSans`, `font.family.expressionKeyboard`๋Š” opt-in ํ‘œํ˜„์šฉ source of truth๋‹ค. `expressive-fonts.css`๋ฅผ importํ•œ ํ‘œ๋ฉด์—์„œ๋งŒ ์บ ํŽ˜์ธ, ์„น์…˜ ์ œ๋ชฉ, ์งง์€ ๋ณด์กฐ ์•ˆ๋‚ด, ํ‚ค๋ณด๋“œ ํ‘œ์‹์— ์ œํ•œํ•ด์„œ ์“ด๋‹ค.
420
+ - `control.heightMd`, `control.glyphMd`, `control.choiceSize`, `control.choiceIndicatorSize`, `control.switchWidth`, `control.switchHeight`, `control.scrollbarSize`, `control.radius`, `control.borderWidth`, `control.hitTarget`์€ native control size, icon glyph size, choice mark, switch track, scrollbar ๋‘๊ป˜๋ฅผ ๋งž์ถœ ๋•Œ์˜ ๊ธฐ์ค€์ด๋‹ค.
421
+ - `color.scrollbar.track`, `color.scrollbar.thumb`, `color.scrollbar.thumbHover`๋Š” overflow ์˜์—ญ์˜ light/dark scrollbar ์ƒ‰ ๊ธฐ์ค€์ด๋‹ค.
422
+ - `color.selection.surface`, `color.selection.text`๋Š” `.zdp-surface-reset` ์•ˆ์˜ drag text selection ์ƒ‰ ๊ธฐ์ค€์ด๋‹ค.
423
+ - `focus.surface`, `focus.text`, `focus.line`์€ keyboard focus ๋˜๋Š” TV/desktop focus affordance์˜ ๊ธฐ์ค€์ƒ‰์ด๋‹ค.
424
+ - `.zdp-user-select-control`, `.zdp-user-select-decorative`, `.zdp-user-select-dragging`์€ token์ด ์•„๋‹ˆ๋ผ interaction utility๋‹ค. ์กฐ์ž‘ ๋ถ€ํ’ˆ, ์žฅ์‹ ํ‘œ๋ฉด, ์‹ค์ œ ๋“œ๋ž˜๊ทธ ์ค‘ ์ƒํƒœ์—๋งŒ ์“ฐ๊ณ  ์ฝ๋Š” ์ •๋ณด์˜ ๊ธฐ๋ณธ ์„ ํƒ ๊ฐ€๋Šฅ์„ฑ์„ ๋ฎ์ง€ ์•Š๋Š”๋‹ค.
425
+
426
+ ## ์†Œ๋น„์ฒ˜ ์ ์šฉ ์ฒดํฌ๋ฆฌ์ŠคํŠธ
427
+
428
+ - `styles.css`๋ฅผ ๋จผ์ € importํ•œ๋‹ค.
429
+ - ๋‹ค๊ตญ์–ด ์›นํฐํŠธ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ `locale-fonts.css`๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.
430
+ - ๋ธŒ๋žœ๋“œ ์›Œ๋“œ๋งˆํฌ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ `brand-fonts.css`๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.
431
+ - ํ‘œํ˜„์šฉ ์„น์…˜์ด๋‚˜ ์บ ํŽ˜์ธ ๋ฌธ๊ตฌ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ `expressive-fonts.css`๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.
432
+ - Svelte component๋Š” package root์—์„œ๋งŒ importํ•œ๋‹ค.
433
+ - Link๋ฅผ ์“ฐ๋Š” ํ™”๋ฉด์€ hover๊ฐ€ ์ƒ‰์ƒ ๋ณ€ํ™” ์ค‘์‹ฌ์ด๊ณ  focus๊ฐ€ sunlit gold highlight๋กœ ๋ณด์ด๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
434
+ - SkipLink๋ฅผ ์“ฐ๋Š” ํ™”๋ฉด์€ ์ฒซ Tab ๋Œ€์ƒ์—์„œ ๋ณด์ด๊ณ  ๋ณธ๋ฌธ target id๋กœ ์ด๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
435
+ - VisuallyHidden์„ ์“ฐ๋Š” ํ™”๋ฉด์€ ํ™”๋ฉด์—๋Š” ๋ณด์ด์ง€ ์•Š์ง€๋งŒ ์ ‘๊ทผ์„ฑ ์ด๋ฆ„์ด๋‚˜ ์„ค๋ช…์— ํฌํ•จ๋˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
436
+ - Page, Container, Section, PageHeader๋ฅผ ์“ฐ๋Š” ํ™”๋ฉด์€ page root, width, section rhythm, header actions๋งŒ ๋ฐ”๋€Œ๊ณ  ๋ผ์šฐํŒ…, SEO, ๋ฐ์ดํ„ฐ, ๊ถŒํ•œ ํŒ๋‹จ์ด ์ƒ๊ธฐ์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
437
+ - Stack์„ ์“ฐ๋Š” ํ™”๋ฉด์€ spacing๋งŒ ๋ฐ”๋€Œ๊ณ  ์ƒ‰์ƒ, ๊ทธ๋ฆผ์ž, hover, ์ œํ’ˆ๋ณ„ layout ํŒ๋‹จ์ด ์ƒ๊ธฐ์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
438
+ - Inline์„ ์“ฐ๋Š” ํ™”๋ฉด์€ horizontal wrapping๋งŒ ๋ฐ”๋€Œ๊ณ  ์ƒ‰์ƒ, ๊ทธ๋ฆผ์ž, hover, ์ œํ’ˆ๋ณ„ layout ํŒ๋‹จ์ด ์ƒ๊ธฐ์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
439
+ - Divider๋ฅผ ์“ฐ๋Š” ํ™”๋ฉด์€ ๊ตฌ๋ถ„์„ ๋งŒ ๋ฐ”๋€Œ๊ณ  section spacing, ๊ทธ๋ฆผ์ž, ๋ฐฐ๊ฒฝ ์žฅ์‹, ์ œํ’ˆ๋ณ„ layout ํŒ๋‹จ์ด ์ƒ๊ธฐ์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
440
+ - Grid๋ฅผ ์“ฐ๋Š” ํ™”๋ฉด์€ ๋ฐ˜๋ณต๋˜๋Š” ์นด๋“œ๋‚˜ ์š”์•ฝ ๋ฌถ์Œ์˜ columns์™€ gap๋งŒ ๋ฐ”๋€Œ๊ณ  ํ•ญ๋ชฉ ์˜๋ฏธ, ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ, ๊ถŒํ•œ ํŒ๋‹จ์ด ์ƒ๊ธฐ์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
441
+ - Toolbar๋ฅผ ์“ฐ๋Š” ํ™”๋ฉด์€ ๊ฐ€๊นŒ์šด ๋„๊ตฌ์™€ ์•ก์…˜ wrapping๋งŒ ๋ฐ”๋€Œ๊ณ  ์ €์žฅ, ์‚ญ์ œ, ํ•„ํ„ฐ, ๊ถŒํ•œ ํŒ๋‹จ์ด ์ƒ๊ธฐ์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
442
+ - CommandField๋ฅผ ์“ฐ๋Š” ํ™”๋ฉด์€ label, help/error id, Tab focus, `/` ๊ฐ™์€ shortcut ํ‘œ์‹œ๊ฐ€ ๋งž๊ณ , ์‹ค์ œ ๊ฒ€์ƒ‰/๋ผ์šฐํŒ…/command ์‹คํ–‰ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์— ๋‚จ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
443
+ - Combobox๋ฅผ ์“ฐ๋Š” ํ™”๋ฉด์€ combobox/listbox/option aria ๊ตฌ์กฐ, ArrowUp/ArrowDown/Enter/Escape ๋™์ž‘, disabled option skip, hidden submitted value๊ฐ€ ๋งž๊ณ , ์‹ค์ œ ํ•„ํ„ฐ๋ง, async search, command ์‹คํ–‰, ๊ถŒํ•œ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ์— ๋‚จ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
444
+ - Kbd์™€ ShortcutHint๋ฅผ ์“ฐ๋Š” ํ™”๋ฉด์€ ๋ณด์ด๋Š” ๋‹จ์ถ•ํ‚ค๊ฐ€ ์‹ค์ œ๋กœ ๋™์ž‘ํ•˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค. ๋™์ž‘ํ•˜์ง€ ์•Š๋Š” ํžŒํŠธ๋Š” ์ œ๊ฑฐํ•˜๊ณ , ์‹ค์ œ ๋‹จ์ถ•ํ‚ค๊ฐ€ ์žˆ๋Š” control์—๋งŒ `ariaKeyShortcuts`๋ฅผ ๋ถ™์ธ๋‹ค.
445
+ - Avatar์™€ IdentityChip์„ ์“ฐ๋Š” ํ™”๋ฉด์€ ์ด๋ฆ„, ์ด๋‹ˆ์…œ, ๋ณด์กฐ ํ…์ŠคํŠธ, ํ˜„์žฌ ๋งํฌ ์ƒํƒœ๋งŒ ํ‘œ๋ฉด์— ๋‚จ๊ณ , ์‹ค์ œ ๊ณ„์ • ์‹๋ณ„, ์˜จ๋ผ์ธ ์ƒํƒœ, ๊ถŒํ•œ, ์ดˆ๋Œ€ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ ์ƒํƒœ์™€ ๋งž๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
446
+ - Accordion๊ณผ Disclosure๋ฅผ ์“ฐ๋Š” ํ™”๋ฉด์€ trigger์— `aria-expanded`์™€ `aria-controls`๊ฐ€ ๋‚จ๊ณ , ์‹ค์ œ ํ•ญ๋ชฉ ๋…ธ์ถœ, ๊ถŒํ•œ, ๋ฐ์ดํ„ฐ fetch ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ ์ƒํƒœ์™€ ๋งž๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
447
+ - SegmentedControl์„ ์“ฐ๋Š” ํ™”๋ฉด์€ `radiogroup`, `radio`, `aria-checked`๊ฐ€ ๋‚จ๊ณ , ์‹ค์ œ ํ•„ํ„ฐ ์˜๋ฏธ, URL state, ์ •๋ ฌ, ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ, ๊ถŒํ•œ ํŒ๋‹จ์€ ์†Œ๋น„ ์•ฑ ์ƒํƒœ์™€ ๋งž๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
448
+ - Table์„ ์“ฐ๋Š” ํ™”๋ฉด์€ caption ๋˜๋Š” labelledBy๊ฐ€ ์žˆ๊ณ , `th scope="col"`๊ณผ `th scope="row"`๊ฐ€ ํ•„์š”ํ•œ ๊ณณ์— ๋‚จ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
449
+ - SortHeader์™€ TableToolbar๋ฅผ ์“ฐ๋Š” ํ™”๋ฉด์€ ์ •๋ ฌ ์ค‘์ธ ์—ด์˜ owning `th`์— `aria-sort`๊ฐ€ ๋‚จ๊ณ , ์„ ํƒ ํ–‰ ์•ก์…˜๊ณผ ๋ฐ€๋„ ์ „ํ™˜์ด ์†Œ๋น„ ์•ฑ ์ƒํƒœ์™€ ๋งž๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
450
+ - TermTrigger์™€ TermSheet๋ฅผ ์“ฐ๋Š” ํ™”๋ฉด์€ ํด๋ฆญ์œผ๋กœ ์—ด๋ฆฌ๊ณ , Escape ๋‹ซ๊ธฐ, Tab ์ˆœํ™˜, ์ด์ „ focus ๋ณต๊ท€๊ฐ€ ์œ ์ง€๋˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
451
+ - Dialog, Sheet, TermSheet๋ฅผ ์“ฐ๋Š” ํ™”๋ฉด์€ ์—ด๋ฆฐ ๋™์•ˆ body scroll์ด ์ž ๊ธฐ๊ณ  ๋‹ซํžŒ ๋’ค ์ด์ „ scroll ์ƒํƒœ๊ฐ€ ๋ณต๊ตฌ๋˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
452
+ - Sheet๋ฅผ ์“ฐ๋Š” ํ™”๋ฉด์€ `data-zdp-sheet-placement`, `data-zdp-sheet-size`, `data-zdp-sheet-surface="sheet"`๊ฐ€ ๋‚จ๊ณ  Drawer ๋ณ€ํ˜•์„ ๋ณ„๋„ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ณต์ œํ•˜์ง€ ์•Š์•˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
453
+ - TermSheet root์—๋Š” `data-term-id`, `data-zdp-term-id`, `data-zdp-term-placement`, `data-zdp-term-surface="sheet"`๊ฐ€ ๋‚จ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
454
+ - TermSheet์—๋Š” ๊ด‘๊ณ  slot์ด ์—†๊ณ  root์— `data-zdp-ad-exclude="true"`๊ฐ€ ๋‚จ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
455
+ - Pagination์„ ์“ฐ๋Š” ํ™”๋ฉด์€ ํ˜„์žฌ ํŽ˜์ด์ง€ ํ•ญ๋ชฉ์— `aria-current="page"`๊ฐ€ ๋‚จ๊ณ , URL ๋˜๋Š” ๋ฒ„ํŠผ ์ฝœ๋ฐฑ์ด ์†Œ๋น„ ์•ฑ์˜ ์‹ค์ œ page state์™€ ๋งž๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
456
+ - KeyValue๋ฅผ ์“ฐ๋Š” ํ™”๋ฉด์€ ์šฉ์–ด์™€ ๊ฐ’์ด `dt`์™€ `dd`๋กœ ๋‚จ๊ณ , ๊ฐ’์˜ ์ƒ์„ฑ/๊ถŒํ•œ/๊ฒฐ์ œ ํŒ๋‹จ์ด ์ปดํฌ๋„ŒํŠธ๋กœ ๋“ค์–ด์˜ค์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
457
+ - EmptyState๋ฅผ ์“ฐ๋Š” ํ™”๋ฉด์€ ์ œ๋ชฉ id๊ฐ€ ์—ฐ๊ฒฐ๋˜๊ณ  ๋‹ค์Œ ์•ก์…˜ ๊ฐ€๋Šฅ ์—ฌ๋ถ€๋ฅผ ์†Œ๋น„ ์•ฑ์ด ๊ฒฐ์ •ํ•˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
458
+ - Input, Textarea, Select์˜ invalid ์ƒํƒœ๋Š” help id์™€ error id๋ฅผ ๋ชจ๋‘ `aria-describedby`๋กœ ์—ฐ๊ฒฐํ•˜๊ณ , error id๋ฅผ `aria-errormessage`๋กœ๋„ ์—ฐ๊ฒฐํ•˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
459
+ - Input๊ณผ Textarea์˜ readonly ์ƒํƒœ๋Š” disabled์ฒ˜๋Ÿผ ํ๋ ค์ ธ ์ œ์ถœ/๋ณต์‚ฌ/ํฌ์ปค์Šค ํ๋ฆ„์„ ๋Š์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
460
+ - Breadcrumb๋ฅผ ์“ฐ๋Š” ํ™”๋ฉด์€ ํ˜„์žฌ ํŽ˜์ด์ง€ ํ•ญ๋ชฉ์— `aria-current="page"`๊ฐ€ ๋‚จ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
461
+ - Flutter/native adapter๋Š” `tokens/zdp.tokens.json`์˜ token name์„ ์œ ์ง€ํ•œ๋‹ค.
462
+ - ์†Œ๋น„์ฒ˜ ์ž์ฒด CSS์—์„œ `box-shadow`, gradient, hover transform์œผ๋กœ shared component ๊ธฐ๋ณธ๊ฐ’์„ ๋ฎ์–ด์“ฐ์ง€ ์•Š๋Š”๋‹ค.
463
+ - Overflow๊ฐ€ ์ƒ๊ธฐ๋Š” ํ‘œ, ํŒจ๋„, ํŽ˜์ด์ง€๋Š” `.zdp-surface-reset` ๋ฒ”์œ„ ์•ˆ์—์„œ theme scrollbar๊ฐ€ ๋ณด์ด๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
464
+ - ๋“œ๋ž˜๊ทธ๋กœ ํ…์ŠคํŠธ๋ฅผ ์„ ํƒํ–ˆ์„ ๋•Œ `.zdp-surface-reset` ๋ฒ”์œ„ ์•ˆ์—์„œ theme selection surface/text๊ฐ€ ๋ณด์ด๊ณ  ๋ธŒ๋ผ์šฐ์ € ๊ธฐ๋ณธ ํŒŒ๋ž€์ƒ‰์ด ๋‚จ์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
465
+ - Button, IconButton, MenuItem, SegmentedControl item, Pagination link, SortHeader, copy button, icon, separator, spinner, skeleton์ฒ˜๋Ÿผ ๋ˆ„๋ฅด๊ฑฐ๋‚˜ ์žฅ์‹์ธ ํ‘œ๋ฉด๋งŒ ์„ ํƒ๋˜์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
466
+ - Table cell, code body, toast message, document body, card data, identity label, ์ฃผ์†Œ, ์ด๋ฉ”์ผ, ID, ๋‚ ์งœ, ๊ฐ€๊ฒฉ, ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋Š” ๊ณ„์† ์„ ํƒํ•˜๊ณ  ๋ณต์‚ฌํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
467
+ - Drag interaction์€ drag start๋ถ€ํ„ฐ end/cancel/pointer release๊นŒ์ง€๋งŒ `.zdp-user-select-dragging`์„ ๋ถ™์ด๊ณ , ์•ฑ root๋‚˜ page/card/list/table container์— ์ƒ์‹œ `user-select: none`์ด ๋‚จ์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
468
+ - light/dark, keyboard focus, disabled, invalid ์ƒํƒœ๋ฅผ ์†Œ๋น„์ฒ˜ ํ™”๋ฉด์—์„œ ํ™•์ธํ•œ๋‹ค.
469
+ - Theme / Locale Stress story์—์„œ light/dark, ZDP Mobile ํญ, ๊ธด ํ•œ๊ตญ์–ด/์˜์–ด/์ค‘๊ตญ์–ด/ํžŒ๋””์–ด ๋ฌธ์žฅ, focus-visible ์ƒํƒœ๊ฐ€ ํ•จ๊ป˜ ๋ฌด๋„ˆ์ง€์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
470
+ - Dialog๋ฅผ ์“ฐ๋Š” ํ™”๋ฉด์€ Tab ์ˆœํ™˜, Escape ๋‹ซ๊ธฐ, backdrop ๋‹ซ๊ธฐ, ์ด์ „ focus ๋ณต๊ท€๋ฅผ ํ™•์ธํ•œ๋‹ค.
471
+ - ์ƒˆ ๋””์ž์ธ ์‹œ์Šคํ…œ ๋ฒ„์ „์€ ๋Œ€ํ‘œ ์†Œ๋น„์ฒ˜ ํ•œ ๊ณณ์—์„œ build์™€ ์‹œ๊ฐ QA๋ฅผ ํ†ต๊ณผํ•œ ๋’ค ํ™•์‚ฐํ•œ๋‹ค.
472
+
473
+ ## ๊ธˆ์ง€ ๊ฒฝ๊ณ„
474
+
475
+ - ๋””์ž์ธ ์‹œ์Šคํ…œ์— ์ œํ’ˆ๋ณ„ ํ™”๋ฉด, ๋žœ๋”ฉ ๋ฌธ๊ตฌ, admin ์ •์ฑ…, ๊ฒฐ์ œ ํŒ๋‹จ, ๊ถŒํ•œ ํŒ๋‹จ, ๊ฐœ์ธ์ •๋ณด ์ฒ˜๋ฆฌ ๋กœ์ง์„ ๋„ฃ์ง€ ์•Š๋Š”๋‹ค.
476
+ - ์†Œ๋น„ ์ €์žฅ์†Œ๊ฐ€ `zdp-design-system/src/...` ๊ฐ™์€ ๋‚ด๋ถ€ ๊ฒฝ๋กœ๋ฅผ ์ง์ ‘ importํ•˜์ง€ ์•Š๋Š”๋‹ค.
477
+ - ๋ฐฐํฌ package๋Š” `bun run package:build`๋กœ ๋งŒ๋“  `dist/` export๋ฅผ ์“ฐ๋ฉฐ, ์†Œ๋น„์ž fixture๊ฐ€ public import๋งŒ์œผ๋กœ build๋˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
478
+ - token name์„ ์ œํ’ˆ๋ณ„ ๋ณ„์นญ์œผ๋กœ ๋ณต์‚ฌํ•ด forkํ•˜์ง€ ์•Š๋Š”๋‹ค.
479
+ - focus ์ƒ‰์„ ๋ธŒ๋žœ๋“œ ์žฅ์‹์ƒ‰, hover ์ƒ‰, semantic danger/success ์ƒ‰์œผ๋กœ ์žฌ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.
480
+ - ์•ฑ root, page root, card, table cell, code body, document body, toast body์— `user-select: none`์„ ์ ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.
481
+ - ๋ณด์•ˆ์„ ์ด์œ ๋กœ ์„ ํƒ๋งŒ ๋ง‰์ง€ ์•Š๋Š”๋‹ค. ํ™”๋ฉด์— ๋…ธ์ถœํ•˜๋ฉด ๋ณต์‚ฌ ๊ฐ€๋Šฅํ•˜๋‹ค๊ณ  ๋ณด๊ณ , ๋…ธ์ถœํ•˜๋ฉด ์•ˆ ๋˜๋Š” ๊ฐ’์€ ๋ Œ๋”๋งํ•˜์ง€ ์•Š๋Š”๋‹ค.
482
+ - `selectstart` ์ฐจ๋‹จ, ์šฐํด๋ฆญ ์ฐจ๋‹จ, ๋ฌธ์„œ ์ „์ฒด selection ์ฐจ๋‹จ์œผ๋กœ ๋ธŒ๋ผ์šฐ์ € ๊ธฐ๋ณธ ํ–‰๋™์„ ์ฃฝ์ด์ง€ ์•Š๋Š”๋‹ค.
@@ -0,0 +1,141 @@
1
+ # External UI Adoption
2
+
3
+ ์ด ๋ฌธ์„œ๋Š” ์™ธ๋ถ€ UI ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ์˜ˆ์ œ๋ฅผ `zdp-design-system`์— ์ฐธ๊ณ ํ•˜๊ฑฐ๋‚˜ ํก์ˆ˜ํ•  ๋•Œ์˜ ๊ธฐ์ค€์ด๋‹ค.
4
+ ๋ชฉํ‘œ๋Š” ๋” ๋งŽ์€ ๊ธฐ๋Šฅ์„ ๋งŒ๋“ค๋˜, ZDP public API, CSS token, Storybook, consumer fixture, a11y gate๋ฅผ ์™ธ๋ถ€ ์ฒ ํ•™์— ๋„˜๊ธฐ์ง€ ์•Š๋Š” ๊ฒƒ์ด๋‹ค.
5
+
6
+ ## ์›์น™
7
+
8
+ - ์™ธ๋ถ€ UI ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ZDP์˜ dependency source๊ฐ€ ์•„๋‹ˆ๋ผ ๊ฒ€์ฆ source๋‹ค.
9
+ - ๊ณ ๋‚œ๋„ headless primitive๋Š” public API์™€ styling contract๊ฐ€ ZDP ์•ˆ์— ๊ฐ‡ํ˜€ ์žˆ๋‹ค๋Š” ์กฐ๊ฑด์—์„œ ๋‚ด๋ถ€ ๊ตฌํ˜„ ์˜์กด์„ฑ์œผ๋กœ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
10
+ - Tailwind, UnoCSS, registry, `cn()` helper, class merge helper, ์™ธ๋ถ€ theme preset์€ ZDP core public contract๋กœ ์ƒˆ์ง€ ์•Š๋Š”๋‹ค.
11
+ - ZDP public component props, DOM exposure policy, CSS class, token mapping, Storybook coverage, consumer fixture๋Š” ZDP๊ฐ€ ์†Œ์œ ํ•œ๋‹ค.
12
+ - Button, Badge, Card, typography, layout helper์ฒ˜๋Ÿผ ์‹œ๊ฐ ๊ทœ์น™์ด ๋Œ€๋ถ€๋ถ„์ธ ์ปดํฌ๋„ŒํŠธ๋Š” ์™ธ๋ถ€ headless ์˜์กด์„ฑ์„ ๋ถ™์ด์ง€ ์•Š๋Š”๋‹ค.
13
+ - ์™ธ๋ถ€ ์ฝ”๋“œ๋ฅผ ๋ณต์‚ฌํ•˜๊ฑฐ๋‚˜ ํฌํŒ…ํ•˜๋ฉด ์› ์ถœ์ฒ˜, ๋ผ์ด์„ ์Šค, ๋ณ€๊ฒฝ ๋ฒ”์œ„, notice ์œ ์ง€ ์—ฌ๋ถ€๋ฅผ component-level provenance๋กœ ๋‚จ๊ธด๋‹ค.
14
+
15
+ ## ํก์ˆ˜ ๋“ฑ๊ธ‰
16
+
17
+ ### Reference Only
18
+
19
+ ์˜ˆ์œ ํ™”๋ฉด, interaction idea, docs ์„ค๋ช…์„ ๋ณด๊ณ  ์ œํ’ˆ ๋ฐฉํ–ฅ๋งŒ ๋น„๊ตํ•œ ์ƒํƒœ๋‹ค.
20
+ ์ฝ”๋“œ, DOM ๊ตฌ์กฐ, naming, state machine์„ ์˜ฎ๊ธฐ์ง€ ์•Š๋Š”๋‹ค.
21
+ THIRD_PARTY_NOTICES์—๋Š” ๋ณดํ†ต ๋‚จ๊ธฐ์ง€ ์•Š์•„๋„ ๋˜์ง€๋งŒ PR ์„ค๋ช…์—๋Š” ์ฐธ๊ณ ํ•œ ๋งํฌ๋ฅผ ๋‚จ๊ธด๋‹ค.
22
+
23
+ ### Behavior Spec
24
+
25
+ ํ‚ค๋ณด๋“œ ์ด๋™, focus return, Escape ๋‹ซ๊ธฐ, aria state ๊ฐ™์€ ๋™์ž‘ ๋ช…์„ธ๋ฅผ ๋น„๊ตํ•œ ์ƒํƒœ๋‹ค.
26
+ ์ฝ”๋“œ๋Š” ๋ณต์‚ฌํ•˜์ง€ ์•Š๊ณ  ZDP-native Svelte/CSS๋กœ ๋‹ค์‹œ ๊ตฌํ˜„ํ•œ๋‹ค.
27
+ ๋ฌธ์„œ์—๋Š” `behavior reviewed against <source>, no source copied` ํ˜•ํƒœ๋กœ ๋‚จ๊ธด๋‹ค.
28
+
29
+ ### Ported Structure
30
+
31
+ ์ƒํƒœ ํ๋ฆ„, DOM ๋ฐฐ์น˜, ์ด๋ฒคํŠธ ์ˆœ์„œ ๊ฐ™์€ ๊ตฌ์กฐ๋ฅผ Svelte/ZDP ๋ฐฉ์‹์œผ๋กœ ์˜ฎ๊ธด ์ƒํƒœ๋‹ค.
32
+ ์› ์ฝ”๋“œ๊ฐ€ ์ง์ ‘ ๋ณต์‚ฌ๋˜์ง€ ์•Š์•˜์–ด๋„ ํšŒ์ƒ‰์ง€๋Œ€์ด๋ฏ€๋กœ provenance๋ฅผ ๋‚จ๊ธด๋‹ค.
33
+ Storybook interaction, a11y gate, consumer fixture๊ฐ€ ๊ฐ™์ด ์žˆ์–ด์•ผ ํ•œ๋‹ค.
34
+
35
+ ### Source Adapted
36
+
37
+ ์™ธ๋ถ€ ์ฝ”๋“œ ์ผ๋ถ€๋ฅผ ์ง์ ‘ ๋ณต์‚ฌํ•˜๊ฑฐ๋‚˜ ์˜๋ฏธ ์žˆ๊ฒŒ ๋ณ€ํ˜•ํ•œ ์ƒํƒœ๋‹ค.
38
+ MIT ๊ฐ™์€ ํ—ˆ์šฉ ๋ผ์ด์„ ์Šค๋ผ๋„ ์› ์ €์ž‘๊ถŒ ๊ณ ์ง€์™€ license notice๋ฅผ ๋ณด์กดํ•œ๋‹ค.
39
+ `THIRD_PARTY_NOTICES.md`์™€ component provenance์— source URL, license, adapted file, local owner๋ฅผ ๋‚จ๊ธด๋‹ค.
40
+
41
+ ### Runtime Dependency
42
+
43
+ ์™ธ๋ถ€ ํŒจํ‚ค์ง€๋ฅผ dependency๋กœ ์„ค์น˜ํ•ด ๋‚ด๋ถ€ ๊ตฌํ˜„์— ์“ฐ๋Š” ์ƒํƒœ๋‹ค.
44
+ Bits UI ๊ฐ™์€ headless primitive์— ํ•œํ•ด ํ›„๋ณด๊ฐ€ ๋  ์ˆ˜ ์žˆ๊ณ , public export์— ์™ธ๋ถ€ ํƒ€์ž…, prop ์ด๋ฆ„, class, theme token์ด ์ƒˆ๋ฉด ์‹คํŒจ๋‹ค.
45
+ consumer fixture๊ฐ€ ์™ธ๋ถ€ ํŒจํ‚ค์ง€ ์„ค์ • ์—†์ด `zdp-design-system` public export๋งŒ์œผ๋กœ ๋นŒ๋“œ๋˜์–ด์•ผ ํ•œ๋‹ค.
46
+
47
+ ### Prohibited
48
+
49
+ ํŒŒ์ƒ ์ปดํฌ๋„ŒํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ, template, starter kit, redistributable UI kit์— ์ œํ•œ์ด ์žˆ๋Š” ์ƒ์šฉ UI ์†Œ์Šค๋Š” ๊ธˆ์ง€ํ•œ๋‹ค.
50
+ Tailwind Plus/Tailwind UI ๊ณ„์—ด์€ ZDP public package ์žฌ๋ฃŒ๋กœ ์“ฐ์ง€ ์•Š๋Š”๋‹ค.
51
+
52
+ ## ํ›„๋ณด๋ณ„ ๊ธฐ์ค€
53
+
54
+ ### Bits UI / shadcn-svelte
55
+
56
+ Select, Combobox, Dialog, Popover, Menu, Command, Drawer, Sheet์ฒ˜๋Ÿผ focus, keyboard, aria, nested overlay๊ฐ€ ๊นŒ๋‹ค๋กœ์šด primitive์˜ ๋™์ž‘ ๋ช…์„ธ์™€ ํ…Œ์ŠคํŠธ ํ›„๋ณด๋กœ ๊ฒ€ํ† ํ•œ๋‹ค.
57
+ ๋‚ด๋ถ€ ๊ตฌํ˜„ ์˜์กด์„ฑ์€ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, public API์™€ CSS token, class naming, DOM exposure policy๋Š” ZDP๊ฐ€ ์†Œ์œ ํ•œ๋‹ค.
58
+ `bits-ui` ํƒ€์ž…, prop ์ด๋ฆ„, store shape, Tailwind class, shadcn registry ํŒŒ์ผ ๊ตฌ์กฐ๊ฐ€ ZDP public export๋กœ ์ƒˆ๋ฉด ์‹คํŒจ๋‹ค.
59
+
60
+ ### Skeleton / Flowbite Svelte / daisyUI
61
+
62
+ ํŒจํ„ด ์นดํƒˆ๋กœ๊ทธ๋กœ๋งŒ ๋ณธ๋‹ค.
63
+ core primitive์— ์ง์ ‘ ์œ ์ž…ํ•˜์ง€ ์•Š๊ณ , ํ•„์š”ํ•œ ์•„์ด๋””์–ด๋Š” ZDP-native Svelte/CSS์™€ token mapping์œผ๋กœ ๋‹ค์‹œ ์ž‘์„ฑํ•œ๋‹ค.
64
+ ์†Œ๋น„ ์•ฑ์ด Tailwind ์„ค์ •์ด๋‚˜ daisyUI theme์„ ์•Œ์•„์•ผ ํ•˜๋Š” ๊ตฌ์กฐ๋Š” ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.
65
+
66
+ ### Ark UI
67
+
68
+ React, Solid, Vue, Svelte๋ฅผ ๊ฐ™์ด ๋ณด๋Š” ์žฅ๊ธฐ ๋ฉ€ํ‹ฐ ํ”„๋ ˆ์ž„์›Œํฌ ํ›„๋ณด๋กœ ๋‘”๋‹ค.
69
+ ํ˜„์žฌ Svelte-first ํ‘œ๋ฉด์—์„œ๋Š” ๊ธฐ๋ณธ ํ›„๋ณด๊ฐ€ ์•„๋‹ˆ๋ฉฐ, cross-framework package boundary๊ฐ€ ์‹ค์ œ ์š”๊ตฌ๊ฐ€ ๋  ๋•Œ ๋‹ค์‹œ ํ‰๊ฐ€ํ•œ๋‹ค.
70
+
71
+ ### Motion / SmoothUI
72
+
73
+ core component๊ฐ€ ์•„๋‹ˆ๋ผ marketing recipe์™€ campaign surface ํ›„๋ณด๋กœ ๊ฒฉ๋ฆฌํ•œ๋‹ค.
74
+ Motion engine๊ณผ SmoothUI-derived recipe๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ์ถœ์ฒ˜๋กœ ๊ธฐ๋กํ•œ๋‹ค.
75
+ SmoothUI ์ฝ”๋“œ๋ฅผ ์ฐธ๊ณ ํ•˜๊ฑฐ๋‚˜ ํฌํŒ…ํ•˜๋ฉด SmoothUI source์™€ license๋ฅผ ๋”ฐ๋กœ provenance์™€ notice์— ๋‚จ๊ธด๋‹ค.
76
+ ๋ชจ๋“  animation recipe๋Š” `prefers-reduced-motion` ๋Œ€์ฒด ํ๋ฆ„์„ ๊ฐ–๋Š”๋‹ค.
77
+
78
+ ### Tailwind Plus / Tailwind UI
79
+
80
+ ZDP package, template, shared component, starter, registry, generated UI surface์˜ ์žฌ๋ฃŒ๋กœ ์“ฐ์ง€ ์•Š๋Š”๋‹ค.
81
+ ์ œํ’ˆ end screen์—์„œ ๋ณ„๋„ ๋ผ์ด์„ ์Šค ์•„๋ž˜ ์“ฐ๋Š” ๊ฒฐ์ •์€ ํ•ด๋‹น ์†Œ๋น„ ์•ฑ์ด ์†Œ์œ ํ•˜์ง€๋งŒ, ๊ทธ ๊ฒฐ๊ณผ๋ฌผ์ด `zdp-design-system`์œผ๋กœ ์—ญ์œ ์ž…๋˜๋ฉด ์•ˆ ๋œ๋‹ค.
82
+
83
+ ## ๊ณ ๋‚œ๋„ Primitive ๊ฒŒ์ดํŠธ
84
+
85
+ ์™ธ๋ถ€ headless ๊ตฌํ˜„์„ ์ฐธ๊ณ ํ•˜๊ฑฐ๋‚˜ ์˜์กด์„ฑ ํ›„๋ณด๋กœ ์˜ฌ๋ฆฌ๋Š” primitive๋Š” ๋‹ค์Œ ํ•ญ๋ชฉ์„ ๊ฒ€ํ† ํ•ด์•ผ ํ•œ๋‹ค.
86
+
87
+ - focus trap ๋˜๋Š” focus return
88
+ - Escape close
89
+ - outside click ๋˜๋Š” outside pointerdown
90
+ - Tab ์ˆœํ™˜๊ณผ Shift+Tab ์—ญ์ˆœํ™˜
91
+ - SSR/hydration ์•ˆ์ •์„ฑ
92
+ - nested overlay ๋™์ž‘
93
+ - scroll lock๊ณผ ๊ธฐ์กด body overflow ๋ณต์›
94
+ - portal target ๋˜๋Š” layer root
95
+ - reduced motion ๋Œ€์ฒด
96
+ - keyboard interaction ํ‘œ์ค€
97
+ - screen reader label, description, state
98
+ - form integration
99
+ - controlled/uncontrolled state
100
+ - disabled, readonly, invalid ์ƒํƒœ
101
+ - Storybook interaction๊ณผ addon-a11y gate
102
+ - consumer fixture build
103
+
104
+ ## Provenance Template
105
+
106
+ ์ƒˆ component๋‚˜ ํฐ interaction ๋ณ€๊ฒฝ์ด ์™ธ๋ถ€ source๋ฅผ ์ฐธ๊ณ ํ•˜๋ฉด PR์ด๋‚˜ ๋ฌธ์„œ์— ๋‹ค์Œ ํ•ญ๋ชฉ์„ ๋‚จ๊ธด๋‹ค.
107
+
108
+ ```md
109
+ Component:
110
+ Source:
111
+ License:
112
+ Adoption grade:
113
+ What was adapted:
114
+ What was not copied:
115
+ ZDP-owned API:
116
+ ZDP token mapping:
117
+ A11y contract:
118
+ Fixture / story coverage:
119
+ Notice update:
120
+ ```
121
+
122
+ ์˜ˆ์‹œ๋Š” ๋‹ค์Œ์ฒ˜๋Ÿผ ๋‚จ๊ธด๋‹ค.
123
+
124
+ ```md
125
+ Component: Select
126
+ Source: Bits UI Select docs
127
+ License: MIT
128
+ Adoption grade: Behavior Spec
129
+ What was adapted: keyboard movement and aria state checklist
130
+ What was not copied: source code, prop names, Tailwind classes
131
+ ZDP-owned API: Select.svelte props and zdp-select CSS classes
132
+ ZDP token mapping: control, focus, line, surface tokens
133
+ A11y contract: labelled trigger, aria-expanded, roving option focus
134
+ Fixture / story coverage: Interaction story and consumer fixture
135
+ Notice update: not required because no source copied
136
+ ```
137
+
138
+ ## Review Rule
139
+
140
+ ์™ธ๋ถ€ UI๋ฅผ ์ฐธ๊ณ ํ•œ ๋ณ€๊ฒฝ์€ โ€œ์ž‘๋™ํ•œ๋‹คโ€๋งŒ์œผ๋กœ ํ†ต๊ณผํ•˜์ง€ ์•Š๋Š”๋‹ค.
141
+ ZDP public API๊ฐ€ ์™ธ๋ถ€ ์˜์กด์„ฑ์„ ์ˆจ๊ธฐ๊ณ , consumer๊ฐ€ ๋‚ด๋ถ€ ์ฃผ๋ฐฉ์„ ๋ชฐ๋ผ๋„ import๋งŒ์œผ๋กœ ์“ธ ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.