@repobit/dex-system-design 0.25.11 → 0.26.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 (336) hide show
  1. package/CHANGELOG.md +195 -0
  2. package/README.md +131 -8
  3. package/package.json +95 -13
  4. package/schemas/component-manifest.json +3294 -405
  5. package/schemas/manifest-omissions.json +173 -0
  6. package/src/blog/src/breakpoints.js +6 -6
  7. package/src/blog/src/content/blog-atoms-showcase.js +1 -1
  8. package/src/blog/src/content/blog-page-layout.js +2 -2
  9. package/src/blog/src/lib/article-toc.js +7 -7
  10. package/src/blog/src/shell/blog-shell.js +1 -1
  11. package/src/blog/src/tokens/blog.js +2 -2
  12. package/src/blog/src/tokens/core.js +34 -35
  13. package/src/blog/src/tokens/legacy.js +0 -9
  14. package/src/blog/tokens/blog.js +2 -2
  15. package/src/blog/tokens/core.js +34 -35
  16. package/src/blog/tokens/legacy.js +0 -9
  17. package/src/blog/tokens.css +36 -46
  18. package/src/components/accordion/accordion-bg.css.js +83 -59
  19. package/src/components/accordion/accordion-bg.js +29 -10
  20. package/src/components/accordion/accordion-bg.stories.js +67 -67
  21. package/src/components/accordion/accordion-keyboard.js +80 -0
  22. package/src/components/accordion/accordion.css.js +142 -80
  23. package/src/components/accordion/accordion.js +37 -10
  24. package/src/components/accordion/accordion.stories.js +7 -7
  25. package/src/components/agent-endpoints/agent-endpoints.css.js +36 -39
  26. package/src/components/agent-endpoints/agent-endpoints.js +30 -20
  27. package/src/components/agent-endpoints/agent-endpoints.stories.js +1 -1
  28. package/src/components/ai-guardian-demo.stories.js +91 -91
  29. package/src/components/alert/alert.css.js +198 -0
  30. package/src/components/alert/alert.js +103 -0
  31. package/src/components/alert/alert.stories.js +206 -0
  32. package/src/components/anchor/anchor-nav.css.js +213 -101
  33. package/src/components/anchor/anchor-nav.js +26 -40
  34. package/src/components/anchor/anchor.stories.js +22 -12
  35. package/src/components/annotation/annotation.css.js +58 -0
  36. package/src/components/annotation/annotation.js +67 -0
  37. package/src/components/annotation/annotation.stories.js +63 -0
  38. package/src/components/architecture.stories.js +285 -0
  39. package/src/components/atoms.stories.js +342 -0
  40. package/src/components/avatar/avatar.css.js +67 -0
  41. package/src/components/avatar/avatar.js +42 -0
  42. package/src/components/avatar/avatar.stories.js +95 -0
  43. package/src/components/awards/awards-flex.css.js +209 -23
  44. package/src/components/awards/awards-flex.js +66 -7
  45. package/src/components/awards/awards-flex.stories.js +1 -1
  46. package/src/components/awards/{awards-light.stories.js → awards-summary.stories.js} +54 -64
  47. package/src/components/awards/awards.css.js +116 -58
  48. package/src/components/awards/awards.js +102 -28
  49. package/src/components/awards/awards.stories.js +1 -1
  50. package/src/components/back/back.css.js +51 -22
  51. package/src/components/back/back.js +28 -7
  52. package/src/components/back/back.stories.js +9 -3
  53. package/src/components/badge/badge.css.js +158 -46
  54. package/src/components/badge/badge.js +62 -74
  55. package/src/components/badge/badge.stories.js +176 -248
  56. package/src/components/bento-grid/bento-grid.css.js +21 -16
  57. package/src/components/bento-grid/bento-grid.js +16 -4
  58. package/src/components/bento-grid/bento-grid.stories.js +19 -18
  59. package/src/components/bento-grid/bento-item.css.js +52 -28
  60. package/src/components/bento-grid/bento-item.js +2 -2
  61. package/src/components/blockquote/blockquote.css.js +47 -0
  62. package/src/components/blockquote/blockquote.js +29 -0
  63. package/src/components/blockquote/blockquote.stories.js +62 -0
  64. package/src/components/breadcrumb/breadcrumb.css.js +92 -22
  65. package/src/components/breadcrumb/breadcrumb.js +56 -11
  66. package/src/components/button/button.css.js +531 -161
  67. package/src/components/button/button.js +206 -214
  68. package/src/components/button/button.stories.js +322 -174
  69. package/src/components/caption/caption.css.js +21 -0
  70. package/src/components/caption/caption.js +31 -0
  71. package/src/components/caption/caption.stories.js +62 -0
  72. package/src/components/card-features/card-features.css.js +14 -22
  73. package/src/components/card-features/card-features.js +68 -9
  74. package/src/components/card-features/card-features.stories.js +11 -11
  75. package/src/components/cards/card.css.js +60 -81
  76. package/src/components/cards/card.js +56 -25
  77. package/src/components/cards/card.stories.js +39 -39
  78. package/src/components/carousel/carousel.css.js +93 -99
  79. package/src/components/carousel/carousel.js +32 -4
  80. package/src/components/checkbox/checkbox.css.js +111 -93
  81. package/src/components/checkbox/checkbox.js +64 -90
  82. package/src/components/checkbox/checkbox.stories.js +96 -29
  83. package/src/components/code/code.css.js +70 -0
  84. package/src/components/code/code.js +40 -0
  85. package/src/components/code/code.stories.js +73 -0
  86. package/src/components/compare/compare.css.js +179 -43
  87. package/src/components/compare/compare.js +52 -25
  88. package/src/components/compare/compare.stories.js +61 -4
  89. package/src/components/comparison-panel/comparison-panel.css.js +38 -51
  90. package/src/components/comparison-panel/comparison-panel.js +5 -4
  91. package/src/components/comparison-panel/comparison-panel.stories.js +1 -1
  92. package/src/components/compatibility-table/compatibility-table.css.js +180 -80
  93. package/src/components/compatibility-table/compatibility-table.js +37 -9
  94. package/src/components/control-alignment.stories.js +393 -0
  95. package/src/components/cta-banner/cta-banner.css.js +41 -13
  96. package/src/components/cta-banner/cta-banner.js +6 -5
  97. package/src/components/cta-banner/cta-banner.stories.js +43 -98
  98. package/src/components/display/display.css.js +25 -1
  99. package/src/components/display/display.js +46 -13
  100. package/src/components/display/display.stories.js +270 -40
  101. package/src/components/divider/divider-horizontal.js +21 -5
  102. package/src/components/divider/divider-vertical.js +15 -7
  103. package/src/components/divider/divider.css.js +2 -2
  104. package/src/components/divider/divider.stories.js +38 -34
  105. package/src/components/dropdown/dropdown.css.js +93 -126
  106. package/src/components/dropdown/dropdown.js +114 -34
  107. package/src/components/dropdown/dropdown.stories.js +56 -24
  108. package/src/components/features/features.css.js +24 -11
  109. package/src/components/features/features.js +7 -3
  110. package/src/components/features/features.stories.js +37 -37
  111. package/src/components/features-tab/features-tab.css.js +19 -8
  112. package/src/components/features-tab/features-tab.js +6 -5
  113. package/src/components/features-tab/features-tab.stories.js +23 -23
  114. package/src/components/fieldset/fieldset.css.js +30 -0
  115. package/src/components/fieldset/fieldset.js +28 -0
  116. package/src/components/fieldset/fieldset.stories.js +84 -0
  117. package/src/components/footer/footer-links-group.css.js +10 -14
  118. package/src/components/footer/footer-links-group.js +4 -3
  119. package/src/components/footer/footer-lp.css.js +59 -30
  120. package/src/components/footer/footer-lp.js +17 -12
  121. package/src/components/footer/footer-lp.stories.js +63 -75
  122. package/src/components/footer/footer-nav-menu.css.js +26 -4
  123. package/src/components/footer/footer-nav-menu.js +3 -2
  124. package/src/components/footer/footer.css.js +146 -264
  125. package/src/components/footer/footer.js +176 -106
  126. package/src/components/footer/footer.stories.js +9 -9
  127. package/src/components/footer/localeMap.js +1 -1
  128. package/src/components/grid/grid.css.js +1 -1
  129. package/src/components/grid/grid.js +49 -7
  130. package/src/components/grid/grid.stories.js +111 -0
  131. package/src/components/header/header-code.css.js +61 -51
  132. package/src/components/header/header-code.js +28 -14
  133. package/src/components/header/header-code.stories.js +5 -5
  134. package/src/components/header/header.css.js +655 -176
  135. package/src/components/header/header.js +269 -36
  136. package/src/components/header/header.stories.js +841 -18
  137. package/src/components/heading/heading.css.js +14 -17
  138. package/src/components/heading/heading.js +48 -33
  139. package/src/components/heading/heading.stories.js +27 -25
  140. package/src/components/help-text/help-text.css.js +21 -0
  141. package/src/components/help-text/help-text.js +25 -0
  142. package/src/components/help-text/help-text.stories.js +66 -0
  143. package/src/components/highlight/highlight.css.js +86 -64
  144. package/src/components/highlight/highlight.js +18 -27
  145. package/src/components/highlight/highlight.stories.js +14 -3
  146. package/src/components/icons/analysis-icon.js +6 -16
  147. package/src/components/icons/arrow-down-icon.js +6 -19
  148. package/src/components/icons/arrow-icon.js +44 -0
  149. package/src/components/icons/arrow-right-icon.js +30 -23
  150. package/src/components/icons/arrow-up-icon.js +19 -18
  151. package/src/components/icons/bd-ai-icon.js +1 -1
  152. package/src/components/icons/brand-marks.stories.js +279 -0
  153. package/src/components/icons/brand-signature-icon.js +42 -0
  154. package/src/components/icons/check-icon.js +27 -0
  155. package/src/components/icons/circle-info-icon.js +33 -0
  156. package/src/components/icons/close-icon.js +6 -18
  157. package/src/components/icons/family-icon.js +8 -20
  158. package/src/components/icons/globe-icon.js +6 -18
  159. package/src/components/icons/guide-icon.js +6 -18
  160. package/src/components/icons/icon-element.js +99 -0
  161. package/src/components/icons/icons.js +36 -0
  162. package/src/components/icons/icons.stories.js +184 -52
  163. package/src/components/icons/individual-icon.js +6 -18
  164. package/src/components/icons/laurel-icon.js +9 -19
  165. package/src/components/icons/machine-learning-icon.js +6 -17
  166. package/src/components/icons/marks.js +41 -0
  167. package/src/components/icons/minus-icon.js +7 -21
  168. package/src/components/icons/missing-icon.js +52 -0
  169. package/src/components/icons/plus-icon.js +7 -21
  170. package/src/components/icons/quote-icon.js +19 -19
  171. package/src/components/image/image.css.js +72 -25
  172. package/src/components/image/image.js +11 -6
  173. package/src/components/image/image.stories.js +2 -2
  174. package/src/components/input/custom-form.stories.js +214 -62
  175. package/src/components/input/input-clipboard.css.js +51 -144
  176. package/src/components/input/input-clipboard.js +31 -15
  177. package/src/components/input/input.css.js +8 -146
  178. package/src/components/input/input.js +93 -38
  179. package/src/components/install-options/install-options.css.js +84 -77
  180. package/src/components/install-options/install-options.js +33 -30
  181. package/src/components/install-options/install-options.stories.js +3 -3
  182. package/src/components/label/label.css.js +35 -0
  183. package/src/components/label/label.js +38 -0
  184. package/src/components/label/label.stories.js +82 -0
  185. package/src/components/light-carousel/light-carousel.css.js +111 -63
  186. package/src/components/light-carousel/light-carousel.js +85 -11
  187. package/src/components/light-carousel/light-carousel.stories.js +126 -82
  188. package/src/components/link/link.css.js +150 -99
  189. package/src/components/link/link.js +86 -11
  190. package/src/components/link/link.stories.js +124 -30
  191. package/src/components/list/list-item/list-item.css.js +74 -22
  192. package/src/components/list/list-item/list-item.js +32 -10
  193. package/src/components/list/list-item/list-item.stories.js +23 -23
  194. package/src/components/list/list.css.js +8 -2
  195. package/src/components/list/list.js +3 -2
  196. package/src/components/list/list.stories.js +222 -0
  197. package/src/components/modal/modal.css.js +114 -24
  198. package/src/components/modal/modal.js +83 -7
  199. package/src/components/modal/modal.stories.js +9 -9
  200. package/src/components/overview/overview.css.js +19 -14
  201. package/src/components/overview/overview.js +6 -5
  202. package/src/components/overview/overview.stories.js +10 -10
  203. package/src/components/page-switcher/page-switcher.css.js +97 -40
  204. package/src/components/page-switcher/page-switcher.js +28 -5
  205. package/src/components/page-switcher/page-switcher.stories.js +95 -0
  206. package/src/components/paragraph/paragraph.css.js +15 -10
  207. package/src/components/paragraph/paragraph.js +41 -44
  208. package/src/components/paragraph/paragraph.stories.js +56 -21
  209. package/src/components/picture/picture.css.js +103 -44
  210. package/src/components/picture/picture.js +100 -30
  211. package/src/components/picture/picture.stories.js +1 -1
  212. package/src/components/pricing-cards/new-pricing-card.js +3 -3
  213. package/src/components/pricing-cards/new-pricing.css.js +24 -15
  214. package/src/components/pricing-cards/pricing-card-actions.css.js +1 -1
  215. package/src/components/pricing-cards/pricing-card-actions.js +3 -4
  216. package/src/components/pricing-cards/pricing-card-container.css.js +3 -3
  217. package/src/components/pricing-cards/pricing-card-container.js +3 -2
  218. package/src/components/pricing-cards/pricing-card-header.css.js +10 -8
  219. package/src/components/pricing-cards/pricing-card-header.js +6 -7
  220. package/src/components/pricing-cards/pricing-card-pricing.css.js +16 -9
  221. package/src/components/pricing-cards/pricing-card-pricing.js +8 -6
  222. package/src/components/pricing-cards/pricing-card-show-more.css.js +11 -3
  223. package/src/components/pricing-cards/pricing-card-show-more.js +8 -3
  224. package/src/components/pricing-cards/pricing-card.css.js +244 -190
  225. package/src/components/pricing-cards/pricing-card.js +54 -70
  226. package/src/components/pricing-cards/pricing-feature-item.css.js +25 -8
  227. package/src/components/pricing-cards/pricing-feature-item.js +8 -3
  228. package/src/components/process-steps/process-steps.css.js +26 -14
  229. package/src/components/process-steps/process-steps.js +23 -6
  230. package/src/components/process-steps/process-steps.stories.js +1 -1
  231. package/src/components/progress/progress.css.js +80 -0
  232. package/src/components/progress/progress.js +42 -0
  233. package/src/components/progress/progress.stories.js +79 -0
  234. package/src/components/quick-answer/quick-answer.css.js +75 -13
  235. package/src/components/quick-answer/quick-answer.js +8 -3
  236. package/src/components/radio/radio.css.js +92 -128
  237. package/src/components/radio/radio.js +106 -127
  238. package/src/components/radio/radio.stories.js +54 -19
  239. package/src/components/review/review-grid.css.js +5 -6
  240. package/src/components/review/review-grid.js +14 -11
  241. package/src/components/review/review.css.js +11 -6
  242. package/src/components/review/review.js +3 -8
  243. package/src/components/shared/ensemble.css.js +93 -0
  244. package/src/components/shared/form-field.css.js +206 -0
  245. package/src/components/shared/prop-vocabulary.js +48 -0
  246. package/src/components/shared/token-scales.js +306 -0
  247. package/src/components/skeleton/skeleton.css.js +34 -0
  248. package/src/components/skeleton/skeleton.js +32 -0
  249. package/src/components/skeleton/skeleton.stories.js +70 -0
  250. package/src/components/spinner/spinner.css.js +62 -0
  251. package/src/components/spinner/spinner.js +38 -0
  252. package/src/components/spinner/spinner.stories.js +92 -0
  253. package/src/components/spotlight-section/spotlight-section.css.js +14 -13
  254. package/src/components/spotlight-section/spotlight-section.js +42 -39
  255. package/src/components/switch/switch.css.js +103 -0
  256. package/src/components/switch/switch.js +44 -0
  257. package/src/components/switch/switch.stories.js +86 -0
  258. package/src/components/tab-list/content-switcher.stories.js +189 -0
  259. package/src/components/tab-list/tab-list.css.js +250 -0
  260. package/src/components/tab-list/tab-list.js +184 -0
  261. package/src/components/tab-list/tab-list.stories.js +221 -0
  262. package/src/components/tabs/tabs.css.js +14 -123
  263. package/src/components/tabs/tabs.js +16 -19
  264. package/src/components/tabs/tabs.stories.js +95 -95
  265. package/src/components/tag/tag.css.js +54 -0
  266. package/src/components/tag/tag.js +32 -0
  267. package/src/components/tag/tag.stories.js +126 -0
  268. package/src/components/terminal/terminal-message.css.js +164 -60
  269. package/src/components/terminal/terminal-message.js +5 -5
  270. package/src/components/terminal/terminal-message.stories.js +70 -1
  271. package/src/components/termsOfUse/terms.css.js +25 -20
  272. package/src/components/termsOfUse/terms.js +13 -9
  273. package/src/components/termsOfUse/terms.stories.js +1 -1
  274. package/src/components/textarea/textarea.css.js +51 -0
  275. package/src/components/textarea/textarea.js +136 -0
  276. package/src/components/textarea/textarea.stories.js +191 -0
  277. package/src/components/tooltip/tooltip.css.js +75 -0
  278. package/src/components/tooltip/tooltip.js +156 -0
  279. package/src/components/tooltip/tooltip.stories.js +161 -0
  280. package/src/components/trust-panel/trust-panel.css.js +85 -33
  281. package/src/components/trust-panel/trust-panel.js +18 -10
  282. package/src/components/trust-panel/trust-panel.stories.js +1 -1
  283. package/src/components/ultimate-security-demo.stories.js +431 -0
  284. package/src/components/video/video.css.js +17 -0
  285. package/src/components/video/video.js +40 -0
  286. package/src/components/video/video.stories.js +106 -0
  287. package/src/components/video-player/video-player.css.js +67 -11
  288. package/src/components/video-player/video-player.js +35 -4
  289. package/src/components/video-player/video-player.stories.js +1 -1
  290. package/src/components/visual-alignment.stories.js +411 -0
  291. package/src/components/visually-hidden/visually-hidden.css.js +24 -0
  292. package/src/components/visually-hidden/visually-hidden.js +16 -0
  293. package/src/components/visually-hidden/visually-hidden.stories.js +56 -0
  294. package/src/stories/Button.stories.js +17 -17
  295. package/src/stories/Header.stories.js +10 -10
  296. package/src/stories/Page.js +1 -1
  297. package/src/stories/Page.stories.js +6 -6
  298. package/src/tokens/borders.stories.js +339 -0
  299. package/src/tokens/color-responsibilities.stories.js +227 -0
  300. package/src/tokens/dark-derivation.js +309 -0
  301. package/src/tokens/dark-findings.js +197 -0
  302. package/src/tokens/dark-mode.stories.js +207 -0
  303. package/src/tokens/dimension.stories.js +251 -0
  304. package/src/tokens/elevation.stories.js +143 -0
  305. package/src/tokens/focus.stories.js +276 -0
  306. package/src/tokens/fonts.css +20 -20
  307. package/src/tokens/fonts.stories.js +354 -374
  308. package/src/tokens/layout.css +25 -11
  309. package/src/tokens/motion.stories.js +231 -0
  310. package/src/tokens/shape.stories.js +272 -0
  311. package/src/tokens/spacing-rhythm.stories.js +359 -0
  312. package/src/tokens/spacing.stories.js +208 -703
  313. package/src/tokens/story-chrome.js +503 -0
  314. package/src/tokens/surfaces.stories.js +224 -0
  315. package/src/tokens/text-on-surface.stories.js +164 -0
  316. package/src/tokens/token-map.js +220 -0
  317. package/src/tokens/token-map.stories.js +257 -0
  318. package/src/tokens/token-purposes.js +266 -0
  319. package/src/tokens/tokens-grid.stories.js +388 -900
  320. package/src/tokens/tokens.css +1633 -1045
  321. package/src/tokens/tokens.js +1130 -492
  322. package/src/tokens/tokens.stories.js +137 -47
  323. package/src/tokens/type-ceiling-words.js +299 -0
  324. package/src/tokens/typography.stories.js +1003 -965
  325. package/src/tokens/vertical-rhythm.stories.js +224 -0
  326. package/src/components/awards/awards-icon.js +0 -56
  327. package/src/components/awards/awards-light.js +0 -240
  328. package/src/components/banner/banner.js +0 -60
  329. package/src/components/banner/banner.stories.js +0 -51
  330. package/src/components/button/icons.js +0 -24
  331. package/src/components/input/index.js +0 -0
  332. package/src/components/light-carousel/light-carousel-simple.css.js +0 -183
  333. package/src/components/light-carousel/light-carousel-simple.js +0 -74
  334. package/src/tokens/colors.js +0 -121
  335. package/src/tokens/typography.css.js +0 -207
  336. package/src/tokens/typography.js +0 -0
