@mindlogic-ai/logician-ui 5.0.0-alpha.3 → 5.0.0-alpha.4

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 (240) hide show
  1. package/dist/components/Banner/Banner.types.d.ts +24 -1
  2. package/dist/components/Banner/Banner.types.d.ts.map +1 -1
  3. package/dist/components/Card/Card.types.d.ts +12 -0
  4. package/dist/components/Card/Card.types.d.ts.map +1 -1
  5. package/dist/components/ColorMode/ColorModeToggle.d.ts +7 -2
  6. package/dist/components/ColorMode/ColorModeToggle.d.ts.map +1 -1
  7. package/dist/components/ColorMode/ColorModeToggle.js +8 -3
  8. package/dist/components/ColorMode/ColorModeToggle.js.map +1 -1
  9. package/dist/components/ColorMode/ColorModeToggle.mjs +8 -3
  10. package/dist/components/ColorMode/ColorModeToggle.mjs.map +1 -1
  11. package/dist/components/Confetti/Confetti.types.d.ts +5 -1
  12. package/dist/components/Confetti/Confetti.types.d.ts.map +1 -1
  13. package/dist/components/Confetti/confettiColors.d.ts +5 -5
  14. package/dist/components/Confetti/confettiColors.js +5 -5
  15. package/dist/components/Confetti/confettiColors.mjs +5 -5
  16. package/dist/components/ErrorFallback/ErrorFallback.types.d.ts +6 -0
  17. package/dist/components/ErrorFallback/ErrorFallback.types.d.ts.map +1 -1
  18. package/dist/components/Form/FormModalFooter/FormModalFooter.types.d.ts +4 -1
  19. package/dist/components/Form/FormModalFooter/FormModalFooter.types.d.ts.map +1 -1
  20. package/dist/components/LineGraph/LineGraph.d.ts.map +1 -1
  21. package/dist/components/LineGraph/LineGraph.js +4 -5
  22. package/dist/components/LineGraph/LineGraph.js.map +1 -1
  23. package/dist/components/LineGraph/LineGraph.mjs +5 -6
  24. package/dist/components/LineGraph/LineGraph.mjs.map +1 -1
  25. package/dist/components/LineGraph/LineGraph.types.d.ts +12 -2
  26. package/dist/components/LineGraph/LineGraph.types.d.ts.map +1 -1
  27. package/dist/components/LineGraph/seriesColors.d.ts +12 -8
  28. package/dist/components/LineGraph/seriesColors.d.ts.map +1 -1
  29. package/dist/components/LineGraph/seriesColors.js +8 -7
  30. package/dist/components/LineGraph/seriesColors.js.map +1 -1
  31. package/dist/components/LineGraph/seriesColors.mjs +8 -7
  32. package/dist/components/LineGraph/seriesColors.mjs.map +1 -1
  33. package/dist/components/Masonry/Masonry.types.d.ts +8 -3
  34. package/dist/components/Masonry/Masonry.types.d.ts.map +1 -1
  35. package/dist/components/Menu/MenuItem.types.d.ts +8 -0
  36. package/dist/components/Menu/MenuItem.types.d.ts.map +1 -1
  37. package/dist/components/Modal/ModalCloseButton.d.ts +1 -1
  38. package/dist/components/Modal/ModalCloseButton.js +1 -1
  39. package/dist/components/Modal/ModalCloseButton.mjs +1 -1
  40. package/dist/components/Pagination/Pagination.d.ts +11 -10
  41. package/dist/components/Pagination/Pagination.d.ts.map +1 -1
  42. package/dist/components/Pagination/Pagination.js +11 -10
  43. package/dist/components/Pagination/Pagination.js.map +1 -1
  44. package/dist/components/Pagination/Pagination.mjs +11 -10
  45. package/dist/components/Pagination/Pagination.mjs.map +1 -1
  46. package/dist/components/ProgressBar/ProgressBar.types.d.ts +9 -0
  47. package/dist/components/ProgressBar/ProgressBar.types.d.ts.map +1 -1
  48. package/dist/components/RadialProgress/RadialProgress.types.d.ts +21 -1
  49. package/dist/components/RadialProgress/RadialProgress.types.d.ts.map +1 -1
  50. package/dist/components/SeeMoreButton/SeeMoreButton.types.d.ts +8 -0
  51. package/dist/components/SeeMoreButton/SeeMoreButton.types.d.ts.map +1 -1
  52. package/dist/components/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  53. package/dist/components/SegmentedControl/SegmentedControl.js +6 -7
  54. package/dist/components/SegmentedControl/SegmentedControl.js.map +1 -1
  55. package/dist/components/SegmentedControl/SegmentedControl.mjs +6 -7
  56. package/dist/components/SegmentedControl/SegmentedControl.mjs.map +1 -1
  57. package/dist/components/SegmentedProgressBar/SegmentedProgressBar.types.d.ts +2 -0
  58. package/dist/components/SegmentedProgressBar/SegmentedProgressBar.types.d.ts.map +1 -1
  59. package/dist/components/Toast/Toast.styles.d.ts +6 -2
  60. package/dist/components/Toast/Toast.styles.d.ts.map +1 -1
  61. package/dist/components/Toast/Toast.styles.js +18 -10
  62. package/dist/components/Toast/Toast.styles.js.map +1 -1
  63. package/dist/components/Toast/Toast.styles.mjs +18 -10
  64. package/dist/components/Toast/Toast.styles.mjs.map +1 -1
  65. package/dist/theme/colors.d.ts +2 -2
  66. package/dist/theme/colors.d.ts.map +1 -1
  67. package/dist/theme/colors.js +22 -2
  68. package/dist/theme/colors.js.map +1 -1
  69. package/dist/theme/colors.mjs +23 -3
  70. package/dist/theme/colors.mjs.map +1 -1
  71. package/dist/theme/palette.generated.d.ts +98 -0
  72. package/dist/theme/palette.generated.d.ts.map +1 -1
  73. package/dist/theme/palette.generated.js +99 -0
  74. package/dist/theme/palette.generated.js.map +1 -1
  75. package/dist/theme/palette.generated.mjs +99 -1
  76. package/dist/theme/palette.generated.mjs.map +1 -1
  77. package/dist/theme/paletteSwatches.d.ts +20 -0
  78. package/dist/theme/paletteSwatches.d.ts.map +1 -1
  79. package/package.json +1 -1
  80. package/src/components/Accordion/Accordion.stories.tsx +85 -0
  81. package/src/components/Accordion/Accordion.usage.mdx +200 -0
  82. package/src/components/Appear/Appear.usage.mdx +107 -0
  83. package/src/components/Avatar/Avatar.stories.tsx +71 -1
  84. package/src/components/Avatar/Avatar.usage.mdx +166 -0
  85. package/src/components/Banner/Banner.stories.tsx +152 -2
  86. package/src/components/Banner/Banner.types.ts +30 -1
  87. package/src/components/Banner/Banner.usage.mdx +233 -0
  88. package/src/components/BottomSheet/BottomSheet.stories.tsx +168 -1
  89. package/src/components/BottomSheet/BottomSheet.usage.mdx +216 -0
  90. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +59 -0
  91. package/src/components/Breadcrumb/Breadcrumb.usage.mdx +181 -0
  92. package/src/components/Button/Button.stories.tsx +263 -3
  93. package/src/components/Button/Button.usage.mdx +342 -0
  94. package/src/components/Card/Card.stories.tsx +106 -0
  95. package/src/components/Card/Card.types.ts +12 -0
  96. package/src/components/Card/Card.usage.mdx +216 -0
  97. package/src/components/Checkbox/Checkbox.stories.tsx +140 -13
  98. package/src/components/Checkbox/Checkbox.usage.mdx +214 -0
  99. package/src/components/Chip/Chip.usage.mdx +78 -0
  100. package/src/components/Code/Code.stories.tsx +60 -0
  101. package/src/components/Code/Code.usage.mdx +187 -0
  102. package/src/components/CodeTabs/CodeTabs.stories.tsx +53 -0
  103. package/src/components/CodeTabs/CodeTabs.usage.mdx +176 -0
  104. package/src/components/Collapsible/Collapsible.stories.tsx +58 -0
  105. package/src/components/Collapsible/Collapsible.usage.mdx +173 -0
  106. package/src/components/ColorMode/ColorMode.stories.tsx +50 -0
  107. package/src/components/ColorMode/ColorMode.usage.mdx +135 -0
  108. package/src/components/ColorMode/ColorModeToggle.tsx +10 -3
  109. package/src/components/Confetti/Confetti.types.ts +5 -1
  110. package/src/components/Confetti/Confetti.usage.mdx +111 -0
  111. package/src/components/Confetti/confettiColors.ts +5 -5
  112. package/src/components/Container/Container.stories.tsx +32 -0
  113. package/src/components/Container/Container.usage.mdx +130 -0
  114. package/src/components/CopyableCode/CopyableCode.stories.tsx +62 -0
  115. package/src/components/CopyableCode/CopyableCode.usage.mdx +168 -0
  116. package/src/components/CountBadge/CountBadge.stories.tsx +69 -0
  117. package/src/components/CountBadge/CountBadge.usage.mdx +215 -0
  118. package/src/components/CountUp/CountUp.usage.mdx +107 -0
  119. package/src/components/DatePicker/DatePicker.usage.mdx +177 -0
  120. package/src/components/DatePicker/RangeDatePicker.stories.tsx +87 -3
  121. package/src/components/ErrorFallback/ErrorFallback.types.ts +6 -0
  122. package/src/components/ErrorFallback/ErrorFallback.usage.mdx +127 -0
  123. package/src/components/ExpandableText/ExpandableText.stories.tsx +55 -0
  124. package/src/components/ExpandableText/ExpandableText.usage.mdx +176 -0
  125. package/src/components/FileInput/FileInput.stories.tsx +38 -1
  126. package/src/components/FileInput/FileInput.usage.mdx +178 -0
  127. package/src/components/FileItem/FileItem.stories.tsx +71 -0
  128. package/src/components/FileItem/FileItem.usage.mdx +180 -0
  129. package/src/components/FileList/FileList.stories.tsx +25 -0
  130. package/src/components/FileList/FileList.usage.mdx +165 -0
  131. package/src/components/FlyTo/FlyTo.usage.mdx +99 -0
  132. package/src/components/Form/Form.stories.tsx +149 -0
  133. package/src/components/Form/Form.usage.mdx +201 -0
  134. package/src/components/Form/FormModalFooter/FormModalFooter.types.ts +4 -1
  135. package/src/components/FormControl/FormControl.stories.tsx +35 -0
  136. package/src/components/FormControl/FormControl.usage.mdx +128 -0
  137. package/src/components/FormIntegration/FormIntegration.usage.mdx +158 -0
  138. package/src/components/FormLabel/FormLabel.stories.tsx +71 -0
  139. package/src/components/FormLabel/FormLabel.usage.mdx +125 -0
  140. package/src/components/Icon/Icon.stories.tsx +61 -1
  141. package/src/components/Icon/Icon.usage.mdx +158 -0
  142. package/src/components/IconButton/IconButton.stories.tsx +209 -5
  143. package/src/components/IconButton/IconButton.usage.mdx +273 -0
  144. package/src/components/InfoSprinkle/InfoSprinkle.stories.tsx +77 -1
  145. package/src/components/InfoSprinkle/InfoSprinkle.usage.mdx +189 -0
  146. package/src/components/InlineCode/InlineCode.stories.tsx +75 -0
  147. package/src/components/InlineCode/InlineCode.usage.mdx +142 -0
  148. package/src/components/Input/Input.stories.tsx +180 -0
  149. package/src/components/Input/Input.usage.mdx +278 -0
  150. package/src/components/LineGraph/LineGraph.stories.tsx +112 -0
  151. package/src/components/LineGraph/LineGraph.tsx +4 -5
  152. package/src/components/LineGraph/LineGraph.types.ts +12 -2
  153. package/src/components/LineGraph/LineGraph.usage.mdx +186 -0
  154. package/src/components/LineGraph/seriesColors.test.ts +11 -10
  155. package/src/components/LineGraph/seriesColors.ts +18 -16
  156. package/src/components/Loaders/Loaders.stories.tsx +93 -0
  157. package/src/components/Loaders/Loaders.usage.mdx +180 -0
  158. package/src/components/LogicianProvider/LogicianProvider.usage.mdx +98 -0
  159. package/src/components/Markdown/Markdown.stories.tsx +53 -0
  160. package/src/components/Markdown/Markdown.usage.mdx +182 -0
  161. package/src/components/Masonry/Masonry.stories.tsx +63 -1
  162. package/src/components/Masonry/Masonry.types.ts +8 -3
  163. package/src/components/Masonry/Masonry.usage.mdx +142 -0
  164. package/src/components/MaxLengthIndicator/MaxLengthIndicator.stories.tsx +57 -0
  165. package/src/components/MaxLengthIndicator/MaxLengthIndicator.usage.mdx +125 -0
  166. package/src/components/Menu/Menu.stories.tsx +146 -2
  167. package/src/components/Menu/Menu.usage.mdx +230 -0
  168. package/src/components/Menu/MenuItem.types.ts +8 -0
  169. package/src/components/Modal/Modal.stories.tsx +177 -1
  170. package/src/components/Modal/Modal.usage.mdx +262 -0
  171. package/src/components/Modal/ModalCloseButton.tsx +1 -1
  172. package/src/components/MonthPicker/MonthPicker.stories.tsx +30 -0
  173. package/src/components/MonthPicker/MonthPicker.usage.mdx +191 -0
  174. package/src/components/Pagination/Pagination.stories.tsx +90 -1
  175. package/src/components/Pagination/Pagination.tsx +11 -10
  176. package/src/components/Pagination/Pagination.usage.mdx +186 -0
  177. package/src/components/PasswordInput/PasswordInput.stories.tsx +51 -0
  178. package/src/components/PasswordInput/PasswordInput.usage.mdx +193 -0
  179. package/src/components/PinInput/PinInput.stories.tsx +91 -0
  180. package/src/components/PinInput/PinInput.usage.mdx +194 -0
  181. package/src/components/Popover/Popover.stories.tsx +104 -1
  182. package/src/components/Popover/Popover.usage.mdx +197 -0
  183. package/src/components/ProgressBar/ProgressBar.stories.tsx +92 -1
  184. package/src/components/ProgressBar/ProgressBar.types.ts +9 -0
  185. package/src/components/ProgressBar/ProgressBar.usage.mdx +210 -0
  186. package/src/components/Pulse/Pulse.usage.mdx +102 -0
  187. package/src/components/RadialProgress/RadialProgress.stories.tsx +74 -1
  188. package/src/components/RadialProgress/RadialProgress.types.ts +21 -1
  189. package/src/components/RadialProgress/RadialProgress.usage.mdx +153 -0
  190. package/src/components/Radio/Radio.stories.tsx +119 -0
  191. package/src/components/Radio/Radio.usage.mdx +187 -0
  192. package/src/components/Reveal/Reveal.usage.mdx +105 -0
  193. package/src/components/ScaledContext/ScaledContext.usage.mdx +111 -0
  194. package/src/components/SeeMoreButton/SeeMoreButton.stories.tsx +146 -2
  195. package/src/components/SeeMoreButton/SeeMoreButton.types.ts +8 -0
  196. package/src/components/SeeMoreButton/SeeMoreButton.usage.mdx +213 -0
  197. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +69 -0
  198. package/src/components/SegmentedControl/SegmentedControl.tsx +6 -7
  199. package/src/components/SegmentedControl/SegmentedControl.usage.mdx +209 -0
  200. package/src/components/SegmentedProgressBar/SegmentedProgressBar.stories.tsx +54 -0
  201. package/src/components/SegmentedProgressBar/SegmentedProgressBar.types.ts +2 -0
  202. package/src/components/SegmentedProgressBar/SegmentedProgressBar.usage.mdx +145 -0
  203. package/src/components/Select/Select.stories.tsx +209 -1
  204. package/src/components/Select/Select.usage.mdx +278 -0
  205. package/src/components/Shake/Shake.usage.mdx +107 -0
  206. package/src/components/Slider/Slider.stories.tsx +116 -0
  207. package/src/components/Slider/Slider.usage.mdx +179 -0
  208. package/src/components/Spinner/Spinner.stories.tsx +64 -0
  209. package/src/components/Spinner/Spinner.usage.mdx +136 -0
  210. package/src/components/SwapTransition/SwapTransition.usage.mdx +102 -0
  211. package/src/components/Switch/Switch.stories.tsx +131 -6
  212. package/src/components/Switch/Switch.usage.mdx +199 -0
  213. package/src/components/Table/Table.stories.tsx +159 -1
  214. package/src/components/Table/Table.usage.mdx +235 -0
  215. package/src/components/Tabs/Tabs.stories.tsx +86 -0
  216. package/src/components/Tabs/Tabs.usage.mdx +219 -0
  217. package/src/components/Tag/Tag.stories.tsx +181 -4
  218. package/src/components/Tag/Tag.usage.mdx +257 -0
  219. package/src/components/Textarea/Textarea.stories.tsx +113 -0
  220. package/src/components/Textarea/Textarea.usage.mdx +186 -0
  221. package/src/components/Toast/Toast.stories.tsx +185 -3
  222. package/src/components/Toast/Toast.styles.ts +18 -10
  223. package/src/components/Toast/Toast.usage.mdx +265 -0
  224. package/src/components/Tooltip/Tooltip.stories.tsx +86 -1
  225. package/src/components/Tooltip/Tooltip.usage.mdx +211 -0
  226. package/src/components/Tree/Tree.stories.tsx +89 -0
  227. package/src/components/Tree/Tree.usage.mdx +207 -0
  228. package/src/components/Typography/Typography.stories.tsx +117 -0
  229. package/src/components/Typography/Typography.usage.mdx +251 -0
  230. package/src/components/Workflow/Workflow.usage.mdx +199 -0
  231. package/src/components/noRawScales.test.ts +5 -1
  232. package/src/foundations/BrandColour.mdx +65 -2
  233. package/src/theme/BazePalette.stories.tsx +111 -1
  234. package/src/theme/Palette.stories.tsx +2 -2
  235. package/src/theme/SemanticTokens.mdx +75 -16
  236. package/src/theme/claude.md +15 -9
  237. package/src/theme/colors.ts +33 -3
  238. package/src/theme/contrast.test.ts +32 -0
  239. package/src/theme/palette.generated.ts +99 -0
  240. package/src/theme/paletteSwatches.ts +35 -0
