@repobit/dex-system-design 0.25.11 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (336) hide show
  1. package/CHANGELOG.md +195 -0
  2. package/README.md +131 -8
  3. package/package.json +95 -13
  4. package/schemas/component-manifest.json +3294 -405
  5. package/schemas/manifest-omissions.json +173 -0
  6. package/src/blog/src/breakpoints.js +6 -6
  7. package/src/blog/src/content/blog-atoms-showcase.js +1 -1
  8. package/src/blog/src/content/blog-page-layout.js +2 -2
  9. package/src/blog/src/lib/article-toc.js +7 -7
  10. package/src/blog/src/shell/blog-shell.js +1 -1
  11. package/src/blog/src/tokens/blog.js +2 -2
  12. package/src/blog/src/tokens/core.js +34 -35
  13. package/src/blog/src/tokens/legacy.js +0 -9
  14. package/src/blog/tokens/blog.js +2 -2
  15. package/src/blog/tokens/core.js +34 -35
  16. package/src/blog/tokens/legacy.js +0 -9
  17. package/src/blog/tokens.css +36 -46
  18. package/src/components/accordion/accordion-bg.css.js +83 -59
  19. package/src/components/accordion/accordion-bg.js +29 -10
  20. package/src/components/accordion/accordion-bg.stories.js +67 -67
  21. package/src/components/accordion/accordion-keyboard.js +80 -0
  22. package/src/components/accordion/accordion.css.js +142 -80
  23. package/src/components/accordion/accordion.js +37 -10
  24. package/src/components/accordion/accordion.stories.js +7 -7
  25. package/src/components/agent-endpoints/agent-endpoints.css.js +36 -39
  26. package/src/components/agent-endpoints/agent-endpoints.js +30 -20
  27. package/src/components/agent-endpoints/agent-endpoints.stories.js +1 -1
  28. package/src/components/ai-guardian-demo.stories.js +91 -91
  29. package/src/components/alert/alert.css.js +198 -0
  30. package/src/components/alert/alert.js +103 -0
  31. package/src/components/alert/alert.stories.js +206 -0
  32. package/src/components/anchor/anchor-nav.css.js +213 -101
  33. package/src/components/anchor/anchor-nav.js +26 -40
  34. package/src/components/anchor/anchor.stories.js +22 -12
  35. package/src/components/annotation/annotation.css.js +58 -0
  36. package/src/components/annotation/annotation.js +67 -0
  37. package/src/components/annotation/annotation.stories.js +63 -0
  38. package/src/components/architecture.stories.js +285 -0
  39. package/src/components/atoms.stories.js +342 -0
  40. package/src/components/avatar/avatar.css.js +67 -0
  41. package/src/components/avatar/avatar.js +42 -0
  42. package/src/components/avatar/avatar.stories.js +95 -0
  43. package/src/components/awards/awards-flex.css.js +209 -23
  44. package/src/components/awards/awards-flex.js +66 -7
  45. package/src/components/awards/awards-flex.stories.js +1 -1
  46. package/src/components/awards/{awards-light.stories.js → awards-summary.stories.js} +54 -64
  47. package/src/components/awards/awards.css.js +116 -58
  48. package/src/components/awards/awards.js +102 -28
  49. package/src/components/awards/awards.stories.js +1 -1
  50. package/src/components/back/back.css.js +51 -22
  51. package/src/components/back/back.js +28 -7
  52. package/src/components/back/back.stories.js +9 -3
  53. package/src/components/badge/badge.css.js +158 -46
  54. package/src/components/badge/badge.js +62 -74
  55. package/src/components/badge/badge.stories.js +176 -248
  56. package/src/components/bento-grid/bento-grid.css.js +21 -16
  57. package/src/components/bento-grid/bento-grid.js +16 -4
  58. package/src/components/bento-grid/bento-grid.stories.js +19 -18
  59. package/src/components/bento-grid/bento-item.css.js +52 -28
  60. package/src/components/bento-grid/bento-item.js +2 -2
  61. package/src/components/blockquote/blockquote.css.js +47 -0
  62. package/src/components/blockquote/blockquote.js +29 -0
  63. package/src/components/blockquote/blockquote.stories.js +62 -0
  64. package/src/components/breadcrumb/breadcrumb.css.js +92 -22
  65. package/src/components/breadcrumb/breadcrumb.js +56 -11
  66. package/src/components/button/button.css.js +531 -161
  67. package/src/components/button/button.js +206 -214
  68. package/src/components/button/button.stories.js +322 -174
  69. package/src/components/caption/caption.css.js +21 -0
  70. package/src/components/caption/caption.js +31 -0
  71. package/src/components/caption/caption.stories.js +62 -0
  72. package/src/components/card-features/card-features.css.js +14 -22
  73. package/src/components/card-features/card-features.js +68 -9
  74. package/src/components/card-features/card-features.stories.js +11 -11
  75. package/src/components/cards/card.css.js +60 -81
  76. package/src/components/cards/card.js +56 -25
  77. package/src/components/cards/card.stories.js +39 -39
  78. package/src/components/carousel/carousel.css.js +93 -99
  79. package/src/components/carousel/carousel.js +32 -4
  80. package/src/components/checkbox/checkbox.css.js +111 -93
  81. package/src/components/checkbox/checkbox.js +64 -90
  82. package/src/components/checkbox/checkbox.stories.js +96 -29
  83. package/src/components/code/code.css.js +70 -0
  84. package/src/components/code/code.js +40 -0
  85. package/src/components/code/code.stories.js +73 -0
  86. package/src/components/compare/compare.css.js +179 -43
  87. package/src/components/compare/compare.js +52 -25
  88. package/src/components/compare/compare.stories.js +61 -4
  89. package/src/components/comparison-panel/comparison-panel.css.js +38 -51
  90. package/src/components/comparison-panel/comparison-panel.js +5 -4
  91. package/src/components/comparison-panel/comparison-panel.stories.js +1 -1
  92. package/src/components/compatibility-table/compatibility-table.css.js +180 -80
  93. package/src/components/compatibility-table/compatibility-table.js +37 -9
  94. package/src/components/control-alignment.stories.js +393 -0
  95. package/src/components/cta-banner/cta-banner.css.js +41 -13
  96. package/src/components/cta-banner/cta-banner.js +6 -5
  97. package/src/components/cta-banner/cta-banner.stories.js +43 -98
  98. package/src/components/display/display.css.js +25 -1
  99. package/src/components/display/display.js +46 -13
  100. package/src/components/display/display.stories.js +270 -40
  101. package/src/components/divider/divider-horizontal.js +21 -5
  102. package/src/components/divider/divider-vertical.js +15 -7
  103. package/src/components/divider/divider.css.js +2 -2
  104. package/src/components/divider/divider.stories.js +38 -34
  105. package/src/components/dropdown/dropdown.css.js +93 -126
  106. package/src/components/dropdown/dropdown.js +114 -34
  107. package/src/components/dropdown/dropdown.stories.js +56 -24
  108. package/src/components/features/features.css.js +24 -11
  109. package/src/components/features/features.js +7 -3
  110. package/src/components/features/features.stories.js +37 -37
  111. package/src/components/features-tab/features-tab.css.js +19 -8
  112. package/src/components/features-tab/features-tab.js +6 -5
  113. package/src/components/features-tab/features-tab.stories.js +23 -23
  114. package/src/components/fieldset/fieldset.css.js +30 -0
  115. package/src/components/fieldset/fieldset.js +28 -0
  116. package/src/components/fieldset/fieldset.stories.js +84 -0
  117. package/src/components/footer/footer-links-group.css.js +10 -14
  118. package/src/components/footer/footer-links-group.js +4 -3
  119. package/src/components/footer/footer-lp.css.js +59 -30
  120. package/src/components/footer/footer-lp.js +17 -12
  121. package/src/components/footer/footer-lp.stories.js +63 -75
  122. package/src/components/footer/footer-nav-menu.css.js +26 -4
  123. package/src/components/footer/footer-nav-menu.js +3 -2
  124. package/src/components/footer/footer.css.js +146 -264
  125. package/src/components/footer/footer.js +176 -106
  126. package/src/components/footer/footer.stories.js +9 -9
  127. package/src/components/footer/localeMap.js +1 -1
  128. package/src/components/grid/grid.css.js +1 -1
  129. package/src/components/grid/grid.js +49 -7
  130. package/src/components/grid/grid.stories.js +111 -0
  131. package/src/components/header/header-code.css.js +61 -51
  132. package/src/components/header/header-code.js +28 -14
  133. package/src/components/header/header-code.stories.js +5 -5
  134. package/src/components/header/header.css.js +655 -176
  135. package/src/components/header/header.js +269 -36
  136. package/src/components/header/header.stories.js +841 -18
  137. package/src/components/heading/heading.css.js +14 -17
  138. package/src/components/heading/heading.js +48 -33
  139. package/src/components/heading/heading.stories.js +27 -25
  140. package/src/components/help-text/help-text.css.js +21 -0
  141. package/src/components/help-text/help-text.js +25 -0
  142. package/src/components/help-text/help-text.stories.js +66 -0
  143. package/src/components/highlight/highlight.css.js +86 -64
  144. package/src/components/highlight/highlight.js +18 -27
  145. package/src/components/highlight/highlight.stories.js +14 -3
  146. package/src/components/icons/analysis-icon.js +6 -16
  147. package/src/components/icons/arrow-down-icon.js +6 -19
  148. package/src/components/icons/arrow-icon.js +44 -0
  149. package/src/components/icons/arrow-right-icon.js +30 -23
  150. package/src/components/icons/arrow-up-icon.js +19 -18
  151. package/src/components/icons/bd-ai-icon.js +1 -1
  152. package/src/components/icons/brand-marks.stories.js +279 -0
  153. package/src/components/icons/brand-signature-icon.js +42 -0
  154. package/src/components/icons/check-icon.js +27 -0
  155. package/src/components/icons/circle-info-icon.js +33 -0
  156. package/src/components/icons/close-icon.js +6 -18
  157. package/src/components/icons/family-icon.js +8 -20
  158. package/src/components/icons/globe-icon.js +6 -18
  159. package/src/components/icons/guide-icon.js +6 -18
  160. package/src/components/icons/icon-element.js +99 -0
  161. package/src/components/icons/icons.js +36 -0
  162. package/src/components/icons/icons.stories.js +184 -52
  163. package/src/components/icons/individual-icon.js +6 -18
  164. package/src/components/icons/laurel-icon.js +9 -19
  165. package/src/components/icons/machine-learning-icon.js +6 -17
  166. package/src/components/icons/marks.js +41 -0
  167. package/src/components/icons/minus-icon.js +7 -21
  168. package/src/components/icons/missing-icon.js +52 -0
  169. package/src/components/icons/plus-icon.js +7 -21
  170. package/src/components/icons/quote-icon.js +19 -19
  171. package/src/components/image/image.css.js +72 -25
  172. package/src/components/image/image.js +11 -6
  173. package/src/components/image/image.stories.js +2 -2
  174. package/src/components/input/custom-form.stories.js +214 -62
  175. package/src/components/input/input-clipboard.css.js +51 -144
  176. package/src/components/input/input-clipboard.js +31 -15
  177. package/src/components/input/input.css.js +8 -146
  178. package/src/components/input/input.js +93 -38
  179. package/src/components/install-options/install-options.css.js +84 -77
  180. package/src/components/install-options/install-options.js +33 -30
  181. package/src/components/install-options/install-options.stories.js +3 -3
  182. package/src/components/label/label.css.js +35 -0
  183. package/src/components/label/label.js +38 -0
  184. package/src/components/label/label.stories.js +82 -0
  185. package/src/components/light-carousel/light-carousel.css.js +111 -63
  186. package/src/components/light-carousel/light-carousel.js +85 -11
  187. package/src/components/light-carousel/light-carousel.stories.js +126 -82
  188. package/src/components/link/link.css.js +150 -99
  189. package/src/components/link/link.js +86 -11
  190. package/src/components/link/link.stories.js +124 -30
  191. package/src/components/list/list-item/list-item.css.js +74 -22
  192. package/src/components/list/list-item/list-item.js +32 -10
  193. package/src/components/list/list-item/list-item.stories.js +23 -23
  194. package/src/components/list/list.css.js +8 -2
  195. package/src/components/list/list.js +3 -2
  196. package/src/components/list/list.stories.js +222 -0
  197. package/src/components/modal/modal.css.js +114 -24
  198. package/src/components/modal/modal.js +83 -7
  199. package/src/components/modal/modal.stories.js +9 -9
  200. package/src/components/overview/overview.css.js +19 -14
  201. package/src/components/overview/overview.js +6 -5
  202. package/src/components/overview/overview.stories.js +10 -10
  203. package/src/components/page-switcher/page-switcher.css.js +97 -40
  204. package/src/components/page-switcher/page-switcher.js +28 -5
  205. package/src/components/page-switcher/page-switcher.stories.js +95 -0
  206. package/src/components/paragraph/paragraph.css.js +15 -10
  207. package/src/components/paragraph/paragraph.js +41 -44
  208. package/src/components/paragraph/paragraph.stories.js +56 -21
  209. package/src/components/picture/picture.css.js +103 -44
  210. package/src/components/picture/picture.js +100 -30
  211. package/src/components/picture/picture.stories.js +1 -1
  212. package/src/components/pricing-cards/new-pricing-card.js +3 -3
  213. package/src/components/pricing-cards/new-pricing.css.js +24 -15
  214. package/src/components/pricing-cards/pricing-card-actions.css.js +1 -1
  215. package/src/components/pricing-cards/pricing-card-actions.js +3 -4
  216. package/src/components/pricing-cards/pricing-card-container.css.js +3 -3
  217. package/src/components/pricing-cards/pricing-card-container.js +3 -2
  218. package/src/components/pricing-cards/pricing-card-header.css.js +10 -8
  219. package/src/components/pricing-cards/pricing-card-header.js +6 -7
  220. package/src/components/pricing-cards/pricing-card-pricing.css.js +16 -9
  221. package/src/components/pricing-cards/pricing-card-pricing.js +8 -6
  222. package/src/components/pricing-cards/pricing-card-show-more.css.js +11 -3
  223. package/src/components/pricing-cards/pricing-card-show-more.js +8 -3
  224. package/src/components/pricing-cards/pricing-card.css.js +244 -190
  225. package/src/components/pricing-cards/pricing-card.js +54 -70
  226. package/src/components/pricing-cards/pricing-feature-item.css.js +25 -8
  227. package/src/components/pricing-cards/pricing-feature-item.js +8 -3
  228. package/src/components/process-steps/process-steps.css.js +26 -14
  229. package/src/components/process-steps/process-steps.js +23 -6
  230. package/src/components/process-steps/process-steps.stories.js +1 -1
  231. package/src/components/progress/progress.css.js +80 -0
  232. package/src/components/progress/progress.js +42 -0
  233. package/src/components/progress/progress.stories.js +79 -0
  234. package/src/components/quick-answer/quick-answer.css.js +75 -13
  235. package/src/components/quick-answer/quick-answer.js +8 -3
  236. package/src/components/radio/radio.css.js +92 -128
  237. package/src/components/radio/radio.js +106 -127
  238. package/src/components/radio/radio.stories.js +54 -19
  239. package/src/components/review/review-grid.css.js +5 -6
  240. package/src/components/review/review-grid.js +14 -11
  241. package/src/components/review/review.css.js +11 -6
  242. package/src/components/review/review.js +3 -8
  243. package/src/components/shared/ensemble.css.js +93 -0
  244. package/src/components/shared/form-field.css.js +206 -0
  245. package/src/components/shared/prop-vocabulary.js +48 -0
  246. package/src/components/shared/token-scales.js +306 -0
  247. package/src/components/skeleton/skeleton.css.js +34 -0
  248. package/src/components/skeleton/skeleton.js +32 -0
  249. package/src/components/skeleton/skeleton.stories.js +70 -0
  250. package/src/components/spinner/spinner.css.js +62 -0
  251. package/src/components/spinner/spinner.js +38 -0
  252. package/src/components/spinner/spinner.stories.js +92 -0
  253. package/src/components/spotlight-section/spotlight-section.css.js +14 -13
  254. package/src/components/spotlight-section/spotlight-section.js +42 -39
  255. package/src/components/switch/switch.css.js +103 -0
  256. package/src/components/switch/switch.js +44 -0
  257. package/src/components/switch/switch.stories.js +86 -0
  258. package/src/components/tab-list/content-switcher.stories.js +189 -0
  259. package/src/components/tab-list/tab-list.css.js +250 -0
  260. package/src/components/tab-list/tab-list.js +184 -0
  261. package/src/components/tab-list/tab-list.stories.js +221 -0
  262. package/src/components/tabs/tabs.css.js +14 -123
  263. package/src/components/tabs/tabs.js +16 -19
  264. package/src/components/tabs/tabs.stories.js +95 -95
  265. package/src/components/tag/tag.css.js +54 -0
  266. package/src/components/tag/tag.js +32 -0
  267. package/src/components/tag/tag.stories.js +126 -0
  268. package/src/components/terminal/terminal-message.css.js +164 -60
  269. package/src/components/terminal/terminal-message.js +5 -5
  270. package/src/components/terminal/terminal-message.stories.js +70 -1
  271. package/src/components/termsOfUse/terms.css.js +25 -20
  272. package/src/components/termsOfUse/terms.js +13 -9
  273. package/src/components/termsOfUse/terms.stories.js +1 -1
  274. package/src/components/textarea/textarea.css.js +51 -0
  275. package/src/components/textarea/textarea.js +136 -0
  276. package/src/components/textarea/textarea.stories.js +191 -0
  277. package/src/components/tooltip/tooltip.css.js +75 -0
  278. package/src/components/tooltip/tooltip.js +156 -0
  279. package/src/components/tooltip/tooltip.stories.js +161 -0
  280. package/src/components/trust-panel/trust-panel.css.js +85 -33
  281. package/src/components/trust-panel/trust-panel.js +18 -10
  282. package/src/components/trust-panel/trust-panel.stories.js +1 -1
  283. package/src/components/ultimate-security-demo.stories.js +431 -0
  284. package/src/components/video/video.css.js +17 -0
  285. package/src/components/video/video.js +40 -0
  286. package/src/components/video/video.stories.js +106 -0
  287. package/src/components/video-player/video-player.css.js +67 -11
  288. package/src/components/video-player/video-player.js +35 -4
  289. package/src/components/video-player/video-player.stories.js +1 -1
  290. package/src/components/visual-alignment.stories.js +411 -0
  291. package/src/components/visually-hidden/visually-hidden.css.js +24 -0
  292. package/src/components/visually-hidden/visually-hidden.js +16 -0
  293. package/src/components/visually-hidden/visually-hidden.stories.js +56 -0
  294. package/src/stories/Button.stories.js +17 -17
  295. package/src/stories/Header.stories.js +10 -10
  296. package/src/stories/Page.js +1 -1
  297. package/src/stories/Page.stories.js +6 -6
  298. package/src/tokens/borders.stories.js +339 -0
  299. package/src/tokens/color-responsibilities.stories.js +227 -0
  300. package/src/tokens/dark-derivation.js +309 -0
  301. package/src/tokens/dark-findings.js +197 -0
  302. package/src/tokens/dark-mode.stories.js +207 -0
  303. package/src/tokens/dimension.stories.js +251 -0
  304. package/src/tokens/elevation.stories.js +143 -0
  305. package/src/tokens/focus.stories.js +276 -0
  306. package/src/tokens/fonts.css +20 -20
  307. package/src/tokens/fonts.stories.js +354 -374
  308. package/src/tokens/layout.css +25 -11
  309. package/src/tokens/motion.stories.js +231 -0
  310. package/src/tokens/shape.stories.js +272 -0
  311. package/src/tokens/spacing-rhythm.stories.js +359 -0
  312. package/src/tokens/spacing.stories.js +208 -703
  313. package/src/tokens/story-chrome.js +503 -0
  314. package/src/tokens/surfaces.stories.js +224 -0
  315. package/src/tokens/text-on-surface.stories.js +164 -0
  316. package/src/tokens/token-map.js +220 -0
  317. package/src/tokens/token-map.stories.js +257 -0
  318. package/src/tokens/token-purposes.js +266 -0
  319. package/src/tokens/tokens-grid.stories.js +388 -900
  320. package/src/tokens/tokens.css +1633 -1045
  321. package/src/tokens/tokens.js +1130 -492
  322. package/src/tokens/tokens.stories.js +137 -47
  323. package/src/tokens/type-ceiling-words.js +299 -0
  324. package/src/tokens/typography.stories.js +1003 -965
  325. package/src/tokens/vertical-rhythm.stories.js +224 -0
  326. package/src/components/awards/awards-icon.js +0 -56
  327. package/src/components/awards/awards-light.js +0 -240
  328. package/src/components/banner/banner.js +0 -60
  329. package/src/components/banner/banner.stories.js +0 -51
  330. package/src/components/button/icons.js +0 -24
  331. package/src/components/input/index.js +0 -0
  332. package/src/components/light-carousel/light-carousel-simple.css.js +0 -183
  333. package/src/components/light-carousel/light-carousel-simple.js +0 -74
  334. package/src/tokens/colors.js +0 -121
  335. package/src/tokens/typography.css.js +0 -207
  336. package/src/tokens/typography.js +0 -0