@@ -0,0 +1,80 @@
1
+ import { css } from 'lit';
2
+
3
+ /** Styled entirely from design tokens — see npm run lint:tokens. */
4
+ export const progressCSS = css`
5
+ :host { display: block; }
6
+
7
+ .track {
8
+ height: var(--spacing-8);
9
+ background: var(--color-surface-muted);
10
+ border-radius: var(--radius-full);
11
+ overflow: hidden;
12
+ }
13
+
14
+ .fill {
15
+ height: 100%;
16
+ background: var(--status-info-accent);
17
+ border-radius: var(--radius-full);
18
+ transition: width var(--transition-duration-slow) var(--transition-easing-smooth);
19
+ }
20
+
21
+ /* The tones come from the shared status roles, so a progress bar and a
22
+ bd-alert rule or a bd-badge dot of the same tone are the same colour by
23
+ construction. They were not: this atom spelled all three out in palette
24
+ steps that happened to match, so retinting --status-success-accent moved
25
+ alert, badge and tag and left the bar green.
26
+
27
+ Measured against the track the fill sits in, not the page: the bar is a
28
+ graphic whose colour carries the meaning, so 1.4.11 wants 3:1 there.
29
+ On the track the default blue is 3.52 and error red-600 is 4.23, but
30
+ success at green-600 was only 2.49. green-700 — which is the step
31
+ --status-success-accent names — is 3.69. */
32
+ /* info has its own rule even though .fill above already resolves to the same
33
+ token, and the duplication is the point. It used to work by OMISSION --
34
+ there was no info rule, so tone="info" fell through to the default fill,
35
+ which happened to be --status-info-accent. Nothing rendered wrong, and
36
+ nothing ever would have caught it: Figma and the Code Connect template
37
+ both offer info as a tone, the manifest offered "default" instead, and the
38
+ stories only ever exercised success and error, so the info path had never
39
+ been rendered anywhere.
40
+ .
41
+ Two things stay separate now. The bare .fill is what a bd-progress with NO
42
+ tone attribute looks like; this rule is what tone="info" MEANS. They agree
43
+ today. If somebody later changes the untoned default, info keeps its
44
+ meaning instead of silently following it. */
45
+ :host([tone='info']) .fill { background: var(--status-info-accent); }
46
+ :host([tone='success']) .fill { background: var(--status-success-accent); }
47
+ :host([tone='error']) .fill { background: var(--status-error-accent); }
48
+
49
+ /* The caption role, all five axes from the role rather than one from it and
50
+ the rest from nowhere. This box holds the label and the percentage, so it
51
+ owns their typography -- and it declared a family, a size and a colour and
52
+ never declared a line-height, leaving IBM Plex Sans's own "normal" metric
53
+ to decide. Measured before: 12px text in a 15px box, a leading nobody
54
+ chose, and one that stops being 1.25 the moment the font falls back.
55
+
56
+ The colour is the same value it already used: --typography-caption-default-color
57
+ resolves to --color-text-muted. It is named through the role here so that
58
+ retinting captions moves this label with them.
59
+
60
+ Neither gate could see it. lint:tokens has nothing to scan when a leading
61
+ is absent rather than wrong, and verify:typography fails on multi-line
62
+ text a component renders with no role -- these two spans are single-line. */
63
+ .label {
64
+ display: flex;
65
+ justify-content: space-between;
66
+ margin-bottom: var(--spacing-4);
67
+ font-family: var(--typography-caption-default-fontFamily);
68
+ font-size: var(--typography-caption-default-fontSize);
69
+ font-weight: var(--typography-caption-default-fontWeight);
70
+ line-height: var(--typography-caption-default-lineHeight);
71
+ letter-spacing: var(--typography-caption-default-letterSpacing);
72
+ color: var(--typography-caption-default-color);
73
+ }
74
+
75
+ @media (prefers-reduced-motion: reduce) {
76
+ .fill { transition: none; }
77
+ }
78
+ `;
79
+
80
+ export default progressCSS;
@@ -0,0 +1,42 @@
1
+ import { LitElement, html, nothing } from 'lit';
2
+ // Installs the design tokens into document scope; see src/tokens/tokens.js
3
+ import '../../tokens/tokens.js';
4
+ import { progressCSS } from './progress.css.js';
5
+
6
+ export class BdProgress extends LitElement {
7
+ static styles = [progressCSS];
8
+
9
+ static properties = {
10
+ value: { type: Number },
11
+ max : { type: Number },
12
+ label: { type: String },
13
+ tone : { type: String, reflect: true }
14
+ };
15
+
16
+ constructor() {
17
+ super();
18
+ this.value = 0;
19
+ this.max = 100;
20
+ this.label = '';
21
+ }
22
+
23
+ render() {
24
+ return html`
25
+ ${this.label
26
+ ? html`<span class="label"><span>${this.label}</span><span>${Math.round((this.value / this.max) * 100)}%</span></span>`
27
+ : nothing}
28
+ <div
29
+ class="track"
30
+ role="progressbar"
31
+ aria-valuenow=${this.value}
32
+ aria-valuemin="0"
33
+ aria-valuemax=${this.max}
34
+ aria-label=${this.label || 'Progress'}
35
+ >
36
+ <div class="fill" style="width: ${Math.min(100, (this.value / this.max) * 100)}%"></div>
37
+ </div>
38
+ `;
39
+ }
40
+ }
41
+
42
+ customElements.define('bd-progress', BdProgress);
@@ -0,0 +1,79 @@
1
+ import { html } from 'lit';
2
+ import './progress.js';
3
+
4
+ export default {
5
+ title : 'Atoms/Progress',
6
+ tags : ['autodocs'],
7
+ parameters: {
8
+ docs: {
9
+ description: {
10
+ component: `
11
+ **BdProgress** is a determinate progress bar — it shows how far through a known
12
+ quantity something is. For work of unknown length use \`<bd-spinner>\`.
13
+
14
+ ### Usage
15
+ \`\`\`html
16
+ <bd-progress value="40"></bd-progress>
17
+ <bd-progress value="7" max="10" label="Devices protected"></bd-progress>
18
+ <bd-progress value="95" max="100" label="Storage used" tone="error"></bd-progress>
19
+ \`\`\`
20
+
21
+ ### Props
22
+ | Prop | Values | Default |
23
+ |---|---|---|
24
+ | \`value\` | number, current progress | \`0\` |
25
+ | \`max\` | number, the total | \`100\` |
26
+ | \`label\` | caption shown above the bar, with a percentage | \`''\` |
27
+ | \`tone\` | \`default\`, \`success\`, \`error\` | \`default\` |
28
+
29
+ ### Notes
30
+ When \`label\` is set, a row above the bar shows the label on the left and the
31
+ rounded percentage on the right, so the number is visible and not only
32
+ announced.
33
+
34
+ The fill is clamped at 100%, so a \`value\` above \`max\` cannot overflow the
35
+ track.
36
+
37
+ ### Accessibility
38
+ The track carries \`role="progressbar"\` with \`aria-valuenow\`, \`aria-valuemin\`
39
+ and \`aria-valuemax\`, so assistive tech reports real progress rather than just
40
+ "busy". Its accessible name comes from \`label\`, falling back to the literal
41
+ "Progress" — pass a \`label\` so it says what is progressing.
42
+ `
43
+ }
44
+ }
45
+ },
46
+ argTypes: {
47
+ value: {
48
+ control : 'number',
49
+ description: 'Current progress. Clamped to max when rendering the fill.',
50
+ table : { type: { summary: 'number' }, defaultValue: { summary: "0" }, category: 'Data' }
51
+ },
52
+ max: {
53
+ control : 'number',
54
+ description: 'The total that value is measured against.',
55
+ table : { type: { summary: 'number' }, defaultValue: { summary: "100" }, category: 'Data' }
56
+ },
57
+ label: {
58
+ control : 'text',
59
+ description: 'Caption above the bar, shown with the percentage. Also the accessible name.',
60
+ table : { type: { summary: 'string' }, defaultValue: { summary: "" }, category: 'Content' }
61
+ },
62
+ tone: {
63
+ control : { type: 'select' },
64
+ options : ['default', 'success', 'error'],
65
+ description: 'Colour of the fill.',
66
+ table : { type: { summary: 'string' }, defaultValue: { summary: "default" }, category: 'Appearance' }
67
+ }
68
+ }
69
+ };
70
+
71
+ export const Default = () => html`
72
+ <bd-progress value="64" label="Scan progress"></bd-progress>
73
+ `;
74
+
75
+ export const Tones = () => html`
76
+ <bd-progress value="60" tone="info" label="In progress"></bd-progress>
77
+ <bd-progress value="100" tone="success" label="Complete"></bd-progress>
78
+ <bd-progress value="30" tone="error" label="Failed"></bd-progress>
79
+ `;
@@ -1,33 +1,63 @@
1
- import { css } from "lit";
1
+ import { css, unsafeCSS } from "lit";
2
+ import { below } from "../shared/token-scales.js";
2
3
 
