@repobit/dex-system-design 0.25.12 → 1.0.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 +204 -0
  2. package/README.md +131 -8
  3. package/package.json +96 -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
@@ -1,8 +1,9 @@
1
1
  import { html } from 'lit';
2
+ import { until } from 'lit/directives/until.js';
2
3
  import './display.js';
3
4
 
4
5
  export default {
5
- title : 'Components/Display',
6
+ title : 'Atoms/Display',
6
7
  tags : ['autodocs'],
7
8
  parameters: {
8
9
  docs: {
@@ -12,35 +13,61 @@ export default {
12
13
 
13
14
  ### Usage
14
15
  \`\`\`html
15
- <bd-display kind="xl" color="#026DFF" align="center">
16
+ <bd-display variant="xl" color="primary" align="center">
16
17
  World-class protection
17
18
  </bd-display>
18
19
  \`\`\`
19
20
 
20
- ### Kind Values
21
- | Kind | Description |
22
- |---|---|
23
- | \`sm\` | Small display |
24
- | \`md\` | Medium display (default) |
25
- | \`lg\` | Large display |
26
- | \`xl\` | Extra large |
27
- | \`xxl\` | 2x extra large |
28
- | \`xxxl\` | 3x extra large |
21
+ ### The six steps, and which of them a phone can take
22
+
23
+ | variant | role | desktop | at 320 | fits a 288px column? |
24
+ |---|---|---|---|---|
25
+ | \`sm\` | \`display-sm\` | 36px | **30px**, fluid | yes |
26
+ | \`md\` | \`display-md\` | 48px | **30px**, fluid | yes |
27
+ | \`lg\` | \`display-lg\` | 60px | 60px, fixed | only words under 480 per 100px |
28
+ | \`xl\` | \`display-xl\` | 72px | 72px, fixed | rarely |
29
+ | \`xxl\` | \`display-2xl\` | 96px | 96px, fixed | no |
30
+ | \`xxxl\` | \`display-3xl\` | 128px | 128px, fixed | no |
31
+
32
+ **\`md\` is the default**, as of 2026-09-17 — the largest step that fits at
33
+ every width. It used to be \`lg\`, the largest step that does *not*; see
34
+ \`plans/LATER.md\` entry 14, and *On a phone* below, which measures all six in
35
+ a real 288px column. An unrecognised variant lands on \`md\` too, because a
36
+ typo should not render larger than what was asked for.
37
+
38
+ ### Four of these roles are desktop-only, and that is a decision
39
+
40
+ Decided 2026-09-17, \`plans/LATER.md\` entry 9. \`display-sm\` and
41
+ \`display-md\` are fluid — \`clamp()\` in the role token, floor 30px at a 320px
42
+ viewport. **\`lg\`, \`xl\`, \`2xl\` and \`3xl\` are not, and will not be.**
43
+
44
+ Giving them mobile endpoints was measured and rejected. A floor that fits the
45
+ widest token in the production sample is **29px**, so all four would land on
46
+ the same number as \`sm\` and \`md\` — which already share 30 and are
47
+ indistinguishable at 320. Six steps rendering one size makes \`variant\` a
48
+ no-op on a phone, which is worse than a step that has to be chosen.
49
+
50
+ So the rule is: **which step belongs at which breakpoint is the composing
51
+ page's choice, and the role never shrinks itself.** The atom contains the
52
+ damage rather than hiding it — \`overflow-wrap: break-word\` keeps a 128px
53
+ word inside the column instead of scrolling the document sideways — but a
54
+ contained word is still split across four lines. Step down.
29
55
  `
30
56
  }
31
57
  }
32
58
  },
33
59
  argTypes: {
34
- kind: {
60
+ variant: {
35
61
  control : { type: 'select' },
36
62
  options : ['sm', 'md', 'lg', 'xl', 'xxl', 'xxxl'],
37
- description: 'Display size variant — maps to a CSS class',
38
- table : { type: { summary: "'sm'|'md'|'lg'|'xl'|'xxl'|'xxxl'" }, defaultValue: { summary: 'lg' }, category: 'Appearance' }
63
+ description: 'Which display role to render. `kind` is the old name and still resolves.',
64
+ table : { type: { summary: "'sm'|'md'|'lg'|'xl'|'xxl'|'xxxl'" }, defaultValue: { summary: 'md' }, category: 'Appearance' }
39
65
  },
40
66
  color: {
41
- control : 'color',
42
- description: 'Inline text color applied via style attribute',
43
- table : { type: { summary: 'string' }, defaultValue: { summary: '' }, category: 'Appearance' }
67
+ control : { type: 'select' },
68
+ options : ['', 'primary', 'strong', 'muted', 'subtle', 'inverse', 'success', 'warning', 'error'],
69
+ description: 'A semantic colour role, not a CSS colour. Resolves to a palette token; anything else is dropped.',
70
+ table : { type: { summary: 'string' }, defaultValue: { summary: "''" }, category: 'Appearance' }
44
71
  },
45
72
  align: {
46
73
  control : { type: 'select' },
@@ -52,43 +79,51 @@ export default {
52
79
  };
53
80
 
54
81
  const render = (args) => html`
55
- <bd-display kind="${args.kind}" color="${args.color}" align="${args.align}">
82
+ <bd-display variant="${args.variant}" color="${args.color}" align="${args.align}">
56
83
  World-class security software
57
84
  </bd-display>
58
85
  `;
59
86
 
60
- const defaultArgs = { kind: 'lg', color: '', align: 'left' };
87
+ const defaultArgs = { variant: 'md', color: '', align: 'left' };
61
88
 
62
89
  // ─── Stories ───────────────────────────────────────────────────────────────
63
90
 
64
91
  export const Default = {
65
- name : 'Default (lg, left)',
66
- render : () => html`<bd-display kind="lg">World-class security software</bd-display>`,
67
- parameters: { docs: { description: { story: 'Default display text with `kind="lg"` and left alignment.' } } }
92
+ name : 'Default (md, left)',
93
+ render : () => html`<bd-display>World-class security software</bd-display>`,
94
+ parameters: {
95
+ docs: {
96
+ description: {
97
+ story: 'No `variant` at all — this is what a bare `<bd-display>` renders. It is '
98
+ + '`md` (48px on desktop, 30px on a phone) since 2026-09-17; it was `lg` (60px, '
99
+ + 'fixed at every width) before. See `plans/LATER.md` entry 14.'
100
+ }
101
+ }
102
+ }
68
103
  };
69
104
 
70
105
  export const AllKinds = {
71
106
  name : 'All Kinds',
72
107
  render: () => html`
73
108
  <div style="display:flex; flex-direction:column; gap:16px;">
74
- <bd-display kind="sm">Small Display</bd-display>
75
- <bd-display kind="md">Medium Display</bd-display>
76
- <bd-display kind="lg">Large Display</bd-display>
77
- <bd-display kind="xl">Extra Large Display</bd-display>
78
- <bd-display kind="xxl">2x Extra Large</bd-display>
79
- <bd-display kind="xxxl">3x Extra Large</bd-display>
109
+ <bd-display variant="sm">Small Display</bd-display>
110
+ <bd-display variant="md">Medium Display</bd-display>
111
+ <bd-display variant="lg">Large Display</bd-display>
112
+ <bd-display variant="xl">Extra Large Display</bd-display>
113
+ <bd-display variant="xxl">2x Extra Large</bd-display>
114
+ <bd-display variant="xxxl">3x Extra Large</bd-display>
80
115
  </div>
81
116
  `,
82
- parameters: { docs: { description: { story: 'All six `kind` values stacked vertically for scale comparison.' } } }
117
+ parameters: { docs: { description: { story: 'All six `variant` values stacked vertically for scale comparison.' } } }
83
118
  };
84
119
 
85
120
  export const AllAlignments = {
86
121
  name : 'All Alignments',
87
122
  render: () => html`
88
123
  <div style="display:flex; flex-direction:column; gap:16px; width:100%;">
89
- <bd-display kind="lg" align="left">Left aligned display</bd-display>
90
- <bd-display kind="lg" align="center">Center aligned display</bd-display>
91
- <bd-display kind="lg" align="right">Right aligned display</bd-display>
124
+ <bd-display variant="lg" align="left">Left aligned display</bd-display>
125
+ <bd-display variant="lg" align="center">Center aligned display</bd-display>
126
+ <bd-display variant="lg" align="right">Right aligned display</bd-display>
92
127
  </div>
93
128
  `,
94
129
  parameters: { docs: { description: { story: 'All three alignment options: left, center, and right.' } } }
@@ -98,10 +133,10 @@ export const CustomColor = {
98
133
  name : 'Custom Color',
99
134
  render: () => html`
100
135
  <div style="display:flex; flex-direction:column; gap:12px;">
101
- <bd-display kind="lg" color="#026DFF">Blue Display</bd-display>
102
- <bd-display kind="lg" color="#E53935">Red Display</bd-display>
103
- <bd-display kind="lg" color="#43A047">Green Display</bd-display>
104
- <bd-display kind="lg" color="var(--color-neutral-1000)">Token Color</bd-display>
136
+ <bd-display variant="lg" color="primary">Blue Display</bd-display>
137
+ <bd-display variant="lg" color="error">Red Display</bd-display>
138
+ <bd-display variant="lg" color="success">Green Display</bd-display>
139
+ <bd-display variant="lg" color="strong">Token Color</bd-display>
105
140
  </div>
106
141
  `,
107
142
  parameters: { docs: { description: { story: 'Custom `color` values including hex codes and CSS custom properties.' } } }
@@ -111,17 +146,212 @@ export const HeroVariant = {
111
146
  name : 'Hero Variant',
112
147
  render: () => html`
113
148
  <div style="text-align:center; padding:40px;">
114
- <bd-display kind="xxxl" color="#026DFF" align="center">
149
+ <bd-display variant="xxxl" color="primary" align="center">
115
150
  Award-winning cybersecurity
116
151
  </bd-display>
117
152
  </div>
118
153
  `,
119
- parameters: { docs: { description: { story: 'Large hero-style display with xxxl size, blue color, and center alignment.' } } }
154
+ parameters: {
155
+ docs: {
156
+ description: {
157
+ story: 'Large hero-style display with xxxl size, blue color and center '
158
+ + 'alignment. **A usage pattern, not a variant** — the name predates, and '
159
+ + 'outlived, a `hero` variant that no longer exists. That variant and its '
160
+ + '`--typography-display-hero-*` role were retired because a 64px header '
161
+ + 'headline was their only reason to exist and the chosen header '
162
+ + 'configuration dropped to 48. There is no `hero` value on this prop; '
163
+ + 'this story reaches for `xxxl` and always did.'
164
+ }
165
+ }
166
+ }
167
+ };
168
+
169
+ /* Measured live, because a width written down is a width that goes stale --
170
+ and because measuring before IBM Plex Bold has loaded reads system-ui and
171
+ comes out about 3% narrow. See Foundations/Typography -> Why These Sizes. */
172
+ const PHONE_WORDS = [
173
+ ['Safe', 'en'],
174
+ ['Security', 'en'],
175
+ ['Protection', 'en'],
176
+ ['Cybersecurity', 'en'],
177
+ ['Gründungsmitglied', 'de'],
178
+ ['kalenderinbjudningar', 'sv']
179
+ ];
180
+ /* variant, desktop size, and the 320px floor for the two FLUID roles -- null
181
+ means the role has no mobile endpoint and renders its desktop size at every
182
+ width, which is the whole subject of this story. */
183
+ const STEPS = [
184
+ ['sm', 36, 30], ['md', 48, 30],
185
+ ['lg', 60, null], ['xl', 72, null], ['xxl', 96, null], ['xxxl', 128, null]
186
+ ];
187
+ const COLS = [[320, 288], [375, 343]];
188
+ const FLUID_WINDOW = [320, 992];
189
+
190
+ /** What a clamp(min, .., max) role resolves to at a given viewport width. */
191
+ const fluidAt = (vw, min, max) => {
192
+ const [v1, v2] = FLUID_WINDOW;
193
+ if (vw <= v1) return min;
194
+ if (vw >= v2) return max;
195
+ return min + ((max - min) * (vw - v1)) / (v2 - v1);
196
+ };
197
+
198
+ /** Width per px of size, at the display family's own tight tracking. */
199
+ function displayPer(text) {
200
+ const el = document.createElement('span');
201
+ el.style.cssText = 'position:absolute;visibility:hidden;white-space:nowrap;'
202
+ + 'font-family:var(--typography-fontFamily-sans);font-weight:700;'
203
+ + 'letter-spacing:var(--typography-letterSpacing-tight);font-size:100px';
204
+ el.textContent = text;
205
+ document.body.appendChild(el);
206
+ const w = el.getBoundingClientRect().width / 100;
207
+ el.remove();
208
+ return w;
209
+ }
210
+
211
+ const phoneColumn = async () => {
212
+ await document.fonts.load('700 100px "IBM Plex Sans"');
213
+ await document.fonts.ready;
214
+ const rows = PHONE_WORDS.map(([word, lang]) => {
215
+ const per = displayPer(word);
216
+ return { word, lang, per, max: COLS.map(([, col]) => Math.floor(col / per)) };
217
+ });
218
+ const probe = displayPer('Cybersecurity');
219
+
220
+ return html`
221
+ <div style="display:grid; gap:var(--spacing-32)">
222
+ <p style="margin:0; max-width:64ch">
223
+ Every step of the family set in <b>Cybersecurity</b> inside a real 288px column —
224
+ what type gets on a 320px phone once both <code>--grid-padding-*</code> gutters
225
+ come out. Nothing scrolls sideways, because the atom sets
226
+ <code>overflow-wrap: break-word</code>; look instead at <b>where the word breaks</b>.
227
+ </p>
228
+ <!-- STACKED, not side by side. At 128px this word overruns its column by
229
+ 508px, so two columns in a row painted over each other and the wider
230
+ one won. The overflow is the finding; the overlap was just my layout. -->
231
+ <div style="display:flex; flex-direction:column; gap:var(--spacing-48)">
232
+ ${COLS.map(([vw, col]) => html`
233
+ <div>
234
+ <p style="margin:0 0 var(--spacing-8); font:500 12px/1.4 var(--typography-fontFamily-mono);
235
+ color:var(--color-text-muted)">
236
+ ${vw}px viewport · ${col}px column
237
+ </p>
238
+ <!-- The two fluid roles are pinned to the value their clamp resolves to
239
+ at THIS viewport, not at the one your browser happens to be. Without
240
+ the pin the demo drew md at its desktop 48 inside a phone column and
241
+ called it a split, which is the opposite of what a phone does. -->
242
+ <div style="width:${col}px; outline:2px dashed var(--color-text-error);
243
+ display:grid; gap:var(--spacing-16); padding-block:var(--spacing-12);
244
+ --typography-display-sm-fontSize:${Math.round(fluidAt(vw, 30, 36))}px;
245
+ --typography-display-md-fontSize:${Math.round(fluidAt(vw, 30, 48))}px">
246
+ ${STEPS.map(([variant, desktop, floor]) => {
247
+ /* The size this role really renders at THIS viewport: the
248
+ clamp's value for the two fluid roles, the fixed desktop
249
+ size for the other four. */
250
+ const size = floor === null ? desktop : Math.round(fluidAt(vw, floor, desktop));
251
+ const need = Math.round(probe * size);
252
+ const fits = need <= col;
253
+ return html`
254
+ <!-- min-width:0 on the row and display:block on the atom: a grid
255
+ item keeps its min-content width by default, and an inline
256
+ host does not hand the shadow div a width to break against,
257
+ so without both the word overflowed instead of wrapping --
258
+ which would have libelled the component's own break-word. -->
259
+ <div style="min-width:0">
260
+ <div style="font:500 10px/1.4 var(--typography-fontFamily-mono);
261
+ color:${fits ? 'var(--color-text-muted)' : 'var(--color-text-error)'}">
262
+ ${variant} · ${size}px${floor === null ? '' : ' (fluid)'} · needs ${need}
263
+ ${fits ? html`· fits by ${col - need}` : html`· <b>splits</b>, over by ${need - col}`}
264
+ </div>
265
+ <bd-display variant="${variant}" style="display:block">Cybersecurity</bd-display>
266
+ </div>
267
+ `;
268
+ })}
269
+ </div>
270
+ </div>
271
+ `)}
272
+ </div>
273
+ <div style="overflow-x:auto">
274
+ <table style="border-collapse:collapse; font-size:14px">
275
+ <caption style="text-align:left; padding-bottom:var(--spacing-8); color:var(--color-text-muted)">
276
+ The largest display size each word can take, measured in this browser at the
277
+ family's own tracking
278
+ </caption>
279
+ <thead>
280
+ <tr>
281
+ ${['word', 'lang', 'w / 100px', '288px column', '343px column'].map(h => html`
282
+ <th style="text-align:left; padding:6px 12px; border-bottom:1px solid var(--color-border-default)">${h}</th>
283
+ `)}
284
+ </tr>
285
+ </thead>
286
+ <tbody>
287
+ ${rows.map(r => html`
288
+ <tr>
289
+ <td style="padding:6px 12px">${r.word}</td>
290
+ <td style="padding:6px 12px"><code>${r.lang}</code></td>
291
+ <td style="padding:6px 12px">${Math.round(r.per * 100)}</td>
292
+ <td style="padding:6px 12px">${r.max[0]}px</td>
293
+ <td style="padding:6px 12px">${r.max[1]}px</td>
294
+ </tr>
295
+ `)}
296
+ </tbody>
297
+ </table>
298
+ </div>
299
+ <p style="margin:0; max-width:64ch">
300
+ <b>Read the last two rows.</b> A German or Swedish compound caps the family at
301
+ ${rows[4].max[0]}–${rows[5].max[0]}px on a phone — below every step except the
302
+ fluid floor that <code>sm</code> and <code>md</code> already reach. That is the
303
+ measurement that decided the four large roles stay desktop-only: there is no
304
+ mobile endpoint to give them that would not collapse the whole family onto one
305
+ size.
306
+ </p>
307
+ </div>
308
+ `;
309
+ };
310
+
311
+ export const PhoneColumn = {
312
+ name : 'On a phone (288px column)',
313
+ render : () => html`${until(phoneColumn(), html`<p style="color:var(--color-text-muted)">Loading IBM Plex Sans Bold before measuring anything…</p>`)}`,
314
+ parameters: {
315
+ controls: { disable: true },
316
+ docs : {
317
+ description: {
318
+ story: `The limit, measured rather than asserted. **\`sm\` and \`md\` are fluid** and
319
+ reach a 30px floor at 320, so they fit. **\`lg\` and up are fixed**, so on a phone the
320
+ word breaks mid-syllable — contained, but not designed.
321
+
322
+ The atom deliberately knows nothing about viewports: it maps a variant onto a
323
+ \`--typography-display-*\` role, and six steps exist precisely so the composing page can
324
+ choose one per breakpoint. \`plans/LATER.md\` entry 9 has the decision and the rejected
325
+ alternative.`
326
+ }
327
+ }
328
+ }
120
329
  };
121
330
 
122
331
  export const Playground = {
123
332
  name : '🛝 Playground',
124
333
  args : { ...defaultArgs },
125
334
  render,
126
- parameters: { docs: { description: { story: 'Interactive playground. Adjust kind, color, and alignment via Controls.' } } }
127
- };
335
+ parameters: { docs: { description: { story: 'Interactive playground. Adjust variant, color, and alignment via Controls.' } } }
336
+ };
337
+ export const LegacyKind = {
338
+ name : 'Legacy kind prop',
339
+ render: () => html`
340
+ <div style="display:grid; gap: var(--spacing-16)">
341
+ <bd-display variant="sm">kind="sm" — the old spelling</bd-display>
342
+ <bd-display variant="sm">variant="sm" — the current one</bd-display>
343
+ </div>
344
+ `,
345
+ parameters: {
346
+ docs: {
347
+ description: {
348
+ story: `The visual axis was called \`kind\` before the vocabulary settled on
349
+ one word per axis — \`size\` for how big, \`variant\` for how it looks, \`tone\` for
350
+ what it means. bd-p and bd-li were converted then and this atom was missed.
351
+
352
+ \`kind\` still resolves to \`variant\`, so no consumer's markup breaks. These two
353
+ rows must render identically; if they ever stop, the alias has been dropped.`
354
+ }
355
+ }
356
+ }
357
+ };
@@ -1,9 +1,11 @@
1
1
  import { LitElement, html } from "lit";
2
- import { tokens } from "../../tokens/tokens.js";
2
+ // Installs the design tokens into document scope; see src/tokens/tokens.js
3
+ import "../../tokens/tokens.js";
3
4
  import { dividerHorizontal } from "./divider.css.js";
5
+ import { borderColor } from "../shared/token-scales.js";
4
6
 
5
7
  export class BdDividerHorizontal extends LitElement {
6
- static styles = [tokens, dividerHorizontal];
8
+ static styles = [dividerHorizontal];
7
9
 
8
10
  static properties = {
9
11
  width : { type: String },
@@ -13,18 +15,32 @@ export class BdDividerHorizontal extends LitElement {
13
15
 
14
16
  constructor() {
15
17
  super();
16
- this.width = "";
17
- this.color = "var(--color-neutral-400)";
18
+ this.width = "100%"; // the rule spans its container by default
19
+ /* No colour by default: the stylesheet draws the rule in
20
+ --color-border-default, which is the role for a hairline, and leaving
21
+ this empty lets that stand. It used to say "subtle", which is a *text*
22
+ role — it resolved to the same step by coincidence, so the divider was
23
+ reading its colour out of the ink vocabulary and nobody could see it.
24
+
25
+ The prop now resolves through BORDER_ROLES first (see token-scales.js),
26
+ so `subtle` means --color-border-subtle and a rule on a brand tint can
27
+ ask for `brand-subtle`. The ink vocabulary is still accepted as a
28
+ fallback for the names already in the markup. */
29
+ this.color = "";
18
30
  this.opacity = "0.25";
19
31
  }
20
32
 
21
33
  render() {
34
+ // An unrecognised or empty colour emits no declaration at all, so the
35
+ // stylesheet's --color-border-default stands rather than being overridden
36
+ // with an empty value.
37
+ const ink = borderColor(this.color);
22
38
  return html`
23
39
  <hr
24
40
  class="hr-line"
25
41
  style="
26
42
  width: ${this.width};
27
- border-top-color: ${this.color};
43
+ ${ink ? `border-top-color: ${ink};` : ''}
28
44
  opacity: ${this.opacity};
29
45
  "
30
46
  />
@@ -1,9 +1,11 @@
1
1
  import { LitElement, html } from "lit";
2
- import { tokens } from "../../tokens/tokens.js";
2
+ // Installs the design tokens into document scope; see src/tokens/tokens.js
3
+ import "../../tokens/tokens.js";
3
4
  import { dividerVertical } from "./divider.css.js";
5
+ import { borderColor, spacing } from "../shared/token-scales.js";
4
6
 
5
7
  export class BdDividerVertical extends LitElement {
6
- static styles = [tokens, dividerVertical];
8
+ static styles = [dividerVertical];
7
9
 
8
10
  static properties = {
9
11
  height : { type: String },
@@ -15,23 +17,29 @@ export class BdDividerVertical extends LitElement {
15
17
 
16
18
  constructor() {
17
19
  super();
18
- this.height = "15px";
20
+ this.height = "16"; // a spacing step; was a 15px literal, off every scale
19
21
  this.thickness = "1px";
20
- this.color = "var(--color-neutral-400)";
22
+ /* No colour by default — see the note in divider-horizontal.js. The
23
+ stylesheet's --color-border-default is the role for a hairline; "subtle"
24
+ was a text role that happened to resolve to the same step. The prop
25
+ resolves through BORDER_ROLES first; see token-scales.js. */
26
+ this.color = "";
21
27
  this.opacity = "1.00";
22
28
 
23
29
  }
24
30
 
25
31
  render() {
32
+ // See divider-horizontal.js: no colour means no declaration, so the
33
+ // stylesheet's --color-border-default stands.
34
+ const ink = borderColor(this.color);
26
35
  return html`
27
36
  <div
28
37
  class="divider"
29
38
  style="
30
39
  width: ${this.thickness};
31
- height: ${this.height};
32
- background-color: ${this.color};
40
+ height: ${spacing(this.height)};
41
+ ${ink ? `background-color: ${ink};` : ''}
33
42
  opacity: ${this.opacity};
34
-
35
43
  "
36
44
  ></div>
37
45
  `;
@@ -3,7 +3,7 @@ import { css } from "lit";
3
3
  export const dividerHorizontal = css`
4
4
  .hr-line {
5
5
  border: none;
6
- border-top: 1px solid var(--color-neutral-400);
6
+ border-top: var(--border-width-1) solid var(--color-border-default);
7
7
  margin: 0;
8
8
  width: 100%;
9
9
  margin-left: auto;
@@ -13,7 +13,7 @@ export const dividerHorizontal = css`
13
13
 
14
14
  export const dividerVertical = css`
15
15
  .divider {
16
- background-color: var(--color-neutral-400);
16
+ background-color: var(--color-border-default);
17
17
  display: inline-block;
18
18
  }
19
19
  `;