@mindlogic-ai/logician-ui 5.0.0-alpha.2 → 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 (256) hide show
  1. package/dist/components/Badge/Badge.d.ts.map +1 -1
  2. package/dist/components/Badge/Badge.js +5 -3
  3. package/dist/components/Badge/Badge.js.map +1 -1
  4. package/dist/components/Badge/Badge.mjs +5 -3
  5. package/dist/components/Badge/Badge.mjs.map +1 -1
  6. package/dist/components/Badge/Badge.types.d.ts +7 -5
  7. package/dist/components/Badge/Badge.types.d.ts.map +1 -1
  8. package/dist/components/Banner/Banner.types.d.ts +24 -1
  9. package/dist/components/Banner/Banner.types.d.ts.map +1 -1
  10. package/dist/components/Card/Card.types.d.ts +12 -0
  11. package/dist/components/Card/Card.types.d.ts.map +1 -1
  12. package/dist/components/ColorMode/ColorModeToggle.d.ts +7 -2
  13. package/dist/components/ColorMode/ColorModeToggle.d.ts.map +1 -1
  14. package/dist/components/ColorMode/ColorModeToggle.js +8 -3
  15. package/dist/components/ColorMode/ColorModeToggle.js.map +1 -1
  16. package/dist/components/ColorMode/ColorModeToggle.mjs +8 -3
  17. package/dist/components/ColorMode/ColorModeToggle.mjs.map +1 -1
  18. package/dist/components/Confetti/Confetti.types.d.ts +5 -1
  19. package/dist/components/Confetti/Confetti.types.d.ts.map +1 -1
  20. package/dist/components/Confetti/confettiColors.d.ts +5 -5
  21. package/dist/components/Confetti/confettiColors.js +5 -5
  22. package/dist/components/Confetti/confettiColors.mjs +5 -5
  23. package/dist/components/ErrorFallback/ErrorFallback.types.d.ts +6 -0
  24. package/dist/components/ErrorFallback/ErrorFallback.types.d.ts.map +1 -1
  25. package/dist/components/Form/FormModalFooter/FormModalFooter.types.d.ts +4 -1
  26. package/dist/components/Form/FormModalFooter/FormModalFooter.types.d.ts.map +1 -1
  27. package/dist/components/LineGraph/LineGraph.d.ts.map +1 -1
  28. package/dist/components/LineGraph/LineGraph.js +4 -5
  29. package/dist/components/LineGraph/LineGraph.js.map +1 -1
  30. package/dist/components/LineGraph/LineGraph.mjs +5 -6
  31. package/dist/components/LineGraph/LineGraph.mjs.map +1 -1
  32. package/dist/components/LineGraph/LineGraph.types.d.ts +12 -2
  33. package/dist/components/LineGraph/LineGraph.types.d.ts.map +1 -1
  34. package/dist/components/LineGraph/seriesColors.d.ts +12 -8
  35. package/dist/components/LineGraph/seriesColors.d.ts.map +1 -1
  36. package/dist/components/LineGraph/seriesColors.js +8 -7
  37. package/dist/components/LineGraph/seriesColors.js.map +1 -1
  38. package/dist/components/LineGraph/seriesColors.mjs +8 -7
  39. package/dist/components/LineGraph/seriesColors.mjs.map +1 -1
  40. package/dist/components/Masonry/Masonry.types.d.ts +8 -3
  41. package/dist/components/Masonry/Masonry.types.d.ts.map +1 -1
  42. package/dist/components/Menu/MenuItem.types.d.ts +8 -0
  43. package/dist/components/Menu/MenuItem.types.d.ts.map +1 -1
  44. package/dist/components/Modal/ModalCloseButton.d.ts +1 -1
  45. package/dist/components/Modal/ModalCloseButton.js +1 -1
  46. package/dist/components/Modal/ModalCloseButton.mjs +1 -1
  47. package/dist/components/Pagination/Pagination.d.ts +11 -10
  48. package/dist/components/Pagination/Pagination.d.ts.map +1 -1
  49. package/dist/components/Pagination/Pagination.js +11 -10
  50. package/dist/components/Pagination/Pagination.js.map +1 -1
  51. package/dist/components/Pagination/Pagination.mjs +11 -10
  52. package/dist/components/Pagination/Pagination.mjs.map +1 -1
  53. package/dist/components/ProgressBar/ProgressBar.types.d.ts +9 -0
  54. package/dist/components/ProgressBar/ProgressBar.types.d.ts.map +1 -1
  55. package/dist/components/RadialProgress/RadialProgress.types.d.ts +21 -1
  56. package/dist/components/RadialProgress/RadialProgress.types.d.ts.map +1 -1
  57. package/dist/components/SeeMoreButton/SeeMoreButton.types.d.ts +8 -0
  58. package/dist/components/SeeMoreButton/SeeMoreButton.types.d.ts.map +1 -1
  59. package/dist/components/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  60. package/dist/components/SegmentedControl/SegmentedControl.js +6 -7
  61. package/dist/components/SegmentedControl/SegmentedControl.js.map +1 -1
  62. package/dist/components/SegmentedControl/SegmentedControl.mjs +6 -7
  63. package/dist/components/SegmentedControl/SegmentedControl.mjs.map +1 -1
  64. package/dist/components/SegmentedProgressBar/SegmentedProgressBar.types.d.ts +2 -0
  65. package/dist/components/SegmentedProgressBar/SegmentedProgressBar.types.d.ts.map +1 -1
  66. package/dist/components/Toast/Toast.styles.d.ts +6 -2
  67. package/dist/components/Toast/Toast.styles.d.ts.map +1 -1
  68. package/dist/components/Toast/Toast.styles.js +18 -10
  69. package/dist/components/Toast/Toast.styles.js.map +1 -1
  70. package/dist/components/Toast/Toast.styles.mjs +18 -10
  71. package/dist/components/Toast/Toast.styles.mjs.map +1 -1
  72. package/dist/theme/colors.d.ts +2 -2
  73. package/dist/theme/colors.d.ts.map +1 -1
  74. package/dist/theme/colors.js +22 -2
  75. package/dist/theme/colors.js.map +1 -1
  76. package/dist/theme/colors.mjs +23 -3
  77. package/dist/theme/colors.mjs.map +1 -1
  78. package/dist/theme/palette.generated.d.ts +98 -0
  79. package/dist/theme/palette.generated.d.ts.map +1 -1
  80. package/dist/theme/palette.generated.js +99 -0
  81. package/dist/theme/palette.generated.js.map +1 -1
  82. package/dist/theme/palette.generated.mjs +99 -1
  83. package/dist/theme/palette.generated.mjs.map +1 -1
  84. package/dist/theme/paletteSwatches.d.ts +20 -0
  85. package/dist/theme/paletteSwatches.d.ts.map +1 -1
  86. package/package.json +1 -1
  87. package/src/components/Accordion/Accordion.stories.tsx +85 -0
  88. package/src/components/Accordion/Accordion.usage.mdx +200 -0
  89. package/src/components/Appear/Appear.usage.mdx +107 -0
  90. package/src/components/Avatar/Avatar.stories.tsx +71 -1
  91. package/src/components/Avatar/Avatar.usage.mdx +166 -0
  92. package/src/components/Badge/Badge.stories.tsx +193 -3
  93. package/src/components/Badge/Badge.tsx +5 -3
  94. package/src/components/Badge/Badge.types.ts +7 -5
  95. package/src/components/Badge/Badge.usage.mdx +265 -0
  96. package/src/components/Banner/Banner.stories.tsx +152 -2
  97. package/src/components/Banner/Banner.types.ts +30 -1
  98. package/src/components/Banner/Banner.usage.mdx +233 -0
  99. package/src/components/BottomSheet/BottomSheet.stories.tsx +168 -1
  100. package/src/components/BottomSheet/BottomSheet.usage.mdx +216 -0
  101. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +59 -0
  102. package/src/components/Breadcrumb/Breadcrumb.usage.mdx +181 -0
  103. package/src/components/Button/Button.stories.tsx +263 -3
  104. package/src/components/Button/Button.usage.mdx +342 -0
  105. package/src/components/Card/Card.stories.tsx +106 -0
  106. package/src/components/Card/Card.types.ts +12 -0
  107. package/src/components/Card/Card.usage.mdx +216 -0
  108. package/src/components/Checkbox/Checkbox.stories.tsx +140 -13
  109. package/src/components/Checkbox/Checkbox.usage.mdx +214 -0
  110. package/src/components/Chip/Chip.usage.mdx +78 -0
  111. package/src/components/Code/Code.stories.tsx +60 -0
  112. package/src/components/Code/Code.usage.mdx +187 -0
  113. package/src/components/CodeTabs/CodeTabs.stories.tsx +53 -0
  114. package/src/components/CodeTabs/CodeTabs.usage.mdx +176 -0
  115. package/src/components/Collapsible/Collapsible.stories.tsx +58 -0
  116. package/src/components/Collapsible/Collapsible.usage.mdx +173 -0
  117. package/src/components/ColorMode/ColorMode.stories.tsx +50 -0
  118. package/src/components/ColorMode/ColorMode.usage.mdx +135 -0
  119. package/src/components/ColorMode/ColorModeToggle.tsx +10 -3
  120. package/src/components/Confetti/Confetti.types.ts +5 -1
  121. package/src/components/Confetti/Confetti.usage.mdx +111 -0
  122. package/src/components/Confetti/confettiColors.ts +5 -5
  123. package/src/components/Container/Container.stories.tsx +32 -0
  124. package/src/components/Container/Container.usage.mdx +130 -0
  125. package/src/components/CopyableCode/CopyableCode.stories.tsx +62 -0
  126. package/src/components/CopyableCode/CopyableCode.usage.mdx +168 -0
  127. package/src/components/CountBadge/CountBadge.stories.tsx +69 -0
  128. package/src/components/CountBadge/CountBadge.usage.mdx +215 -0
  129. package/src/components/CountUp/CountUp.usage.mdx +107 -0
  130. package/src/components/DatePicker/DatePicker.usage.mdx +177 -0
  131. package/src/components/DatePicker/RangeDatePicker.stories.tsx +87 -3
  132. package/src/components/ErrorFallback/ErrorFallback.types.ts +6 -0
  133. package/src/components/ErrorFallback/ErrorFallback.usage.mdx +127 -0
  134. package/src/components/ExpandableText/ExpandableText.stories.tsx +55 -0
  135. package/src/components/ExpandableText/ExpandableText.usage.mdx +176 -0
  136. package/src/components/FileInput/FileInput.stories.tsx +38 -1
  137. package/src/components/FileInput/FileInput.usage.mdx +178 -0
  138. package/src/components/FileItem/FileItem.stories.tsx +71 -0
  139. package/src/components/FileItem/FileItem.usage.mdx +180 -0
  140. package/src/components/FileList/FileList.stories.tsx +25 -0
  141. package/src/components/FileList/FileList.usage.mdx +165 -0
  142. package/src/components/FlyTo/FlyTo.usage.mdx +99 -0
  143. package/src/components/Form/Form.stories.tsx +149 -0
  144. package/src/components/Form/Form.usage.mdx +201 -0
  145. package/src/components/Form/FormModalFooter/FormModalFooter.types.ts +4 -1
  146. package/src/components/FormControl/FormControl.stories.tsx +35 -0
  147. package/src/components/FormControl/FormControl.usage.mdx +128 -0
  148. package/src/components/FormIntegration/FormIntegration.usage.mdx +158 -0
  149. package/src/components/FormLabel/FormLabel.stories.tsx +71 -0
  150. package/src/components/FormLabel/FormLabel.usage.mdx +125 -0
  151. package/src/components/Icon/Icon.stories.tsx +61 -1
  152. package/src/components/Icon/Icon.usage.mdx +158 -0
  153. package/src/components/IconButton/IconButton.stories.tsx +209 -5
  154. package/src/components/IconButton/IconButton.usage.mdx +273 -0
  155. package/src/components/InfoSprinkle/InfoSprinkle.stories.tsx +77 -1
  156. package/src/components/InfoSprinkle/InfoSprinkle.usage.mdx +189 -0
  157. package/src/components/InlineCode/InlineCode.stories.tsx +75 -0
  158. package/src/components/InlineCode/InlineCode.usage.mdx +142 -0
  159. package/src/components/Input/Input.stories.tsx +180 -0
  160. package/src/components/Input/Input.usage.mdx +278 -0
  161. package/src/components/LineGraph/LineGraph.stories.tsx +112 -0
  162. package/src/components/LineGraph/LineGraph.tsx +4 -5
  163. package/src/components/LineGraph/LineGraph.types.ts +12 -2
  164. package/src/components/LineGraph/LineGraph.usage.mdx +186 -0
  165. package/src/components/LineGraph/seriesColors.test.ts +11 -10
  166. package/src/components/LineGraph/seriesColors.ts +18 -16
  167. package/src/components/Loaders/Loaders.stories.tsx +93 -0
  168. package/src/components/Loaders/Loaders.usage.mdx +180 -0
  169. package/src/components/LogicianProvider/LogicianProvider.usage.mdx +98 -0
  170. package/src/components/Markdown/Markdown.stories.tsx +53 -0
  171. package/src/components/Markdown/Markdown.usage.mdx +182 -0
  172. package/src/components/Masonry/Masonry.stories.tsx +63 -1
  173. package/src/components/Masonry/Masonry.types.ts +8 -3
  174. package/src/components/Masonry/Masonry.usage.mdx +142 -0
  175. package/src/components/MaxLengthIndicator/MaxLengthIndicator.stories.tsx +57 -0
  176. package/src/components/MaxLengthIndicator/MaxLengthIndicator.usage.mdx +125 -0
  177. package/src/components/Menu/Menu.stories.tsx +146 -2
  178. package/src/components/Menu/Menu.usage.mdx +230 -0
  179. package/src/components/Menu/MenuItem.types.ts +8 -0
  180. package/src/components/Modal/Modal.stories.tsx +177 -1
  181. package/src/components/Modal/Modal.usage.mdx +262 -0
  182. package/src/components/Modal/ModalCloseButton.tsx +1 -1
  183. package/src/components/MonthPicker/MonthPicker.stories.tsx +30 -0
  184. package/src/components/MonthPicker/MonthPicker.usage.mdx +191 -0
  185. package/src/components/Pagination/Pagination.stories.tsx +90 -1
  186. package/src/components/Pagination/Pagination.tsx +11 -10
  187. package/src/components/Pagination/Pagination.usage.mdx +186 -0
  188. package/src/components/PasswordInput/PasswordInput.stories.tsx +51 -0
  189. package/src/components/PasswordInput/PasswordInput.usage.mdx +193 -0
  190. package/src/components/PinInput/PinInput.stories.tsx +91 -0
  191. package/src/components/PinInput/PinInput.usage.mdx +194 -0
  192. package/src/components/Popover/Popover.stories.tsx +104 -1
  193. package/src/components/Popover/Popover.usage.mdx +197 -0
  194. package/src/components/ProgressBar/ProgressBar.stories.tsx +92 -1
  195. package/src/components/ProgressBar/ProgressBar.types.ts +9 -0
  196. package/src/components/ProgressBar/ProgressBar.usage.mdx +210 -0
  197. package/src/components/Pulse/Pulse.usage.mdx +102 -0
  198. package/src/components/RadialProgress/RadialProgress.stories.tsx +74 -1
  199. package/src/components/RadialProgress/RadialProgress.types.ts +21 -1
  200. package/src/components/RadialProgress/RadialProgress.usage.mdx +153 -0
  201. package/src/components/Radio/Radio.stories.tsx +119 -0
  202. package/src/components/Radio/Radio.usage.mdx +187 -0
  203. package/src/components/Reveal/Reveal.usage.mdx +105 -0
  204. package/src/components/ScaledContext/ScaledContext.usage.mdx +111 -0
  205. package/src/components/SeeMoreButton/SeeMoreButton.stories.tsx +146 -2
  206. package/src/components/SeeMoreButton/SeeMoreButton.types.ts +8 -0
  207. package/src/components/SeeMoreButton/SeeMoreButton.usage.mdx +213 -0
  208. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +69 -0
  209. package/src/components/SegmentedControl/SegmentedControl.tsx +6 -7
  210. package/src/components/SegmentedControl/SegmentedControl.usage.mdx +209 -0
  211. package/src/components/SegmentedProgressBar/SegmentedProgressBar.stories.tsx +54 -0
  212. package/src/components/SegmentedProgressBar/SegmentedProgressBar.types.ts +2 -0
  213. package/src/components/SegmentedProgressBar/SegmentedProgressBar.usage.mdx +145 -0
  214. package/src/components/Select/Select.stories.tsx +209 -1
  215. package/src/components/Select/Select.usage.mdx +278 -0
  216. package/src/components/Shake/Shake.usage.mdx +107 -0
  217. package/src/components/Slider/Slider.stories.tsx +116 -0
  218. package/src/components/Slider/Slider.usage.mdx +179 -0
  219. package/src/components/Spinner/Spinner.stories.tsx +64 -0
  220. package/src/components/Spinner/Spinner.usage.mdx +136 -0
  221. package/src/components/SwapTransition/SwapTransition.usage.mdx +102 -0
  222. package/src/components/Switch/Switch.stories.tsx +131 -6
  223. package/src/components/Switch/Switch.usage.mdx +199 -0
  224. package/src/components/Table/Table.stories.tsx +159 -1
  225. package/src/components/Table/Table.usage.mdx +235 -0
  226. package/src/components/Tabs/Tabs.stories.tsx +86 -0
  227. package/src/components/Tabs/Tabs.usage.mdx +219 -0
  228. package/src/components/Tag/Tag.stories.tsx +181 -4
  229. package/src/components/Tag/Tag.usage.mdx +257 -0
  230. package/src/components/Textarea/Textarea.stories.tsx +113 -0
  231. package/src/components/Textarea/Textarea.usage.mdx +186 -0
  232. package/src/components/Toast/Toast.stories.tsx +185 -3
  233. package/src/components/Toast/Toast.styles.ts +18 -10
  234. package/src/components/Toast/Toast.usage.mdx +265 -0
  235. package/src/components/Tooltip/Tooltip.stories.tsx +86 -1
  236. package/src/components/Tooltip/Tooltip.usage.mdx +211 -0
  237. package/src/components/Tree/Tree.stories.tsx +89 -0
  238. package/src/components/Tree/Tree.usage.mdx +207 -0
  239. package/src/components/Typography/Typography.stories.tsx +117 -0
  240. package/src/components/Typography/Typography.usage.mdx +251 -0
  241. package/src/components/Workflow/Workflow.usage.mdx +199 -0
  242. package/src/components/noRawScales.test.ts +5 -1
  243. package/src/foundations/BrandColour.mdx +364 -0
  244. package/src/foundations/BrandColour.stories.tsx +334 -0
  245. package/src/guidelines/ComponentPageTemplate.mdx +84 -0
  246. package/src/guidelines/FeedbackActions.mdx +162 -23
  247. package/src/guidelines/_components/Lang.tsx +175 -0
  248. package/src/guidelines/_components/TokenTable.tsx +136 -0
  249. package/src/theme/BazePalette.stories.tsx +111 -1
  250. package/src/theme/Palette.stories.tsx +2 -2
  251. package/src/theme/SemanticTokens.mdx +75 -16
  252. package/src/theme/claude.md +15 -9
  253. package/src/theme/colors.ts +33 -3
  254. package/src/theme/contrast.test.ts +32 -0
  255. package/src/theme/palette.generated.ts +99 -0
  256. package/src/theme/paletteSwatches.ts +35 -0