3
4
  export default css`
4
5
  :host {
5
6
  display: block;
6
7
  font-family: var(--typography-fontFamily-sans);
7
- line-height: 1.55;
8
-
9
8
  }
10
9
 
11
10
  .bd-quickanswer-container {
12
- background: var(--color-blue-50, #eef4ff);
13
- // border-radius: var(--radius-2xl, 16px);
11
+ background: var(--status-brand-surface);
14
12
  padding: var(--spacing-32) var(--spacing-28) var(--spacing-32) var(--spacing-28);
15
13
  box-sizing: border-box;
16
14
  }
17
15
 
16
+ /* text-brand, not blue-500: this label is 16px on --status-brand-surface,
17
+ where blue-500 measures 4.20:1 and fails 1.4.3. blue-600 gives 5.72:1.
18
+
19
+ The weight is set through bd-p's font-weight attribute, not here. This rule
20
+ used to declare --typography-fontWeight-medium and it never reached the
21
+ text: the label renders inside bd-p's shadow paragraph, which sets its own
22
+ weight, and a slotted node inherits from its flattened-tree parent -- that
23
+ paragraph -- rather than from this host. Measured, the label came out at
24
+ 400 while this rule asked for 500. */
18
25
  .bd-quickanswer-label {
19
- color: var(--color-blue-500);
20
- font-weight: var(--typography-fontWeight-medium);
26
+ color: var(--color-text-brand);
21
27
  margin: 0 0 var(--spacing-16);
22
28
  }
23
29
 
24
30
  .bd-quickanswer-text {
25
- color: var(--color-neutral-800);
31
+ /* Body copy, same as above: off the text ladder rather than a
32
+ step on it. */
33
+ color: var(--color-text-primary);
26
34
  margin: 0;
27
35
  }
28
36
 
37
+ /* The atom, not a border of our own.
38
+
39
+ This was a bare div with a border-top, and CLAUDE.md is explicit that a
40
+ line separating regions of content is a divider rather than a boundary.
41
+ The reason it was hand-drawn is that bd-divider-horizontal could not say
42
+ what this line needs: its colour prop resolved through COLOR_ROLES, the
43
+ *ink* vocabulary, and no text role expresses --status-brand-border. A
44
+ neutral hairline reads as dirt on a brand tint, so the component drew its
45
+ own rather than accept the wrong colour -- the atom lost a consumer to a
46
+ category error in its own API.
47
+
48
+ token-scales.js now carries BORDER_ROLES and the atom resolves through it
49
+ first, so brand-subtle is sayable and this is an instance again. The
50
+ colour is unchanged: brand-subtle IS --status-brand-border, which is the
51
+ step the hand-drawn rule already named after an earlier fix moved it off
52
+ --color-blue-100.
53
+
54
+ opacity is set to 1 explicitly because the atom dims to 0.25 by default,
55
+ which
56
+ would have taken this line to a quarter of the value the rule asked for.
57
+
58
+ The margins stay here: they are this panel's rhythm, not the rule's. */
29
59
  .bd-quickanswer-divider {
30
- border-top: 1px solid var(--color-blue-100, rgba(59, 130, 246, 0.15));
60
+ display: block;
31
61
  margin: var(--spacing-24) 0 var(--spacing-16);
32
62
  }
33
63
 
@@ -44,19 +74,51 @@ export default css`
44
74
  }
