@ds-mo/ui 0.2.4 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (356) hide show
  1. package/dist/components/ds-accordion.d.ts +11 -0
  2. package/dist/components/ds-accordion.js +2 -0
  3. package/dist/components/ds-accordion.js.map +1 -0
  4. package/dist/components/ds-badge.d.ts +11 -0
  5. package/dist/components/ds-badge.js +2 -0
  6. package/dist/components/ds-badge.js.map +1 -0
  7. package/dist/components/ds-banner.d.ts +11 -0
  8. package/dist/components/ds-banner.js +2 -0
  9. package/dist/components/ds-banner.js.map +1 -0
  10. package/dist/components/ds-breadcrumb.d.ts +11 -0
  11. package/dist/components/ds-breadcrumb.js +2 -0
  12. package/dist/components/ds-breadcrumb.js.map +1 -0
  13. package/dist/components/ds-button.d.ts +11 -0
  14. package/dist/components/ds-button.js +2 -0
  15. package/dist/components/ds-button.js.map +1 -0
  16. package/dist/components/ds-card.d.ts +11 -0
  17. package/dist/components/ds-card.js +2 -0
  18. package/dist/components/ds-card.js.map +1 -0
  19. package/dist/components/ds-checkbox.d.ts +11 -0
  20. package/dist/components/ds-checkbox.js +2 -0
  21. package/dist/components/ds-checkbox.js.map +1 -0
  22. package/dist/components/ds-divider.d.ts +11 -0
  23. package/dist/components/ds-divider.js +2 -0
  24. package/dist/components/ds-divider.js.map +1 -0
  25. package/dist/components/ds-empty-state.d.ts +11 -0
  26. package/dist/components/ds-empty-state.js +2 -0
  27. package/dist/components/ds-empty-state.js.map +1 -0
  28. package/dist/components/ds-fade.d.ts +11 -0
  29. package/dist/components/ds-fade.js +2 -0
  30. package/dist/components/ds-fade.js.map +1 -0
  31. package/dist/components/ds-field.d.ts +11 -0
  32. package/dist/components/ds-field.js +2 -0
  33. package/dist/components/ds-field.js.map +1 -0
  34. package/dist/components/ds-header.d.ts +11 -0
  35. package/dist/components/ds-header.js +2 -0
  36. package/dist/components/ds-header.js.map +1 -0
  37. package/dist/components/ds-input.d.ts +11 -0
  38. package/dist/components/ds-input.js +2 -0
  39. package/dist/components/ds-input.js.map +1 -0
  40. package/dist/components/ds-loader.d.ts +11 -0
  41. package/dist/components/ds-loader.js +2 -0
  42. package/dist/components/ds-loader.js.map +1 -0
  43. package/dist/components/ds-menu.d.ts +11 -0
  44. package/dist/components/ds-menu.js +2 -0
  45. package/dist/components/ds-menu.js.map +1 -0
  46. package/dist/components/ds-modal.d.ts +11 -0
  47. package/dist/components/ds-modal.js +2 -0
  48. package/dist/components/ds-modal.js.map +1 -0
  49. package/dist/components/ds-pagination.d.ts +11 -0
  50. package/dist/components/ds-pagination.js +2 -0
  51. package/dist/components/ds-pagination.js.map +1 -0
  52. package/dist/components/ds-radio-group.d.ts +11 -0
  53. package/dist/components/ds-radio-group.js +2 -0
  54. package/dist/components/ds-radio-group.js.map +1 -0
  55. package/dist/components/ds-scrollbar.d.ts +11 -0
  56. package/dist/components/ds-scrollbar.js +2 -0
  57. package/dist/components/ds-scrollbar.js.map +1 -0
  58. package/dist/components/ds-sidebar.d.ts +11 -0
  59. package/dist/components/ds-sidebar.js +2 -0
  60. package/dist/components/ds-sidebar.js.map +1 -0
  61. package/dist/components/ds-skeleton.d.ts +11 -0
  62. package/dist/components/ds-skeleton.js +2 -0
  63. package/dist/components/ds-skeleton.js.map +1 -0
  64. package/dist/components/ds-slider.d.ts +11 -0
  65. package/dist/components/ds-slider.js +2 -0
  66. package/dist/components/ds-slider.js.map +1 -0
  67. package/dist/components/ds-surface.d.ts +11 -0
  68. package/dist/components/ds-surface.js +2 -0
  69. package/dist/components/ds-surface.js.map +1 -0
  70. package/dist/components/ds-tab-group.d.ts +11 -0
  71. package/dist/components/ds-tab-group.js +2 -0
  72. package/dist/components/ds-tab-group.js.map +1 -0
  73. package/dist/components/ds-table.d.ts +11 -0
  74. package/dist/components/ds-table.js +2 -0
  75. package/dist/components/ds-table.js.map +1 -0
  76. package/dist/components/ds-tag.d.ts +11 -0
  77. package/dist/components/ds-tag.js +2 -0
  78. package/dist/components/ds-tag.js.map +1 -0
  79. package/dist/components/ds-text.d.ts +11 -0
  80. package/dist/components/ds-text.js +2 -0
  81. package/dist/components/ds-text.js.map +1 -0
  82. package/dist/components/ds-toast-provider.d.ts +11 -0
  83. package/dist/components/ds-toast-provider.js +2 -0
  84. package/dist/components/ds-toast-provider.js.map +1 -0
  85. package/dist/components/ds-toggle.d.ts +11 -0
  86. package/dist/components/ds-toggle.js +2 -0
  87. package/dist/components/ds-toggle.js.map +1 -0
  88. package/dist/components/ds-tooltip.d.ts +11 -0
  89. package/dist/components/ds-tooltip.js +2 -0
  90. package/dist/components/ds-tooltip.js.map +1 -0
  91. package/dist/components/index.d.ts +33 -0
  92. package/dist/components/index.js +2 -0
  93. package/dist/components/index.js.map +1 -0
  94. package/dist/components/p-BcuUR5Ao.js +2 -0
  95. package/dist/components/p-BcuUR5Ao.js.map +1 -0
  96. package/dist/types/.stencil/Accordion/Accordion.d.ts +28 -0
  97. package/dist/types/.stencil/Badge/Badge.d.ts +8 -0
  98. package/dist/types/.stencil/Badge/index.d.ts +2 -0
  99. package/dist/types/.stencil/Banner/Banner.d.ts +29 -0
  100. package/dist/types/.stencil/Breadcrumb/Breadcrumb.d.ts +16 -0
  101. package/dist/types/.stencil/Button/Button.d.ts +38 -0
  102. package/dist/types/.stencil/Button/index.d.ts +2 -0
  103. package/dist/types/.stencil/Card/Card.d.ts +8 -0
  104. package/dist/types/.stencil/Checkbox/Checkbox.d.ts +13 -0
  105. package/dist/types/.stencil/Checkbox/index.d.ts +2 -0
  106. package/dist/types/.stencil/Divider/Divider.d.ts +7 -0
  107. package/dist/types/.stencil/Divider/index.d.ts +2 -0
  108. package/dist/types/.stencil/EmptyState/EmptyState.d.ts +7 -0
  109. package/dist/types/.stencil/Fade/Fade.d.ts +10 -0
  110. package/dist/types/.stencil/Fade/index.d.ts +2 -0
  111. package/dist/types/.stencil/Field/Field.d.ts +8 -0
  112. package/dist/types/.stencil/Header/Header.d.ts +7 -0
  113. package/dist/types/.stencil/Input/Input.d.ts +26 -0
  114. package/dist/types/.stencil/Input/index.d.ts +2 -0
  115. package/dist/types/.stencil/Loader/Loader.d.ts +12 -0
  116. package/dist/types/.stencil/Loader/index.d.ts +2 -0
  117. package/dist/types/.stencil/Menu/Menu.d.ts +60 -0
  118. package/dist/types/.stencil/Modal/Modal.d.ts +31 -0
  119. package/dist/types/.stencil/Pagination/Pagination.d.ts +11 -0
  120. package/dist/types/.stencil/RadioGroup/RadioGroup.d.ts +21 -0
  121. package/dist/types/.stencil/RadioGroup/index.d.ts +2 -0
  122. package/dist/types/.stencil/Scrollbar/Scrollbar.d.ts +27 -0
  123. package/dist/types/.stencil/Sidebar/Sidebar.d.ts +29 -0
  124. package/dist/types/.stencil/Skeleton/Skeleton.d.ts +16 -0
  125. package/dist/types/.stencil/Skeleton/index.d.ts +2 -0
  126. package/dist/types/.stencil/Slider/Slider.d.ts +18 -0
  127. package/dist/types/.stencil/Slider/index.d.ts +2 -0
  128. package/dist/types/.stencil/Surface/Surface.d.ts +22 -0
  129. package/dist/types/.stencil/TabGroup/TabGroup.d.ts +29 -0
  130. package/dist/types/.stencil/Table/Table.d.ts +50 -0
  131. package/dist/types/.stencil/Tag/Tag.d.ts +32 -0
  132. package/dist/types/.stencil/Tag/index.d.ts +2 -0
  133. package/dist/types/.stencil/Text/Text.d.ts +22 -0
  134. package/dist/types/.stencil/Text/index.d.ts +2 -0
  135. package/dist/types/.stencil/Toast/Toast.d.ts +15 -0
  136. package/dist/types/.stencil/Toast/toast-service.d.ts +24 -0
  137. package/dist/types/.stencil/Toggle/Toggle.d.ts +10 -0
  138. package/dist/types/.stencil/Toggle/index.d.ts +2 -0
  139. package/dist/types/.stencil/Tooltip/Tooltip.d.ts +36 -0
  140. package/dist/types/components.d.ts +2024 -0
  141. package/dist/types/stencil-public-runtime.d.ts +1860 -0
  142. package/package.json +33 -29
  143. package/src/angular/angular-component-lib/utils.ts +65 -0
  144. package/src/angular/index.ts +35 -0
  145. package/src/angular/proxies.ts +819 -0
  146. package/dist/index.css +0 -2
  147. package/dist/index.d.ts +0 -969
  148. package/dist/index.js +0 -2492
  149. package/dist/index.js.map +0 -1
  150. package/dist/r/accordion.json +0 -79
  151. package/dist/r/badge.json +0 -69
  152. package/dist/r/banner.json +0 -90
  153. package/dist/r/breadcrumb.json +0 -70
  154. package/dist/r/button-group.json +0 -65
  155. package/dist/r/button.json +0 -137
  156. package/dist/r/card.json +0 -82
  157. package/dist/r/checkbox.json +0 -91
  158. package/dist/r/divider.json +0 -57
  159. package/dist/r/empty-state.json +0 -69
  160. package/dist/r/error-boundary.json +0 -66
  161. package/dist/r/fade.json +0 -65
  162. package/dist/r/field.json +0 -71
  163. package/dist/r/header.json +0 -67
  164. package/dist/r/input.json +0 -77
  165. package/dist/r/loader.json +0 -54
  166. package/dist/r/menu.json +0 -130
  167. package/dist/r/modal.json +0 -93
  168. package/dist/r/pagination.json +0 -80
  169. package/dist/r/radio.json +0 -85
  170. package/dist/r/registry.json +0 -1600
  171. package/dist/r/scrollbar.json +0 -68
  172. package/dist/r/select.json +0 -93
  173. package/dist/r/sidebar.json +0 -105
  174. package/dist/r/skeleton.json +0 -72
  175. package/dist/r/slider.json +0 -87
  176. package/dist/r/surface.json +0 -97
  177. package/dist/r/tab-group.json +0 -72
  178. package/dist/r/tab.json +0 -71
  179. package/dist/r/table.json +0 -110
  180. package/dist/r/tag.json +0 -110
  181. package/dist/r/text.json +0 -94
  182. package/dist/r/toast.json +0 -77
  183. package/dist/r/toggle-button-group.json +0 -65
  184. package/dist/r/toggle-button.json +0 -94
  185. package/dist/r/toggle.json +0 -65
  186. package/dist/r/tooltip.json +0 -86
  187. package/src/components/Accordion/Accordion.module.css +0 -66
  188. package/src/components/Accordion/Accordion.stories.tsx +0 -95
  189. package/src/components/Accordion/Accordion.tsx +0 -122
  190. package/src/components/Accordion/index.ts +0 -2
  191. package/src/components/Badge/Badge.module.css +0 -6
  192. package/src/components/Badge/Badge.stories.tsx +0 -99
  193. package/src/components/Badge/Badge.tsx +0 -23
  194. package/src/components/Badge/index.ts +0 -2
  195. package/src/components/Banner/Banner.module.css +0 -67
  196. package/src/components/Banner/Banner.stories.tsx +0 -81
  197. package/src/components/Banner/Banner.tsx +0 -109
  198. package/src/components/Banner/index.ts +0 -2
  199. package/src/components/Breadcrumb/Breadcrumb.module.css +0 -46
  200. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +0 -72
  201. package/src/components/Breadcrumb/Breadcrumb.tsx +0 -68
  202. package/src/components/Breadcrumb/index.ts +0 -2
  203. package/src/components/Button/Button.mdx +0 -143
  204. package/src/components/Button/Button.module.css +0 -343
  205. package/src/components/Button/Button.stories.tsx +0 -575
  206. package/src/components/Button/Button.tsx +0 -201
  207. package/src/components/Button/index.ts +0 -10
  208. package/src/components/ButtonGroup/ButtonGroup.module.css +0 -157
  209. package/src/components/ButtonGroup/ButtonGroup.stories.tsx +0 -384
  210. package/src/components/ButtonGroup/ButtonGroup.tsx +0 -122
  211. package/src/components/ButtonGroup/index.ts +0 -2
  212. package/src/components/Card/Card.module.css +0 -36
  213. package/src/components/Card/Card.stories.tsx +0 -78
  214. package/src/components/Card/Card.tsx +0 -53
  215. package/src/components/Card/index.ts +0 -2
  216. package/src/components/Checkbox/Checkbox.module.css +0 -47
  217. package/src/components/Checkbox/Checkbox.stories.tsx +0 -129
  218. package/src/components/Checkbox/Checkbox.tsx +0 -68
  219. package/src/components/Checkbox/index.ts +0 -2
  220. package/src/components/Divider/Divider.module.css +0 -19
  221. package/src/components/Divider/Divider.stories.tsx +0 -55
  222. package/src/components/Divider/Divider.tsx +0 -28
  223. package/src/components/Divider/index.ts +0 -2
  224. package/src/components/EmptyState/EmptyState.module.css +0 -8
  225. package/src/components/EmptyState/EmptyState.stories.tsx +0 -53
  226. package/src/components/EmptyState/EmptyState.tsx +0 -31
  227. package/src/components/EmptyState/index.ts +0 -2
  228. package/src/components/ErrorBoundary/ErrorBoundary.module.css +0 -18
  229. package/src/components/ErrorBoundary/ErrorBoundary.stories.tsx +0 -38
  230. package/src/components/ErrorBoundary/ErrorBoundary.tsx +0 -50
  231. package/src/components/ErrorBoundary/index.ts +0 -2
  232. package/src/components/Fade/Fade.module.css +0 -31
  233. package/src/components/Fade/Fade.stories.tsx +0 -35
  234. package/src/components/Fade/Fade.tsx +0 -33
  235. package/src/components/Fade/index.ts +0 -2
  236. package/src/components/Field/Field.module.css +0 -5
  237. package/src/components/Field/Field.stories.tsx +0 -111
  238. package/src/components/Field/Field.tsx +0 -22
  239. package/src/components/Field/index.ts +0 -2
  240. package/src/components/Header/Header.module.css +0 -33
  241. package/src/components/Header/Header.stories.tsx +0 -52
  242. package/src/components/Header/Header.tsx +0 -42
  243. package/src/components/Header/index.ts +0 -2
  244. package/src/components/Input/Input.module.css +0 -71
  245. package/src/components/Input/Input.stories.tsx +0 -135
  246. package/src/components/Input/Input.tsx +0 -76
  247. package/src/components/Input/index.ts +0 -2
  248. package/src/components/LabelWrap/LabelWrap.module.css +0 -34
  249. package/src/components/LabelWrap/LabelWrap.tsx +0 -32
  250. package/src/components/LabelWrap/index.ts +0 -1
  251. package/src/components/Loader/Loader.module.css +0 -9
  252. package/src/components/Loader/Loader.stories.tsx +0 -44
  253. package/src/components/Loader/Loader.tsx +0 -43
  254. package/src/components/Loader/index.ts +0 -2
  255. package/src/components/Menu/DestructiveMenuItem.module.css +0 -57
  256. package/src/components/Menu/DestructiveMenuItem.tsx +0 -64
  257. package/src/components/Menu/Menu.module.css +0 -49
  258. package/src/components/Menu/Menu.stories.tsx +0 -129
  259. package/src/components/Menu/Menu.tsx +0 -269
  260. package/src/components/Menu/MenuItem.module.css +0 -84
  261. package/src/components/Menu/MenuItem.tsx +0 -101
  262. package/src/components/Menu/index.ts +0 -6
  263. package/src/components/Modal/Modal.module.css +0 -67
  264. package/src/components/Modal/Modal.stories.tsx +0 -71
  265. package/src/components/Modal/Modal.tsx +0 -122
  266. package/src/components/Modal/index.ts +0 -2
  267. package/src/components/Pagination/Pagination.module.css +0 -64
  268. package/src/components/Pagination/Pagination.stories.tsx +0 -51
  269. package/src/components/Pagination/Pagination.tsx +0 -103
  270. package/src/components/Pagination/index.ts +0 -2
  271. package/src/components/Radio/Radio.module.css +0 -61
  272. package/src/components/Radio/Radio.stories.tsx +0 -101
  273. package/src/components/Radio/Radio.tsx +0 -108
  274. package/src/components/Radio/index.ts +0 -2
  275. package/src/components/Scrollbar/Scrollbar.module.css +0 -81
  276. package/src/components/Scrollbar/Scrollbar.stories.tsx +0 -46
  277. package/src/components/Scrollbar/Scrollbar.tsx +0 -187
  278. package/src/components/Scrollbar/index.ts +0 -2
  279. package/src/components/Select/Select.module.css +0 -31
  280. package/src/components/Select/Select.stories.tsx +0 -59
  281. package/src/components/Select/Select.tsx +0 -92
  282. package/src/components/Select/index.ts +0 -2
  283. package/src/components/Sidebar/Sidebar.module.css +0 -161
  284. package/src/components/Sidebar/Sidebar.stories.tsx +0 -125
  285. package/src/components/Sidebar/Sidebar.tsx +0 -129
  286. package/src/components/Sidebar/SidebarItem.tsx +0 -57
  287. package/src/components/Sidebar/SidebarSection.tsx +0 -42
  288. package/src/components/Sidebar/index.ts +0 -6
  289. package/src/components/Skeleton/Skeleton.module.css +0 -53
  290. package/src/components/Skeleton/Skeleton.stories.tsx +0 -89
  291. package/src/components/Skeleton/Skeleton.tsx +0 -66
  292. package/src/components/Skeleton/index.ts +0 -2
  293. package/src/components/Slider/Slider.module.css +0 -62
  294. package/src/components/Slider/Slider.stories.tsx +0 -120
  295. package/src/components/Slider/Slider.tsx +0 -74
  296. package/src/components/Slider/index.ts +0 -2
  297. package/src/components/Surface/Surface.module.css +0 -222
  298. package/src/components/Surface/Surface.stories.tsx +0 -213
  299. package/src/components/Surface/Surface.tsx +0 -219
  300. package/src/components/Surface/index.ts +0 -12
  301. package/src/components/Tab/Tab.module.css +0 -66
  302. package/src/components/Tab/Tab.stories.tsx +0 -103
  303. package/src/components/Tab/Tab.tsx +0 -41
  304. package/src/components/Tab/index.ts +0 -2
  305. package/src/components/TabGroup/TabGroup.module.css +0 -26
  306. package/src/components/TabGroup/TabGroup.stories.tsx +0 -60
  307. package/src/components/TabGroup/TabGroup.tsx +0 -83
  308. package/src/components/TabGroup/index.ts +0 -2
  309. package/src/components/Table/Table.module.css +0 -130
  310. package/src/components/Table/Table.stories.tsx +0 -111
  311. package/src/components/Table/Table.tsx +0 -226
  312. package/src/components/Table/index.ts +0 -11
  313. package/src/components/Tag/Tag.module.css +0 -270
  314. package/src/components/Tag/Tag.stories.tsx +0 -399
  315. package/src/components/Tag/Tag.tsx +0 -162
  316. package/src/components/Tag/index.ts +0 -2
  317. package/src/components/Text/Text.module.css +0 -166
  318. package/src/components/Text/Text.stories.tsx +0 -212
  319. package/src/components/Text/Text.tsx +0 -181
  320. package/src/components/Text/index.ts +0 -13
  321. package/src/components/Toast/Toast.module.css +0 -91
  322. package/src/components/Toast/Toast.stories.tsx +0 -66
  323. package/src/components/Toast/Toast.tsx +0 -182
  324. package/src/components/Toast/index.ts +0 -8
  325. package/src/components/Toggle/Toggle.module.css +0 -87
  326. package/src/components/Toggle/Toggle.stories.tsx +0 -85
  327. package/src/components/Toggle/Toggle.tsx +0 -52
  328. package/src/components/Toggle/index.ts +0 -2
  329. package/src/components/ToggleButton/ToggleButton.module.css +0 -172
  330. package/src/components/ToggleButton/ToggleButton.stories.tsx +0 -299
  331. package/src/components/ToggleButton/ToggleButton.tsx +0 -118
  332. package/src/components/ToggleButton/index.ts +0 -2
  333. package/src/components/ToggleButtonGroup/ToggleButtonGroup.module.css +0 -163
  334. package/src/components/ToggleButtonGroup/ToggleButtonGroup.stories.tsx +0 -341
  335. package/src/components/ToggleButtonGroup/ToggleButtonGroup.tsx +0 -111
  336. package/src/components/ToggleButtonGroup/index.ts +0 -2
  337. package/src/components/Tooltip/Tooltip.module.css +0 -45
  338. package/src/components/Tooltip/Tooltip.stories.tsx +0 -46
  339. package/src/components/Tooltip/Tooltip.tsx +0 -224
  340. package/src/components/Tooltip/index.ts +0 -2
  341. package/src/css-modules.d.ts +0 -4
  342. package/src/docs/ColorUsage.mdx +0 -195
  343. package/src/docs/ElevationUsage.mdx +0 -95
  344. package/src/docs/Introduction.mdx +0 -97
  345. package/src/docs/OpticalSizing.mdx +0 -178
  346. package/src/docs/TypographyUsage.mdx +0 -121
  347. package/src/index.ts +0 -154
  348. package/src/stories/Colors.stories.tsx +0 -528
  349. package/src/stories/Dimensions.stories.tsx +0 -200
  350. package/src/stories/Effects.stories.tsx +0 -231
  351. package/src/stories/Icons.stories.tsx +0 -159
  352. package/src/stories/Typography.stories.tsx +0 -157
  353. package/src/types/icons.ts +0 -15
  354. package/src/types/index.ts +0 -1
  355. package/src/utils/cn.ts +0 -6
  356. package/src/utils/css-tokens.ts +0 -22
