@repobit/dex-system-design 0.25.12 → 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 +187 -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,251 @@
1
+ import { html } from 'lit';
2
+ import {
3
+ discoverConsumers,
4
+ docsPage,
5
+ primitiveTable,
6
+ readAllCssText,
7
+ refSection,
8
+ referenceNote,
9
+ resolve,
10
+ tokensFor
11
+ } from './story-chrome.js';
12
+
13
+ export default {
14
+ title: 'Foundations/Dimension',
15
+ tags : ['autodocs']
16
+ };
17
+
18
+ const dimensionStyles = html`
19
+ <style>
20
+ .rule {
21
+ height: var(--spacing-12);
22
+ background: var(--color-blue-500);
23
+ border-radius: var(--radius-sm);
24
+ min-width: 1px;
25
+ }
26
+
27
+ .multiple {
28
+ font-family: var(--typography-fontFamily-mono);
29
+ font-size: var(--typography-fontSize-xxs);
30
+ color: var(--color-neutral-500);
31
+ }
32
+
33
+ .multiple[data-of4='false'] {
34
+ color: var(--color-neutral-900);
35
+ font-weight: var(--typography-fontWeight-semibold);
36
+ }
37
+
38
+ .callout {
39
+ font-size: var(--typography-fontSize-xs);
40
+ line-height: var(--typography-lineHeight-normal);
41
+ color: var(--color-neutral-700);
42
+ background: var(--color-neutral-50);
43
+ border-radius: var(--radius-md);
44
+ padding: var(--spacing-12) var(--spacing-16);
45
+ }
46
+
47
+ .callout code {
48
+ font-family: var(--typography-fontFamily-mono);
49
+ }
50
+
51
+ /* The guide line must cross the boxes at the target height, so the boxes
52
+ and the line share one positioned container and both sit on its floor. */
53
+ .target-zone {
54
+ position: relative;
55
+ padding-top: var(--spacing-24);
56
+ overflow-x: auto;
57
+ }
58
+
59
+ .target-demo {
60
+ display: flex;
61
+ align-items: flex-end;
62
+ gap: var(--spacing-16);
63
+ flex-wrap: nowrap;
64
+ }
65
+
66
+ .guide {
67
+ position: absolute;
68
+ left: 0;
69
+ right: 0;
70
+ border-top: var(--border-width-2) dashed var(--color-red-500);
71
+ pointer-events: none;
72
+ }
73
+
74
+ .guide span {
75
+ position: absolute;
76
+ right: 0;
77
+ top: calc(-1 * var(--spacing-18));
78
+ font-family: var(--typography-fontFamily-mono);
79
+ font-size: var(--typography-fontSize-xxs);
80
+ color: var(--color-red-800);
81
+ background: var(--color-neutral-25);
82
+ padding: 0 var(--spacing-4);
83
+ }
84
+
85
+ .target {
86
+ display: flex;
87
+ align-items: center;
88
+ justify-content: center;
89
+ background: var(--color-blue-100);
90
+ border: var(--border-width-1) solid var(--color-blue-500);
91
+ border-radius: var(--radius-md);
92
+ font-family: var(--typography-fontFamily-mono);
93
+ font-size: var(--typography-fontSize-xxs);
94
+ color: var(--color-neutral-900);
95
+ padding: 0 var(--spacing-8);
96
+ white-space: nowrap;
97
+ }
98
+
99
+ .target--under {
100
+ background: var(--color-red-50);
101
+ border-color: var(--color-red-500);
102
+ }
103
+
104
+ </style>
105
+ `;
106
+
107
+ /**
108
+ * Purely factual: is the value a multiple of 4?
109
+ *
110
+ * The dimension scale never claims a 4px grid — that claim belonged to the
111
+ * --space-* scale, which is gone. So this column
112
+ * reports, it does not judge. What is worth noticing is which values are not
113
+ * multiples of 4, and that is called out under the table.
114
+ */
115
+ function multipleOfFour(value) {
116
+ const px = parseFloat(value);
117
+ if (!Number.isFinite(px)) return html``;
118
+ const isMultiple = px % 4 === 0;
119
+ return html`<span class="multiple" data-of4=${isMultiple}>${isMultiple ? 'yes' : 'no'}</span>`;
120
+ }
121
+
122
+ export const Dimensions = () => {
123
+ const cssText = readAllCssText();
124
+ const consumers = discoverConsumers(cssText);
125
+ const dimensions = tokensFor(cssText, 'dimension-');
126
+ const max = Math.max(...dimensions.map(token => parseFloat(resolve(token)) || 0), 1);
127
+
128
+ // any step that is not a multiple of 4 — should be empty now that the scale is aligned
129
+ const offGrid = dimensions
130
+ .map(token => ({ token, px: parseFloat(resolve(token)) || 0 }))
131
+ .filter(({ px }) => px % 4 !== 0);
132
+
133
+ return html`
134
+ ${dimensionStyles}
135
+ ${docsPage({
136
+ title: 'Dimension',
137
+ lede : html`Fixed sizes for control heights and icon boxes — button and input heights, icon
138
+ squares. Unlike spacing, these are not a rhythm scale; each value exists because a specific
139
+ control needs it.`,
140
+ note: html`The names embed the value (<code>--dimension-36</code>), so changing a value
141
+ means renaming the token or leaving the name lying. There is no semantic height alias
142
+ to prefer instead: the <code>--button-medium-*</code> family covers fontSize, padding,
143
+ gap and borderRadius and deliberately has no height, because buttons here are
144
+ padding-driven and have no height at all. Form controls are the ones with a height
145
+ contract, and <code>form-field.css.js</code> derives it — padding plus fontSize times
146
+ lineHeight — so the box and the text it holds cannot disagree. Copy that shape rather
147
+ than reaching for a height token. ${referenceNote}`,
148
+ children: html`
149
+ ${refSection({
150
+ name : 'Scale',
151
+ meta : `${dimensions.length} steps · --dimension-*`,
152
+ children: primitiveTable({
153
+ caption : 'Dimension scale',
154
+ tokens : dimensions,
155
+ consumers,
156
+ visualHeader: 'Multiple of 4',
157
+ visual : (_token, value) => html`
158
+ <div style="display: flex; align-items: center; gap: var(--spacing-8)">
159
+ <div class="rule" style="width: ${((parseFloat(value) || 0) / max) * 120}px"></div>
160
+ ${multipleOfFour(value)}
161
+ </div>
162
+ `
163
+ })
164
+ })}
165
+ ${refSection({
166
+ name : 'Grid alignment',
167
+ children: html`
168
+ <div class="callout">
169
+ <p style="margin: 0">
170
+ ${offGrid.length
171
+ ? html`<b>${offGrid.map(({ px }) => `${px}px`).join(', ')}</b> ${offGrid.length === 1 ? 'is' : 'are'}
172
+ not ${offGrid.length === 1 ? 'a multiple' : 'multiples'} of 4. Every other step is.`
173
+ : html`Every step is a multiple of 4, and each token is named after its own
174
+ value. The control heights were <code>34px</code>, <code>45px</code> and
175
+ <code>55px</code> before this scale was aligned; they are now
176
+ <code>36px</code>, <code>44px</code> and <code>56px</code>, which also puts
177
+ the medium control exactly on the 44px WCAG 2.5.5 target.`}
178
+ </p>
179
+ </div>
180
+ `
181
+ })}
182
+ `
183
+ })}
184
+ `;
185
+ };
186
+
187
+ export const TouchTargets = () => {
188
+ const cssText = readAllCssText();
189
+ const consumers = discoverConsumers(cssText);
190
+ const touch = tokensFor(cssText, 'touch-');
191
+
192
+ const minimum = parseFloat(resolve('--touch-target-size')) || 44;
193
+ const controls = [
194
+ ['--dimension-36', 'button/input small'],
195
+ ['--dimension-44', 'button/input medium'],
196
+ ['--dimension-56', 'button/input large']
197
+ ];
198
+
199
+ return html`
200
+ ${dimensionStyles}
201
+ ${docsPage({
202
+ title: 'Touch targets',
203
+ lede : html`<code>--touch-target-size</code> is the minimum hit area for a pointer or finger,
204
+ and <code>--touch-target-spacing</code> the minimum gap between two of them.`,
205
+ note: html`WCAG 2.2 has two thresholds: <b>2.5.8 Target Size (Minimum)</b> is level AA and
206
+ asks for <b>24×24</b> CSS px; <b>2.5.5 Target Size (Enhanced)</b> is level AAA and asks for
207
+ <b>44×44</b>. This token encodes the AAA figure. ${referenceNote}`,
208
+ children: html`
209
+ ${refSection({
210
+ name : 'Tokens',
211
+ meta : `${touch.length} tokens · --touch-*`,
212
+ children: primitiveTable({ caption: 'Touch target tokens', tokens: touch, consumers })
213
+ })}
214
+ ${refSection({
215
+ name : 'Control heights against the target',
216
+ meta : `dashed line = --touch-target-size (${minimum}px)`,
217
+ children: html`
218
+ <div class="specimen">
219
+ <div class="target-zone">
220
+ <div class="target-demo">
221
+ ${controls.map(([token, label]) => {
222
+ const height = parseFloat(resolve(token)) || 0;
223
+ const under = height < minimum;
224
+ return html`
225
+ <div
226
+ class="target ${under ? 'target--under' : ''}"
227
+ style="height: ${height}px"
228
+ title="${label}"
229
+ >
230
+ ${height}px
231
+ </div>
232
+ `;
233
+ })}
234
+ </div>
235
+ <div class="guide" style="bottom: ${minimum}px">
236
+ <span>${minimum}px — WCAG 2.5.5 (AAA)</span>
237
+ </div>
238
+ </div>
239
+ <p class="docs-lede" style="margin-top: var(--spacing-16)">
240
+ The small control height is
241
+ <b>${resolve('--dimension-36')}</b>, below the ${minimum}px AAA target but above
242
+ the 24px AA minimum. Where a small control is the only way to perform an action,
243
+ give it padding or spacing so the hit area still reaches ${minimum}px.
244
+ </p>
245
+ </div>
246
+ `
247
+ })}
248
+ `
249
+ })}
250
+ `;
251
+ };
@@ -0,0 +1,143 @@
1
+ import { html } from 'lit';
2
+ import {
3
+ discoverConsumers,
4
+ docsPage,
5
+ primitiveTable,
6
+ readAllCssText,
7
+ refSection,
8
+ referenceNote,
9
+ tokensFor
10
+ } from './story-chrome.js';
11
+
12
+ export default {
13
+ title: 'Foundations/Elevation',
14
+ tags : ['autodocs']
15
+ };
16
+
17
+ const elevationStyles = html`
18
+ <style>
19
+ .shadow-chip {
20
+ width: var(--spacing-64);
21
+ height: var(--spacing-40);
22
+ background: var(--color-neutral-0);
23
+ border-radius: var(--radius-md);
24
+ }
25
+
26
+ /* shadows need room around them or the blur is clipped */
27
+ .shadow-cell {
28
+ padding: var(--spacing-12) var(--spacing-8);
29
+ }
30
+
31
+ .ladder {
32
+ display: flex;
33
+ flex-wrap: wrap;
34
+ gap: var(--spacing-32);
35
+ background: var(--color-neutral-50);
36
+ padding: var(--spacing-32);
37
+ border-radius: var(--radius-md);
38
+ }
39
+
40
+ .ladder figure {
41
+ margin: 0;
42
+ text-align: center;
43
+ }
44
+
45
+ .ladder .card {
46
+ width: var(--spacing-96);
47
+ height: var(--spacing-64);
48
+ background: var(--color-neutral-0);
49
+ border-radius: var(--radius-lg);
50
+ margin-bottom: var(--spacing-8);
51
+ }
52
+
53
+ .ladder figcaption {
54
+ font-family: var(--typography-fontFamily-mono);
55
+ font-size: var(--typography-fontSize-xxs);
56
+ color: var(--color-neutral-600);
57
+ }
58
+
59
+ .value {
60
+ font-family: var(--typography-fontFamily-mono);
61
+ font-size: var(--typography-fontSize-xxs);
62
+ color: var(--color-neutral-600);
63
+ white-space: normal;
64
+ max-width: 32ch;
65
+ line-height: var(--typography-lineHeight-normal);
66
+ }
67
+ </style>
68
+ `;
69
+
70
+ export const Shadows = () => {
71
+ const cssText = readAllCssText();
72
+ const consumers = discoverConsumers(cssText);
73
+
74
+ const all = tokensFor(cssText, 'shadow-');
75
+ const surface = all.filter(token => !token.includes('focus'));
76
+ const rings = all.filter(token => token.includes('focus'));
77
+
78
+ const ladder = ['--shadow-sm', '--shadow-md', '--shadow-lg', '--shadow-xl', '--shadow-2xl'];
79
+
80
+ return html`
81
+ ${elevationStyles}
82
+ ${docsPage({
83
+ title: 'Elevation',
84
+ lede : html`Shadows are the only elevation mechanism in the system — there is no z-index
85
+ scale. <code>sm</code> through <code>2xl</code> form a ladder;
86
+ <code>--shadow-inner</code> is an inset press state.`,
87
+ note : referenceNote,
88
+ children: html`
89
+ ${refSection({
90
+ name : 'Surface shadows',
91
+ meta : `${surface.length} tokens · --shadow-*`,
92
+ children: primitiveTable({
93
+ caption : 'Surface shadow tokens',
94
+ tokens : surface,
95
+ consumers,
96
+ valueClass : 'value',
97
+ visualHeader: 'Preview',
98
+ visual : token =>
99
+ html`<div class="shadow-cell">
100
+ <div class="shadow-chip" style="box-shadow: var(${token})"></div>
101
+ </div>`
102
+ })
103
+ })}
104
+ ${refSection({
105
+ name : 'The ladder on a tinted surface',
106
+ meta : 'sm → 2xl',
107
+ children: html`
108
+ <div class="ladder">
109
+ ${ladder.map(
110
+ token => html`
111
+ <figure>
112
+ <div class="card" style="box-shadow: var(${token})"></div>
113
+ <figcaption>${token.replace('--shadow-', '')}</figcaption>
114
+ </figure>
115
+ `
116
+ )}
117
+ </div>
118
+ `
119
+ })}
120
+ ${refSection({
121
+ name : 'Focus ring shadows',
122
+ meta : `${rings.length} tokens · --shadow-focus-outline-*`,
123
+ children: html`
124
+ <p class="docs-lede">
125
+ Soft 3px rings at 15% alpha. These are decorative glows, not accessible focus
126
+ indicators — see the <b>Focus</b> page for the rings that meet contrast requirements.
127
+ </p>
128
+ ${primitiveTable({
129
+ caption : 'Focus ring shadow tokens',
130
+ tokens : rings,
131
+ consumers,
132
+ valueClass: 'value',
133
+ visual : token =>
134
+ html`<div class="shadow-cell">
135
+ <div class="shadow-chip" style="box-shadow: var(${token})"></div>
136
+ </div>`
137
+ })}
138
+ `
139
+ })}
140
+ `
141
+ })}
142
+ `;
143
+ };
@@ -0,0 +1,276 @@
1
+ import { html } from 'lit';
2
+ import {
3
+ INK,
4
+ PAPER,
5
+ contrast,
6
+ discoverConsumers,
7
+ docsPage,
8
+ levelBadge,
9
+ primitiveTable,
10
+ readAllCssText,
11
+ refSection,
12
+ referenceNote,
13
+ resolve,
14
+ tokensFor
15
+ } from './story-chrome.js';
16
+
17
+ export default {
18
+ title: 'Foundations/Focus',
19
+ tags : ['autodocs']
20
+ };
21
+
22
+ const focusStyles = html`
23
+ <style>
24
+ .rule-note {
25
+ margin: 0 0 var(--spacing-12);
26
+ font-size: var(--typography-fontSize-sm);
27
+ line-height: var(--typography-lineHeight-normal);
28
+ color: var(--color-neutral-900);
29
+ }
30
+
31
+ .rule-note:last-child { margin-bottom: 0; }
32
+
33
+ .rule-code {
34
+ margin: 0 0 var(--spacing-16);
35
+ padding: var(--spacing-12) var(--spacing-16);
36
+ background: var(--color-neutral-50);
37
+ border-radius: var(--radius-md);
38
+ font-family: var(--typography-fontFamily-mono);
39
+ font-size: var(--typography-fontSize-xs);
40
+ line-height: var(--typography-lineHeight-relaxed);
41
+ overflow-x: auto;
42
+ }
43
+ .focus-demo {
44
+ display: flex;
45
+ flex-wrap: wrap;
46
+ gap: var(--spacing-24);
47
+ align-items: center;
48
+ }
49
+
50
+ .focus-demo--dark {
51
+ background: var(--color-neutral-900);
52
+ padding: var(--spacing-24);
53
+ border-radius: var(--radius-md);
54
+ }
55
+
56
+ /* Rings are shown permanently so they can be compared without tabbing. */
57
+ .ring {
58
+ font-family: var(--typography-fontFamily-sans);
59
+ font-size: var(--typography-fontSize-sm);
60
+ font-weight: var(--typography-fontWeight-medium);
61
+ padding: var(--spacing-8) var(--spacing-16);
62
+ border: var(--border-width-1) solid var(--color-neutral-300);
63
+ border-radius: var(--radius-md);
64
+ background: var(--color-neutral-0);
65
+ color: var(--color-neutral-900);
66
+ }
67
+
68
+ .ring-label {
69
+ font-family: var(--typography-fontFamily-mono);
70
+ font-size: var(--typography-fontSize-xxs);
71
+ color: var(--color-neutral-600);
72
+ display: block;
73
+ margin-bottom: var(--spacing-6);
74
+ }
75
+
76
+ .focus-demo--dark .ring-label {
77
+ color: var(--color-neutral-300);
78
+ }
79
+
80
+ /* A genuinely interactive control, so the real :focus-visible can be tested. */
81
+ .try-me {
82
+ font: inherit;
83
+ font-size: var(--typography-fontSize-sm);
84
+ padding: var(--spacing-8) var(--spacing-16);
85
+ border: var(--border-width-1) solid var(--color-neutral-300);
86
+ border-radius: var(--radius-md);
87
+ background: var(--color-neutral-0);
88
+ cursor: pointer;
89
+ }
90
+
91
+ .try-me:focus-visible {
92
+ outline: var(--focus-outline-traditional);
93
+ outline-offset: var(--focus-outline-offset);
94
+ }
95
+
96
+ .try-me--shadow:focus-visible {
97
+ outline: none;
98
+ box-shadow: var(--focus-outline-primary);
99
+ }
100
+
101
+ .value {
102
+ font-family: var(--typography-fontFamily-mono);
103
+ font-size: var(--typography-fontSize-xxs);
104
+ color: var(--color-neutral-600);
105
+ white-space: normal;
106
+ max-width: 34ch;
107
+ line-height: var(--typography-lineHeight-normal);
108
+ }
109
+ </style>
110
+ `;
111
+
112
+ export const FocusRings = () => {
113
+ const cssText = readAllCssText();
114
+ const consumers = discoverConsumers(cssText);
115
+ const tokens = tokensFor(cssText, 'focus-');
116
+
117
+ // -offset and -radius are lengths, not rings; they would render as empty swatches
118
+ const NOT_RINGS = ['--focus-outline-offset', '--focus-outline-radius'];
119
+ const rings = tokens.filter(token => token.startsWith('--focus-outline-') && !NOT_RINGS.includes(token));
120
+ const ringColour = resolve('--color-blue-500');
121
+ const onLight = contrast(ringColour, PAPER);
122
+ const onDark = contrast(ringColour, INK);
123
+
124
+ return html`
125
+ ${focusStyles}
126
+ ${docsPage({
127
+ title: 'Focus',
128
+ lede : html`<code>--focus-outline-primary</code> is <b>the</b> focus ring — every interactive
129
+ component uses it and none define their own. It is a two-colour ring: an
130
+ inner band of <code>--color-neutral-0</code> and an outer band of the state colour. The
131
+ inner band is what makes the ring visible on both light and dark backgrounds.
132
+ <br /><br />
133
+ The ring is a <code>box-shadow</code>, so it already follows the radius of whatever it
134
+ sits on — a component with its own radius should set nothing and let the ring take its
135
+ shape. <code>--focus-outline-radius</code> is the default for the ones that have no
136
+ radius of their own, so the ring is not a hard rectangle around a link or a tab.`,
137
+ note: html`WCAG 2.2 <b>1.4.11 Non-text Contrast</b> asks for <b>3:1</b> between a focus
138
+ indicator and its adjacent background. The blue ring is
139
+ ${onLight.toFixed(2)}${levelBadge(onLight)} on white and
140
+ ${onDark.toFixed(2)}${levelBadge(onDark)} on <code>--color-neutral-900</code> — which is
141
+ exactly why the white inner band matters on dark surfaces. ${referenceNote}`,
142
+ children: html`
143
+ ${refSection({
144
+ name : 'The rule',
145
+ meta : 'one ring, every interactive component',
146
+ children: html`
147
+ <div class="specimen">
148
+ <p class="rule-note">
149
+ Every interactive component shows the same ring on keyboard focus,
150
+ and it is two lines:
151
+ </p>
152
+ <pre class="rule-code"><code>.control:focus-visible {
153
+ outline: none;
154
+ box-shadow: var(--focus-outline-primary);
155
+ }</code></pre>
156
+ <p class="rule-note">
157
+ <b>Always <code>:focus-visible</code>, never <code>:focus</code>.</b>
158
+ <code>:focus</code> fires on a mouse click too, which rings
159
+ something the user just clicked. The browser already decides
160
+ keyboard modality — do not reimplement it. bd-button used to,
161
+ with two requestAnimationFrame hops and a data attribute.
162
+ </p>
163
+ <p class="rule-note">
164
+ <b>Never suppress it without replacing it.</b>
165
+ <code>outline: none</code> on its own removes the only cue a
166
+ keyboard user has for where they are, which fails WCAG 2.4.7. Two
167
+ accordion triggers did exactly that.
168
+ </p>
169
+ <p class="rule-note">
170
+ <b>Text fields are the one exception.</b> Inputs, textareas and
171
+ selects keep the field border and add
172
+ <code>--shadow-focus-outline-blue</code> as a glow, because an
173
+ offset ring around a full-width field reads as a second border.
174
+ Everything else you can operate — buttons, links, checkboxes,
175
+ radios, switches, tabs, accordion triggers, the scrollable code
176
+ block — uses the ring.
177
+ </p>
178
+ </div>
179
+ `
180
+ })}
181
+ ${refSection({
182
+ name : 'Tokens',
183
+ meta : `${tokens.length} tokens · --focus-*`,
184
+ children: primitiveTable({
185
+ caption : 'Focus tokens',
186
+ tokens,
187
+ consumers,
188
+ valueClass: 'value'
189
+ })
190
+ })}
191
+ ${refSection({
192
+ name : 'On a light surface',
193
+ meta : 'rings shown permanently for comparison',
194
+ children: html`
195
+ <div class="specimen">
196
+ <div class="focus-demo">
197
+ ${rings.map(
198
+ token => html`
199
+ <div>
200
+ <span class="ring-label">${token.replace('--focus-outline-', '')}</span>
201
+ <div class="ring" style="box-shadow: var(${token})">Button</div>
202
+ </div>
203
+ `
204
+ )}
205
+ </div>
206
+ </div>
207
+ `
208
+ })}
209
+ ${refSection({
210
+ name : 'On a dark surface',
211
+ meta : 'the white inner band keeps the ring readable',
212
+ children: html`
213
+ <div class="focus-demo focus-demo--dark">
214
+ ${rings.map(
215
+ token => html`
216
+ <div>
217
+ <span class="ring-label">${token.replace('--focus-outline-', '')}</span>
218
+ <div class="ring" style="box-shadow: var(${token})">Button</div>
219
+ </div>
220
+ `
221
+ )}
222
+ </div>
223
+ `
224
+ })}
225
+ ${refSection({
226
+ name : 'Try it',
227
+ meta : 'tab to these — real :focus-visible, not a simulation',
228
+ children: html`
229
+ <div class="specimen">
230
+ <div class="focus-demo">
231
+ <button class="try-me">outline (traditional)</button>
232
+ <button class="try-me try-me--shadow">box-shadow (two-colour)</button>
233
+ </div>
234
+ </div>
235
+ `
236
+ })}
237
+ ${refSection({
238
+ name : 'The ring owns its corner',
239
+ meta : 'one place to change it',
240
+ children: html`
241
+ <p>
242
+ The ring is a <code>box-shadow</code>, so it already follows the corner of whatever
243
+ it is on. <code>--focus-outline-radius</code> is for the elements that have no
244
+ corner of their own, and it is the only place a standard ring should get one.
245
+ Five components used to set <code>--radius-lg</code> here instead, so the same
246
+ indicator drew an 8px corner in five places and a 4px corner in fifteen. They
247
+ resolve through the role now, which makes the radius one decision in one place
248
+ rather than five — <code>focus-radius-bypass</code> in
249
+ <code>npm run lint:tokens</code> fails on a new one.
250
+ </p>
251
+ <p>
252
+ <b>The exception is shape, not preference.</b> A circular control needs a circular
253
+ ring, so <code>--radius-full</code> and <code>50%</code> are allowed and the
254
+ AwardsFlex dot uses one. The rule knows about that case; a new kind of exception
255
+ belongs in the rule with a self-test, not in a comment.
256
+ </p>
257
+ <p>
258
+ <b>A ring that is clipped is not an indicator.</b> It is drawn outside the box, so
259
+ an ancestor with <code>overflow: hidden</code> can cut it off entirely while every
260
+ static check still passes. Leave at least 4px of room inside any clipping ancestor,
261
+ or move the clipping.
262
+ </p>
263
+ <p>
264
+ <b>Verify with the keyboard, not with code.</b> Calling
265
+ <code>element.focus()</code> does not reliably match
266
+ <code>:focus-visible</code>, so a programmatic check can report a ring that a
267
+ reader never sees — and can equally miss one that is broken. Press Tab. Two real
268
+ defects in this package were invisible to programmatic focus and obvious to a
269
+ keyboard: the header's ring never reached its slotted links, and one accordion
270
+ variant drew a different colour from the other.
271
+ </p>`
272
+ })}
273
+ `
274
+ })}
275
+ `;
276
+ };