45
75
 
46
76
  .bd-quickanswer-meta-label {
47
- color: var(--color-neutral-500);
77
+ /* subtle is only safe on the page ground: on this tint it lands at 4.33:1 and
78
+ these labels are 11px. muted is the next step in the same family. */
79
+ color: var(--color-text-muted);
80
+ /* no role: this is not the "eyebrow" the package keeps almost naming a role
81
+ for. Measured against the other three sites that share that visual job --
82
+ a small label above a heading -- it shares no axis with any of them:
83
+ .
84
+ bento-grid .bd-bentogrid-eyebrow 16px / 1.5 / 400 / sans / 0 / none
85
+ header-code .bd-headercode-eyebrow 16px / 1.5 / 400 / sans / 0 / none
86
+ highlight .sub-title 14px / 1.5 / 400 / sans / 0 / none
87
+ here 11px / - / 400 / MONO / .04em / UPPERCASE
88
+ .
89
+ The first three are the same treatment at two size steps, and all three
90
+ already resolve through a role: each is a <bd-p variant="regular"|"small">
91
+ and declares nothing but colour and margin, so body-regular and body-small
92
+ answer them and none of them ever had a typography finding. "Eyebrow" turns
93
+ out to be a design pattern -- text above a heading, brand-coloured -- and
94
+ not a typography combination, so there is nothing for a role to name that
95
+ body-regular and body-small do not already say.
96
+ .
97
+ This label is a different treatment: mono, uppercase and tracked at 11px,
98
+ which is a meta strip's key, not a kicker above a title. label-extra-small
99
+ is the only declared role at xxs and it is sans with normal tracking, so it
100
+ describes different text. The size stays a primitive and says why. */
48
101
  font-size: var(--typography-fontSize-xxs);
49
102
  text-transform: uppercase;
50
103
  letter-spacing: 0.04em;
51
- font-family: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
104
+ font-family: var(--typography-fontFamily-mono);
52
105
  }