@@ -0,0 +1,230 @@
1
+ import { Canvas, Meta } from '@storybook/blocks';
2
+
3
+ import { En, Ko, LangToggle, Verdict } from '../../guidelines/_components/Lang';
4
+ import * as MenuStories from './Menu.stories';
5
+
6
+ <Meta of={MenuStories} name="Usage" />
7
+
8
+ <LangToggle />
9
+
10
+ <En>
11
+
12
+ # Menu
13
+
14
+ A list of actions or choices that opens from a button. Each row does one
15
+ thing when chosen.
16
+
17
+ ## When to use
18
+
19
+ - For the actions on one row or object, behind a "more" button: 이름 변경,
20
+ 복제, 삭제.
21
+ - For a set of related commands under one button: export as CSV or Excel.
22
+ - For picking one setting from a short list in a top bar, such as the display
23
+ language.
24
+
25
+ ## When not to use
26
+
27
+ - Two or three actions that fit on screen → show them as `Button`s. A menu
28
+ hides them behind an extra click.
29
+ - A value in a form → `Select`. A menu does not hold a value or work with a
30
+ label and validation.
31
+ - A panel with inputs or checkboxes → `Popover`.
32
+ - Switching between views of the same content → `Tabs` or `SegmentedControl`.
33
+
34
+ ## Variants and what they mean
35
+
36
+ `Menu.Item` takes a `variant`:
37
+
38
+ </En>
39
+
40
+ <Ko>
41
+
42
+ # Menu
43
+
44
+ 버튼을 누르면 열리는 동작이나 선택지 목록입니다. 한 줄을 고르면 한 가지 일을 합니다.
45
+
46
+ ## 언제 쓰나요
47
+
48
+ - 한 줄이나 한 대상에 대한 동작을 "더 보기" 버튼 뒤에 모을 때: 이름 변경, 복제, 삭제.
49
+ - 관련된 명령 여러 개를 버튼 하나에 묶을 때: CSV나 Excel로 내보내기.
50
+ - 상단 바에서 짧은 목록 중 설정 하나를 고를 때: 표시 언어.
51
+
52
+ ## 언제 쓰지 않나요
53
+
54
+ - 화면에 들어가는 동작 두세 개는 `Button`으로 그대로 보입니다. 메뉴에 넣으면 한 번 더
55
+ 눌러야 합니다.
56
+ - 양식의 값은 `Select`로 받습니다. 메뉴는 값을 들고 있지 않고 라벨이나 검증과도 엮이지
57
+ 않습니다.
58
+ - 입력란이나 체크박스가 있는 패널은 `Popover`를 씁니다.
59
+ - 같은 내용의 보기를 바꾸는 것은 `Tabs`나 `SegmentedControl`을 씁니다.
60
+
61
+ ## 변형과 뜻
62
+
63
+ `Menu.Item`에는 `variant`가 있습니다.
64
+
65
+ </Ko>
66
+
67
+ <En>
68
+
69
+ | Variant | Means | Use for |
70
+ | --- | --- | --- |
71
+ | `default` | An ordinary action | 이름 변경, 복제, 내보내기 |
72
+ | `danger` | Deletes or removes something and cannot be undone | 삭제, 연결 해제 |
73
+
74
+ `Menu.List stagger` deals the rows in one after another; keep it for short
75
+ menus opened on purpose. `baseFontSize` (default `14px`) sets the base size
76
+ the list scales from.
77
+
78
+ ## Do / Don't
79
+
80
+ </En>
81
+
82
+ <Ko>
83
+
84
+ | 변형 | 뜻 | 예 |
85
+ | --- | --- | --- |
86
+ | `default` | 일반 동작 | 이름 변경, 복제, 내보내기 |
87
+ | `danger` | 무언가를 지우거나 없애며 되돌릴 수 없음 | 삭제, 연결 해제 |
88
+
89
+ `Menu.List`의 `stagger`는 줄을 하나씩 차례로 보입니다. 일부러 여는 짧은 메뉴에만
90
+ 씁니다. `baseFontSize`(기본 `14px`)는 목록 크기의 기준입니다.
91
+
92
+ ## 이렇게 하세요 / 이렇게 하지 마세요
93
+
94
+ </Ko>
95
+
96
+ <Canvas of={MenuStories.DoRowActions} />
97
+ <Verdict
98
+ kind="do"
99
+ en="Name the trigger after the row ('김민지 님 작업 메뉴'), put the destructive action last behind a separator, and confirm it in a Modal."
100
+ ko="여는 버튼 이름에 대상을 밝히고('김민지 님 작업 메뉴'), 되돌릴 수 없는 동작은 구분선 뒤 맨 아래에 두고, Modal로 한 번 더 확인합니다."
101
+ />
102
+
103
+ <Canvas of={MenuStories.DontDangerEverywhere} />
104
+ <Verdict
105
+ kind="dont"
106
+ en="Mark every row danger. Danger is a promise that the action destroys something; spent on 이름 변경 it stops warning anyone."
107
+ ko="모든 줄을 danger로 칠하지 마세요. danger는 무언가를 없애는 동작이라는 약속입니다. '이름 변경'에까지 쓰면 아무에게도 경고가 되지 않습니다."
108
+ />
109
+
110
+ <Canvas of={MenuStories.DontUnnamedTrigger} />
111
+ <Verdict
112
+ kind="dont"
113
+ en="Give every row's more button the same name. A screen reader user tabbing down a table hears '메뉴' twenty times."
114
+ ko="모든 줄의 더 보기 버튼에 같은 이름을 붙이지 마세요. 화면 낭독기 사용자가 표를 따라 내려가면 '메뉴'를 스무 번 듣습니다."
115
+ />
116
+
117
+ <En>
118
+
119
+ ## Content
120
+
121
+ - Rows start with a verb or are the verb: "이름 변경", "CSV로 내보내기". No full
122
+ stop.
123
+ - Order by frequency, with destructive actions last.
124
+ - If a row opens a dialog, the label does not need "…"; the dialog's title
125
+ repeats the action.
126
+ - Keep one menu under about seven rows. Group longer ones with
127
+ `Menu.ItemGroup` and `Menu.ItemGroupLabel`.
128
+
129
+ ## Accessibility
130
+
131
+ What Menu does for you:
132
+
133
+ - The list is `role="menu"`, its rows `role="menuitem"`, and the list is named
134
+ by its trigger. The trigger gets `aria-haspopup`, `aria-expanded` and
135
+ `aria-controls` (WCAG 4.1.2).
136
+ - Keyboard (WCAG 2.1.1): `Enter`, `Space` or `↓` opens the menu; `↑` / `↓`
137
+ move between rows, typing a letter jumps to a row, `Enter` chooses, and
138
+ `Escape` closes and returns focus to the trigger.
139
+ - The highlighted row is painted the same way for the pointer and the
140
+ keyboard (`primary.wash`, `danger.bg` on a danger row). Focus stays on the
141
+ list and the row is tracked with `aria-activedescendant`, so that fill is
142
+ the visible focus indicator (WCAG 2.4.7).
143
+ - A disabled row cannot be chosen and shows a not-allowed cursor.
144
+
145
+ What you still have to do:
146
+
147
+ - **Name an icon-only trigger, and include the object.** `aria-label` on the
148
+ `IconButton` inside `Menu.Trigger asChild`: "김민지 님 작업 메뉴", not "메뉴"
149
+ (WCAG 2.4.6).
150
+ - **Give row icons `aria-hidden`.** The text is the name.
151
+ - **Confirm destructive rows.** `variant="danger"` colours the row; it does not
152
+ ask the user. Open a `Modal`.
153
+ - A row that navigates should be a real link: `Menu.Item as={NextLink}
154
+ href=…`, so middle-click and "open in new tab" still work.
155
+
156
+ ## Tokens
157
+
158
+ The table lists the tokens set in `MenuItem.tsx` and `MenuList.tsx`, plus the
159
+ list panel colour from Chakra's Menu recipe.
160
+
161
+ </En>
162
+
163
+ <Ko>
164
+
165
+ ## 문구
166
+
167
+ - 줄은 동사로 쓰거나 동사로 시작합니다. "이름 변경", "CSV로 내보내기". 마침표를 찍지
168
+ 않습니다.
169
+ - 자주 쓰는 순서로 놓고, 되돌릴 수 없는 동작은 맨 아래에 둡니다.
170
+ - 대화상자를 여는 줄이라도 "…"를 붙이지 않아도 됩니다. 대화상자 제목이 동작을 다시
171
+ 말해 줍니다.
172
+ - 메뉴 하나는 일곱 줄 안쪽으로 둡니다. 더 길면 `Menu.ItemGroup`과
173
+ `Menu.ItemGroupLabel`로 묶습니다.
174
+
175
+ ## 접근성
176
+
177
+ Menu가 알아서 하는 일
178
+
179
+ - 목록은 `role="menu"`, 줄은 `role="menuitem"`이며, 목록의 이름은 여는 버튼에서
180
+ 옵니다. 여는 버튼에는 `aria-haspopup`, `aria-expanded`, `aria-controls`가 붙습니다
181
+ (WCAG 4.1.2).
182
+ - 키보드(WCAG 2.1.1): `Enter`, `Space`, `↓`로 열고, `↑`/`↓`로 줄을 옮기고, 글자를
183
+ 입력하면 그 글자로 시작하는 줄로 가고, `Enter`로 고르고, `Escape`로 닫으면 초점이 여는
184
+ 버튼으로 돌아옵니다.
185
+ - 강조된 줄은 포인터든 키보드든 같은 모양(`primary.wash`, 위험 줄은 `danger.bg`)으로
186
+ 칠해집니다. 초점은 목록에 머물고 줄은 `aria-activedescendant`로 가리키므로, 이 배경색이
187
+ 눈에 보이는 초점 표시입니다(WCAG 2.4.7).
188
+ - 비활성 줄은 고를 수 없고, 커서가 금지 모양으로 바뀝니다.
189
+
190
+ 직접 챙겨야 하는 일
191
+
192
+ - **아이콘만 있는 여는 버튼에 대상까지 담은 이름을 붙입니다.** `Menu.Trigger asChild`
193
+ 안의 `IconButton`에 `aria-label`을 줍니다. "메뉴"가 아니라 "김민지 님 작업 메뉴"처럼
194
+ 씁니다(WCAG 2.4.6).
195
+ - **줄 아이콘에는 `aria-hidden`을 붙입니다.** 이름은 문구가 맡습니다.
196
+ - **되돌릴 수 없는 줄은 한 번 더 확인합니다.** `variant="danger"`는 색만 바꿀 뿐 사용자에게
197
+ 묻지 않습니다. `Modal`을 엽니다.
198
+ - 다른 페이지로 가는 줄은 실제 링크로 만듭니다. `Menu.Item as={NextLink} href=…`로
199
+ 쓰면 가운데 클릭과 "새 탭에서 열기"가 그대로 동작합니다.
200
+
201
+ ## 토큰
202
+
203
+ 아래 표는 `MenuItem.tsx`와 `MenuList.tsx`에서 정한 토큰과, Chakra Menu 레시피에서 오는
204
+ 목록 패널 색입니다.
205
+
206
+ </Ko>
207
+
208
+ <Canvas of={MenuStories.UsageTokens} sourceState="none" />
209
+
210
+ <En>
211
+
212
+ ## Related
213
+
214
+ - **Button**: actions that fit on screen.
215
+ - **Select**: a value in a form.
216
+ - **Popover**: a panel with controls.
217
+ - **Modal**: confirming a destructive row.
218
+
219
+ </En>
220
+
221
+ <Ko>
222
+
223
+ ## 관련 컴포넌트
224
+
225
+ - **Button**: 화면에 그대로 둘 수 있는 동작.
226
+ - **Select**: 양식의 값.
227
+ - **Popover**: 컨트롤이 있는 패널.
228
+ - **Modal**: 되돌릴 수 없는 줄의 확인.
229
+
230
+ </Ko>
@@ -15,8 +15,16 @@ export type ItemVariant = (typeof ItemVariant)[keyof typeof ItemVariant];
15
15
 