@@ -1,17 +1,33 @@
1
- import { LitElement, html } from "lit";
2
- import { tokens } from "../../tokens/tokens.js";
1
+ import { LitElement, html, nothing } from "lit";
2
+ // Installs the design tokens into document scope; see src/tokens/tokens.js
3
+ import "../../tokens/tokens.js";
3
4
  import backCSS from "./back.css.js";
4
5
 
6
+ /**
7
+ * The compact back control: an arrow and a short label.
8
+ *
9
+ * The accessible name is the label. `label=""` is a supported configuration --
10
+ * it renders the arrow alone -- and an arrow is not a name, so the host's
11
+ * `aria-label` is forwarded to the button for that case. Without it the button
12
+ * had no accessible name at all: measured on Atoms/Back "No Label", empty text
13
+ * content, no aria-label, and an svg with neither a title nor aria-hidden.
14
+ */
5
15
  export class BdBack extends LitElement {
6
16
  static properties = {
7
- href : { type: String },
8
- label: { type: String }
17
+ href : { type: String },
18
+ label : { type: String },
19
+ /**
20
+ * Read off the host so it can be put on the button, which is the element a
21
+ * screen reader actually lands on. Required when `label` is empty.
22
+ */
23
+ ariaLabel: { type: String, attribute: "aria-label" }
9
24
  };
10
25
 
11
26
  constructor() {
12
27
  super();
13
28
  this.href = "";
14
29
  this.label = "Back";
30
+ this.ariaLabel = null;
15
31
  }
16
32
 
17
33
  handleClick() {
@@ -24,8 +40,13 @@ export class BdBack extends LitElement {
24
40
 
25
41
  render() {
26
42
  return html`
27
- <button class="bd-back" @click="${this.handleClick}">
28
- <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" class="mi-solid mi-arrow-back" viewBox="0 0 24 24">
43
+ <button
44
+ type="button"
45
+ class="bd-back"
46
+ aria-label="${this.ariaLabel ?? nothing}"
47
+ @click="${this.handleClick}"
48
+ >
49
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" aria-hidden="true" class="mi-solid mi-arrow-back" viewBox="0 0 24 24">
29
50
  <path d="M19 11H7.83l4.88-4.88c.39-.39.39-1.03 0-1.42a.996.996 0 0 0-1.41 0l-6.59 6.59a.996.996 0 0 0 0 1.41l6.59 6.59a.996.996 0 1 0 1.41-1.41L7.83 13H19c.55 0 1-.45 1-1s-.45-1-1-1"/>
30
51
  </svg>
31
52
  <span class="bd-back-label">${this.label}</span>
@@ -33,7 +54,7 @@ export class BdBack extends LitElement {
33
54
  `;
34
55
  }
35
56
 
36
- static styles = [tokens, backCSS];
57
+ static styles = [backCSS];
37
58
  }
38
59
 
39
60
  customElements.define("bd-back", BdBack);
@@ -2,7 +2,7 @@ import { html } from 'lit';
2
2
  import './back.js';
3
3
 
4
4
  export default {
5
- title : 'Components/Back',
5
+ title : 'Atoms/Back',
6
6
  tags : ['autodocs'],
7
7
  parameters: {
8
8
  docs: {
@@ -101,11 +101,17 @@ export const LongLabel = {
101
101
 
102
102
  export const NoLabel = {
103
103
  name : 'No Label (empty string)',
104
- render : () => html`<bd-back label=""></bd-back>`,
104
+ render : () => html`<bd-back label="" aria-label="Back to the product list"></bd-back>`,
105
105
  parameters: {
106
106
  docs: {
107
107
  description: {
108
- story: 'Edge case: `label` set to an empty string. Only the arrow icon is visible.'
108
+ story: `\`label\` set to an empty string, so only the arrow renders — and an arrow
109
+ is not a name. Measured before P6C.2: the button had empty text content,
110
+ no \`aria-label\` and an svg with neither a title nor \`aria-hidden\`, which
111
+ is a control a screen reader announces as "button" and nothing else. The
112
+ arrow is \`aria-hidden\` now and the host's \`aria-label\` reaches the
113
+ button, which is what this story passes. An icon-only bd-back without one
114
+ has no accessible name.`
109
115
  }
110
116
  }
111
117
  }
@@ -1,72 +1,184 @@
1
1
  import { css } from "lit";
2
2
 
3
+ /**
4
+ * Styled entirely from src/tokens/tokens.js — see CLAUDE.md, "The foundation
5
+ * rule". Values were matched to the ds-badge design by finding the token that
6
+ * already carries each value, never by copying a literal out of Figma.
7
+ */
3
8
  export default css`
4
9
  :host {
5
- --badge-font-weight: var(--typography-fontWeight-medium);
6
- --badge-font-family: var(--typography-fontFamily-sans, sans-serif);
7
- --badge-padding: var(--spacing-4) var(--spacing-10);
8
- --badge-border-radius: var(--spacing-16);
9
- --badge-font-size: var(--typography-label-small-fontSize);
10
- --badge-icon-size: 16px;
11
- --badge-gap: var(--spacing-4);
10
+ display: inline-flex;
11
+ vertical-align: middle;
12
12
  }
13
13
 
14
14
  .badge {
15
15
  display: inline-flex;
16
16
  align-items: center;
17
- gap: var(--badge-gap);
18
- background-color: var(--badge-bg, var(--color-blue-500));
19
- color: var(--color-neutral-0);
20
- border-radius: var(--badge-border-radius);
21
- font-size: var(--badge-font-size);
22
- font-weight: var(--badge-font-weight);
23
- font-family: var(--badge-font-family);
24
- line-height: 1;
25
- padding: var(--badge-padding);
17
+ justify-content: center;
18
+ gap: var(--spacing-4);
19
+ box-sizing: border-box;
20
+ font-family: var(--typography-fontFamily-sans);
21
+ font-weight: var(--typography-control-label-small-fontWeight);
22
+ line-height: var(--typography-control-label-small-lineHeight);
23
+ border-radius: var(--radius-full);
26
24
  white-space: nowrap;
27
25
  user-select: none;
28
- vertical-align: middle;
29
- box-sizing: border-box;
30
- position: relative;
31
26
  }
32
27
 
33
- .badge-icon {
34
- display: inline-block;
35
- flex-shrink: 0;
36
- width: var(--badge-icon-size);
37
- height: var(--badge-icon-size);
38
- background-repeat: no-repeat;
39
- background-position: center center;
40
- background-size: contain;
28
+ /* ---- size -------------------------------------------------------------
29
+ sm and md share their padding and differ only in type size, which is what
30
+ makes them 22px and 23px tall. lg steps both up. */
31
+ :host([size='sm']) .badge {
32
+ /* no role: this rung sits below the control-label-* family's floor. The
33
+ base rule takes its weight and leading from control-label-small and the
34
+ lg rung takes its size from control-label-default, so the ladder already
35
+ resolves through the family -- but the family's smallest size is xs, and
36
+ this is xxs. label-extra-small is the only declared role at this size and
37
+ it carries normal leading where this badge is tight, so it describes
38
+ different text. The family was deliberately scoped to four rungs; adding
39
+ a fifth for one consumer is what the token-hygiene item exists to resist,
40
+ so the size stays a primitive and says why. */
41
+ font-size: var(--typography-fontSize-xxs);
42
+ padding: var(--spacing-4) var(--spacing-8);
43
+ }
44
+
45
+ :host([size='md']) .badge,
46
+ :host(:not([size])) .badge {
47
+ /* control-label-small's size, completing the rung: the base rule already
48
+ takes this text's weight and leading from that role, so the size is its
49
+ third axis rather than a separate choice. */
50
+ font-size: var(--typography-control-label-small-fontSize);
51
+ padding: var(--spacing-4) var(--spacing-8);
52
+ }
53
+
54
+ :host([size='lg']) .badge {
55
+ font-size: var(--typography-control-label-default-fontSize);
56
+ padding: var(--spacing-8) var(--spacing-12);
57
+ }
58
+
59
+ /* ---- tone × variant --------------------------------------------------
60
+ shade is a tinted background with dark text; fill is a saturated
61
+ background. Defaults below are the shade/default pair. */
62
+ /* Grey, not blue: a tone called "default" reading as pale blue is
63
+ surprising, and it left default and primary sharing a background while
64
+ differing only in text colour.
65
+
66
+ A badge takes the heavier tint and a tag the lighter one, so the two read
67
+ apart. Neutral follows that; it used to sit on the lighter grey, which made
68
+ a neutral badge and a neutral tag the same colour. */
69
+ .badge {
70
+ color: var(--status-neutral-text);
71
+ background: var(--status-neutral-surface-strong);
41
72
  }
42
73
 
74
+ /* Brand is the one tone that stays on the lighter tint. Its heavier tint
75
+ would be blue-100, which is info's, and a brand badge would then be
76
+ indistinguishable from an info badge. Telling brand from info matters more
77
+ than telling a brand badge from a brand tag, so brand has no heavier tint
78
+ at all. */
79
+ :host([tone='brand']) .badge {
80
+ color: var(--status-brand-text);
81
+ background: var(--status-brand-surface);
82
+ }
43
83
 
84
+ :host([tone='success']) .badge {
85
+ /* green-800 rather than green-700: on green-100 that is 5.93:1 against
86
+ 4.17:1, and it matches the step the warning tone already uses */
87
+ color: var(--status-success-text);
88
+ background: var(--status-success-surface-strong);
89
+ }
44
90
 
45
- /* Stil pentru badge-ul bd-light-blue */
46
- .badge.bd-light-blue {
47
- background-color: var(--color-blue-500);
48
- color: var(--color-neutral-0);
91
+ :host([tone='warning']) .badge {
92
+ color: var(--status-warning-text);
93
+ background: var(--status-warning-surface-strong);
49
94
  }
50
95
 
51
- /* Stil pentru badge-ul bd-light-green */
52
- .badge.bd-light-green {
53
- background-color: var(--color-green-100);
54
- color: var(--color-green-800);
96
+ :host([tone='error']) .badge {
97
+ color: var(--status-error-text);
98
+ background: var(--status-error-surface-strong);
55
99
  }
56
100
 
57
- /* Stiluri pentru variantele cu size (doar ajustări de icon și gap) */
58
- .badge.sm {
59
- --badge-icon-size: 14px;
60
- --badge-gap: var(--spacing-2);
101
+ :host([tone='info']) .badge {
102
+ color: var(--status-info-text);
103
+ background: var(--status-info-surface-strong);
61
104
  }
62
105
 
63
- .badge.md {
64
- --badge-icon-size: 16px;
65
- --badge-gap: var(--spacing-4);
106
+ :host([variant='fill']) .badge {
107
+ color: var(--status-neutral-on-fill);
108
+ background: var(--status-neutral-fill);
109
+ }
110
+
111
+ :host([variant='fill'][tone='brand']) .badge {
112
+ color: var(--status-brand-on-fill);
113
+ background: var(--status-brand-fill);
114
+ }
115
+
116
+ /* Info reads its own fill roles, not brand's. The two resolve to the same
117
+ blue-500 today, which is why info used to borrow brand's; sharing a value
118
+ is not sharing a role, and borrowing meant a change to brand's fill would
119
+ have moved every filled info badge with it. */
120
+ :host([variant='fill'][tone='info']) .badge {
121
+ color: var(--status-info-on-fill);
122
+ background: var(--status-info-fill);
123
+ }
124
+
125
+ /* green-700 with a white label, rather than the design's green-500 with a
126
+ dark one. green-700 is the lightest step in the family that carries white
127
+ text at 4.5:1 — it measures 4.75, where green-600 is only 3.20. It also
128
+ lines up with the success dot, which already uses green-700. */
129
+ :host([variant='fill'][tone='success']) .badge {
130
+ color: var(--status-success-on-fill);
131
+ background: var(--status-success-fill);
132
+ }
133
+
134
+ :host([variant='fill'][tone='warning']) .badge {
135
+ color: var(--status-warning-on-fill);
136
+ background: var(--status-warning-fill);
137
+ }
138
+
139
+ :host([variant='fill'][tone='error']) .badge {
140
+ color: var(--status-error-on-fill);
141
+ background: var(--status-error-fill);
142
+ }
143
+
144
+ /* ---- mode: dot ------------------------------------------------------
145
+ The design keeps the dot at one size across sm/md/lg, so size has no
146
+ effect in this mode.
147
+
148
+ variant has no effect either. A dot has no text, so there is no
149
+ foreground/background pair for shade and fill to describe — the colour
150
+ *is* the content. That also means it has to carry itself on the page:
151
+ WCAG 1.4.11 wants 3:1 for a graphical object whose colour conveys
152
+ meaning, and the tint steps the shade text sits on measure 1.08 to 1.33.
153
+ Each tone therefore uses a saturated step chosen to clear 3:1. */
154
+ :host([mode='dot']) .badge {
155
+ width: var(--spacing-8);
156
+ height: var(--spacing-8);
157
+ padding: 0;
158
+ gap: 0;
159
+ }
160
+
161
+ :host([mode='dot']) .badge { background: var(--status-neutral-accent); }
162
+ :host([mode='dot'][tone='brand']) .badge { background: var(--status-brand-accent); }
163
+ /* green-700 rather than the lighter steps: green-500 measures 2.39 and
164
+ green-600 only 3.20, where 700 gives 4.75 and still reads as green */
165
+ :host([mode='dot'][tone='success']) .badge { background: var(--status-success-accent); }
166
+ /* yellow is inherently light — 700 at 3.61 is the lightest step that both
167
+ clears 3:1 and still reads as yellow rather than brown */
168
+ :host([mode='dot'][tone='warning']) .badge { background: var(--status-warning-accent); }
169
+ :host([mode='dot'][tone='error']) .badge { background: var(--status-error-accent); }
170
+ :host([mode='dot'][tone='info']) .badge { background: var(--status-info-accent); }
171
+
172
+ /* ---- mode: count ----------------------------------------------------
173
+ Digits are set tabular so a counter does not change width as it counts:
174
+ measured, "12" and "99" both come out at the same width. The padding
175
+ already makes a single digit near-circular, so no min-width is needed. */
176
+ :host([mode='count']) .badge {
177
+ font-variant-numeric: tabular-nums;
66
178
  }
67
179
 
68
- .badge.lg {
69
- --badge-icon-size: 18px;
70
- --badge-gap: var(--spacing-6);
180
+ /* ---- icon ------------------------------------------------------------ */
181
+ ::slotted(*) {
182
+ flex: none;
71
183
  }
72
- `;
184
+ `;
@@ -1,108 +1,96 @@
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 "../icons/family-icon.js";
4
5
  import "../icons/individual-icon.js";
5
6
  import badgeCSS from './badge.css.js';
6
7
 
8
+ /**
9
+ * Maps the pre-ds-badge `variant` values onto the tone/variant pair that
10
+ * reproduces them, so existing markup keeps rendering the same thing.
11
+ */
12
+ const LEGACY_VARIANTS = {
13
+ 'bd-light-blue' : { tone: 'brand', variant: 'fill' }, // blue-500 / neutral-0
14
+ 'bd-light-green': { tone: 'success', variant: 'shade' } // green-100 / green-800
15
+ };
16
+
17
+ const MODES = ['text', 'dot', 'count'];
18
+ const SIZES = ['sm', 'md', 'lg'];
19
+ /**
20
+ * The six tones bd-badge, bd-tag and bd-alert now share. `default` and
21
+ * `primary` are the names this component started with and keep working; they
22
+ * resolve to `neutral` and `brand`, which say what they mean and are what the
23
+ * other two already called them. `primary` in particular collided with
24
+ * bd-button's primary kind while describing something else entirely.
25
+ */
26
+ const TONES = ['neutral', 'brand', 'success', 'warning', 'error', 'info'];
27
+ const LEGACY_TONES = { default: 'neutral', primary: 'brand' };
28
+ const VARIANTS = ['shade', 'fill'];
29
+
7
30
  export class BdBadge extends LitElement {
8
- static styles = [tokens, badgeCSS];
31
+ static styles = [badgeCSS];
9
32
 
10
33
  static properties = {
11
- color : { type: String },
12
- variant : { type: String },
13
- size : { type: String }, // sm, md, lg
14
- fontsize : { type: String }, // 12, 14, 16
15
- fontweight: { type: String }, // 400, 500, 600, 700, etc.
16
- icon : { type: String } // individual, family
34
+ mode : { type: String, reflect: true }, // text, dot, count
35
+ size : { type: String, reflect: true }, // sm, md, lg
36
+ tone : { type: String, reflect: true }, // neutral, brand, success, warning, error, info
37
+ variant: { type: String, reflect: true }, // shade, fill
38
+ icon : { type: String }, // individual, family
39
+ label : { type: String } // accessible name for mode="dot"
17
40
  };
18
41
 
19
42
  constructor() {
20
43
  super();
21
- this.color = '';
22
- this.variant = '';
44
+ this.mode = 'text';
23
45
  this.size = 'md';
24
- this.fontsize = '';
25
- this.fontweight = '';
46
+ this.tone = 'neutral';
47
+ this.variant = 'shade';
26
48
  this.icon = '';
49
+ this.label = '';
27
50
  }
28
51
 
29
- updated(changed) {
30
- if (changed.has('color')) {
31
- this.style.setProperty('--badge-bg', this.color || '');
32
- }
33
-
34
- if (changed.has('size') || changed.has('fontsize')) {
35
- this._updateSizeStyles();
36
- }
37
-
38
- if (changed.has('fontweight')) {
39
- this._updateFontWeight();
40
- }
41
- }
42
-
43
- _updateSizeStyles() {
44
- const sizeMap = {
45
- 'sm': {
46
- padding : 'var(--spacing-2) var(--spacing-8)',
47
- borderRadius: 'var(--spacing-12)',
48
- fontSize : 'var(--typography-label-extra-small-fontSize)'
49
- },
50
- 'md': {
51
- padding : 'var(--spacing-4) var(--spacing-10)',
52
- borderRadius: 'var(--spacing-16)',
53
- fontSize : 'var(--typography-label-small-fontSize)'
54
- },
55
- 'lg': {
56
- padding : 'var(--spacing-6) var(--spacing-12)',
57
- borderRadius: 'var(--spacing-20)',
58
- fontSize : 'var(--typography-label-default-fontSize)'
59
- }
60
- };
61
-
62
- const fontSizeMap = {
63
- '12': 'var(--typography-label-small-fontSize)',
64
- '14': 'var(--typography-label-default-fontSize)',
65
- '16': 'var(--typography-label-large-fontSize)'
66
- };
67
-
68
- if (this.size && sizeMap[this.size]) {
69
- const sizeStyle = sizeMap[this.size];
70
- this.style.setProperty('--badge-padding', sizeStyle.padding);
71
- this.style.setProperty('--badge-border-radius', sizeStyle.borderRadius);
72
-
73
- if (!this.fontsize) {
74
- this.style.setProperty('--badge-font-size', sizeStyle.fontSize);
75
- }
52
+ willUpdate(changed) {
53
+ if (changed.has('variant') && LEGACY_VARIANTS[this.variant]) {
54
+ const { tone, variant } = LEGACY_VARIANTS[this.variant];
55
+ this.tone = tone;
56
+ this.variant = variant;
76
57
  }
77
58
 
78
- if (this.fontsize && fontSizeMap[this.fontsize]) {
79
- this.style.setProperty('--badge-font-size', fontSizeMap[this.fontsize]);
80
- }
81
- }
82
-
83
- _updateFontWeight() {
84
- if (this.fontweight) {
85
- this.style.setProperty('--badge-font-weight', this.fontweight);
59
+ // an unset or unrecognised value falls back to the default rather than
60
+ // dropping out of every selector and rendering unstyled
61
+ if (changed.has('mode') && !MODES.includes(this.mode)) this.mode = 'text';
62
+ if (changed.has('size') && !SIZES.includes(this.size)) this.size = 'md';
63
+ if (changed.has('tone')) {
64
+ if (LEGACY_TONES[this.tone]) this.tone = LEGACY_TONES[this.tone];
65
+ else if (!TONES.includes(this.tone)) this.tone = 'neutral';
86
66
  }
67
+ if (changed.has('variant') && !VARIANTS.includes(this.variant)) this.variant = 'shade';
87
68
  }
88
69
 
89
70
  _renderIcon() {
90
- if (!this.icon) return '';
91
- const color = this.variant === 'bd-light-green' ? '#0b6a26' : 'white';
71
+ if (!this.icon || this.mode === 'dot') return '';
92
72
 
73
+ // currentColor makes the icon follow the tone's text colour, so there is
74
+ // no per-tone icon colour to keep in step
93
75
  switch (this.icon) {
94
76
  case 'individual':
95
- return html`<bd-individual-icon size="16" color="${color}"></bd-individual-icon>`;
77
+ return html`<bd-individual-icon size="16" color="currentColor"></bd-individual-icon>`;
96
78
  case 'family':
97
- return html`<bd-family-icon size="16" color="${color}"></bd-family-icon>`;
79
+ return html`<bd-family-icon size="16" color="currentColor"></bd-family-icon>`;
98
80
  default:
99
81
  return '';
100
82
  }
101
83
  }
102
84
 
103
85
  render() {
104
- return html`
105
- <span class="badge ${this.variant} ${this.size}">
86
+ // a dot renders no text, so it needs a name of its own. Reading
87
+ // textContent here would be unreliable — light DOM children are not
88
+ // guaranteed to be parsed at first update, and later edits to them would
89
+ // not trigger a re-render.
90
+ return this.mode === 'dot'
91
+ ? html`<span class="badge" role="img" aria-label="${this.label || this.tone}"></span>`
92
+ : html`
93
+ <span class="badge">
106
94
  ${this._renderIcon()}
107
95
  <slot></slot>
108
96
  </span>
@@ -110,4 +98,4 @@ export class BdBadge extends LitElement {
110
98
  }
111
99
  }
112
100
 
113
- customElements.define('bd-badge', BdBadge);
101
+ customElements.define('bd-badge', BdBadge);