@@ -1,111 +0,0 @@
1
- import React from 'react';
2
- import { cn } from '@/utils/cn';
3
- import styles from './ToggleButtonGroup.module.css';
4
-
5
- export interface ToggleButtonGroupProps {
6
- children: React.ReactNode;
7
- className?: string;
8
- }
9
-
10
- /**
11
- * Renders ToggleButton children flush side-by-side with a 1px divider between them.
12
- * Outer corners keep the button's own border-radius; inner corners are flattened.
13
- *
14
- * Individual button chrome (shadow/border) is suppressed — the group container
15
- * carries the elevation so it wraps the whole control as one visual unit.
16
- *
17
- * Divider behaviour by elevation:
18
- * elevated / flat / floating — full-height color-border-tertiary line
19
- * none (ghost) — short centred line (icon/text height)
20
- *
21
- * Rounded groups: outer edges keep pill padding; inner edges revert to base padding.
22
- * Pressed state and onPressedChange are managed by the consumer on each ToggleButton.
23
- */
24
- export const ToggleButtonGroup = ({ children, className }: ToggleButtonGroupProps) => {
25
- const items = React.Children.toArray(children).filter(React.isValidElement);
26
- const count = items.length;
27
-
28
- // Read elevation + rounded from first child to drive the group container style.
29
- const firstEl = items[0] as React.ReactElement<Record<string, unknown>> | undefined;
30
- const firstProps = firstEl?.props as { elevation?: string; rounded?: boolean } | undefined;
31
- const groupElevation = firstProps?.elevation ?? 'elevated';
32
- const groupRounded = !!firstProps?.rounded;
33
- const groupElevKey = groupElevation.charAt(0).toUpperCase() + groupElevation.slice(1);
34
-
35
- return (
36
- <div
37
- className={cn(
38
- styles.group,
39
- (styles as Record<string, string>)[`group${groupElevKey}`],
40
- groupRounded && styles.groupRounded,
41
- className,
42
- )}
43
- role="group"
44
- >
45
- {items.map((child, i) => {
46
- const el = child as React.ReactElement<Record<string, unknown>>;
47
- const p = el.props as {
48
- className?: string;
49
- elevation?: string;
50
- size?: string;
51
- rounded?: boolean;
52
- pressed?: boolean;
53
- icon?: unknown;
54
- label?: unknown;
55
- };
56
-
57
- const isFirst = i === 0;
58
- const isLast = i === count - 1;
59
- const isMid = !isFirst && !isLast;
60
-
61
- const size = (p.size ?? 'md') as 'xs' | 'sm' | 'md';
62
- const isRounded = !!p.rounded;
63
- const isPressed = !!p.pressed;
64
- const isIconOnly = !!p.icon && !p.label;
65
- // Ghost: elevation='none' (no chrome) → short centred divider
66
- const isGhost = (p.elevation ?? 'elevated') === 'none';
67
-
68
- // XS rounded has no extra padding in ToggleButton so needs no correction
69
- const sizeKey = size.toUpperCase() as 'XS' | 'SM' | 'MD';
70
- const needsRoundedCorrection = isRounded && !isIconOnly && size !== 'xs';
71
-
72
- // Divider injected as a separate element so it's never affected by
73
- // the adjacent button's opacity (e.g. disabled state).
74
- const dividerClasses = cn(
75
- styles.divider,
76
- isGhost && styles.dividerGhost,
77
- isGhost && size === 'xs' && styles.dividerGhostXS,
78
- isGhost && size === 'sm' && styles.dividerGhostSM,
79
- );
80
-
81
- return (
82
- <React.Fragment key={i}>
83
- {i > 0 && <div className={dividerClasses} aria-hidden="true" />}
84
- {React.cloneElement(el, {
85
- className: cn(
86
- p.className,
87
- styles.item,
88
- isFirst && styles.first,
89
- isLast && styles.last,
90
- isMid && styles.middle,
91
-
92
- // Ghost variant: ::after overlay gets 4px radius treatment
93
- isGhost && styles.itemShort,
94
-
95
- // Ghost + pressed: selected state background chip
96
- isGhost && isPressed && styles.itemPressed,
97
-
98
- // Rounded: revert inner-edge padding to base (non-pill) value
99
- needsRoundedCorrection && isFirst && (styles as Record<string, string>)[`roundedFirst${sizeKey}`],
100
- needsRoundedCorrection && isLast && (styles as Record<string, string>)[`roundedLast${sizeKey}`],
101
- needsRoundedCorrection && isMid && (styles as Record<string, string>)[`roundedMid${sizeKey}`],
102
- ),
103
- })}
104
- </React.Fragment>
105
- );
106
- })}
107
- </div>
108
- );
109
- };
110
-
111
- ToggleButtonGroup.displayName = 'ToggleButtonGroup';
@@ -1,2 +0,0 @@
1
- export { ToggleButtonGroup } from './ToggleButtonGroup';
2
- export type { ToggleButtonGroupProps } from './ToggleButtonGroup';
@@ -1,45 +0,0 @@
1
- .tooltip {
2
- box-sizing: border-box;
3
- background-color: var(--color-background-primary);
4
- border-radius: var(--dimension-radius-075);
5
- box-shadow: var(--effect-elevation-elevated-floating);
6
- padding: var(--dimension-space-050);
7
- line-height: var(--typography-lineheight-sm);
8
- pointer-events: none;
9
- backface-visibility: hidden;
10
- -webkit-font-smoothing: subpixel-antialiased;
11
- animation: tooltipFadeIn var(--effect-motion-short-2) forwards;
12
- }
13
-
14
- .tooltipInner {
15
- display: flex;
16
- flex-direction: row;
17
- align-items: center;
18
- gap: var(--dimension-space-050);
19
- }
20
-
21
- .keyHint {
22
- width: var(--dimension-size-200);
23
- height: var(--dimension-size-200);
24
- flex-shrink: 0;
25
- display: flex;
26
- align-items: center;
27
- justify-content: center;
28
- border: var(--dimension-stroke-width-015) solid var(--color-foreground-tertiary);
29
- border-bottom-width: var(--dimension-stroke-width-025);
30
- border-radius: var(--dimension-radius-025);
31
- }
32
-
33
- .tooltip.closing {
34
- animation: tooltipFadeOut var(--effect-motion-short-3) forwards;
35
- }
36
-
37
- @keyframes tooltipFadeIn {
38
- from { opacity: 0; }
39
- to { opacity: 1; }
40
- }
41
-
42
- @keyframes tooltipFadeOut {
43
- from { opacity: 1; }
44
- to { opacity: 0; }
45
- }
@@ -1,46 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite';
2
- import { Tooltip } from './Tooltip';
3
- import { Button } from '../Button';
4
-
5
- const meta: Meta<typeof Tooltip> = {
6
- title: 'Components/Tooltip',
7
- component: Tooltip,
8
- };
9
-
10
- export default meta;
11
- type Story = StoryObj<typeof Tooltip>;
12
-
13
- export const Default: Story = {
14
- render: () => (
15
- <div style={{ padding: 80, display: 'flex', justifyContent: 'center' }}>
16
- <Tooltip label="This is a tooltip">
17
- <Button variant="secondary" label="Hover me" />
18
- </Tooltip>
19
- </div>
20
- ),
21
- };
22
-
23
- export const Positions: Story = {
24
- render: () => (
25
- <div style={{ padding: 100, display: 'flex', gap: 24, justifyContent: 'center' }}>
26
- {(['top', 'right', 'bottom', 'left'] as const).map(side => (
27
- <Tooltip key={side} label={`Tooltip on ${side}`} side={side}>
28
- <Button variant="secondary" label={side} />
29
- </Tooltip>
30
- ))}
31
- </div>
32
- ),
33
- };
34
-
35
- export const WithShortcut: Story = {
36
- render: () => (
37
- <div style={{ padding: 80, display: 'flex', gap: 24, justifyContent: 'center' }}>
38
- <Tooltip label="Save" shortcutKey="S">
39
- <Button variant="secondary" label="Save" />
40
- </Tooltip>
41
- <Tooltip label="Undo" shortcutKey="Z" shortcutKeyPosition="start">
42
- <Button variant="secondary" label="Undo" />
43
- </Tooltip>
44
- </div>
45
- ),
46
- };
@@ -1,224 +0,0 @@
1
- import React, { useState, useRef, useEffect, useLayoutEffect, useCallback } from 'react';
2
- import { createPortal } from 'react-dom';
3
- import { getCssTimeMs } from '@/utils/css-tokens';
4
- import { Text } from '@/components/Text';
5
- import styles from './Tooltip.module.css';
6
-
7
- const HOVER_DELAY_FALLBACK_MS = 1000;
8
- const INSTANT_REOPEN_MS = 300;
9
- const FADE_OUT_DURATION_MS = 200;
10
-
11
- let lastTooltipDismissedAt = 0;
12
-
13
- export type TooltipSide = 'top' | 'right' | 'bottom' | 'left';
14
- export type TooltipAlign = 'start' | 'center' | 'end';
15
-
16
- export interface TooltipProps {
17
- label: string;
18
- children: React.ReactElement;
19
- delay?: number;
20
- side?: TooltipSide;
21
- align?: TooltipAlign;
22
- sideOffset?: number;
23
- alignOffset?: number;
24
- shortcutKey?: string;
25
- shortcutKeyPosition?: 'start' | 'end';
26
- usePortal?: boolean;
27
- }
28
-
29
- export const Tooltip: React.FC<TooltipProps> = ({
30
- label,
31
- children,
32
- delay,
33
- side = 'top',
34
- align = 'center',
35
- sideOffset = 4,
36
- alignOffset = 0,
37
- shortcutKey,
38
- shortcutKeyPosition = 'end',
39
- usePortal = true,
40
- }) => {
41
- const hoverDelayMs = getCssTimeMs('--effect-animation-delay-medium-3', HOVER_DELAY_FALLBACK_MS);
42
- const resolvedDelay = delay ?? hoverDelayMs;
43
- const anchorRef = useRef<HTMLElement | null>(null);
44
- const tooltipRef = useRef<HTMLDivElement>(null);
45
-
46
- const setAnchorRef = useCallback(
47
- (el: HTMLElement | null) => {
48
- (anchorRef as React.MutableRefObject<HTMLElement | null>).current = el;
49
- const childEl = React.Children.only(children) as React.ReactElement<{ ref?: React.Ref<unknown> }>;
50
- const childRef = 'ref' in childEl ? childEl.ref : undefined;
51
- if (typeof childRef === 'function') childRef(el);
52
- else if (childRef && typeof childRef === 'object') (childRef as React.MutableRefObject<unknown>).current = el;
53
- },
54
- [children]
55
- );
56
-
57
- const [open, setOpen] = useState(false);
58
- const [isClosing, setIsClosing] = useState(false);
59
- const [shouldRender, setShouldRender] = useState(false);
60
- const [position, setPosition] = useState<{ x: number; y: number }>({ x: 0, y: 0 });
61
- const [tooltipSize, setTooltipSize] = useState<{ width: number; height: number }>({ width: 0, height: 0 });
62
- const delayTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
63
- const closeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
64
- const viewportPadding = 4;
65
-
66
- const clearDelayTimer = () => {
67
- if (delayTimerRef.current) { clearTimeout(delayTimerRef.current); delayTimerRef.current = null; }
68
- };
69
-
70
- const handleOpen = () => {
71
- clearDelayTimer();
72
- const showImmediately = Date.now() - lastTooltipDismissedAt < INSTANT_REOPEN_MS;
73
- if (showImmediately) {
74
- setOpen(true); setShouldRender(true); setIsClosing(false); return;
75
- }
76
- delayTimerRef.current = setTimeout(() => {
77
- delayTimerRef.current = null;
78
- setOpen(true); setShouldRender(true); setIsClosing(false);
79
- }, resolvedDelay);
80
- };
81
-
82
- const handleClose = () => {
83
- clearDelayTimer();
84
- if (closeTimerRef.current) { clearTimeout(closeTimerRef.current); closeTimerRef.current = null; }
85
- if (!open && !shouldRender) return;
86
- lastTooltipDismissedAt = Date.now();
87
- setIsClosing(true);
88
- closeTimerRef.current = setTimeout(() => {
89
- closeTimerRef.current = null;
90
- setShouldRender(false); setOpen(false); setIsClosing(false);
91
- }, FADE_OUT_DURATION_MS);
92
- };
93
-
94
- useEffect(() => () => { clearDelayTimer(); if (closeTimerRef.current) clearTimeout(closeTimerRef.current); }, []);
95
-
96
- useLayoutEffect(() => {
97
- if (!shouldRender || !tooltipRef.current) return;
98
- const updateSize = () => {
99
- if (!tooltipRef.current) return;
100
- const rect = tooltipRef.current.getBoundingClientRect();
101
- const w = rect.width || tooltipRef.current.offsetWidth;
102
- const h = rect.height || tooltipRef.current.offsetHeight;
103
- if (w > 0 && h > 0) setTooltipSize({ width: w, height: h });
104
- };
105
- updateSize();
106
- requestAnimationFrame(updateSize);
107
- if (typeof ResizeObserver !== 'undefined') {
108
- const observer = new ResizeObserver(updateSize);
109
- observer.observe(tooltipRef.current);
110
- return () => observer.disconnect();
111
- }
112
- }, [shouldRender, label, shortcutKey, shortcutKeyPosition]);
113
-
114
- useLayoutEffect(() => {
115
- if (!shouldRender || !anchorRef.current || !tooltipRef.current) return;
116
- const calculatePosition = () => {
117
- if (!anchorRef.current || !tooltipRef.current) return;
118
- const a = anchorRef.current.getBoundingClientRect();
119
- const tw = tooltipRef.current.getBoundingClientRect().width || tooltipSize.width || 80;
120
- const th = tooltipRef.current.getBoundingClientRect().height || tooltipSize.height || 24;
121
- let x = 0, y = 0;
122
- switch (side) {
123
- case 'top':
124
- y = a.top - th - sideOffset;
125
- x = align === 'start' ? a.left + alignOffset : align === 'end' ? a.right - tw + alignOffset : a.left + a.width / 2 - tw / 2 + alignOffset;
126
- break;
127
- case 'bottom':
128
- y = a.bottom + sideOffset;
129
- x = align === 'start' ? a.left + alignOffset : align === 'end' ? a.right - tw + alignOffset : a.left + a.width / 2 - tw / 2 + alignOffset;
130
- break;
131
- case 'left':
132
- x = a.left - tw - sideOffset;
133
- y = align === 'start' ? a.top + alignOffset : align === 'end' ? a.bottom - th + alignOffset : a.top + a.height / 2 - th / 2 + alignOffset;
134
- break;
135
- case 'right':
136
- x = a.right + sideOffset;
137
- y = align === 'start' ? a.top + alignOffset : align === 'end' ? a.bottom - th + alignOffset : a.top + a.height / 2 - th / 2 + alignOffset;
138
- break;
139
- }
140
- setPosition({
141
- x: Math.min(Math.max(x, viewportPadding), window.innerWidth - tw - viewportPadding),
142
- y: Math.min(Math.max(y, viewportPadding), window.innerHeight - th - viewportPadding),
143
- });
144
- };
145
- calculatePosition();
146
- requestAnimationFrame(() => requestAnimationFrame(calculatePosition));
147
- }, [shouldRender, side, align, sideOffset, alignOffset, tooltipSize.width, tooltipSize.height, label]);
148
-
149
- useEffect(() => {
150
- if (!shouldRender) return;
151
- const onScrollResize = () => {
152
- if (!anchorRef.current || !tooltipRef.current) return;
153
- const a = anchorRef.current.getBoundingClientRect();
154
- const tw = tooltipSize.width || 80;
155
- const th = tooltipSize.height || 24;
156
- let x = 0, y = 0;
157
- switch (side) {
158
- case 'top': y = a.top - th - sideOffset; x = align === 'start' ? a.left + alignOffset : align === 'end' ? a.right - tw + alignOffset : a.left + a.width / 2 - tw / 2 + alignOffset; break;
159
- case 'bottom': y = a.bottom + sideOffset; x = align === 'start' ? a.left + alignOffset : align === 'end' ? a.right - tw + alignOffset : a.left + a.width / 2 - tw / 2 + alignOffset; break;
160
- case 'left': x = a.left - tw - sideOffset; y = align === 'start' ? a.top + alignOffset : align === 'end' ? a.bottom - th + alignOffset : a.top + a.height / 2 - th / 2 + alignOffset; break;
161
- case 'right': x = a.right + sideOffset; y = align === 'start' ? a.top + alignOffset : align === 'end' ? a.bottom - th + alignOffset : a.top + a.height / 2 - th / 2 + alignOffset; break;
162
- }
163
- setPosition({
164
- x: Math.min(Math.max(x, viewportPadding), window.innerWidth - tw - viewportPadding),
165
- y: Math.min(Math.max(y, viewportPadding), window.innerHeight - th - viewportPadding),
166
- });
167
- };
168
- window.addEventListener('scroll', onScrollResize, true);
169
- window.addEventListener('resize', onScrollResize);
170
- return () => { window.removeEventListener('scroll', onScrollResize, true); window.removeEventListener('resize', onScrollResize); };
171
- }, [shouldRender, side, align, sideOffset, alignOffset, tooltipSize.width, tooltipSize.height]);
172
-
173
- const keyHint = shortcutKey ? (
174
- <div className={styles.keyHint} aria-hidden>
175
- <Text variant="text-caption-emphasis" as="span" color="primary">{shortcutKey}</Text>
176
- </div>
177
- ) : null;
178
-
179
- const tooltipContent = shouldRender ? (
180
- <div
181
- ref={tooltipRef}
182
- className={`${styles.tooltip} ${isClosing ? styles.closing : ''}`}
183
- style={{
184
- position: 'fixed',
185
- left: 0,
186
- top: 0,
187
- transform: `translate(${Math.round(position.x)}px, ${Math.round(position.y)}px)`,
188
- willChange: 'transform',
189
- zIndex: 10000,
190
- }}
191
- role="tooltip"
192
- >
193
- <div className={styles.tooltipInner}>
194
- {shortcutKey && shortcutKeyPosition === 'start' && keyHint}
195
- <Text variant="text-body-small" as="span" color="primary">{label}</Text>
196
- {shortcutKey && shortcutKeyPosition === 'end' && keyHint}
197
- </div>
198
- </div>
199
- ) : null;
200
-
201
- const trigger = React.Children.only(children);
202
- const triggerWithRefAndHandlers = React.isValidElement(trigger)
203
- ? React.cloneElement(trigger as React.ReactElement<any>, {
204
- ref: setAnchorRef,
205
- onMouseEnter: (e: React.MouseEvent) => {
206
- handleOpen();
207
- (trigger as any).props.onMouseEnter?.(e);
208
- },
209
- onMouseLeave: (e: React.MouseEvent) => {
210
- handleClose();
211
- (trigger as any).props.onMouseLeave?.(e);
212
- },
213
- })
214
- : children;
215
-
216
- return (
217
- <>
218
- {triggerWithRefAndHandlers}
219
- {usePortal ? createPortal(tooltipContent, document.body) : tooltipContent}
220
- </>
221
- );
222
- };
223
-
224
- Tooltip.displayName = 'Tooltip';
@@ -1,2 +0,0 @@
1
- export { Tooltip } from './Tooltip';
2
- export type { TooltipProps, TooltipSide, TooltipAlign } from './Tooltip';
@@ -1,4 +0,0 @@
1
- declare module '*.module.css' {
2
- const classes: { [key: string]: string };
3
- export default classes;
4
- }
@@ -1,195 +0,0 @@
1
- import { Meta } from '@storybook/addon-docs/blocks';
2
-
3
- <Meta title="Docs/Color Usage" />
4
-
5
- # Color Usage Guidelines
6
-
7
- ## 1. Objective
8
-
9
- This document explains how to use color tokens in product code and design implementation.
10
-
11
- The key distinction in this repository is:
12
-
13
- 1. semantic colors are for UI meaning, hierarchy, and component states,
14
- 2. data colors are for charts, graphs, and other visualization marks,
15
- 3. both layers are aliases on top of the reference palette.
16
-
17
- If a choice is available between semantic and data tokens, default to semantic for interface chrome and default to data for visualization marks.
18
-
19
- ## 2. Quick Decision Rule
20
-
21
- Use this rule first:
22
-
23
- 1. use semantic colors when the color communicates UI role,
24
- 2. use data colors when the color differentiates or encodes data,
25
- 3. use reference colors only when working on the token system itself.
26
-
27
- Examples:
28
-
29
- 1. page background, card text, button hover, error banner: **semantic**
30
- 2. bar series, line series, pie slices, heatmap steps: **data**
31
- 3. palette generation or alias maintenance: **reference**
32
-
33
- ## 3. Semantic Colors
34
-
35
- ### 3.1 What Semantic Means
36
-
37
- Semantic tokens are named by purpose, not by visual appearance. They should be chosen based on what the UI element is doing, not based on whether a blue, red, or grey value looks convenient.
38
-
39
- For example:
40
-
41
- - `background.primary` means the main surface
42
- - `foreground.secondary` means lower-emphasis content
43
- - `background.strong.negative` means a strong negative-intent surface
44
- - `interaction.hover` means an interaction overlay
45
- - `foreground.on-strong-background.primary` means primary content placed on a strong colored background
46
-
47
- ### 3.2 When To Use Semantic Colors
48
-
49
- Use semantic tokens for:
50
-
51
- 1. application and component surfaces,
52
- 2. text and icon hierarchy,
53
- 3. borders and strokes when they convey UI structure,
54
- 4. status styling such as brand, positive, warning, and negative,
55
- 5. hover and pressed overlays,
56
- 6. special product-domain markers that are part of the product language.
57
-
58
- Do not use semantic tokens to color arbitrary chart series just because a semantic hue looks nice.
59
-
60
- ### 3.3 Common Semantic Families
61
-
62
- #### Background
63
-
64
- Use background tokens for surfaces and fills.
65
-
66
- - `background.primary` and `background.secondary` are standard UI surfaces
67
- - `background.strong.*`, `background.bold.*`, `background.medium.*`, and `background.faint.*` express emphasis and intent
68
- - `background.translucent`, `background.shade`, and `background.transparent` are utility surface values
69
-
70
- Typical mapping:
71
-
72
- | Use case | Token |
73
- |----------|-------|
74
- | Nested card or panel surface | <code>background.primary</code> |
75
- | App shell or secondary panel | <code>background.secondary</code> |
76
- | Bold status banner | <code>background.bold.negative</code> |
77
- | Subtle info container | <code>background.faint.neutral</code> |
78
-
79
- #### Foreground
80
-
81
- Use foreground tokens for text, icons, and strokes that follow content hierarchy.
82
-
83
- - `foreground.primary` is the highest-emphasis content
84
- - `foreground.secondary` through `foreground.quaternary` reduce emphasis
85
- - `foreground.strong.*`, `foreground.bold.*`, `foreground.medium.*`, and `foreground.faint.*` provide colored content roles
86
- - `foreground.on-strong-background.*` is for content placed on strong colored surfaces
87
-
88
- Typical mapping:
89
-
90
- | Use case | Token |
91
- |----------|-------|
92
- | Main body text | <code>foreground.primary</code> |
93
- | Helper text or secondary icon | <code>foreground.secondary</code> |
94
- | Inactive or de-emphasized content | <code>foreground.tertiary</code> |
95
- | Disabled or very low-emphasis ornament | <code>foreground.quaternary</code> |
96
- | Text on a bold brand fill | <code>foreground.on-bold-background.primary</code> |
97
-
98
- > **Note:** `foreground.tertiary` is only about 3.35:1 in light mode and 3.23:1 in dark mode, so it does not meet AA for standard text sizes. Use it only for genuinely low-emphasis content.
99
-
100
- #### Interaction
101
-
102
- Use interaction tokens for overlays caused by state changes, not for base surfaces or replacement fills.
103
-
104
- - `interaction.hover` and `interaction.pressed` are for standard surfaces
105
- - `interaction.on-strong-background.hover` and similar are for colored fills
106
- - Interaction tokens preserve the underlying semantic meaning of the surface they sit on
107
-
108
- #### Border & Divider
109
-
110
- - `border.primary`, `border.secondary`, and `border.tertiary` are for container edges, field outlines, card strokes
111
- - `divider.divider` is for internal rules that separate content inside a surface
112
- - `divider.on-strong-background`, `divider.on-bold-background`, etc. are divider variants for colored fills
113
-
114
- > **Divider tokens** are narrower in purpose than border tokens. Use them only when drawing a horizontal or vertical rule inside a surface.
115
-
116
- #### Always-Dark
117
-
118
- Use `always-dark.*` only when the component must stay dark regardless of surrounding theme. This is a special-case family for fixed dark contexts.
119
-
120
- ### 3.4 Semantic Tone Selection
121
-
122
- When multiple semantic intensities exist, choose the one that matches the amount of emphasis required:
123
-
124
- | Tone | Purpose |
125
- |------|---------|
126
- | <code>strong</code> | Highest-emphasis fills or content |
127
- | <code>bold</code> | Strong but less dominant than strong |
128
- | <code>medium</code> | Mid-emphasis |
129
- | <code>faint</code> | Low-emphasis tinting or supporting treatment |
130
-
131
- When a surface uses a strong semantic background, pair it with the matching `on-background` content token rather than reusing normal foreground tokens.
132
-
133
- ## 4. Data Colors
134
-
135
- ### 4.1 When To Use Data Colors
136
-
137
- Use data tokens for:
138
-
139
- 1. chart series colors,
140
- 2. legend keys,
141
- 3. map overlays and plotted markers,
142
- 4. heatmaps and gradients tied to values,
143
- 5. ordered or diverging color ramps.
144
-
145
- Do **not** use data tokens for page backgrounds, standard text hierarchy, button states, banners, or form validation.
146
-
147
- ### 4.2 Common Data Families
148
-
149
- | Family | Purpose | Examples |
150
- |--------|---------|----------|
151
- | <code>data-misc</code> | Neutral visualization elements | Gridlines, reference lines, axes |
152
- | <code>data-category</code> | Nominal categories (unordered) | Multi-series bars, pie slices, legend palettes |
153
- | <code>data-win-loss</code> | Outcome polarity | Pass/fail, win/loss, positive/negative |
154
- | <code>data-sequence-&#42;</code> | Ordered single-direction values | Intensity ramps, ordered buckets, choropleths |
155
- | <code>data-diverging-&#42;</code> | Values extending from a midpoint | Above/below target, deviation from baseline |
156
-
157
- > **Important:** When using `data-category` colors together, use them in numeric order (1, 2, 3...). This is especially important when categories touch each other (donut charts, stacked bars).
158
-
159
- ### 4.3 How Semantic And Data Work Together
160
-
161
- | Element | Token source |
162
- |---------|-------------|
163
- | Chart card background | <code>background.primary</code> (semantic) |
164
- | Chart title | <code>foreground.primary</code> (semantic) |
165
- | Axis labels | <code>foreground.secondary</code> (semantic) |
166
- | Chart bars/lines | <code>data-category.&#42;</code> or <code>data-sequence-&#42;</code> (data) |
167
- | Alert banner around chart | <code>background.faint.warning</code> (semantic) |
168
-
169
- ## 5. Accessibility & Pairing
170
-
171
- ### Preferred Text Pairings
172
-
173
- | Background | Safe foreground | Lowest contrast |
174
- |-----------|----------------|-----------------|
175
- | <code>background.primary</code> | <code>foreground.primary</code> or <code>.secondary</code> | ~5.74:1 light, ~6.13:1 dark |
176
- | <code>background.strong.&#42;</code> | <code>foreground.on-strong-background.primary</code> or <code>.secondary</code> | ~6.54:1 light, ~5.28:1 dark |
177
- | <code>background.bold.&#42;</code> | <code>foreground.on-bold-background.primary</code> or <code>.secondary</code> | ~5.45:1 light, ~4.89:1 dark |
178
-
179
- ### Tone Pairs
180
-
181
- - `background.bold.*` with `foreground.faint.*` — safe, lowest floor ~4.54:1
182
- - `background.faint.*` with `foreground.bold.*` — safe, same reciprocal rule
183
- - `background.strong.*` with `foreground.medium.*` — near-AA, not guaranteed for every intent
184
-
185
- ## 6. Anti-Patterns
186
-
187
- Avoid these patterns:
188
-
189
- 1. choosing a token only because the hue looks visually convenient,
190
- 2. using semantic status colors as a chart palette,
191
- 3. using data colors for ordinary UI text or surfaces,
192
- 4. mixing reference tokens directly into product code,
193
- 5. pairing strong backgrounds with regular foreground tokens instead of `on-background` tokens,
194
- 6. using `divider.*` as a generic border token,
195
- 7. changing token meaning across screens without a strong product reason.