@@ -0,0 +1,278 @@
1
+ import { ArgTypes, Canvas, Meta } from '@storybook/blocks';
2
+
3
+ import { En, Ko, LangToggle, Verdict } from '../../guidelines/_components/Lang';
4
+ import * as InputStories from './Input.stories';
5
+
6
+ <Meta of={InputStories} name="Usage" />
7
+
8
+ <LangToggle />
9
+
10
+ <En>
11
+
12
+ # Input
13
+
14
+ A single-line text field: names, email addresses, amounts, search terms.
15
+
16
+ ## When to use
17
+
18
+ - One line of free text the user types: a name, an email address, a URL.
19
+ - A number the user types exactly, such as a credit limit. Use
20
+ `type="number"` with `maskNumber` to show thousands separators.
21
+ - A search or filter box, with a `leftIcon`.
22
+
23
+ ## When not to use
24
+
25
+ - More than one line, or text that wraps → `Textarea`.
26
+ - A password or secret → `PasswordInput`.
27
+ - A short one-time code typed box by box → `PinInput`.
28
+ - A choice from a known list → `SelectField`, `ComboboxField`, `Radio`.
29
+ - A date or month → `SingleDatePicker`, `RangeDatePicker`, `MonthPicker`.
30
+ - A rough value on a scale, where the exact number does not matter → `Slider`.
31
+
32
+ ## Props that change behaviour
33
+
34
+ </En>
35
+
36
+ <Ko>
37
+
38
+ # Input
39
+
40
+ 한 줄짜리 텍스트 입력란입니다. 이름, 이메일 주소, 금액, 검색어에 씁니다.
41
+
42
+ ## 언제 쓰나요
43
+
44
+ - 사용자가 직접 입력하는 한 줄짜리 텍스트: 이름, 이메일 주소, URL.
45
+ - 정확하게 입력해야 하는 숫자(예: 크레딧 한도). 천 단위 쉼표가 필요하면
46
+ `type="number"`와 `maskNumber`를 함께 씁니다.
47
+ - 검색창이나 필터 입력란. 이때는 `leftIcon`에 아이콘을 넣습니다.
48
+
49
+ ## 언제 쓰지 않나요
50
+
51
+ - 두 줄 이상이거나 줄바꿈이 필요한 글은 `Textarea`를 씁니다.
52
+ - 비밀번호나 비밀 값은 `PasswordInput`을 씁니다.
53
+ - 한 칸에 한 글자씩 넣는 짧은 인증 코드는 `PinInput`을 씁니다.
54
+ - 정해진 목록에서 고르는 값은 `SelectField`, `ComboboxField`, `Radio`를 씁니다.
55
+ - 날짜나 월은 `SingleDatePicker`, `RangeDatePicker`, `MonthPicker`를 씁니다.
56
+ - 정확한 숫자보다 대략적인 위치가 중요한 값은 `Slider`를 씁니다.
57
+
58
+ ## 동작을 바꾸는 속성
59
+
60
+ </Ko>
61
+
62
+ <ArgTypes
63
+ of={InputStories}
64
+ include={[
65
+ 'maskNumber',
66
+ 'trimWhiteSpace',
67
+ 'noSpaces',
68
+ 'invalid',
69
+ 'leftIcon',
70
+ 'rightIcon',
71
+ ]}
72
+ />
73
+
74
+ <En>
75
+
76
+ | Prop | What it does | Use for |
77
+ | ---------------- | ----------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
78
+ | `maskNumber` | Only with `type="number"`. Renders a text input that shows `2,000,000` while `onChange` receives the digits (`2000000`). | Amounts, limits, counts |
79
+ | `noSpaces` | Blocks the space key and strips every space, including pasted ones. | Email addresses, IDs, codes |
80
+ | `trimWhiteSpace` | Blocks a leading space and trims **both ends on every keystroke**, so a space between two words cannot be typed, only pasted. | Single-word values only. Never names or titles; trim at submit instead |
81
+ | `invalid` | Red border only. It does not tell assistive technology anything; see Accessibility. | With `FieldRow` `error` |
82
+ | `readOnly` | `bg.subtle` fill and muted text. The value can still be selected and copied. | Values the user may see but not change |
83
+ | `disabled` | The fixed `disabled.*` pair, not reduced opacity. | A field that does not apply right now |
84
+
85
+ Good to know:
86
+
87
+ - While a Korean IME is composing, Enter is swallowed, so a half-typed syllable
88
+ never submits the form.
89
+ - `onKeyDown` is only called for Enter. Listen on a wrapper if you need other
90
+ keys.
91
+ - On touch devices the text is raised to 16px so iOS Safari does not zoom the
92
+ page on focus.
93
+
94
+ ## Do / Don't
95
+
96
+ </En>
97
+
98
+ <Ko>
99
+
100
+ | 속성 | 하는 일 | 쓰는 곳 |
101
+ | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
102
+ | `maskNumber` | `type="number"`와 함께일 때만 동작합니다. 화면에는 `2,000,000`으로 보이고 `onChange`에는 숫자만(`2000000`) 전달됩니다. | 금액, 한도, 개수 |
103
+ | `noSpaces` | 스페이스 키를 막고, 붙여 넣은 내용까지 모든 공백을 지웁니다. | 이메일 주소, 아이디, 코드 |
104
+ | `trimWhiteSpace` | 맨 앞 공백을 막고 **입력할 때마다 앞뒤 공백을 지웁니다.** 그래서 단어 사이 공백은 타이핑으로 넣을 수 없고 붙여 넣기로만 들어갑니다. | 한 단어짜리 값에만 씁니다. 이름이나 제목에는 쓰지 말고 제출할 때 공백을 정리합니다 |
105
+ | `invalid` | 테두리만 빨갛게 바꿉니다. 보조기술에는 아무것도 알리지 않습니다. 접근성 절을 보세요. | `FieldRow`의 `error`와 함께 |
106
+ | `readOnly` | `bg.subtle` 배경에 흐린 글자로 바뀝니다. 값을 선택하고 복사할 수는 있습니다. | 보여 주되 바꾸면 안 되는 값 |
107
+ | `disabled` | 투명도를 낮추지 않고 고정된 `disabled.*` 색 한 쌍을 씁니다. | 지금은 해당하지 않는 입력란 |
108
+
109
+ 알아 두면 좋은 점
110
+
111
+ - 한글 입력기로 글자를 조합하는 동안에는 Enter를 무시합니다. 조합 중인 글자 때문에 폼이
112
+ 제출되지 않습니다.
113
+ - `onKeyDown`은 Enter를 눌렀을 때만 호출됩니다. 다른 키가 필요하면 바깥 요소에서
114
+ 받습니다.
115
+ - 터치 기기에서는 글자를 16px로 키워 iOS Safari가 초점을 받을 때 화면을 확대하지 않게
116
+ 합니다.
117
+
118
+ ## 이렇게 하세요 / 이렇게 하지 마세요
119
+
120
+ </Ko>
121
+
122
+ <Canvas of={InputStories.DoLabelAbove} />
123
+ <Verdict
124
+ kind="do"
125
+ en="Put a visible label above the field with FieldRow. The label stays while the user types, and FieldRow connects it to the input."
126
+ ko="FieldRow로 입력란 위에 보이는 라벨을 둡니다. 라벨은 입력하는 동안에도 남아 있고, FieldRow가 라벨과 입력란을 연결합니다."
127
+ />
128
+
129
+ <Canvas of={InputStories.DontPlaceholderAsLabel} />
130
+ <Verdict
131
+ kind="dont"
132
+ en="Use the placeholder as the label. It disappears on the first keystroke, and the field has no name for a screen reader."
133
+ ko="플레이스홀더를 라벨 대신 쓰지 마세요. 첫 글자를 입력하면 사라지고, 화면 낭독기에는 입력란의 이름이 없습니다."
134
+ />
135
+
136
+ <Canvas of={InputStories.DoErrorInWords} />
137
+ <Verdict
138
+ kind="do"
139
+ en="Pass the message to FieldRow error. The field turns invalid for assistive technology too, and the message is read with it."
140
+ ko="오류 문구는 FieldRow의 error에 넘깁니다. 보조기술에도 오류 상태가 전달되고, 입력란과 함께 문구가 읽힙니다."
141
+ />
142
+
143
+ <Canvas of={InputStories.DontBorderOnly} />
144
+ <Verdict
145
+ kind="dont"
146
+ en="Signal an error with the red border alone. Colour is the only cue, and nothing says what to fix (WCAG 1.4.1, 3.3.1)."
147
+ ko="빨간 테두리만으로 오류를 알리지 마세요. 색 말고는 단서가 없고, 무엇을 고쳐야 하는지도 알 수 없습니다(WCAG 1.4.1, 3.3.1)."
148
+ />
149
+
150
+ <Canvas of={InputStories.DoMaskedAmount} />
151
+ <Verdict
152
+ kind="do"
153
+ en="Use type='number' with maskNumber for amounts. The reader sees separators; your form state keeps plain digits."
154
+ ko="금액에는 type='number'와 maskNumber를 씁니다. 화면에는 쉼표가 보이고, 폼 상태에는 숫자만 남습니다."
155
+ />
156
+
157
+ <Canvas of={InputStories.DoCountWithLimit} />
158
+ <Verdict
159
+ kind="do"
160
+ en="When you set maxLength, show the count with MaxLengthIndicator in the label row, so the limit is not a surprise."
161
+ ko="maxLength를 정했다면 라벨 줄에 MaxLengthIndicator로 글자 수를 보여 줍니다. 그래야 제한에 걸려도 당황하지 않습니다."
162
+ />
163
+
164
+ <En>
165
+
166
+ ## Content
167
+
168
+ - Label: a noun phrase in sentence case, no colon ("Work email", not
169
+ "Work Email:"). Korean labels are nouns too: 업무용 이메일, not 이메일을
170
+ 입력하세요.
171
+ - Placeholder: an example of the format (`name@company.com`), never the label
172
+ and never an instruction the user needs after they start typing.
173
+ - Helper text: one sentence on what happens with the value or which format is
174
+ accepted. Put it in `FieldRow` `helperText`, not in the placeholder.
175
+ - Error text: say what is wrong and how to fix it, in one sentence: 이메일 주소
176
+ 형식이 아닙니다.
177
+
178
+ ## Accessibility
179
+
180
+ What Input does for you:
181
+
182
+ - Renders a native `<input>`, so Tab, typing, selection and copy and paste
183
+ work as the browser provides.
184
+ - Shows a visible focus state: a `primary.main` border and 1px ring (WCAG
185
+ 2.4.7).
186
+ - Inside `FormControl` or `FieldRow` it takes the field's id, so the label is
187
+ associated, and it picks up `aria-invalid`, `required` and the
188
+ `aria-describedby` that points at helper and error text.
189
+
190
+ What you still have to do:
191
+
192
+ - **Name every field.** Use `FieldRow` `label` or `FormControl` + `FormLabel`.
193
+ A placeholder is not a name, and an icon is not either (WCAG 4.1.2; KWCAG
194
+ 5.3.4.1 레이블 제공).
195
+ - **Mark errors on the field, not on the input.** The `invalid` prop changes
196
+ the border only. Set `error` on `FieldRow` (or `invalid` on `FormControl`)
197
+ so the state and the message reach assistive technology (WCAG 3.3.1).
198
+ - **Say what the field is for** with `type` and `autoComplete` (`email`,
199
+ `name`, `tel`), so browsers and assistive tools can fill it (WCAG 1.3.5).
200
+ - An icon-only `rightIcon` that does something (clear, search) has to be a
201
+ button with an `aria-label`. A decorative `leftIcon` gets `aria-hidden`.
202
+
203
+ ## Tokens
204
+
205
+ Input has no styles file; the table follows the values in `Input.tsx`, which
206
+ `Select.styles.ts` mirrors.
207
+
208
+ </En>
209
+
210
+ <Ko>
211
+
212
+ ## 문구
213
+
214
+ - 라벨: 문장형 대소문자의 명사구로 쓰고 쌍점을 붙이지 않습니다("Work email",
215
+ "Work Email:"이 아님). 한국어 라벨도 명사로 씁니다. "이메일을 입력하세요"가 아니라
216
+ "업무용 이메일"입니다.
217
+ - 플레이스홀더: 형식의 예(`name@company.com`)만 씁니다. 라벨을 대신하지 않고, 입력을
218
+ 시작한 뒤에도 필요한 안내를 넣지 않습니다.
219
+ - 도움말: 값이 어디에 쓰이는지나 받는 형식을 한 문장으로 씁니다. 플레이스홀더가 아니라
220
+ `FieldRow`의 `helperText`에 넣습니다.
221
+ - 오류 문구: 무엇이 잘못됐고 어떻게 고치는지 한 문장으로 씁니다. 예: 이메일 주소
222
+ 형식이 아닙니다.
223
+
224
+ ## 접근성
225
+
226
+ Input이 알아서 하는 일
227
+
228
+ - 네이티브 `<input>`을 그리므로 Tab 이동, 입력, 선택, 복사와 붙여 넣기가 브라우저
229
+ 기본대로 동작합니다.
230
+ - 초점을 받으면 `primary.main` 테두리와 1px 링으로 눈에 띄게 표시합니다(WCAG 2.4.7).
231
+ - `FormControl`이나 `FieldRow` 안에 두면 필드의 id를 받아 라벨과 연결되고,
232
+ `aria-invalid`, `required`, 도움말과 오류 문구를 가리키는 `aria-describedby`도
233
+ 함께 받습니다.
234
+
235
+ 직접 챙겨야 하는 일
236
+
237
+ - **모든 입력란에 이름을 붙입니다.** `FieldRow`의 `label`이나 `FormControl`과
238
+ `FormLabel`을 씁니다. 플레이스홀더나 아이콘은 이름이 아닙니다(WCAG 4.1.2, KWCAG
239
+ 5.3.4.1 레이블 제공).
240
+ - **오류는 입력란이 아니라 필드에 표시합니다.** `invalid` 속성은 테두리만 바꿉니다.
241
+ `FieldRow`에 `error`를 넘기거나 `FormControl`에 `invalid`를 주어야 오류 상태와 문구가
242
+ 보조기술에 전달됩니다(WCAG 3.3.1).
243
+ - **입력란의 용도를 밝힙니다.** `type`과 `autoComplete`(`email`, `name`, `tel`)를
244
+ 지정하면 브라우저와 보조 도구가 값을 채워 줄 수 있습니다(WCAG 1.3.5).
245
+ - 지우기나 검색처럼 동작하는 `rightIcon`은 `aria-label`이 있는 버튼이어야 합니다.
246
+ 꾸밈용 `leftIcon`에는 `aria-hidden`을 붙입니다.
247
+
248
+ ## 토큰
249
+
250
+ Input에는 스타일 파일이 없습니다. 아래 표는 `Input.tsx`에 적힌 값을 따르며,
251
+ `Select.styles.ts`도 같은 값을 씁니다.
252
+
253
+ </Ko>
254
+
255
+ <Canvas of={InputStories.UsageTokens} sourceState="none" />
256
+
257
+ <En>
258
+
259
+ ## Related
260
+
261
+ - **FieldRow** / **FormControl**: label, helper text and error around the
262
+ field.
263
+ - **Textarea**, **PasswordInput**, **PinInput**: other text entry.
264
+ - **SelectField** / **ComboboxField**: a choice from a list.
265
+ - **MaxLengthIndicator**: the character count next to the label.
266
+
267
+ </En>
268
+
269
+ <Ko>
270
+
271
+ ## 관련 컴포넌트
272
+
273
+ - **FieldRow** / **FormControl**: 입력란을 둘러싼 라벨, 도움말, 오류 문구.
274
+ - **Textarea**, **PasswordInput**, **PinInput**: 다른 텍스트 입력.
275
+ - **SelectField** / **ComboboxField**: 목록에서 고르는 값.
276
+ - **MaxLengthIndicator**: 라벨 옆 글자 수 표시.
277
+
278
+ </Ko>
@@ -1,6 +1,10 @@
1
+ import { Fragment } from 'react';
2
+ import { Box, Grid } from '@chakra-ui/react';
1
3
  import type { Meta, StoryObj } from '@storybook/react';