53
106
 
54
107
  .bd-quickanswer-meta-value {
55
- color: var(--color-neutral-1000);
108
+ color: var(--color-text-primary);
109
+ /* no role: and this is a separate question from the label above, not the
110
+ other half of one. Measured 16px / 400-weight-overridden-to-600 / sans,
111
+ with no transform and no tracking -- it shares nothing with the label but
112
+ the strip it sits in. The two are a pair by function, a key and its
113
+ value, and by treatment they are deliberately unlike: a mono uppercase
114
+ key at 11px against a sans value at 16px. The weight is what marks the
115
+ value as the answer rather than the question, which is emphasis within
116
+ the component's own micro-vocabulary and not a text-content type -- see
117
+ button.css.js's .button--bold for that argument. */
56
118
  font-weight: var(--typography-fontWeight-semibold);
57
119
  }
58
120
 
59
- @media (max-width: 599px) {
121
+ @media ${unsafeCSS(below('sm'))} {
60
122
  .bd-quickanswer-container {
61
123
  padding: var(--spacing-24);
62
124
  }
@@ -2,6 +2,7 @@ import { LitElement, html, nothing } from "lit";
2
2
  import { tokens } from "../../tokens/tokens.js";
3
3
  import "../paragraph/paragraph.js";
4
4
  import quickAnswerCSS from "./quick-answer.css.js";
5
+ import "../divider/divider-horizontal.js";
5
6
 
6
7
  class QuickAnswer extends LitElement {
7
8
  static properties = {
@@ -24,13 +25,13 @@ class QuickAnswer extends LitElement {
24
25
  <div class="bd-quickanswer-container">
25
26
  ${this.label
26
27
  ? html`
27
- <bd-p kind="normal" class="bd-quickanswer-label">
28
+ <bd-p variant="regular" font-weight="medium" class="bd-quickanswer-label">
28
29
  <slot name="label">${this.label}</slot>
29
30
  </bd-p>
30
31
  `
31
32
  : nothing}
32
33
 
33
- <bd-p kind="large" class="bd-quickanswer-text">
34
+ <bd-p variant="large" class="bd-quickanswer-text">
34
35
  <slot name="text">${this.text}</slot>
35
36
  </bd-p>
36
37
 
@@ -38,7 +39,11 @@ class QuickAnswer extends LitElement {
38
39
 
39
40
  ${this.items && this.items.length
40
41
  ? html`
41
- <div class="bd-quickanswer-divider"></div>
42
+ <bd-divider-horizontal
43
+ class="bd-quickanswer-divider"
44
+ color="brand-subtle"
45
+ opacity="1"
46
+ ></bd-divider-horizontal>
42
47
  <div class="bd-quickanswer-meta">
43
48
  ${this.items.map(
44
49
  (item) => html`
@@ -1,5 +1,17 @@
1
1
  import { css } from "lit";
2
2
 
3
+ /**
4
+ * Shared by bd-radio and bd-toggle-radio.
5
+ *
6
+ * Styled entirely from src/tokens/tokens.js — see CLAUDE.md, "The foundation
7
+ * rule". Measurements were matched to the ds-radio design by finding the token
8
+ * that already carries each value.
9
+ *
10
+ * The whole row is the control, not just the circle. That makes clicking the
11
+ * label work and gives the target the 24px minimum WCAG 2.5.8 asks for, which
12
+ * a 20px circle alone cannot reach. Padding rather than a min-height, so the
13
+ * focus ring is inset evenly on all four sides.
14
+ */
3
15
  export default css`
4
16
  :host {
5
17
  display: inline-block;
@@ -8,161 +20,113 @@ export default css`
8
20
  .bd-radio {
9
21
  display: inline-flex;
10
22
  align-items: center;
11
- cursor: pointer;
12
23
  gap: var(--spacing-8);
13
- font-family: sans-serif;
14
- font-size: 14px;
24
+ padding: var(--spacing-2);
25
+ cursor: pointer;
26
+ font-family: var(--typography-fontFamily-sans);
27
+ /* body-small: sm / normal / 1.5, which is what this already rendered on all
28
+ three axes. Only the axes this rule declares are adopted -- the role also
29
+ carries a family and a tracking, and importing those would change text
30
+ the rule never spoke for. */
31
+ font-size: var(--typography-body-small-fontSize);
32
+ line-height: var(--typography-body-small-lineHeight);
33
+ color: var(--color-text-primary);
15
34
  vertical-align: middle;
35
+ outline: none;
16
36
  }
17
37
 
18
- .bd-radio.disabled {
19
- cursor: not-allowed;
20
- opacity: 0.6;
21
- }
22
-
23
- .radio-label {
24
- font-size: 14px;
25
- color: black;
38
+ .bd-radio:focus-visible {
39
+ /* the one focus ring — see Foundations/Focus. A two-colour ring whose
40
+ white inner band keeps it visible on a coloured or dark surface, which a
41
+ single-colour outline cannot do. */
42
+ outline: none;
43
+ box-shadow: var(--focus-outline-primary);
44
+ border-radius: var(--focus-outline-radius);
26
45
  }
27
46
 
28
- .bd-outer,
29
- .custom-radio {
30
- width: var(--spacing-22);
31
- height: var(--spacing-22);
32
- border:var(--spacing-2) solid var(--color-blue-500);
33
- border-radius: 50%;
34
- display: flex;
47
+ /* ---- the circle -------------------------------------------------------
48
+ flex: none matters. Without it the circle shrank in the flex row — it
49
+ rendered 16x22, and a 50% radius on a non-square box is an ellipse. */
50
+ .box {
51
+ flex: none;
52
+ width: var(--dimension-20);
53
+ height: var(--dimension-20);
54
+ box-sizing: border-box;
55
+ /* The action role when unchecked, matching bd-checkbox. ds-radio specifies
56
+ a neutral ring and ds-checkbox a brand one for the same conceptual
57
+ state; the two frames disagree, and one system should not.
58
+
59
+ Spelled as the role rather than the blue-500 step it resolves to: this
60
+ and bd-checkbox were the two atoms a --color-action-primary override
61
+ did not reach, where bd-button and bd-switch already did. */
62
+ border: var(--border-width-2) solid var(--color-action-primary);
63
+ border-radius: var(--radius-full);
64
+ background: var(--color-surface-default);
65
+ display: inline-flex;
35
66
  align-items: center;
36
67
  justify-content: center;
37
- box-sizing: border-box;
38
- transition: border-color 0.2s ease;
68
+ transition: background-color var(--transition-duration-normal) var(--transition-easing-smooth),
69
+ border-color var(--transition-duration-normal) var(--transition-easing-smooth);
39
70
  }
40
71
 
41
- .bd-inner {
42
- width: var(--spacing-12);
43
- height: var(--spacing-12);
44
- background-color: var(--color-blue-500);
45
- border-radius: 50%;
46
- transform: scale(0);
47
- transition: transform 0.2s ease, background-color 0.2s ease;
48
- }
49
-
50
- .bd-inner.visible {
51
- transform: scale(1);
52
- }
53
-
54
- .bd-outer:hover {
55
- border-color: var(--color-blue-700);
72
+ /* ---- checked: the circle fills and the dot is the hole in it ---------- */
73
+ :host([checked]) .box {
74
+ background: var(--color-action-primary);
75
+ border-color: var(--color-action-primary);
56
76
  }
57
77
 
58
- .bd-inner:hover {
59
- background-color: var(--color-blue-700);
78
+ .bd-radio:hover .box {
79
+ border-color: var(--color-action-primary-hover);
60
80
  }
61
81
 
62
- .bd-radio.disabled .bd-outer.checked {
63
- border-color: #b0b0b0;
82
+ :host([checked]) .bd-radio:hover .box {
83
+ background: var(--color-action-primary-hover);
84
+ border-color: var(--color-action-primary-hover);
64
85
  }
65
86
 
66
- .bd-outer.checked:hover {
67
- border-color: var(--color-blue-700);
87
+ .dot {
88
+ width: var(--dimension-12);
89
+ height: var(--dimension-12);
90
+ border-radius: var(--radius-full);
91
+ /* ink on an action fill, like the checkbox mark */
92
+ background: var(--color-action-on-fill);
93
+ transform: scale(0);
94
+ transition: transform var(--transition-duration-normal) var(--transition-easing-smooth);
68
95
  }
69
96
 
70
-
71
- .bd-radio.disabled .bd-outer {
72
- border-color: #b0b0b0;
97
+ :host([checked]) .dot {
98
+ transform: scale(1);
73
99
  }
74
100
 
75
- .bd-radio.disabled .bd-inner {
76
- background-color: #b0b0b0;
77
- }
101
+ /* ---- disabled --------------------------------------------------------
102
+ The label greys with the control rather than the whole row dropping to an
103
+ opacity. Exempt from contrast under WCAG 1.4.3.
78
104
 
79
- .bd-radio[disabled] {
80
- opacity: 0.5;
105
+ The edge is --color-border-disabled, the state role, for the reasons
106
+ written out over bd-checkbox's disabled block: one disabled-edge value
107
+ across the control family, and 2.27:1 where the hierarchy role gave 1.66.
108
+ The dot fill below is a fill rather than an edge and is unchanged. */
109
+ :host([disabled]) .bd-radio {
81
110
  cursor: not-allowed;
111
+ color: var(--color-text-subtle);
82
112
  }
83
113
 
84
-
85
- .bd-radio.focus .bd-outer,
86
- .bd-outer.focus {
87
- outline: var(--spacing-2) solid var(--color-blue-500);
88
- outline-offset: var(--spacing-2);
114
+ :host([disabled]) .box,
115
+ :host([disabled]) .bd-radio:hover .box {
116
+ border-color: var(--color-border-disabled);
117
+ background: var(--color-surface-default);
89
118
  }
90
119
 
91
- .hidden-input {
92
- position: absolute;
93
- width: 1px;
94
- height: 1px;
95
- margin: -1px;
96
- padding: 0;
97
- border: 0;
98
- clip: rect(0 0 0 0);
99
- overflow: hidden;
100
- white-space: nowrap;
120
+ :host([disabled][checked]) .box,
121
+ :host([disabled][checked]) .bd-radio:hover .box {
122
+ background: var(--color-border-subtle);
123
+ border-color: var(--color-border-disabled);
101
124
  }
102
125
 
103
-
104
- .custom-radio::after {
105
- content: "";
106
- position: absolute;
107
- top: 50%;
108
- left: 50%;
109
- width: var(--spacing-12);
110
- height: var(--spacing-12);
111
- background-color: #006dff;
112
- border-radius: 50%;
113
- transform: translate(-50%, -50%) scale(0);
114
- transition: transform 0.2s;
126
+ @media (prefers-reduced-motion: reduce) {
127
+ .box,
128
+ .dot {
129
+ transition: none;
130
+ }
115
131
  }
116
-
117
- input:checked + .custom-radio::after {
118
- transform: translate(-50%, -50%) scale(1);
119
- }
120
-
121
- .bd-radio:not(.disabled):hover .custom-radio {
122
- border-color: #004bbd;
123
- }
124
- .bd-radio.disabled .bd-inner.visible {
125
- background-color: #b0b0b0;
126
- transform: scale(1);
127
- }
128
- .bd-radio:not(.disabled):focus-within .custom-radio {
129
- box-shadow: 0 0 0 3px rgba(0, 109, 255, 0.5);
130
- }
131
- .bd-outer:focus {
132
- outline: none;
133
- }
134
-
135
- .bd-outer:focus-visible {
136
- outline: var(--spacing-2) solid var(--color-blue-500);
137
- outline-offset: var(--spacing-2);
138
- }
139
- .bd-outer:focus:not(:focus-visible) {
140
- outline: none;
141
- }
142
- .bd-outer.focus {
143
- outline: var(--spacing-2) solid var(--color-blue-500);
144
- outline-offset: var(--spacing-2);
145
- }
146
- .bd-outer:active {
147
- outline: var(--spacing-2) solid var(--color-blue-500);
148
- outline-offset: var(--spacing-2);
149
- }
150
- .bd-outer:focus-visible.checked {
151
- outline: var(--spacing-2) solid var(--color-blue-500);
152
- outline-offset: var(--spacing-2);
153
- }
154
-
155
- .bd-outer:focus-visible.checked .bd-inner {
156
- background-color: var(--color-blue-500);
157
- }
158
- .bd-outer:focus-visible .bd-inner.visible {
159
- background-color: var(--color-blue-700);
160
- }
161
- .bd-outer:focus-visible {
162
- border-color: var(--color-blue-700);
163
- }
164
-
165
- .bd-outer:focus-visible .bd-inner.visible {
166
- background-color: var(--color-blue-700);
167
- }
168
132
  `;