@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
@@ -1,51 +1,67 @@
1
- import { html } from 'lit';
1
+ import { html, nothing } from 'lit';
2
2
  import './button.js';
3
+ import '../icons/close-icon.js';
4
+ import '../icons/plus-icon.js';
3
5
 
4
6
  export default {
5
- title : 'Components/Button',
7
+ title : 'Atoms/Button',
6
8
  tags : ['autodocs'],
7
9
  parameters: {
8
10
  docs: {
9
11
  description: {
10
12
  component: `
11
- Three button components are available:
13
+ Three elements, styled identically and **not** interchangeable:
12
14
 
13
- - \`<bd-button>\` — a standard \`<button>\` element with click/keyboard events and active state
14
- - \`<bd-button-link>\` — an \`<a>\` tag styled as a button, supports buy link data attributes
15
- - \`<bd-contact-button>\` — a specialized contact CTA with an arrow icon
15
+ - \`<bd-button>\` — a \`<button>\`. **Performs an action in place.** Announced as
16
+ "button", activated by Space *and* Enter.
17
+ - \`<bd-button-link>\` — an \`<a href>\`. **Navigates.** Announced as "link",
18
+ appears in a screen reader's list of links, and supports open-in-new-tab,
19
+ middle-click and copy-address. Enter only.
20
+ - \`<bd-contact-button>\` — a fixed "Contact us" CTA with a trailing arrow. A
21
+ preset, not a variant: no size or variant axis.
22
+
23
+ Pick by what the control *does*, never by how it should look. The two share a
24
+ base class, so \`kind\`, \`size\`, the states and the focus ring are defined once.
16
25
 
17
26
  ### Usage
18
27
  \`\`\`html
19
- <bd-button kind="primary" size="md">Click me</bd-button>
20
- <bd-button kind="danger" size="md">Activez votre protection</bd-button>
21
- <bd-button kind="primary" size="md" shape="rounded">Rounded</bd-button>
22
- <bd-button-link kind="danger" size="lg" href="/buy">Buy now</bd-button-link>
28
+ <bd-button variant="primary" size="md">Click me</bd-button>
29
+ <bd-button-link variant="accent" size="lg" href="/buy">Buy now</bd-button-link>
23
30
  <bd-contact-button label="Contact us" href="/contact"></bd-contact-button>
24
31
  \`\`\`
25
32
 
26
- ### Kind Values
27
- | Kind | Class |
33
+ ### Kind
34
+ | Kind | Appearance | Was |
35
+ |---|---|---|
36
+ | \`primary\` | blue fill | \`primary\` |
37
+ | \`secondary\` | near-black fill | \`secondary\` |
38
+ | \`tertiary\` | blue 2px outline | \`primary-outline\` |
39
+ | \`ghost\` | dark 2px outline | \`outline\` |
40
+ | \`accent\` | red fill | \`danger\`, \`destructive\` |
41
+
42
+ All four old values still work as deprecated aliases. Note \`ghost\` here is an
43
+ *outlined* button, not the borderless control the name usually implies.
44
+
45
+ ### Red means conversion, not danger
46
+
47
+ In this system red is the **conversion** colour — Buy now and equivalents — not
48
+ a destructive signal. That is why the design file carries an \`accent\` and a
49
+ \`destructive\` variant styled identically: they are one variant recorded twice,
50
+ once under the wrong name. \`accent\` is the one that survives here.
51
+
52
+ The consequence is worth stating plainly: **there is no danger variant.** A
53
+ delete confirmation or a irreversible-action button has nothing to reach for,
54
+ because the obvious colour for it already means "buy". Giving danger its own
55
+ treatment means choosing a colour that is not the conversion red, which is a
56
+ design decision rather than an implementation one.
57
+
58
+ ### State
59
+ | State | |
28
60
  |---|---|
29
- | \`primary\` | \`button--primary\` |
30
- | \`primary-outline\` | \`button--primary--outline\` |
31
- | \`outline\` | \`button--outline\` |
32
- | \`secondary\` | \`button--secondary\` |
33
- | \`danger\` | \`button--danger\` + \`button--with-arrow\` |
34
- | \`white\` | \`button--white\` |
35
- | \`outline-white\` | \`button--outline-white\` |
36
-
37
- ### Danger hover arrow
38
- Every \`kind="danger"\` button (both \`bd-button\` and \`bd-button-link\`) has an arrow hover effect by default:
39
- on hover (and on keyboard \`:focus-visible\`) the label slides to the left and an arrow fades in on the right.
40
- The button width does not change.
41
-
42
- To disable it on a specific button, add the \`no-arrow\` attribute:
43
- \`\`\`html
44
- <bd-button kind="danger" no-arrow>No arrow</bd-button>
45
- \`\`\`
61
+ | \`disabled\` | Filled variants go grey; outlined ones keep a transparent fill and take a subtle border. On the link this drops the \`href\` and sets \`aria-disabled\`, since a link has no native disabled state. |
62
+ | \`loading\` | A spinner in the variant's own colour, sized in \`em\` so it tracks the type scale, plus \`aria-busy\`. Blocks interaction and respects \`prefers-reduced-motion\`. |
46
63
 
47
- The effect can be tuned from outside via CSS custom properties:
48
- \`--button-arrow-size\`, \`--button-arrow-shift\`, \`--button-arrow-inset\`, \`--button-arrow-offset\`.
64
+ Focus is not in the design, but 2.4.7 requires it, so the focus ring is kept.
49
65
 
50
66
  ### Size Values
51
67
  | Size | Class |
@@ -54,13 +70,27 @@ The effect can be tuned from outside via CSS custom properties:
54
70
  | \`md\` | \`button--medium\` |
55
71
  | \`lg\` | \`button--large\` |
56
72
 
57
- ### Shape Values
58
- | Shape | Effect |
59
- |---|---|
60
- | \`default\` | Border radius from the size (\`--radius-md\` / \`--radius-lg\`) |
61
- | \`rounded\` | \`button--rounded\` — border radius \`--spacing-30\` |
73
+ ### Icon-only
74
+ \`icon-only\` turns either element into a circle around one icon: the arrow on
75
+ the homepage's audience cards, a menu or close toggle. It is a mode, not a
76
+ variant, so every \`variant\`, \`size\`, \`surface\` and state applies unchanged.
77
+
78
+ \`\`\`html
79
+ <bd-button-link icon-only variant="accent" href="/home" label="Protect your digital life"></bd-button-link>
80
+ <bd-button icon-only variant="ghost" label="Close"><bd-close-icon></bd-close-icon></bd-button>
81
+ \`\`\`
62
82
 
63
- The rounded radius can be overridden via the \`--button-radius-rounded\` CSS custom property.
83
+ - **\`label\` is required.** There is no visible text, so it is the only name
84
+ the control has. Name what happens, not the picture: "Open menu", not "Menu
85
+ icon".
86
+ - **The icon is a slot** and defaults to \`bd-arrow-icon\`, the only true
87
+ shafted arrow. Whatever goes in is sized to the button's step.
88
+ - **The diameter comes from padding**, like the labelled height: 32, 44 and 56
89
+ for \`sm\`, \`md\` and \`lg\`. Only \`md\` matches the labelled height (33.5,
90
+ 44, 54.5). \`md\` and \`lg\` clear the 44px target; \`sm\` does not.
91
+ - **\`fullwidth\` is ignored**, because a stretched circle is a pill.
92
+ - **\`loading\` replaces the icon** with the spinner at the icon's size, so the
93
+ circle does not change size while busy.
64
94
 
65
95
  ### Alignment Values
66
96
  | Align | Effect |
@@ -81,12 +111,28 @@ The rounded radius can be overridden via the \`--button-radius-rounded\` CSS cus
81
111
  description: 'Accessible aria-label for the button',
82
112
  table : { type: { summary: 'string' }, defaultValue: { summary: 'Buy now' }, category: 'Content' }
83
113
  },
84
- kind: {
114
+ variant: {
85
115
  control : { type: 'select' },
86
- options : ['primary', 'primary-outline', 'outline', 'secondary', 'danger', 'white', 'outline-white'],
87
- description: 'Visual style variant of the button. `danger` includes the hover arrow by default.',
116
+ options : ['primary', 'secondary', 'tertiary', 'ghost', 'accent'],
117
+ description: 'Visual variant. `tertiary` is a blue outline, `ghost` a dark outline.',
88
118
  table : { type: { summary: 'string' }, defaultValue: { summary: 'primary' }, category: 'Appearance' }
89
119
  },
120
+ disabled: {
121
+ control : 'boolean',
122
+ description: 'Blocks interaction and greys the control. Exempt from contrast requirements under WCAG 1.4.3.',
123
+ table : { type: { summary: 'boolean' }, defaultValue: { summary: 'false' }, category: 'State' }
124
+ },
125
+ loading: {
126
+ control : 'boolean',
127
+ description: 'Shows a spinner in the variant colour and sets `aria-busy`.',
128
+ table : { type: { summary: 'boolean' }, defaultValue: { summary: 'false' }, category: 'State' }
129
+ },
130
+ surface: {
131
+ control : { type: 'inline-radio' },
132
+ options : ['light', 'dark'],
133
+ description: 'The surface the button sits on. `dark` retunes every variant for a hero with a full background colour.',
134
+ table : { type: { summary: 'string' }, defaultValue: { summary: 'light' }, category: 'Appearance' }
135
+ },
90
136
  size: {
91
137
  control : { type: 'select' },
92
138
  options : ['sm', 'md', 'lg'],
@@ -94,14 +140,19 @@ The rounded radius can be overridden via the \`--button-radius-rounded\` CSS cus
94
140
  table : { type: { summary: "'sm' | 'md' | 'lg'" }, defaultValue: { summary: 'md' }, category: 'Appearance' }
95
141
  },
96
142
  shape: {
97
- control : { type: 'select' },
143
+ control : { type: 'inline-radio' },
98
144
  options : ['default', 'rounded'],
99
- description: 'Shape of the button. `rounded` applies `--spacing-30` border radius.',
145
+ description: 'Corner shape. `rounded` takes `--radius-3xl` whatever the size.',
100
146
  table : { type: { summary: "'default' | 'rounded'" }, defaultValue: { summary: 'default' }, category: 'Appearance' }
101
147
  },
102
148
  noArrow: {
103
149
  control : 'boolean',
104
- description: '(kind="danger" only) Disables the hover arrow. Attribute: `no-arrow`',
150
+ description: '(accent only) Opts out of the hover arrow. Attribute: `no-arrow`',
151
+ table : { type: { summary: 'boolean' }, defaultValue: { summary: 'false' }, category: 'Appearance' }
152
+ },
153
+ iconOnly: {
154
+ control : 'boolean',
155
+ description: 'A circle around one icon instead of a label. Slot any `bd-*-icon`; the default is the arrow. `label` becomes required, since it is the only name the control has.',
105
156
  table : { type: { summary: 'boolean' }, defaultValue: { summary: 'false' }, category: 'Appearance' }
106
157
  },
107
158
  fullWidth: {
@@ -139,33 +190,30 @@ The rounded radius can be overridden via the \`--button-radius-rounded\` CSS cus
139
190
  control : 'boolean',
140
191
  description: '(ButtonLink only) Adds `data-store-render` and `data-store-buy-link` attributes',
141
192
  table : { type: { summary: 'boolean' }, defaultValue: { summary: 'false' }, category: 'ButtonLink' }
142
- },
143
- shadow: {
144
- control : 'boolean',
145
- description: '(ButtonLink only) Reflects `shadow` attribute',
146
- table : { type: { summary: 'boolean' }, defaultValue: { summary: 'true' }, category: 'ButtonLink' }
147
193
  }
148
194
  }
149
195
  };
150
196
 
151
197
  const defaultArgs = {
152
198
  label : 'Buy now',
153
- kind : 'primary',
199
+ variant : 'primary',
154
200
  size : 'md',
155
201
  shape : 'default',
156
202
  noArrow : false,
203
+ iconOnly : false,
157
204
  fullWidth : false,
158
205
  strong : false,
159
206
  align : 'left',
160
207
  fontSize : '',
161
- fontWeight: ''
208
+ fontWeight: '',
209
+ surface : 'light'
162
210
  };
163
211
 
164
212
  // ─── bd-button Stories ─────────────────────────────────────────────────────
165
213
 
166
214
  export const ButtonDefault = {
167
215
  name : 'Button — Default',
168
- render : () => html`<bd-button kind="primary" size="md">Buy now</bd-button>`,
216
+ render : () => html`<bd-button variant="primary" size="md">Buy now</bd-button>`,
169
217
  parameters: { docs: { description: { story: 'Default primary medium button.' } } }
170
218
  };
171
219
 
@@ -173,14 +221,14 @@ export const ButtonAllKinds = {
173
221
  name : 'Button — All Kinds',
174
222
  render: () => html`
175
223
  <div style="display:flex; gap:12px; flex-wrap:wrap; align-items:center;">
176
- <bd-button kind="primary" size="md">Primary</bd-button>
177
- <bd-button kind="primary-outline" size="md">Primary Outline</bd-button>
178
- <bd-button kind="outline" size="md">Outline</bd-button>
179
- <bd-button kind="secondary" size="md">Secondary</bd-button>
180
- <bd-button kind="danger" size="md">Danger</bd-button>
224
+ <bd-button variant="primary" size="md">primary</bd-button>
225
+ <bd-button variant="secondary" size="md">secondary</bd-button>
226
+ <bd-button variant="tertiary" size="md">tertiary</bd-button>
227
+ <bd-button variant="ghost" size="md">ghost</bd-button>
228
+ <bd-button variant="accent" size="md">accent</bd-button>
181
229
  </div>
182
230
  `,
183
- parameters: { docs: { description: { story: 'All five `kind` variants side by side. Hover the danger button to see the arrow.' } } }
231
+ parameters: { docs: { description: { story: 'All five variants. There is no danger variant — see the notes above.' } } }
184
232
  };
185
233
 
186
234
  export const ButtonRounded = {
@@ -188,96 +236,141 @@ export const ButtonRounded = {
188
236
  render: () => html`
189
237
  <div style="display:flex; flex-direction:column; gap:16px; align-items:flex-start;">
190
238
  <div style="display:flex; gap:12px; flex-wrap:wrap; align-items:center;">
191
- <bd-button kind="primary" size="md" shape="rounded">Primary</bd-button>
192
- <bd-button kind="primary-outline" size="md" shape="rounded">Primary Outline</bd-button>
193
- <bd-button kind="outline" size="md" shape="rounded">Outline</bd-button>
194
- <bd-button kind="secondary" size="md" shape="rounded">Secondary</bd-button>
195
- <bd-button kind="danger" size="md" shape="rounded" strong>Danger</bd-button>
239
+ <bd-button variant="primary" size="md" shape="rounded">primary</bd-button>
240
+ <bd-button variant="secondary" size="md" shape="rounded">secondary</bd-button>
241
+ <bd-button variant="tertiary" size="md" shape="rounded">tertiary</bd-button>
242
+ <bd-button variant="ghost" size="md" shape="rounded">ghost</bd-button>
243
+ <bd-button variant="accent" size="md" shape="rounded">accent</bd-button>
196
244
  </div>
197
245
  <div style="display:flex; gap:12px; flex-wrap:wrap; align-items:center;">
198
- <bd-button kind="primary" size="sm" shape="rounded">Small</bd-button>
199
- <bd-button kind="primary" size="md" shape="rounded">Medium</bd-button>
200
- <bd-button kind="primary" size="lg" shape="rounded">Large</bd-button>
246
+ <bd-button variant="primary" size="sm" shape="rounded">Small</bd-button>
247
+ <bd-button variant="primary" size="md" shape="rounded">Medium</bd-button>
248
+ <bd-button variant="primary" size="lg" shape="rounded">Large</bd-button>
249
+ <bd-button-link variant="primary" size="md" shape="rounded" href="#">Link</bd-button-link>
250
+ <bd-contact-button label="Contact us" href="#" shape="rounded"></bd-contact-button>
201
251
  </div>
202
252
  </div>
203
253
  `,
204
- parameters: { docs: { description: { story: '`shape="rounded"` applies `--spacing-30` border radius across all kinds and sizes.' } } }
254
+ parameters: { docs: { description: { story: '`shape="rounded"` replaces the size band\'s corner with `--radius-3xl`, on every variant and size.' } } }
205
255
  };
206
256
 
207
- export const ButtonShapeComparison = {
208
- name : 'Button — Default vs Rounded',
257
+ export const ButtonAccentArrow = {
258
+ name : 'Button — Accent Hover Arrow',
209
259
  render: () => html`
210
260
  <div style="display:flex; gap:12px; align-items:center; flex-wrap:wrap;">
211
- <bd-button kind="primary" size="md">Default</bd-button>
212
- <bd-button kind="primary" size="md" shape="rounded">Rounded</bd-button>
261
+ <bd-button variant="accent" size="sm" strong>Small</bd-button>
262
+ <bd-button variant="accent" size="md" strong>Activate protection</bd-button>
263
+ <bd-button variant="accent" size="lg" strong>Large</bd-button>
264
+ <bd-button-link variant="accent" size="md" strong href="#">Buy now</bd-button-link>
265
+ <bd-button variant="accent" size="md" strong no-arrow>No arrow</bd-button>
213
266
  </div>
214
267
  `,
215
- parameters: { docs: { description: { story: 'Side-by-side comparison of the `default` and `rounded` shapes.' } } }
268
+ parameters: { docs: { description: { story: 'Every accent button reveals a trailing arrow on hover and `:focus-visible`: the label slides left and the button keeps its width. `no-arrow` opts out; a disabled or loading button never shows it.' } } }
216
269
  };
217
270
 
218
- export const ButtonDangerArrow = {
219
- name : 'Button — Danger (Hover Arrow)',
271
+ export const ButtonAllSizes = {
272
+ name : 'Button — All Sizes',
220
273
  render: () => html`
221
- <div style="display:flex; flex-direction:column; gap:16px; align-items:flex-start;">
222
- <p style="font-size:14px; margin:0;">Hover (or Tab to focus) any button to see the arrow.</p>
223
- <bd-button kind="danger" size="md" strong>Activez votre protection</bd-button>
224
- <div style="display:flex; gap:12px; align-items:center; flex-wrap:wrap;">
225
- <bd-button kind="danger" size="sm" strong>Small</bd-button>
226
- <bd-button kind="danger" size="md" strong>Medium</bd-button>
227
- <bd-button kind="danger" size="lg" strong>Large</bd-button>
228
- </div>
274
+ <div style="display:flex; gap:12px; align-items:center; flex-wrap:wrap;">
275
+ <bd-button variant="primary" size="sm">Small</bd-button>
276
+ <bd-button variant="primary" size="md">Medium</bd-button>
277
+ <bd-button variant="primary" size="lg">Large</bd-button>
229
278
  </div>
230
279
  `,
231
- parameters: {
232
- docs: {
233
- description: {
234
- story: 'Default behaviour for every `kind="danger"` button: on hover / `:focus-visible` the label slides left and an arrow appears on the right, without changing the button width.'
235
- }
236
- }
237
- }
280
+ parameters: { docs: { description: { story: 'All three size variants.' } } }
238
281
  };
239
282
 
240
- export const ButtonDangerNoArrow = {
241
- name : 'Button — Danger without Arrow',
283
+ const VARIANTS = ['primary', 'secondary', 'tertiary', 'ghost', 'accent'];
284
+ const SIZES = ['sm', 'md', 'lg'];
285
+
286
+ const strip = label => html`
287
+ <p style="margin:var(--spacing-16) 0 var(--spacing-8);font:var(--typography-fontSize-xs)/1.4 var(--typography-fontFamily-sans);color:var(--color-neutral-600)">
288
+ ${label}
289
+ </p>
290
+ `;
291
+
292
+ export const ButtonDisabled = {
293
+ name : 'Button — Disabled',
242
294
  render: () => html`
243
- <div style="display:flex; gap:12px; align-items:center; flex-wrap:wrap;">
244
- <bd-button kind="danger" size="md" strong>With arrow (default)</bd-button>
245
- <bd-button kind="danger" size="md" strong no-arrow>Without arrow</bd-button>
295
+ ${strip('disabled — filled variants grey out, outlined ones keep a transparent fill and take a subtle border')}
296
+ <div style="display:flex; gap:var(--spacing-12); flex-wrap:wrap; align-items:center;">
297
+ ${VARIANTS.map(variant => html`<bd-button variant="${variant}" disabled>${variant}</bd-button>`)}
298
+ </div>
299
+ ${strip('the same variants enabled, for comparison')}
300
+ <div style="display:flex; gap:var(--spacing-12); flex-wrap:wrap; align-items:center;">
301
+ ${VARIANTS.map(variant => html`<bd-button variant="${variant}">${variant}</bd-button>`)}
302
+ </div>
303
+ ${strip('bd-button-link disabled — the href is dropped and aria-disabled is set, because a link has no native disabled state')}
304
+ <div style="display:flex; gap:var(--spacing-12); flex-wrap:wrap; align-items:center;">
305
+ ${VARIANTS.map(variant => html`<bd-button-link variant="${variant}" href="#" disabled>${variant}</bd-button-link>`)}
246
306
  </div>
247
307
  `,
248
- parameters: { docs: { description: { story: 'Use the `no-arrow` attribute to opt out of the hover arrow on a specific danger button.' } } }
308
+ parameters: { docs: { description: { story: 'Disabled controls are exempt from contrast requirements under WCAG 1.4.3.' } } }
249
309
  };
250
310
 
251
- export const ButtonAllSizes = {
252
- name : 'Button — All Sizes',
311
+ export const ButtonLoading = {
312
+ name : 'Button — Loading',
253
313
  render: () => html`
254
- <div style="display:flex; gap:12px; align-items:center; flex-wrap:wrap;">
255
- <bd-button kind="primary" size="sm">Small</bd-button>
256
- <bd-button kind="primary" size="md">Medium</bd-button>
257
- <bd-button kind="primary" size="lg">Large</bd-button>
314
+ ${strip('loading — the variant keeps its own colours and the spinner is drawn in currentColor')}
315
+ <div style="display:flex; gap:var(--spacing-12); flex-wrap:wrap; align-items:center;">
316
+ ${VARIANTS.map(variant => html`<bd-button variant="${variant}" loading>${variant}</bd-button>`)}
317
+ </div>
318
+ ${strip('the spinner is sized in em, so it tracks the type scale across sizes')}
319
+ <div style="display:flex; gap:var(--spacing-12); flex-wrap:wrap; align-items:center;">
320
+ ${SIZES.map(size => html`<bd-button size="${size}" loading>${size}</bd-button>`)}
258
321
  </div>
259
322
  `,
260
- parameters: { docs: { description: { story: 'All three size variants.' } } }
323
+ parameters: { docs: { description: { story: 'Sets `aria-busy`, blocks interaction, and falls back to a pulse under `prefers-reduced-motion`.' } } }
324
+ };
325
+
326
+ const HEROES = [
327
+ ['blue-500 — the worst case for contrast', 'var(--color-blue-500)'],
328
+ ['blue-700', 'var(--color-blue-700)'],
329
+ ['neutral-950', 'var(--color-neutral-950)']
330
+ ];
331
+
332
+ export const ButtonOnDark = {
333
+ name : 'Button — On a dark surface',
334
+ render: () => html`
335
+ ${HEROES.map(([label, bg]) => html`
336
+ <p style="margin:var(--spacing-24) 0 var(--spacing-8);font:var(--typography-fontSize-xs)/1.4 var(--typography-fontFamily-sans);color:var(--color-neutral-600)">
337
+ ${label}
338
+ </p>
339
+ <div style="background:${bg};padding:var(--spacing-24);border-radius:var(--radius-md);display:flex;gap:var(--spacing-12);flex-wrap:wrap;align-items:center;">
340
+ ${VARIANTS.map(variant => html`
341
+ <bd-button variant="${variant}" surface="dark">${variant}</bd-button>
342
+ `)}
343
+ <bd-button variant="primary" surface="dark" disabled>disabled</bd-button>
344
+ <bd-button variant="accent" surface="dark" loading>loading</bd-button>
345
+ </div>
346
+ `)}
347
+ <p style="margin:var(--spacing-24) 0 var(--spacing-8);font:var(--typography-fontSize-xs)/1.4 var(--typography-fontFamily-sans);color:var(--color-neutral-600)">
348
+ the same variants without surface="dark", for comparison — this is what a hero looks like today
349
+ </p>
350
+ <div style="background:var(--color-blue-500);padding:var(--spacing-24);border-radius:var(--radius-md);display:flex;gap:var(--spacing-12);flex-wrap:wrap;align-items:center;">
351
+ ${VARIANTS.map(variant => html`<bd-button variant="${variant}">${variant}</bd-button>`)}
352
+ </div>
353
+ `,
354
+ parameters: { docs: { description: { story:
355
+ 'For a hero or panel with a full background colour. The design specifies no on-dark set, so these values are derived from our palette and measured against every plausible hero colour — they need a designer\'s sign-off. ghost drops its ring so it stays distinct from tertiary; accent keeps its red and gains a white boundary.' } } }
261
356
  };
262
357
 
263
358
  export const ButtonFullWidth = {
264
359
  name : 'Button — Full Width',
265
360
  render: () => html`
266
- <div style="width:400px; display:flex; flex-direction:column; gap:12px;">
267
- <bd-button kind="primary" size="md" .fullWidth="${true}">Full Width Button</bd-button>
268
- <bd-button kind="danger" size="md" strong .fullWidth="${true}">Full Width Danger</bd-button>
269
- <bd-button kind="primary" size="md" shape="rounded" .fullWidth="${true}">Full Width Rounded</bd-button>
361
+ <div style="width:400px;">
362
+ <bd-button variant="primary" size="md" .fullWidth="${true}">Full Width Button</bd-button>
270
363
  </div>
271
364
  `,
272
- parameters: { docs: { description: { story: '`fullWidth` set to true — applies `max--width` class. The danger arrow and rounded shape also work at full width.' } } }
365
+ parameters: { docs: { description: { story: '`fullWidth` set to true — applies `max--width` class.' } } }
273
366
  };
274
367
 
275
368
  export const ButtonStrong = {
276
369
  name : 'Button — Strong (Bold)',
277
370
  render: () => html`
278
371
  <div style="display:flex; gap:12px;">
279
- <bd-button kind="primary" size="md">Normal</bd-button>
280
- <bd-button kind="primary" size="md" .strong="${true}">Strong</bd-button>
372
+ <bd-button variant="primary" size="md">Normal</bd-button>
373
+ <bd-button variant="primary" size="md" .strong="${true}">Strong</bd-button>
281
374
  </div>
282
375
  `,
283
376
  parameters: { docs: { description: { story: 'Comparison between normal and `strong` (bold) button.' } } }
@@ -287,7 +380,7 @@ export const ButtonAlignCenter = {
287
380
  name : 'Button — Align Center',
288
381
  render: () => html`
289
382
  <div style="width:100%;">
290
- <bd-button kind="primary" size="md" align="center">Centered Button</bd-button>
383
+ <bd-button variant="primary" size="md" align="center">Centered Button</bd-button>
291
384
  </div>
292
385
  `,
293
386
  parameters: { docs: { description: { story: 'Button centered horizontally using `align="center"`.' } } }
@@ -297,7 +390,7 @@ export const ButtonAlignRight = {
297
390
  name : 'Button — Align Right',
298
391
  render: () => html`
299
392
  <div style="width:100%;">
300
- <bd-button kind="danger" size="md" align="right">Right Aligned Button</bd-button>
393
+ <bd-button variant="accent" size="md" align="right">Right Aligned Button</bd-button>
301
394
  </div>
302
395
  `,
303
396
  parameters: { docs: { description: { story: 'Button aligned to the right using `align="right"`.' } } }
@@ -308,13 +401,13 @@ export const ButtonAllAlignments = {
308
401
  render: () => html`
309
402
  <div style="width:100%; max-width:600px; display:flex; flex-direction:column; gap:16px;">
310
403
  <div style="border:1px dashed #ccc; padding:12px; border-radius:4px;">
311
- <bd-button kind="primary" size="md" align="left">Left (default)</bd-button>
404
+ <bd-button variant="primary" size="md" align="left">Left (default)</bd-button>
312
405
  </div>
313
406
  <div style="border:1px dashed #ccc; padding:12px; border-radius:4px;">
314
- <bd-button kind="primary" size="md" align="center">Center</bd-button>
407
+ <bd-button variant="primary" size="md" align="center">Center</bd-button>
315
408
  </div>
316
409
  <div style="border:1px dashed #ccc; padding:12px; border-radius:4px;">
317
- <bd-button kind="primary" size="md" align="right">Right</bd-button>
410
+ <bd-button variant="primary" size="md" align="right">Right</bd-button>
318
411
  </div>
319
412
  </div>
320
413
  `,
@@ -324,18 +417,18 @@ export const ButtonAllAlignments = {
324
417
  export const ButtonCustomTypography = {
325
418
  name : 'Button — Custom Font Size & Weight',
326
419
  render: () => html`
327
- <bd-button kind="danger" size="md" font-size="20px" font-weight="800">
420
+ <bd-button variant="accent" size="md" font-size="xl" font-weight="bold">
328
421
  Buy now
329
422
  </bd-button>
330
423
  `,
331
- parameters: { docs: { description: { story: 'Custom `font-size` and `font-weight` applied via inline styles. The arrow scales with the font size.' } } }
424
+ parameters: { docs: { description: { story: 'Custom `font-size` and `font-weight` applied via inline styles.' } } }
332
425
  };
333
426
 
334
427
  export const ButtonKeyboard = {
335
428
  name : 'Button — Keyboard Accessible',
336
429
  render: () => html`
337
430
  <p style="font-size:14px; margin-bottom:8px;">Tab to focus, press Enter or Space to trigger.</p>
338
- <bd-button kind="primary" size="md" label="Keyboard test">Press me</bd-button>
431
+ <bd-button variant="primary" size="md" label="Keyboard test">Press me</bd-button>
339
432
  `,
340
433
  parameters: { docs: { description: { story: 'Demonstrates keyboard activation. Enter/Space trigger `custom-click` and toggle the `active` class briefly.' } } }
341
434
  };
@@ -345,7 +438,7 @@ export const ButtonKeyboard = {
345
438
  export const ButtonLinkDefault = {
346
439
  name : 'ButtonLink — Default',
347
440
  render: () => html`
348
- <bd-button-link kind="primary" size="md" href="/buy">Buy now</bd-button-link>
441
+ <bd-button-link variant="primary" size="md" href="/buy">Buy now</bd-button-link>
349
442
  `,
350
443
  parameters: { docs: { description: { story: 'Default `bd-button-link` rendered as an `<a>` tag.' } } }
351
444
  };
@@ -354,55 +447,32 @@ export const ButtonLinkAllKinds = {
354
447
  name : 'ButtonLink — All Kinds',
355
448
  render: () => html`
356
449
  <div style="display:flex; gap:12px; flex-wrap:wrap; align-items:center;">
357
- <bd-button-link kind="primary" size="md" href="#">Primary</bd-button-link>
358
- <bd-button-link kind="primary-outline" size="md" href="#">Primary Outline</bd-button-link>
359
- <bd-button-link kind="outline" size="md" href="#">Outline</bd-button-link>
360
- <bd-button-link kind="secondary" size="md" href="#">Secondary</bd-button-link>
361
- <bd-button-link kind="danger" size="md" href="#">Danger</bd-button-link>
450
+ <bd-button-link variant="primary" size="md" href="#">primary</bd-button-link>
451
+ <bd-button-link variant="secondary" size="md" href="#">secondary</bd-button-link>
452
+ <bd-button-link variant="tertiary" size="md" href="#">tertiary</bd-button-link>
453
+ <bd-button-link variant="ghost" size="md" href="#">ghost</bd-button-link>
454
+ <bd-button-link variant="accent" size="md" href="#">accent</bd-button-link>
362
455
  </div>
363
456
  `,
364
- parameters: { docs: { description: { story: 'All `kind` variants for `bd-button-link`.' } } }
365
- };
366
-
367
- export const ButtonLinkRounded = {
368
- name : 'ButtonLink — Rounded',
369
- render: () => html`
370
- <div style="display:flex; gap:12px; flex-wrap:wrap; align-items:center;">
371
- <bd-button-link kind="primary" size="md" href="#" shape="rounded">Primary</bd-button-link>
372
- <bd-button-link kind="primary-outline" size="md" href="#" shape="rounded">Primary Outline</bd-button-link>
373
- <bd-button-link kind="danger" size="md" href="#" shape="rounded" strong>Danger</bd-button-link>
374
- </div>
375
- `,
376
- parameters: { docs: { description: { story: '`shape="rounded"` on `bd-button-link`.' } } }
457
+ parameters: { docs: { description: { story: 'All `variant` values for `bd-button-link`.' } } }
377
458
  };
378
459
 
379
460
  export const ButtonLinkAllSizes = {
380
461
  name : 'ButtonLink — All Sizes',
381
462
  render: () => html`
382
463
  <div style="display:flex; gap:12px; align-items:center; flex-wrap:wrap;">
383
- <bd-button-link kind="danger" size="sm" href="#">Small</bd-button-link>
384
- <bd-button-link kind="danger" size="md" href="#">Medium</bd-button-link>
385
- <bd-button-link kind="danger" size="lg" href="#">Large</bd-button-link>
386
- </div>
387
- `,
388
- parameters: { docs: { description: { story: 'All three sizes for `bd-button-link` (danger, with hover arrow).' } } }
389
- };
390
-
391
- export const ButtonLinkDangerArrow = {
392
- name : 'ButtonLink — Danger (Hover Arrow)',
393
- render: () => html`
394
- <div style="display:flex; gap:12px; align-items:center; flex-wrap:wrap;">
395
- <bd-button-link kind="danger" size="md" href="#" strong>Activez votre protection</bd-button-link>
396
- <bd-button-link kind="danger" size="md" href="#" strong no-arrow>Without arrow</bd-button-link>
464
+ <bd-button-link variant="accent" size="sm" href="#">Small</bd-button-link>
465
+ <bd-button-link variant="accent" size="md" href="#">Medium</bd-button-link>
466
+ <bd-button-link variant="accent" size="lg" href="#">Large</bd-button-link>
397
467
  </div>
398
468
  `,
399
- parameters: { docs: { description: { story: 'The hover arrow is also on by default for `bd-button-link` with `kind="danger"`; `no-arrow` disables it.' } } }
469
+ parameters: { docs: { description: { story: 'All three sizes for `bd-button-link`.' } } }
400
470
  };
401
471
 
402
472
  export const ButtonLinkBuyLink = {
403
473
  name : 'ButtonLink — Buy Link Mode',
404
474
  render: () => html`
405
- <bd-button-link kind="danger" size="md" href="/buy" .buyLink="${true}">
475
+ <bd-button-link variant="accent" size="md" href="/buy" .buyLink="${true}">
406
476
  Buy now
407
477
  </bd-button-link>
408
478
  `,
@@ -413,7 +483,7 @@ export const ButtonLinkFullWidth = {
413
483
  name : 'ButtonLink — Full Width',
414
484
  render: () => html`
415
485
  <div style="width:400px;">
416
- <bd-button-link kind="primary" size="md" href="#" .fullWidth="${true}">
486
+ <bd-button-link variant="primary" size="md" href="#" .fullWidth="${true}">
417
487
  Full Width Link Button
418
488
  </bd-button-link>
419
489
  </div>
@@ -425,7 +495,7 @@ export const ButtonLinkAlignCenter = {
425
495
  name : 'ButtonLink — Align Center',
426
496
  render: () => html`
427
497
  <div style="width:100%;">
428
- <bd-button-link kind="primary" size="md" href="#" align="center">
498
+ <bd-button-link variant="primary" size="md" href="#" align="center">
429
499
  Centered Link Button
430
500
  </bd-button-link>
431
501
  </div>
@@ -437,7 +507,7 @@ export const ButtonLinkAlignRight = {
437
507
  name : 'ButtonLink — Align Right',
438
508
  render: () => html`
439
509
  <div style="width:100%;">
440
- <bd-button-link kind="danger" size="md" href="#" align="right">
510
+ <bd-button-link variant="accent" size="md" href="#" align="right">
441
511
  Right Aligned Link Button
442
512
  </bd-button-link>
443
513
  </div>
@@ -448,13 +518,100 @@ export const ButtonLinkAlignRight = {
448
518
  export const ButtonLinkCustomTypography = {
449
519
  name : 'ButtonLink — Custom Typography',
450
520
  render: () => html`
451
- <bd-button-link kind="danger" size="md" href="#" font-size="18px" font-weight="600">
521
+ <bd-button-link variant="accent" size="md" href="#" font-size="lg" font-weight="semibold">
452
522
  Buy now
453
523
  </bd-button-link>
454
524
  `,
455
525
  parameters: { docs: { description: { story: 'Inline `font-size` and `font-weight` applied to the anchor element.' } } }
456
526
  };
457
527
 
528
+ // ─── Icon-only ─────────────────────────────────────────────────────────────
529
+
530
+ const row = 'display:flex; gap:var(--spacing-12); flex-wrap:wrap; align-items:center;';
531
+
532
+ export const ButtonIconOnly = {
533
+ name : 'Button — Icon only',
534
+ render: () => html`
535
+ ${SIZES.map(size => html`
536
+ ${strip(`${size} — every variant`)}
537
+ <div style="${row}">
538
+ ${VARIANTS.map(variant => html`<bd-button icon-only variant="${variant}" size="${size}" label="Continue"></bd-button>`)}
539
+ </div>
540
+ `)}
541
+ ${strip('beside a labelled button of the same size — md sits level; sm is 1.5px shorter and lg 1.5px taller')}
542
+ <div style="${row}">
543
+ ${SIZES.map(size => html`
544
+ <bd-button size="${size}">Get protected</bd-button>
545
+ <bd-button icon-only size="${size}" label="Get protected"></bd-button>
546
+ `)}
547
+ </div>
548
+ `,
549
+ parameters: { docs: { description: { story: 'The circle is 32, 44 and 56 — equal padding around a 16, 20 and 24 icon. `label` names each one, since there is no visible text.' } } }
550
+ };
551
+
552
+ export const ButtonIconOnlyStates = {
553
+ name : 'Button — Icon only, states',
554
+ render: () => html`
555
+ ${strip('disabled — the same treatment as the labelled button')}
556
+ <div style="${row}">
557
+ ${VARIANTS.map(variant => html`<bd-button icon-only variant="${variant}" label="Continue" disabled></bd-button>`)}
558
+ </div>
559
+ ${strip('loading — the spinner replaces the icon at the icon\'s size, so the circle keeps its size')}
560
+ <div style="${row}">
561
+ ${SIZES.map(size => html`
562
+ <bd-button icon-only size="${size}" label="Continue"></bd-button>
563
+ <bd-button icon-only size="${size}" label="Continue" loading></bd-button>
564
+ `)}
565
+ </div>
566
+ `,
567
+ parameters: { docs: { description: { story: 'Focus is the shared two-colour ring, which follows the circle. Tab through the Keyboard story to see it.' } } }
568
+ };
569
+
570
+ export const ButtonIconOnlyOwnIcon = {
571
+ name : 'Button — Icon only, your own icon',
572
+ render: () => html`
573
+ ${strip('any bd-*-icon in the slot — sized to the button\'s step, whatever size it was given')}
574
+ <div style="${row}">
575
+ <bd-button icon-only variant="ghost" label="Close"><bd-close-icon></bd-close-icon></bd-button>
576
+ <bd-button icon-only variant="tertiary" label="Add to comparison"><bd-plus-icon></bd-plus-icon></bd-button>
577
+ <bd-button icon-only variant="tertiary" size="lg" label="Add to comparison"><bd-plus-icon size="xs"></bd-plus-icon></bd-button>
578
+ </div>
579
+ `,
580
+ parameters: { docs: { description: { story: 'The last one slots an xs icon into an lg button and still gets 24px: the button owns the glyph size, so a circle never holds an icon too small for it.' } } }
581
+ };
582
+
583
+ export const ButtonIconOnlyOnBand = {
584
+ name : 'Button — Icon only, on a band',
585
+ render: () => html`
586
+ ${HEROES.map(([label, bg]) => html`
587
+ ${strip(`${label} — surface="dark"`)}
588
+ <div style="background:${bg};padding:var(--spacing-24);border-radius:var(--radius-md);${row}">
589
+ ${VARIANTS.map(variant => html`<bd-button icon-only variant="${variant}" surface="dark" label="Continue"></bd-button>`)}
590
+ </div>
591
+ `)}
592
+ ${strip('white and outline-white — bd-button-link presets for a full-colour band')}
593
+ <div style="background:var(--color-surface-brand);padding:var(--spacing-24);border-radius:var(--radius-md);${row}">
594
+ <bd-button-link icon-only variant="white" href="#" label="Read the Ferrari story"></bd-button-link>
595
+ <bd-button-link icon-only variant="outline-white" href="#" label="Explore consumer AI"></bd-button-link>
596
+ <bd-button-link icon-only variant="outline-white" size="lg" href="#" label="Explore consumer AI"></bd-button-link>
597
+ </div>
598
+ `,
599
+ parameters: { docs: { description: { story: 'The same surface rules as the labelled button. white and outline-white keep their look on any band.' } } }
600
+ };
601
+
602
+ export const ButtonLinkIconOnly = {
603
+ name : 'ButtonLink — Icon only (homepage audience card)',
604
+ render: () => html`
605
+ <div style="max-width:384px;padding:var(--spacing-24);border:var(--border-width-1) solid var(--color-border-container);border-radius:var(--radius-2xl);display:flex;flex-direction:column;align-items:flex-end;gap:var(--spacing-8);">
606
+ <p style="margin:0;align-self:stretch;font:var(--typography-body-regular-fontWeight) var(--typography-body-regular-fontSize)/var(--typography-body-regular-lineHeight) var(--typography-fontFamily-sans);color:var(--color-text-primary);">
607
+ AI-powered protection against scams, deepfake fraud, identity theft, and online threats across all your devices.
608
+ </p>
609
+ <bd-button-link icon-only variant="accent" href="#" label="Protect your digital life"></bd-button-link>
610
+ </div>
611
+ `,
612
+ parameters: { docs: { description: { story: 'As the homepage\'s audience cards use it: accent, md, and a link because it navigates. The name says where it goes; the card\'s title is not its name.' } } }
613
+ };
614
+
458
615
  // ─── bd-contact-button Stories ─────────────────────────────────────────────
459
616
 
460
617
  export const ContactButtonDefault = {
@@ -481,14 +638,6 @@ export const ContactButtonCustomHref = {
481
638
  parameters: { docs: { description: { story: 'Contact button linking to an external support URL.' } } }
482
639
  };
483
640
 
484
- export const ContactButtonRounded = {
485
- name : 'ContactButton — Rounded',
486
- render: () => html`
487
- <bd-contact-button label="Contact us" href="#" shape="rounded"></bd-contact-button>
488
- `,
489
- parameters: { docs: { description: { story: '`shape="rounded"` on `bd-contact-button`.' } } }
490
- };
491
-
492
641
  export const ContactButtonAlignCenter = {
493
642
  name : 'ContactButton — Align Center',
494
643
  render: () => html`
@@ -515,8 +664,8 @@ export const AllButtonTypes = {
515
664
  name : 'All Button Types',
516
665
  render: () => html`
517
666
  <div style="display:flex; gap:16px; flex-wrap:wrap; align-items:center;">
518
- <bd-button kind="primary" size="md">bd-button</bd-button>
519
- <bd-button-link kind="danger" size="md" href="#">bd-button-link</bd-button-link>
667
+ <bd-button variant="primary" size="md">bd-button</bd-button>
668
+ <bd-button-link variant="accent" size="md" href="#">bd-button-link</bd-button-link>
520
669
  <bd-contact-button label="bd-contact-button" href="#"></bd-contact-button>
521
670
  </div>
522
671
  `,
@@ -529,7 +678,7 @@ export const Playground = {
529
678
  render: (args) => html`
530
679
  <div style="width:100%;">
531
680
  <bd-button
532
- kind="${args.kind}"
681
+ variant="${args.variant}"
533
682
  size="${args.size}"
534
683
  shape="${args.shape}"
535
684
  label="${args.label}"
@@ -539,23 +688,22 @@ export const Playground = {
539
688
  ?no-arrow="${args.noArrow}"
540
689
  font-size="${args.fontSize}"
541
690
  font-weight="${args.fontWeight}"
542
- >${args.label}</bd-button>
691
+ surface="${args.surface}"
692
+ ?icon-only="${args.iconOnly}"
693
+ >${args.iconOnly ? nothing : args.label}</bd-button>
543
694
  </div>
544
695
  `,
545
- parameters: { docs: { description: { story: 'Interactive playground for `bd-button`. Use Controls to adjust all props including shape, alignment and the danger hover arrow.' } } }
696
+ parameters: { docs: { description: { story: 'Interactive playground for `bd-button`. Use Controls to adjust all props including alignment.' } } }
546
697
  };
547
-
548
698
  // ─── White / Outline-White (on dark background) ───────────────────────────
549
699
 
550
700
  export const ButtonWhiteOnDark = {
551
701
  name : 'Button — White / Outline-White (on dark background)',
552
702
  render: () => html`
553
703
  <div style="background: linear-gradient(120deg, #0038e0 0%, #061a5c 100%); padding: 48px; border-radius: 12px; display:flex; gap:16px; flex-wrap:wrap; align-items:center; justify-content:center;">
554
- <bd-button-link kind="white" size="md" strong href="#">Download BETA Today</bd-button-link>
555
- <bd-button-link kind="outline-white" size="md" strong href="#">Read the docs</bd-button-link>
556
- <bd-button-link kind="white" size="md" strong href="#" shape="rounded">Rounded White</bd-button-link>
557
- <bd-button-link kind="outline-white" size="md" strong href="#" shape="rounded">Rounded Outline</bd-button-link>
704
+ <bd-button-link variant="white" size="md" strong href="#">Download BETA Today</bd-button-link>
705
+ <bd-button-link variant="outline-white" size="md" strong href="#">Read the docs</bd-button-link>
558
706
  </div>
559
707
  `,
560
- parameters: { docs: { description: { story: '`white` and `outline-white` kinds, meant for use on colored/dark backgrounds like `bd-cta-banner` or hero sections. Also shown with `shape="rounded"`.' } } }
708
+ parameters: { docs: { description: { story: '`white` and `outline-white` variants, meant for use on colored/dark backgrounds like `bd-cta-banner` or hero sections.' } } }
561
709
  };