16
16
  export type MenuItemOwnProps = Omit<ChakraMenuItemProps, 'as'> & {
17
17
  value: string; // Required in Chakra v3 for menu item identification
18
+ /**
19
+ * `'danger'`: an action that deletes or removes something and cannot be
20
+ * undone (삭제, 연결 해제). Text is `danger.fg`; the highlighted row is
21
+ * `danger.bg`. Everything else is `'default'`.
22
+ * @default 'default'
23
+ */
18
24
  variant?: ItemVariant | null;
25
+ /** Leading icon. Decorative: give it `aria-hidden`. */
19
26
  icon?: React.ReactElement;
27
+ /** Trailing icon, pushed to the end of the row. Decorative: give it `aria-hidden`. */
20
28
  rightIcon?: React.ReactElement;
21
29
  };
22
30
 
@@ -17,11 +17,16 @@
17
17
  *
18
18
  * @see ModalCloseButton.tsx - 구현 세부사항 확인
19
19
  */
20
- import { useState } from 'react';
20
+ import { ReactNode, useState } from 'react';
21
+ import { Box, Stack } from '@chakra-ui/react';
21
22
  import { Meta, StoryObj } from '@storybook/react';
22
23
 
24
+ import { T } from '../../guidelines/_components/Lang';
25
+ import { TokenTable } from '../../guidelines/_components/TokenTable';
23
26
  import { Button } from '../Button';