2
4
 
5
+ import { TokenTable } from '../../guidelines/_components/TokenTable';
3
6
  import { LineGraph } from '.';
7
+ import { CHART_SERIES_HUES, seriesColor } from './seriesColors';
4
8
  import type { DatumBase } from './LineGraph.types';
5
9
 
6
10
  type TestDataType = {
@@ -105,3 +109,111 @@ export const CustomColors: Story = {
105
109
  ],
106
110
  },
107
111
  };
112
+
113
+ // ───────────────────────── Usage-page specimens ─────────────────────────
114
+ // Pulled into `LineGraph.usage.mdx` with <Canvas of={…} />. Hidden from the
115
+ // sidebar (`!dev`); `tags` is written out on each story because the indexer
116
+ // reads CSF statically.
117
+
118
+ type DailyType = { 질문?: number; 답변실패?: number };
119
+
120
+ const DAILY: Array<{ name: string } & DailyType> = [
121
+ { name: '10/16', 질문: 120, 답변실패: 9 },
122
+ { name: '10/17', 질문: 148, 답변실패: 12 },
123
+ { name: '10/18', 질문: 96, 답변실패: 4 },
124
+ { name: '10/19', 질문: 60, 답변실패: 3 },
125
+ { name: '10/20', 질문: 171, 답변실패: 15 },
126
+ { name: '10/21', 질문: 188, 답변실패: 11 },
127
+ { name: '10/22', 질문: 164, 답변실패: 8 },
128
+ ];
129
+
130
+ export const DoDefaultSeriesColours: Story = {
131
+ tags: ['!dev'],
132
+ parameters: { layout: 'padded' },
133
+ name: 'Usage / Do: default series colours, a trend over time',
134
+ render: () => (
135
+ <LineGraph<DailyType>
136
+ h="280px"
137
+ data={DAILY}
138
+ dataKeys={[
139
+ { key: '질문', label: '질문 수' },
140
+ { key: '답변실패', label: '답변하지 못한 질문' },
141
+ ]}
142
+ />
143
+ ),
144
+ };
145
+
146
+ export const DontStatusColours: Story = {
147
+ tags: ['!dev'],
148
+ parameters: { layout: 'padded' },
149
+ name: "Usage / Don't: status colours for ordinary series",
150
+ render: () => (
151
+ <LineGraph<DailyType>
152
+ h="280px"
153
+ data={DAILY}
154
+ dataKeys={[
155
+ {
156
+ key: '질문',
157
+ label: '질문 수',
158
+ color: 'var(--chakra-colors-success-fg)',
159
+ },
160
+ {
161
+ key: '답변실패',
162
+ label: '답변하지 못한 질문',
163
+ color: 'var(--chakra-colors-danger-fg)',
164
+ },
165
+ ]}
166
+ />
167
+ ),
168
+ };
169
+
170
+ export const UsageTokens: Story = {
171
+ tags: ['!dev'],
172
+ parameters: { layout: 'padded' },
173
+ name: 'Usage / Tokens',
174
+ render: () => (
175
+ <TokenTable
176
+ rows={[
177
+ { token: 'primary.main', use: 'series 1' },
178
+ { token: 'border.default', use: 'grid lines, tooltip border' },
179
+ { token: 'fg.muted', use: 'axis labels' },
180
+ { token: 'bg.surface', use: 'tooltip background' },
181
+ { token: 'fg.default', use: 'tooltip text' },
182
+ ]}
183
+ />
184
+ ),
185
+ };
186
+
187
+ /**
188
+ * Default stroke for series 2 onwards, light and dark, computed with the same
189
+ * `seriesColor` the chart calls.
190
+ */
191
+ export const UsageSeriesOrder: Story = {
192
+ tags: ['!dev'],
193
+ parameters: { layout: 'padded' },
194
+ name: 'Usage / Series order',
195
+ render: () => (
196
+ <Grid templateColumns="auto auto auto" gap={2} fontSize="13px">
197
+ {CHART_SERIES_HUES.map(({ hue }, i) => (
198
+ <Fragment key={hue}>
199
+ <Box fontFamily="mono">
200
+ {i + 2}. {hue}
201
+ </Box>
202
+ {[false, true].map((dark) => {
203
+ const stroke = seriesColor(i + 1, dark);
204
+ return (
205
+ <Box
206
+ key={String(dark)}
207
+ style={{ background: stroke }}
208
+ w="88px"
209
+ h="20px"
210
+ borderRadius="sm"
211
+ title={`${hue} ${dark ? 'dark' : 'light'} ${stroke}`}
212
+ />
213
+ );
214
+ })}
215
+ </Fragment>
216
+ ))}
217
+ </Grid>
218
+ ),
219
+ };
@@ -21,10 +21,9 @@ export const LineGraph = <T extends DatumBase>({
21
21
  displayLegend = true,
22
22
  ...rest
23
23
  }: LineGraphProps<T>) => {
24
- const primaryColor = useToken('colors', 'primary.main')[0];
25
- // Series 1 is the neutral brand line; further series cycle hues with no
26
- // status meaning (see seriesColors.ts). Strokes read the generated palette
27
- // directly because no semantic role fits a chart line.
24
+ // Series 1 is the data blue; further series cycle hues with no status
25
+ // meaning (see seriesColors.ts). Strokes read the generated palette directly
26
+ // because no semantic role fits a chart line.
28
27
  const { colorMode } = useColorMode();
29
28
  const isDark = colorMode === 'dark';
30
29
  return (
@@ -100,7 +99,7 @@ export const LineGraph = <T extends DatumBase>({
100
99
  type="monotone"
101
100
  dataKey={key}
102
101
  name={label}
103
- stroke={color ?? seriesColor(index, primaryColor, isDark)}
102
+ stroke={color ?? seriesColor(index, isDark)}
104
103
  dot={{ r: 0 }}
105
104
  />
106
105
  ))}
@@ -2,8 +2,14 @@ import { BoxProps } from '@chakra-ui/react';
2
2
  import { type DataKey as RechartsDataKey } from 'recharts/types/util/types.d';
3
3
 
4
4
  export interface LineGraphProps<T extends DatumBase> extends BoxProps {
5
+ /** One object per point on the X axis; `name` is the axis label. */
5
6
  data: Array<Datum<T>>;
7
+ /** The series to draw, in order. */
6
8
  dataKeys: Array<DataKey<T>>;
9
+ /**
10
+ * Show the legend under the chart.
11
+ * @default true
12
+ */
7
13
  displayLegend?: boolean;
8
14
  }
9
15
 
@@ -31,12 +37,16 @@ export type DataKey<T extends DatumBase> = {
31
37
  key: RechartsDataKey<keyof T>;
32
38
 
33
39
  /**
34
- * Label for the XAxis
40
+ * Series name, shown in the legend and the tooltip.
35
41
  */
36
42
  label: string;
37
43
 
38
44
  /**
39
- * Optional custom colors for the series
45
+ * Stroke colour for this series, passed straight to the SVG (recharts does
46
+ * not resolve Chakra tokens — use a CSS variable such as
47
+ * `var(--chakra-colors-category-teal-fg)`). Defaults: series 1 is
48
+ * `primary.main`, the rest cycle meaning-free category hues
49
+ * (`CHART_SERIES_HUES`).
40
50
  */
41
51
  color?: string;
42
52
  };
@@ -0,0 +1,186 @@
1
+ import { ArgTypes, Canvas, Meta } from '@storybook/blocks';
2
+
3
+ import { En, Ko, LangToggle, Verdict } from '../../guidelines/_components/Lang';
4
+ import * as LineGraphStories from './LineGraph.stories';
5
+
6
+ <Meta of={LineGraphStories} name="Usage" />
7
+
8
+ <LangToggle />
9
+
10
+ <En>
11
+
12
+ # LineGraph
13
+
14
+ A line chart (recharts) for one or more numeric series over an ordered X
15
+ axis, usually time: daily questions, usage by model, feedback over a month.
16
+ It ships the house grid, axes, tooltip and series colours, in both modes.
17
+
18
+ ## When to use
19
+
20
+ - A trend over time or another ordered axis, where the shape matters more
21
+ than any single value.
22
+
23
+ ## When not to use
24
+
25
+ - Comparing categories with no order (models, groups) → a bar chart or a
26
+ `Table`.
27
+ - One number → a stat with `Text`. A share of a whole → a `ProgressBar` or a
28
+ table of percentages.
29
+ - When the reader needs exact values → a `Table`, with the chart as a
30
+ summary if at all.
31
+
32
+ ## Props
33
+
34
+ </En>
35
+
36
+ <Ko>
37
+
38
+ # LineGraph
39
+
40
+ 순서가 있는 X축(대개 시간) 위에 숫자 계열 하나 이상을 그리는 꺾은선 그래프(recharts)
41
+ 입니다. 일별 질문 수, 모델별 사용량, 한 달 동안의 피드백에 씁니다. 격자, 축, 툴팁,
42
+ 계열 색이 두 모드 모두에 맞춰져 있습니다.
43
+
44
+ ## 언제 쓰나요
45
+
46
+ - 값 하나하나보다 흐름의 모양이 중요한, 시간이나 순서가 있는 축 위의 추세.
47
+
48
+ ## 언제 쓰지 않나요
49
+
50
+ - 순서가 없는 항목(모델, 그룹) 비교에는 막대 그래프나 `Table`을 씁니다.
51
+ - 숫자 하나는 `Text`로 보여 줍니다. 전체 중 비율은 `ProgressBar`나 비율 표를 씁니다.
52
+ - 정확한 값이 필요하다면 `Table`을 쓰고, 그래프는 요약으로만 씁니다.
53
+
54
+ ## 속성
55
+
56
+ </Ko>
57
+
58
+ <ArgTypes of={LineGraphStories} include={['data', 'dataKeys', 'displayLegend']} />
59
+
60
+ <En>
61
+
62
+ **Series colours.** Series 1 is the data blue (`blue.base`), the same blue a
63
+ single-measure chart uses. Series 2 onwards cycle eight category hues that
64
+ carry no meaning, alternating cool and warm (teal, pink, indigo, purple,
65
+ brown, …). Red, yellow and green are left out, because they mean danger,
66
+ warning and success. Every default stroke clears 3:1 against the page in both modes.
67
+
68
+ ## Do / Don't
69
+
70
+ </En>
71
+
72
+ <Ko>
73
+
74
+ **계열 색.** 첫 계열은 데이터 파랑(`blue.base`)으로, 측정값이 하나인 차트와 같은 색입니다.
75
+ 둘째 계열부터는 뜻이 없는 category 색 여덟 가지를 차가운 색과 따뜻한 색이 번갈아 오도록
76
+ 돌아가며 씁니다(청록, 분홍, 남색, 보라, 갈색 …). 빨강, 노랑, 초록은 위험, 경고, 성공을
77
+ 뜻하므로 빠져 있습니다. 기본 선 색은 두 모드 모두에서 바탕과 3:1 이상입니다.
78
+
79
+ ## 이렇게 하세요 / 이렇게 하지 마세요
80
+
81
+ </Ko>
82
+
83
+ <Canvas of={LineGraphStories.DoDefaultSeriesColours} />
84
+ <Verdict
85
+ kind="do"
86
+ en="Keep the default series colours and name each series in words; the legend and the tooltip show the label."
87
+ ko="기본 계열 색을 그대로 쓰고 계열마다 이름을 붙입니다. 범례와 툴팁에 그 이름이 나옵니다."
88
+ />
89
+
90
+ <Canvas of={LineGraphStories.DontStatusColours} />
91
+ <Verdict
92
+ kind="dont"
93
+ en="Colour ordinary series with success and danger. Readers take the red line as an error even when the numbers are fine."
94
+ ko="일반 계열에 success와 danger 색을 쓰지 마세요. 숫자에 문제가 없어도 읽는 사람은 빨간 선을 오류로 받아들입니다."
95
+ />
96
+
97
+ <En>
98
+
99
+ ## Content
100
+
101
+ - Name series in words the reader uses (질문 수), not field names (`uv`).
102
+ - X labels short: 10/22, not 2026-10-22 00:00.
103
+ - Two or three series at most; split into several charts beyond that.
104
+
105
+ ## Accessibility
106
+
107
+ What LineGraph does for you:
108
+
109
+ - Axis labels, grid and tooltip read CSS variables, so they follow light and
110
+ dark mode. Default strokes clear 3:1 (WCAG 1.4.11).
111
+ - Series names appear as text in the legend and tooltip.
112
+
113
+ What you still have to do:
114
+
115
+ - **Give the chart a text alternative** (WCAG 1.1.1). The SVG has no name.
116
+ Put a heading and a one-sentence summary next to it (질문 수는 지난주보다
117
+ 12% 늘었습니다), and offer the numbers as a table when they matter.
118
+ - **Lines differ only by colour** (no markers, no dash patterns), so with
119
+ three or more series the legend alone can be hard to match (WCAG 1.4.1).
120
+ Keep series few, or label them at the line end.
121
+ - The tooltip appears on pointer hover only; keyboard users cannot reach
122
+ values (WCAG 2.1.1). Another reason to offer the table.
123
+
124
+ ## Tokens
125
+
126
+ The chart reads these roles as CSS variables. The default series strokes
127
+ come from the palette, in the order below.
128
+
129
+ </En>
130
+
131
+ <Ko>
132
+
133
+ ## 문구
134
+
135
+ - 계열 이름은 필드 이름(`uv`)이 아니라 읽는 사람이 쓰는 말(질문 수)로 씁니다.
136
+ - X축 라벨은 짧게 씁니다. '2026-10-22 00:00'이 아니라 '10/22'로 씁니다.
137
+ - 계열은 많아야 두세 개로 두고, 더 많으면 그래프를 나눕니다.
138
+
139
+ ## 접근성
140
+
141
+ LineGraph가 알아서 하는 일
142
+
143
+ - 축 라벨, 격자, 툴팁이 CSS 변수를 읽으므로 라이트·다크 모드를 따릅니다. 기본 선
144
+ 색은 3:1 이상입니다(WCAG 1.4.11).
145
+ - 계열 이름이 범례와 툴팁에 글자로 나옵니다.
146
+
147
+ 직접 챙겨야 하는 일
148
+
149
+ - **그래프에 글로 된 대체 내용을 붙입니다**(WCAG 1.1.1). SVG에는 이름이 없습니다.
150
+ 옆에 제목과 한 문장 요약('질문 수는 지난주보다 12% 늘었습니다')을 두고, 숫자가
151
+ 중요하면 표로도 보여 줍니다.
152
+ - **선은 색으로만 구분됩니다**(점 표시나 점선 없음). 계열이 셋 이상이면 범례만으로는
153
+ 짝을 맞추기 어렵습니다(WCAG 1.4.1). 계열 수를 줄이거나 선 끝에 이름을 붙입니다.
154
+ - 툴팁은 마우스를 올려야만 나타나서 키보드 사용자는 값을 볼 수 없습니다(WCAG
155
+ 2.1.1). 이 점에서도 표를 함께 주는 편이 좋습니다.
156
+
157
+ ## 토큰
158
+
159
+ 그래프는 아래 역할을 CSS 변수로 읽습니다. 기본 계열 선 색은 팔레트에서 아래 순서대로
160
+ 가져옵니다.
161
+
162
+ </Ko>
163
+
164
+ <Canvas of={LineGraphStories.UsageTokens} sourceState="none" />
165
+
166
+ <Canvas of={LineGraphStories.UsageSeriesOrder} sourceState="none" />
167
+
168
+ <En>
169
+
170
+ ## Related
171
+
172
+ - **Table**: exact values, and the accessible alternative to a chart.
173
+ - **ProgressBar** / **RadialProgress**: a single share or progress.
174
+ - **Setup/Theme/Using Semantic Tokens**: "Blue means data and links".
175
+
176
+ </En>
177
+
178
+ <Ko>
179
+
180
+ ## 관련 컴포넌트
181
+
182
+ - **Table**: 정확한 값, 그리고 그래프의 접근 가능한 대안.
183
+ - **ProgressBar** / **RadialProgress**: 비율이나 진행률 하나.
184
+ - **Setup/Theme/Using Semantic Tokens**: "Blue means data and links".
185
+
186
+ </Ko>
@@ -22,19 +22,20 @@ describe('chart series colours', () => {
22
22
  expect(CHART_SERIES_HUES.filter(({ hue }) => banned.has(hue))).toEqual([]);
23
23
  });
24
24
 
25
- it('series 1 is the primary line, series 2 is brown', () => {
26
- expect(seriesColor(0, '#252525', false)).toBe('#252525');
27
- expect(seriesColor(1, '#252525', false)).toBe(SYSTEM_HUES.brown.base);
25
+ it('series 1 is the data blue, series 2 is teal', () => {
26
+ expect(seriesColor(0, false)).toBe(SYSTEM_HUES.blue.base);
27
+ expect(seriesColor(0, true)).toBe(SYSTEM_HUES.blue.baseDark);
28
+ expect(seriesColor(1, false)).toBe(SYSTEM_HUES.teal.base);
28
29
  });
29
30
 
30
31
  it('every default stroke clears 3:1 against the page in both modes', () => {
31
- CHART_SERIES_HUES.forEach((_, i) => {
32
- expect(
33
- contrast(seriesColor(i + 1, '', false), '#FFFFFF')
34
- ).toBeGreaterThanOrEqual(3);
35
- expect(
36
- contrast(seriesColor(i + 1, '', true), '#1F1E1D')
37
- ).toBeGreaterThanOrEqual(3);
32
+ [undefined, ...CHART_SERIES_HUES].forEach((_, i) => {
33
+ expect(contrast(seriesColor(i, false), '#FFFFFF')).toBeGreaterThanOrEqual(
34
+ 3
35
+ );
36
+ expect(contrast(seriesColor(i, true), '#1F1E1D')).toBeGreaterThanOrEqual(
37
+ 3
38
+ );
38
39
  });
39
40
  });
40
41
  });