24
27
  import { ButtonVariant } from '../Button/Button.types';
28
+ import { Input } from '../Input';
29
+ import { Text } from '../Typography';
25
30
  import {
26
31
  Modal,
27
32
  ModalBody,
@@ -29,6 +34,7 @@ import {
29
34
  ModalContent,
30
35
  ModalFooter,
31
36
  ModalHeader,
37
+ type ModalProps,
32
38
  } from '.';
33
39
 
34
40
  interface ModalArgs {
@@ -620,3 +626,173 @@ export const BrandHeader: Story = {
620
626
  );
621
627
  },
622
628
  };
629
+
630
+ // ───────────────────────── Usage-page specimens ─────────────────────────
631
+ // Pulled into `Modal.usage.mdx` with <Canvas of={…} />. Hidden from the
632
+ // sidebar (`!dev`). Each one is a real, open `Modal` held inside a framed box
633
+ // on the docs page rather than over it: the portal is disabled, the frame's
634
+ // transform makes it the containing block for the fixed positioner and
635
+ // backdrop, and `modal={false}` keeps the specimen from trapping focus or
636
+ // locking the page's scroll.
637
+
638
+ const ModalFrame = ({ children }: { children: ReactNode }) => (
639
+ <Box
640
+ position="relative"
641
+ h="320px"
642
+ overflow="hidden"
643
+ borderRadius="l3"
644
+ borderWidth="1px"
645
+ borderColor="border.subtle"
646
+ bg="bg.canvas"
647
+ transform="translateZ(0)"
648
+ css={{
649
+ '& [data-scope=dialog][data-part=positioner], & [data-scope=dialog][data-part=backdrop]':
650
+ { width: '100%', height: '100%' },
651
+ }}
652
+ >
653
+ {children}
654
+ </Box>
655
+ );
656
+
657
+ /** An open, inert `Modal` for a docs specimen. */
658
+ const OpenModal = ({
659
+ children,
660
+ ...props
661
+ }: Omit<ModalProps, 'open' | 'children'> & { children: ReactNode }) => (
662
+ <ModalFrame>
663
+ <Modal
664
+ open
665
+ modal={false}
666
+ trapFocus={false}
667
+ preventScroll={false}
668
+ closeOnInteractOutside={false}
669
+ closeOnEscape={false}
670
+ portalProps={{ disabled: true }}
671
+ {...props}
672
+ >
673
+ <ModalContent maxW="400px">{children}</ModalContent>
674
+ </Modal>
675
+ </ModalFrame>
676
+ );
677
+
678
+ export const DoConfirmNamesTheAction: Story = {
679
+ tags: ['!dev'],
680
+ parameters: { layout: 'padded' },
681
+ name: 'Usage / Do: the title asks, the button answers',
682
+ render: () => (
683
+ <OpenModal>
684
+ <ModalHeader>멤버를 삭제할까요?</ModalHeader>
685
+ <ModalCloseButton />
686
+ <ModalBody>
687
+ 김민지 님의 대화 기록과 크레딧 내역이 함께 삭제되며 되돌릴 수 없습니다.
688
+ </ModalBody>
689
+ <ModalFooter>
690
+ <Button variant="secondary">취소</Button>
691
+ <Button variant="danger">삭제</Button>
692
+ </ModalFooter>
693
+ </OpenModal>
694
+ ),
695
+ };
696
+
697
+ export const DontVagueConfirm: Story = {
698
+ tags: ['!dev'],
699
+ parameters: { layout: 'padded' },
700
+ name: "Usage / Don't: a title and buttons that say nothing",
701
+ render: () => (
702
+ <OpenModal>
703
+ <ModalHeader>알림</ModalHeader>
704
+ <ModalBody>정말 진행하시겠습니까?</ModalBody>
705
+ <ModalFooter>
706
+ <Button variant="secondary">아니요</Button>
707
+ <Button variant="primary">예</Button>
708
+ </ModalFooter>
709
+ </OpenModal>
710
+ ),
711
+ };
712
+
713
+ export const DoShortForm: Story = {
714
+ tags: ['!dev'],
715
+ parameters: { layout: 'padded' },
716
+ name: 'Usage / Do: one short task',
717
+ render: () => (
718
+ <OpenModal closeOnInteractOutside={false}>
719
+ <ModalHeader subtitle="허용 목록에 있는 도메인은 SSO 없이 가입할 수 있습니다.">
720
+ 도메인 추가
721
+ </ModalHeader>
722
+ <ModalCloseButton />
723
+ <ModalBody>
724
+ <Input aria-label="도메인" placeholder="example.com" />
725
+ </ModalBody>
726
+ <ModalFooter>
727
+ <Button variant="secondary">취소</Button>
728
+ <Button variant="primary">추가</Button>
729
+ </ModalFooter>
730
+ </OpenModal>
731
+ ),
732
+ };
733
+
734
+ export const DontModalForDone: Story = {
735
+ tags: ['!dev'],
736
+ parameters: { layout: 'padded' },
737
+ name: "Usage / Don't: a modal to say it worked",
738
+ render: () => (
739
+ <OpenModal>
740
+ <ModalBody>
741
+ <Stack gap={2} py={4} align="center">
742
+ <Text fontWeight="bold">저장되었습니다.</Text>
743
+ </Stack>
744
+ </ModalBody>
745
+ <ModalFooter>
746
+ <Button variant="primary">확인</Button>
747
+ </ModalFooter>
748
+ </OpenModal>
749
+ ),
750
+ };
751
+
752
+ export const DoBrandHeaderOnboarding: Story = {
753
+ tags: ['!dev'],
754
+ parameters: { layout: 'padded' },
755
+ name: 'Usage / Do: brand header for a welcome step',
756
+ render: () => (
757
+ <OpenModal headerTone="brand">
758
+ <ModalHeader subtitle="세 단계만 거치면 첫 대화를 시작할 수 있습니다.">
759
+ 워크스페이스를 준비할게요
760
+ </ModalHeader>
761
+ <ModalCloseButton />
762
+ <ModalBody>조직 이름과 기본 모델을 고르면 바로 시작합니다.</ModalBody>
763
+ <ModalFooter>
764
+ <Button variant="primary">시작하기</Button>
765
+ </ModalFooter>
766
+ </OpenModal>
767
+ ),
768
+ };
769
+
770
+ /** Tokens the modal parts read, as written in `ModalHeader` / `ModalFooter` and the Dialog recipe. */
771
+ export const UsageTokens: Story = {
772
+ tags: ['!dev'],
773
+ parameters: { layout: 'padded' },
774
+ name: 'Usage / Tokens',
775
+ render: () => (
776
+ <TokenTable
777
+ rows={[
778
+ { token: 'bg.panel', use: <T en="Panel" ko="패널" /> },
779
+ {
780
+ token: 'fg.muted',
781
+ use: <T en="Header subtitle" ko="헤더 부제목" />,
782
+ },
783
+ {
784
+ token: 'layer.3',
785
+ use: <T en="Brand header · band" ko="브랜드 헤더 · 띠" />,
786
+ },
787
+ {
788
+ token: 'secondary.border',
789
+ use: <T en="Brand header · bottom rule" ko="브랜드 헤더 · 아래 선" />,
790
+ },
791
+ {
792
+ token: 'border.subtle',
793
+ use: <T en="Footer · top rule" ko="푸터 · 위 선" />,
794
+ },
795
+ ]}
796
+ />
797
+ ),
798
+ };