@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.
- package/CHANGELOG.md +187 -0
- package/README.md +131 -8
- package/package.json +95 -13
- package/schemas/component-manifest.json +3294 -405
- package/schemas/manifest-omissions.json +173 -0
- package/src/blog/src/breakpoints.js +6 -6
- package/src/blog/src/content/blog-atoms-showcase.js +1 -1
- package/src/blog/src/content/blog-page-layout.js +2 -2
- package/src/blog/src/lib/article-toc.js +7 -7
- package/src/blog/src/shell/blog-shell.js +1 -1
- package/src/blog/src/tokens/blog.js +2 -2
- package/src/blog/src/tokens/core.js +34 -35
- package/src/blog/src/tokens/legacy.js +0 -9
- package/src/blog/tokens/blog.js +2 -2
- package/src/blog/tokens/core.js +34 -35
- package/src/blog/tokens/legacy.js +0 -9
- package/src/blog/tokens.css +36 -46
- package/src/components/accordion/accordion-bg.css.js +83 -59
- package/src/components/accordion/accordion-bg.js +29 -10
- package/src/components/accordion/accordion-bg.stories.js +67 -67
- package/src/components/accordion/accordion-keyboard.js +80 -0
- package/src/components/accordion/accordion.css.js +142 -80
- package/src/components/accordion/accordion.js +37 -10
- package/src/components/accordion/accordion.stories.js +7 -7
- package/src/components/agent-endpoints/agent-endpoints.css.js +36 -39
- package/src/components/agent-endpoints/agent-endpoints.js +30 -20
- package/src/components/agent-endpoints/agent-endpoints.stories.js +1 -1
- package/src/components/ai-guardian-demo.stories.js +91 -91
- package/src/components/alert/alert.css.js +198 -0
- package/src/components/alert/alert.js +103 -0
- package/src/components/alert/alert.stories.js +206 -0
- package/src/components/anchor/anchor-nav.css.js +213 -101
- package/src/components/anchor/anchor-nav.js +26 -40
- package/src/components/anchor/anchor.stories.js +22 -12
- package/src/components/annotation/annotation.css.js +58 -0
- package/src/components/annotation/annotation.js +67 -0
- package/src/components/annotation/annotation.stories.js +63 -0
- package/src/components/architecture.stories.js +285 -0
- package/src/components/atoms.stories.js +342 -0
- package/src/components/avatar/avatar.css.js +67 -0
- package/src/components/avatar/avatar.js +42 -0
- package/src/components/avatar/avatar.stories.js +95 -0
- package/src/components/awards/awards-flex.css.js +209 -23
- package/src/components/awards/awards-flex.js +66 -7
- package/src/components/awards/awards-flex.stories.js +1 -1
- package/src/components/awards/{awards-light.stories.js → awards-summary.stories.js} +54 -64
- package/src/components/awards/awards.css.js +116 -58
- package/src/components/awards/awards.js +102 -28
- package/src/components/awards/awards.stories.js +1 -1
- package/src/components/back/back.css.js +51 -22
- package/src/components/back/back.js +28 -7
- package/src/components/back/back.stories.js +9 -3
- package/src/components/badge/badge.css.js +158 -46
- package/src/components/badge/badge.js +62 -74
- package/src/components/badge/badge.stories.js +176 -248
- package/src/components/bento-grid/bento-grid.css.js +21 -16
- package/src/components/bento-grid/bento-grid.js +16 -4
- package/src/components/bento-grid/bento-grid.stories.js +19 -18
- package/src/components/bento-grid/bento-item.css.js +52 -28
- package/src/components/bento-grid/bento-item.js +2 -2
- package/src/components/blockquote/blockquote.css.js +47 -0
- package/src/components/blockquote/blockquote.js +29 -0
- package/src/components/blockquote/blockquote.stories.js +62 -0
- package/src/components/breadcrumb/breadcrumb.css.js +92 -22
- package/src/components/breadcrumb/breadcrumb.js +56 -11
- package/src/components/button/button.css.js +531 -161
- package/src/components/button/button.js +206 -214
- package/src/components/button/button.stories.js +322 -174
- package/src/components/caption/caption.css.js +21 -0
- package/src/components/caption/caption.js +31 -0
- package/src/components/caption/caption.stories.js +62 -0
- package/src/components/card-features/card-features.css.js +14 -22
- package/src/components/card-features/card-features.js +68 -9
- package/src/components/card-features/card-features.stories.js +11 -11
- package/src/components/cards/card.css.js +60 -81
- package/src/components/cards/card.js +56 -25
- package/src/components/cards/card.stories.js +39 -39
- package/src/components/carousel/carousel.css.js +93 -99
- package/src/components/carousel/carousel.js +32 -4
- package/src/components/checkbox/checkbox.css.js +111 -93
- package/src/components/checkbox/checkbox.js +64 -90
- package/src/components/checkbox/checkbox.stories.js +96 -29
- package/src/components/code/code.css.js +70 -0
- package/src/components/code/code.js +40 -0
- package/src/components/code/code.stories.js +73 -0
- package/src/components/compare/compare.css.js +179 -43
- package/src/components/compare/compare.js +52 -25
- package/src/components/compare/compare.stories.js +61 -4
- package/src/components/comparison-panel/comparison-panel.css.js +38 -51
- package/src/components/comparison-panel/comparison-panel.js +5 -4
- package/src/components/comparison-panel/comparison-panel.stories.js +1 -1
- package/src/components/compatibility-table/compatibility-table.css.js +180 -80
- package/src/components/compatibility-table/compatibility-table.js +37 -9
- package/src/components/control-alignment.stories.js +393 -0
- package/src/components/cta-banner/cta-banner.css.js +41 -13
- package/src/components/cta-banner/cta-banner.js +6 -5
- package/src/components/cta-banner/cta-banner.stories.js +43 -98
- package/src/components/display/display.css.js +25 -1
- package/src/components/display/display.js +46 -13
- package/src/components/display/display.stories.js +270 -40
- package/src/components/divider/divider-horizontal.js +21 -5
- package/src/components/divider/divider-vertical.js +15 -7
- package/src/components/divider/divider.css.js +2 -2
- package/src/components/divider/divider.stories.js +38 -34
- package/src/components/dropdown/dropdown.css.js +93 -126
- package/src/components/dropdown/dropdown.js +114 -34
- package/src/components/dropdown/dropdown.stories.js +56 -24
- package/src/components/features/features.css.js +24 -11
- package/src/components/features/features.js +7 -3
- package/src/components/features/features.stories.js +37 -37
- package/src/components/features-tab/features-tab.css.js +19 -8
- package/src/components/features-tab/features-tab.js +6 -5
- package/src/components/features-tab/features-tab.stories.js +23 -23
- package/src/components/fieldset/fieldset.css.js +30 -0
- package/src/components/fieldset/fieldset.js +28 -0
- package/src/components/fieldset/fieldset.stories.js +84 -0
- package/src/components/footer/footer-links-group.css.js +10 -14
- package/src/components/footer/footer-links-group.js +4 -3
- package/src/components/footer/footer-lp.css.js +59 -30
- package/src/components/footer/footer-lp.js +17 -12
- package/src/components/footer/footer-lp.stories.js +63 -75
- package/src/components/footer/footer-nav-menu.css.js +26 -4
- package/src/components/footer/footer-nav-menu.js +3 -2
- package/src/components/footer/footer.css.js +146 -264
- package/src/components/footer/footer.js +176 -106
- package/src/components/footer/footer.stories.js +9 -9
- package/src/components/footer/localeMap.js +1 -1
- package/src/components/grid/grid.css.js +1 -1
- package/src/components/grid/grid.js +49 -7
- package/src/components/grid/grid.stories.js +111 -0
- package/src/components/header/header-code.css.js +61 -51
- package/src/components/header/header-code.js +28 -14
- package/src/components/header/header-code.stories.js +5 -5
- package/src/components/header/header.css.js +655 -176
- package/src/components/header/header.js +269 -36
- package/src/components/header/header.stories.js +841 -18
- package/src/components/heading/heading.css.js +14 -17
- package/src/components/heading/heading.js +48 -33
- package/src/components/heading/heading.stories.js +27 -25
- package/src/components/help-text/help-text.css.js +21 -0
- package/src/components/help-text/help-text.js +25 -0
- package/src/components/help-text/help-text.stories.js +66 -0
- package/src/components/highlight/highlight.css.js +86 -64
- package/src/components/highlight/highlight.js +18 -27
- package/src/components/highlight/highlight.stories.js +14 -3
- package/src/components/icons/analysis-icon.js +6 -16
- package/src/components/icons/arrow-down-icon.js +6 -19
- package/src/components/icons/arrow-icon.js +44 -0
- package/src/components/icons/arrow-right-icon.js +30 -23
- package/src/components/icons/arrow-up-icon.js +19 -18
- package/src/components/icons/bd-ai-icon.js +1 -1
- package/src/components/icons/brand-marks.stories.js +279 -0
- package/src/components/icons/brand-signature-icon.js +42 -0
- package/src/components/icons/check-icon.js +27 -0
- package/src/components/icons/circle-info-icon.js +33 -0
- package/src/components/icons/close-icon.js +6 -18
- package/src/components/icons/family-icon.js +8 -20
- package/src/components/icons/globe-icon.js +6 -18
- package/src/components/icons/guide-icon.js +6 -18
- package/src/components/icons/icon-element.js +99 -0
- package/src/components/icons/icons.js +36 -0
- package/src/components/icons/icons.stories.js +184 -52
- package/src/components/icons/individual-icon.js +6 -18
- package/src/components/icons/laurel-icon.js +9 -19
- package/src/components/icons/machine-learning-icon.js +6 -17
- package/src/components/icons/marks.js +41 -0
- package/src/components/icons/minus-icon.js +7 -21
- package/src/components/icons/missing-icon.js +52 -0
- package/src/components/icons/plus-icon.js +7 -21
- package/src/components/icons/quote-icon.js +19 -19
- package/src/components/image/image.css.js +72 -25
- package/src/components/image/image.js +11 -6
- package/src/components/image/image.stories.js +2 -2
- package/src/components/input/custom-form.stories.js +214 -62
- package/src/components/input/input-clipboard.css.js +51 -144
- package/src/components/input/input-clipboard.js +31 -15
- package/src/components/input/input.css.js +8 -146
- package/src/components/input/input.js +93 -38
- package/src/components/install-options/install-options.css.js +84 -77
- package/src/components/install-options/install-options.js +33 -30
- package/src/components/install-options/install-options.stories.js +3 -3
- package/src/components/label/label.css.js +35 -0
- package/src/components/label/label.js +38 -0
- package/src/components/label/label.stories.js +82 -0
- package/src/components/light-carousel/light-carousel.css.js +111 -63
- package/src/components/light-carousel/light-carousel.js +85 -11
- package/src/components/light-carousel/light-carousel.stories.js +126 -82
- package/src/components/link/link.css.js +150 -99
- package/src/components/link/link.js +86 -11
- package/src/components/link/link.stories.js +124 -30
- package/src/components/list/list-item/list-item.css.js +74 -22
- package/src/components/list/list-item/list-item.js +32 -10
- package/src/components/list/list-item/list-item.stories.js +23 -23
- package/src/components/list/list.css.js +8 -2
- package/src/components/list/list.js +3 -2
- package/src/components/list/list.stories.js +222 -0
- package/src/components/modal/modal.css.js +114 -24
- package/src/components/modal/modal.js +83 -7
- package/src/components/modal/modal.stories.js +9 -9
- package/src/components/overview/overview.css.js +19 -14
- package/src/components/overview/overview.js +6 -5
- package/src/components/overview/overview.stories.js +10 -10
- package/src/components/page-switcher/page-switcher.css.js +97 -40
- package/src/components/page-switcher/page-switcher.js +28 -5
- package/src/components/page-switcher/page-switcher.stories.js +95 -0
- package/src/components/paragraph/paragraph.css.js +15 -10
- package/src/components/paragraph/paragraph.js +41 -44
- package/src/components/paragraph/paragraph.stories.js +56 -21
- package/src/components/picture/picture.css.js +103 -44
- package/src/components/picture/picture.js +100 -30
- package/src/components/picture/picture.stories.js +1 -1
- package/src/components/pricing-cards/new-pricing-card.js +3 -3
- package/src/components/pricing-cards/new-pricing.css.js +24 -15
- package/src/components/pricing-cards/pricing-card-actions.css.js +1 -1
- package/src/components/pricing-cards/pricing-card-actions.js +3 -4
- package/src/components/pricing-cards/pricing-card-container.css.js +3 -3
- package/src/components/pricing-cards/pricing-card-container.js +3 -2
- package/src/components/pricing-cards/pricing-card-header.css.js +10 -8
- package/src/components/pricing-cards/pricing-card-header.js +6 -7
- package/src/components/pricing-cards/pricing-card-pricing.css.js +16 -9
- package/src/components/pricing-cards/pricing-card-pricing.js +8 -6
- package/src/components/pricing-cards/pricing-card-show-more.css.js +11 -3
- package/src/components/pricing-cards/pricing-card-show-more.js +8 -3
- package/src/components/pricing-cards/pricing-card.css.js +244 -190
- package/src/components/pricing-cards/pricing-card.js +54 -70
- package/src/components/pricing-cards/pricing-feature-item.css.js +25 -8
- package/src/components/pricing-cards/pricing-feature-item.js +8 -3
- package/src/components/process-steps/process-steps.css.js +26 -14
- package/src/components/process-steps/process-steps.js +23 -6
- package/src/components/process-steps/process-steps.stories.js +1 -1
- package/src/components/progress/progress.css.js +80 -0
- package/src/components/progress/progress.js +42 -0
- package/src/components/progress/progress.stories.js +79 -0
- package/src/components/quick-answer/quick-answer.css.js +75 -13
- package/src/components/quick-answer/quick-answer.js +8 -3
- package/src/components/radio/radio.css.js +92 -128
- package/src/components/radio/radio.js +106 -127
- package/src/components/radio/radio.stories.js +54 -19
- package/src/components/review/review-grid.css.js +5 -6
- package/src/components/review/review-grid.js +14 -11
- package/src/components/review/review.css.js +11 -6
- package/src/components/review/review.js +3 -8
- package/src/components/shared/ensemble.css.js +93 -0
- package/src/components/shared/form-field.css.js +206 -0
- package/src/components/shared/prop-vocabulary.js +48 -0
- package/src/components/shared/token-scales.js +306 -0
- package/src/components/skeleton/skeleton.css.js +34 -0
- package/src/components/skeleton/skeleton.js +32 -0
- package/src/components/skeleton/skeleton.stories.js +70 -0
- package/src/components/spinner/spinner.css.js +62 -0
- package/src/components/spinner/spinner.js +38 -0
- package/src/components/spinner/spinner.stories.js +92 -0
- package/src/components/spotlight-section/spotlight-section.css.js +14 -13
- package/src/components/spotlight-section/spotlight-section.js +42 -39
- package/src/components/switch/switch.css.js +103 -0
- package/src/components/switch/switch.js +44 -0
- package/src/components/switch/switch.stories.js +86 -0
- package/src/components/tab-list/content-switcher.stories.js +189 -0
- package/src/components/tab-list/tab-list.css.js +250 -0
- package/src/components/tab-list/tab-list.js +184 -0
- package/src/components/tab-list/tab-list.stories.js +221 -0
- package/src/components/tabs/tabs.css.js +14 -123
- package/src/components/tabs/tabs.js +16 -19
- package/src/components/tabs/tabs.stories.js +95 -95
- package/src/components/tag/tag.css.js +54 -0
- package/src/components/tag/tag.js +32 -0
- package/src/components/tag/tag.stories.js +126 -0
- package/src/components/terminal/terminal-message.css.js +164 -60
- package/src/components/terminal/terminal-message.js +5 -5
- package/src/components/terminal/terminal-message.stories.js +70 -1
- package/src/components/termsOfUse/terms.css.js +25 -20
- package/src/components/termsOfUse/terms.js +13 -9
- package/src/components/termsOfUse/terms.stories.js +1 -1
- package/src/components/textarea/textarea.css.js +51 -0
- package/src/components/textarea/textarea.js +136 -0
- package/src/components/textarea/textarea.stories.js +191 -0
- package/src/components/tooltip/tooltip.css.js +75 -0
- package/src/components/tooltip/tooltip.js +156 -0
- package/src/components/tooltip/tooltip.stories.js +161 -0
- package/src/components/trust-panel/trust-panel.css.js +85 -33
- package/src/components/trust-panel/trust-panel.js +18 -10
- package/src/components/trust-panel/trust-panel.stories.js +1 -1
- package/src/components/ultimate-security-demo.stories.js +431 -0
- package/src/components/video/video.css.js +17 -0
- package/src/components/video/video.js +40 -0
- package/src/components/video/video.stories.js +106 -0
- package/src/components/video-player/video-player.css.js +67 -11
- package/src/components/video-player/video-player.js +35 -4
- package/src/components/video-player/video-player.stories.js +1 -1
- package/src/components/visual-alignment.stories.js +411 -0
- package/src/components/visually-hidden/visually-hidden.css.js +24 -0
- package/src/components/visually-hidden/visually-hidden.js +16 -0
- package/src/components/visually-hidden/visually-hidden.stories.js +56 -0
- package/src/stories/Button.stories.js +17 -17
- package/src/stories/Header.stories.js +10 -10
- package/src/stories/Page.js +1 -1
- package/src/stories/Page.stories.js +6 -6
- package/src/tokens/borders.stories.js +339 -0
- package/src/tokens/color-responsibilities.stories.js +227 -0
- package/src/tokens/dark-derivation.js +309 -0
- package/src/tokens/dark-findings.js +197 -0
- package/src/tokens/dark-mode.stories.js +207 -0
- package/src/tokens/dimension.stories.js +251 -0
- package/src/tokens/elevation.stories.js +143 -0
- package/src/tokens/focus.stories.js +276 -0
- package/src/tokens/fonts.css +20 -20
- package/src/tokens/fonts.stories.js +354 -374
- package/src/tokens/layout.css +25 -11
- package/src/tokens/motion.stories.js +231 -0
- package/src/tokens/shape.stories.js +272 -0
- package/src/tokens/spacing-rhythm.stories.js +359 -0
- package/src/tokens/spacing.stories.js +208 -703
- package/src/tokens/story-chrome.js +503 -0
- package/src/tokens/surfaces.stories.js +224 -0
- package/src/tokens/text-on-surface.stories.js +164 -0
- package/src/tokens/token-map.js +220 -0
- package/src/tokens/token-map.stories.js +257 -0
- package/src/tokens/token-purposes.js +266 -0
- package/src/tokens/tokens-grid.stories.js +388 -900
- package/src/tokens/tokens.css +1633 -1045
- package/src/tokens/tokens.js +1130 -492
- package/src/tokens/tokens.stories.js +137 -47
- package/src/tokens/type-ceiling-words.js +299 -0
- package/src/tokens/typography.stories.js +1003 -965
- package/src/tokens/vertical-rhythm.stories.js +224 -0
- package/src/components/awards/awards-icon.js +0 -56
- package/src/components/awards/awards-light.js +0 -240
- package/src/components/banner/banner.js +0 -60
- package/src/components/banner/banner.stories.js +0 -51
- package/src/components/button/icons.js +0 -24
- package/src/components/input/index.js +0 -0
- package/src/components/light-carousel/light-carousel-simple.css.js +0 -183
- package/src/components/light-carousel/light-carousel-simple.js +0 -74
- package/src/tokens/colors.js +0 -121
- package/src/tokens/typography.css.js +0 -207
- package/src/tokens/typography.js +0 -0
|
@@ -1,45 +1,90 @@
|
|
|
1
1
|
import { css } from "lit";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Styled entirely from src/tokens/tokens.js — see CLAUDE.md, "The foundation
|
|
5
|
+
* rule". Every measurement was matched to the token that already carries the
|
|
6
|
+
* ds-button value; nothing was copied across as a literal.
|
|
7
|
+
*
|
|
8
|
+
* The --button-* properties below are component-local semantic aliases, not
|
|
9
|
+
* design tokens. Declaring them on :host is deliberate: outer-tree rules beat
|
|
10
|
+
* :host, so a page can still theme a button with
|
|
11
|
+
* `bd-button { --bd-button-primary-bg: … }`.
|
|
12
|
+
*/
|
|
3
13
|
export default css`
|
|
4
14
|
:host {
|
|
5
15
|
display: inline-flex;
|
|
6
|
-
--button-background-primary: var(--color-blue-500);
|
|
7
|
-
--button-background-primary-hover: var(--color-blue-600);
|
|
8
|
-
--button-background-primary-focus: var(--color-blue-700);
|
|
9
16
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
--button-
|
|
21
|
-
--
|
|
22
|
-
--button-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
--button-
|
|
27
|
-
--
|
|
28
|
-
--button-
|
|
29
|
-
--bd-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
--button-
|
|
33
|
-
--button-
|
|
34
|
-
--button-
|
|
35
|
-
|
|
36
|
-
--button-
|
|
17
|
+
/* Component-local aliases, not design tokens. Each defaults to the
|
|
18
|
+
--button-* token that carries the system-wide answer, so there are two
|
|
19
|
+
places to change a button and they do different jobs: set the token on
|
|
20
|
+
:root to move every button in the document, or set the alias on the
|
|
21
|
+
bd-button element to move one.
|
|
22
|
+
|
|
23
|
+
The alias is also what surface="dark" switches further down, which is
|
|
24
|
+
why it stays even now that the tokens behind it are live. */
|
|
25
|
+
|
|
26
|
+
/* ---- primary: blue fill ------------------------------------------- */
|
|
27
|
+
--bd-button-primary-bg: var(--button-primary-background-default);
|
|
28
|
+
--bd-button-primary-bg-hover: var(--button-primary-background-hover);
|
|
29
|
+
--bd-button-primary-bg-active: var(--button-primary-background-active);
|
|
30
|
+
--bd-button-primary-text: var(--button-primary-text-default);
|
|
31
|
+
|
|
32
|
+
/* ---- secondary: near-black fill ----------------------------------- */
|
|
33
|
+
--bd-button-secondary-bg: var(--button-secondary-background-default);
|
|
34
|
+
--bd-button-secondary-bg-hover: var(--button-secondary-background-hover);
|
|
35
|
+
--bd-button-secondary-bg-active: var(--button-secondary-background-active);
|
|
36
|
+
--bd-button-secondary-text: var(--button-secondary-text-default);
|
|
37
|
+
|
|
38
|
+
/* ---- tertiary: blue outline --------------------------------------- */
|
|
39
|
+
--bd-button-tertiary-text: var(--button-tertiary-text-default);
|
|
40
|
+
--bd-button-tertiary-border: var(--button-tertiary-border-default);
|
|
41
|
+
--bd-button-tertiary-bg-hover: var(--button-tertiary-background-hover);
|
|
42
|
+
--bd-button-tertiary-text-hover: var(--button-tertiary-text-hover);
|
|
43
|
+
--bd-button-tertiary-border-hover: var(--button-tertiary-border-hover);
|
|
44
|
+
--bd-button-tertiary-bg-active: var(--button-tertiary-background-active);
|
|
45
|
+
--bd-button-tertiary-text-active: var(--button-tertiary-text-active);
|
|
46
|
+
|
|
47
|
+
/* ---- ghost: dark outline ------------------------------------------ */
|
|
48
|
+
--bd-button-ghost-text: var(--button-ghost-text-default);
|
|
49
|
+
--bd-button-ghost-border: var(--button-ghost-border-default);
|
|
50
|
+
--bd-button-ghost-bg-hover: var(--button-ghost-background-hover);
|
|
51
|
+
--bd-button-ghost-text-hover: var(--button-ghost-text-hover);
|
|
52
|
+
--bd-button-ghost-bg-active: var(--button-ghost-background-active);
|
|
53
|
+
--bd-button-ghost-text-active: var(--button-ghost-text-active);
|
|
54
|
+
|
|
55
|
+
/* ---- accent: red fill --------------------------------------------- */
|
|
56
|
+
--bd-button-accent-bg: var(--button-accent-background-default);
|
|
57
|
+
--bd-button-accent-bg-hover: var(--button-accent-background-hover);
|
|
58
|
+
--bd-button-accent-bg-active: var(--button-accent-background-active);
|
|
59
|
+
--bd-button-accent-text: var(--button-accent-text-default);
|
|
60
|
+
|
|
61
|
+
/* ---- white and outline-white: fixed presets for a coloured banner --
|
|
62
|
+
They ignore surface on purpose; see the note on VARIANTS in button.js. */
|
|
63
|
+
--bd-button-white-bg: var(--button-white-background-default);
|
|
64
|
+
--bd-button-white-bg-hover: var(--button-white-background-hover);
|
|
65
|
+
--bd-button-white-bg-active: var(--button-white-background-active);
|
|
66
|
+
--bd-button-white-text: var(--button-white-text-default);
|
|
67
|
+
|
|
68
|
+
--bd-button-outline-white-text: var(--button-outline-white-text-default);
|
|
69
|
+
--bd-button-outline-white-border: var(--button-outline-white-border-default);
|
|
70
|
+
--bd-button-outline-white-bg-hover: var(--button-outline-white-background-hover);
|
|
71
|
+
--bd-button-outline-white-bg-active: var(--button-outline-white-background-active);
|
|
72
|
+
|
|
73
|
+
/* ---- disabled, shared across every variant ----------------------- */
|
|
74
|
+
--bd-button-disabled-bg: var(--button-disabled-backgroundColor);
|
|
75
|
+
--bd-button-disabled-text: var(--button-disabled-color);
|
|
76
|
+
--bd-button-disabled-border: var(--button-disabled-borderColor);
|
|
77
|
+
|
|
78
|
+
/* accent carries no ring on a light page; on a dark one it needs a
|
|
79
|
+
boundary, so the value is switched rather than the rule */
|
|
80
|
+
--bd-button-accent-ring: var(--button-accent-ring-default);
|
|
81
|
+
|
|
82
|
+
--bd-button-border-width: var(--border-width-2);
|
|
37
83
|
}
|
|
38
84
|
|
|
39
85
|
/* ============================================
|
|
40
|
-
ALIGNMENT
|
|
86
|
+
ALIGNMENT
|
|
41
87
|
============================================ */
|
|
42
|
-
|
|
43
88
|
:host([align="center"]) {
|
|
44
89
|
display: flex;
|
|
45
90
|
justify-content: center;
|
|
@@ -72,28 +117,49 @@ export default css`
|
|
|
72
117
|
display: flex;
|
|
73
118
|
}
|
|
74
119
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
120
|
+
/* ============================================
|
|
121
|
+
FOCUS
|
|
122
|
+
The design specifies no focus state, but 2.4.7 requires one.
|
|
123
|
+
|
|
124
|
+
This used to be driven from JavaScript: two requestAnimationFrame hops
|
|
125
|
+
checked :focus-visible and set a data attribute the CSS then styled.
|
|
126
|
+
:focus-visible does that natively, so the detection is gone and the ring
|
|
127
|
+
is the shared one from Foundations/Focus — a two-colour ring whose white
|
|
128
|
+
inner band keeps it visible on a coloured hero, which the old
|
|
129
|
+
single-colour outline could not do. It is composed with
|
|
130
|
+
--bd-button-edge rather than replacing it, so an outlined variant keeps
|
|
131
|
+
its own boundary while focused; see the note on that property.
|
|
132
|
+
============================================ */
|
|
133
|
+
button:focus,
|
|
134
|
+
a:focus {
|
|
135
|
+
outline: none;
|
|
79
136
|
}
|
|
80
137
|
|
|
81
|
-
:
|
|
82
|
-
|
|
138
|
+
.button:focus-visible {
|
|
139
|
+
outline: none;
|
|
140
|
+
box-shadow: var(--focus-outline-primary), var(--bd-button-edge);
|
|
83
141
|
}
|
|
84
142
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
143
|
+
/* A white control needs the ring the other way up. --focus-outline-primary
|
|
144
|
+
puts its WHITE band against the control, which is what keeps it visible on
|
|
145
|
+
a coloured hero -- and is exactly wrong when the control is itself white:
|
|
146
|
+
measured on Button — White / Outline-White, the inner band was 1.00:1
|
|
147
|
+
against the button's own fill and the blue band 2.38:1 against the hero
|
|
148
|
+
(1.75:1 at the gradient's light end), so neither reached the 3:1 WCAG
|
|
149
|
+
2.4.11 asks. outline-white is here too because restoring its boundary
|
|
150
|
+
above puts a white border where the white band used to sit on the hero. */
|
|
151
|
+
.button--white:focus-visible,
|
|
152
|
+
.button--outline-white:focus-visible {
|
|
153
|
+
box-shadow: var(--focus-outline-inverse), var(--bd-button-edge);
|
|
91
154
|
}
|
|
92
155
|
|
|
93
156
|
a.button {
|
|
94
157
|
text-decoration: none;
|
|
95
158
|
}
|
|
96
159
|
|
|
160
|
+
/* ============================================
|
|
161
|
+
SHARED
|
|
162
|
+
============================================ */
|
|
97
163
|
.button,
|
|
98
164
|
.bd-contact-btn {
|
|
99
165
|
display: inline-flex;
|
|
@@ -101,67 +167,131 @@ export default css`
|
|
|
101
167
|
align-items: center;
|
|
102
168
|
text-align: center;
|
|
103
169
|
text-decoration: none;
|
|
104
|
-
color: var(--color-neutral-0);
|
|
105
170
|
border: none;
|
|
106
171
|
cursor: pointer;
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
color var(--transition-duration-normal) var(--transition-easing-smooth);
|
|
111
|
-
gap: var(--spacing-10);
|
|
172
|
+
font-family: var(--typography-fontFamily-sans);
|
|
173
|
+
font-weight: var(--typography-control-label-large-fontWeight);
|
|
174
|
+
line-height: var(--typography-control-label-large-lineHeight);
|
|
112
175
|
vertical-align: middle;
|
|
113
|
-
line-height: 1;
|
|
114
176
|
box-sizing: border-box;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
.button__label {
|
|
118
|
-
display: inline-block;
|
|
119
|
-
}
|
|
120
177
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
background-color: var(--button-background-primary-focus);
|
|
132
|
-
}
|
|
178
|
+
/* The variant's own boundary, held in a custom property so the focus ring
|
|
179
|
+
can COMPOSE with it. box-shadow is a single list, not additive, and
|
|
180
|
+
.button:focus-visible (0,2,0) outranks .button--ghost (0,1,0) -- so a
|
|
181
|
+
focus rule that declared box-shadow directly erased the border of every
|
|
182
|
+
outlined variant. A focused ghost button lost its dark outline and wore
|
|
183
|
+
a blue ring instead, which read as a tertiary button. The default is a
|
|
184
|
+
zero-spread transparent shadow rather than the keyword none, so the value
|
|
185
|
+
a valid shadow the focus rule can append to. */
|
|
186
|
+
--bd-button-edge: 0 0 0 0 transparent;
|
|
187
|
+
box-shadow: var(--bd-button-edge);
|
|
133
188
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
189
|
+
transition: background-color var(--transition-duration-normal) var(--transition-easing-smooth),
|
|
190
|
+
box-shadow var(--transition-duration-normal) var(--transition-easing-smooth),
|
|
191
|
+
color var(--transition-duration-normal) var(--transition-easing-smooth);
|
|
137
192
|
}
|
|
138
193
|
|
|
139
|
-
|
|
140
|
-
|
|
194
|
+
/* bd-contact-button has no variant, so it would inherit no colour at all */
|
|
195
|
+
.button.bd-contact-btn {
|
|
196
|
+
background-color: transparent;
|
|
197
|
+
color: var(--color-text-brand);
|
|
198
|
+
gap: var(--spacing-8);
|
|
199
|
+
|
|
200
|
+
/* Same inset bd-back carries, and for the same reason. Without it this
|
|
201
|
+
control was a bare line box measuring 159x20 -- a 20px tall target
|
|
202
|
+
against the 24x24 WCAG 2.5.8 asks of anything that is not inline in a
|
|
203
|
+
sentence, so 4px short, and a standalone CTA has no exception to claim.
|
|
204
|
+
It also left the focus ring sitting on the glyphs' ascenders.
|
|
205
|
+
|
|
206
|
+
bd-back is the same shape of control -- text, a trailing mark, no fill --
|
|
207
|
+
and already answers this with 12px 16px, which takes a 16px line to about
|
|
208
|
+
44px: the same height bd-button reaches through its own padding. Reading
|
|
209
|
+
the inset off the sibling rather than picking a number is what keeps the
|
|
210
|
+
two text CTAs in step. */
|
|
211
|
+
padding: var(--spacing-12) var(--spacing-16);
|
|
212
|
+
|
|
213
|
+
/* This control takes no size class -- it is a text CTA with a trailing
|
|
214
|
+
arrow, not a filled button -- so it arrived with no radius at all, and
|
|
215
|
+
the shared ring drew SQUARE corners around a bare line box while every
|
|
216
|
+
other button's ring followed a curve.
|
|
217
|
+
|
|
218
|
+
--button-medium-borderRadius, not --focus-outline-radius. The focus
|
|
219
|
+
token is the documented default for an element with NO radius, and that
|
|
220
|
+
is what this rule used first -- but with the inset above the control is
|
|
221
|
+
now a 44px box standing next to bd-button at the same height, and the
|
|
222
|
+
focus token is --radius-sm where medium buttons are --radius-md. Four
|
|
223
|
+
pixels against six is small, and it is visible when they sit in a row.
|
|
224
|
+
Matching the size band this control actually occupies is the better
|
|
225
|
+
answer than matching the rule for controls that occupy none.
|
|
226
|
+
|
|
227
|
+
Declared unconditionally rather than under :focus-visible because the
|
|
228
|
+
control draws no background and no border at rest, so the radius is
|
|
229
|
+
invisible until the ring needs it. */
|
|
230
|
+
border-radius: var(--button-medium-borderRadius);
|
|
141
231
|
}
|
|
142
232
|
|
|
143
|
-
|
|
144
|
-
|
|
233
|
+
/* ============================================
|
|
234
|
+
SIZE
|
|
235
|
+
Height is left to padding and line-height rather than pinned with a
|
|
236
|
+
min-height, which lands within half a pixel of the design: 33.5 / 44 /
|
|
237
|
+
54.5 against 34 / 45 / 55. The previous rules also carried hardcoded
|
|
238
|
+
min-widths (115px, 150px) that the design does not ask for at all.
|
|
239
|
+
|
|
240
|
+
The radius comes from --button-*-borderRadius rather than --radius-*
|
|
241
|
+
directly. Same values, so nothing moves here — but a button and a field
|
|
242
|
+
of the same size sit in the same form row, and reading both from their
|
|
243
|
+
own size-matched alias is what keeps them in step. Spelled as raw scale
|
|
244
|
+
steps on one side and aliases on the other, they had drifted a step apart
|
|
245
|
+
at sm and md without either side looking wrong on its own.
|
|
246
|
+
============================================ */
|
|
247
|
+
.button--small {
|
|
248
|
+
padding: var(--button-small-padding);
|
|
249
|
+
font-size: var(--button-small-fontSize);
|
|
250
|
+
border-radius: var(--button-small-borderRadius);
|
|
251
|
+
gap: var(--button-small-gap);
|
|
145
252
|
}
|
|
146
253
|
|
|
147
|
-
.button--
|
|
148
|
-
|
|
149
|
-
|
|
254
|
+
.button--medium {
|
|
255
|
+
padding: var(--button-medium-padding);
|
|
256
|
+
font-size: var(--button-medium-fontSize);
|
|
257
|
+
border-radius: var(--button-medium-borderRadius);
|
|
258
|
+
gap: var(--button-medium-gap);
|
|
150
259
|
}
|
|
151
260
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
261
|
+
.button--large {
|
|
262
|
+
padding: var(--button-large-padding);
|
|
263
|
+
font-size: var(--button-large-fontSize);
|
|
264
|
+
border-radius: var(--button-large-borderRadius);
|
|
265
|
+
gap: var(--button-large-gap);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.button--bold {
|
|
269
|
+
/* no role: the class is the semantic. .button--bold says what this
|
|
270
|
+
declaration does, so a role naming it would only restate the class --
|
|
271
|
+
there is no text-content type here for a role to describe, just an
|
|
272
|
+
emphasis the caller asked for by name. The same holds for a weight
|
|
273
|
+
driven by an active or selected state: that is a UI state, the category
|
|
274
|
+
CLAUDE.md keeps apart from type when it says a focus ring is never
|
|
275
|
+
expressed by swapping a border colour. This is the argument for every
|
|
276
|
+
"no role: state or modifier" marker in the package -- the others point
|
|
277
|
+
here rather than restating it. */
|
|
278
|
+
font-weight: var(--typography-fontWeight-semibold);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/* shape="rounded". After the size rules on purpose: same specificity, so
|
|
282
|
+
source order is what lets the shape replace the size band's corner. */
|
|
283
|
+
.button--rounded {
|
|
284
|
+
border-radius: var(--radius-3xl);
|
|
158
285
|
}
|
|
159
286
|
|
|
160
287
|
/* ============================================
|
|
161
|
-
HOVER
|
|
162
|
-
|
|
163
|
-
|
|
288
|
+
HOVER ARROW — accent, unless no-arrow
|
|
289
|
+
The button keeps its width: the label slides left and the arrow,
|
|
290
|
+
absolutely positioned, fades in where the label was.
|
|
164
291
|
============================================ */
|
|
292
|
+
.button__label {
|
|
293
|
+
display: inline-block;
|
|
294
|
+
}
|
|
165
295
|
|
|
166
296
|
.button--with-arrow {
|
|
167
297
|
position: relative;
|
|
@@ -175,115 +305,334 @@ export default css`
|
|
|
175
305
|
.button--with-arrow .button__arrow {
|
|
176
306
|
position: absolute;
|
|
177
307
|
top: 50%;
|
|
178
|
-
right: var(--
|
|
179
|
-
width: var(--button-arrow-size);
|
|
180
|
-
height: var(--button-arrow-size);
|
|
181
|
-
display: inline-flex;
|
|
308
|
+
right: var(--spacing-12);
|
|
182
309
|
opacity: 0;
|
|
183
|
-
transform: translate(var(--
|
|
184
|
-
transition:
|
|
310
|
+
transform: translate(calc(-1 * var(--spacing-8)), -50%);
|
|
311
|
+
transition:
|
|
312
|
+
opacity var(--transition-duration-normal) var(--transition-easing-smooth),
|
|
185
313
|
transform var(--transition-duration-normal) var(--transition-easing-smooth);
|
|
186
314
|
pointer-events: none;
|
|
187
315
|
}
|
|
188
316
|
|
|
189
317
|
.button--with-arrow:hover .button__label,
|
|
190
318
|
.button--with-arrow:focus-visible .button__label {
|
|
191
|
-
transform: translateX(calc(
|
|
319
|
+
transform: translateX(calc(-1 * var(--spacing-12)));
|
|
192
320
|
}
|
|
193
321
|
|
|
194
322
|
.button--with-arrow:hover .button__arrow,
|
|
195
323
|
.button--with-arrow:focus-visible .button__arrow {
|
|
196
324
|
opacity: 1;
|
|
197
|
-
transform: translate(0, -50%);
|
|
325
|
+
transform: translate(var(--spacing-0), -50%);
|
|
198
326
|
}
|
|
199
327
|
|
|
200
|
-
/*
|
|
328
|
+
/* A touch screen has no real hover; do not leave the arrow stuck after a tap. */
|
|
201
329
|
@media (hover: none) {
|
|
202
330
|
.button--with-arrow:hover .button__label {
|
|
203
331
|
transform: none;
|
|
204
332
|
}
|
|
333
|
+
|
|
205
334
|
.button--with-arrow:hover .button__arrow {
|
|
206
335
|
opacity: 0;
|
|
207
336
|
}
|
|
208
337
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
338
|
+
|
|
339
|
+
/* ============================================
|
|
340
|
+
SHAPE — icon-only
|
|
341
|
+
A circle around one icon. The diameter is not pinned, for the same reason
|
|
342
|
+
the labelled height is not: equal padding on every side plus the icon step
|
|
343
|
+
gives 8+16+8 = 32, 12+20+12 = 44 and 16+24+16 = 56. Only md sits level
|
|
344
|
+
with a labelled button beside it: the labelled heights are 33.5, 44 and
|
|
345
|
+
54.5, so sm is 1.5px shorter and lg 1.5px taller. Both differences come
|
|
346
|
+
from the label's line box, which an icon does not have, and closing them
|
|
347
|
+
would need an off-scale padding. sm is below the 44px target, exactly as
|
|
348
|
+
the labelled sm is.
|
|
349
|
+
|
|
350
|
+
The padding stays on the spacing scale, which is rem, while the icon is on
|
|
351
|
+
the icon scale, which is px. So when a reader enlarges their text the
|
|
352
|
+
circle grows and the glyph does not -- the target gets bigger for the
|
|
353
|
+
reader a bigger target helps, and the shape stays round because the
|
|
354
|
+
padding is equal on both axes.
|
|
355
|
+
|
|
356
|
+
The compound selectors outrank the size classes whatever the source
|
|
357
|
+
order, and they carry the radius too, so a size class can never put
|
|
358
|
+
its own corner back. The slotted rule sizes a caller's icon to the step
|
|
359
|
+
even if it was given a size of its own: a 20px glyph in a 56px circle
|
|
360
|
+
reads as the wrong control, not as a choice.
|
|
361
|
+
============================================ */
|
|
362
|
+
.button--icon-only {
|
|
363
|
+
line-height: var(--typography-lineHeight-none);
|
|
364
|
+
}
|
|
365
|
+
.button--icon-only.button--small {
|
|
366
|
+
--bd-button-icon-size: var(--icon-sm-size);
|
|
367
|
+
padding: var(--spacing-8);
|
|
368
|
+
border-radius: var(--radius-full);
|
|
369
|
+
}
|
|
370
|
+
.button--icon-only.button--medium {
|
|
371
|
+
--bd-button-icon-size: var(--icon-md-size);
|
|
372
|
+
padding: var(--spacing-12);
|
|
373
|
+
border-radius: var(--radius-full);
|
|
374
|
+
}
|
|
375
|
+
.button--icon-only.button--large {
|
|
376
|
+
--bd-button-icon-size: var(--icon-lg-size);
|
|
377
|
+
padding: var(--spacing-16);
|
|
378
|
+
border-radius: var(--radius-full);
|
|
379
|
+
}
|
|
380
|
+
.button--icon-only > ::slotted(*) {
|
|
381
|
+
height: var(--bd-button-icon-size);
|
|
382
|
+
}
|
|
383
|
+
/* loading swaps the icon for the spinner, so the spinner takes the icon's
|
|
384
|
+
box rather than its em size, and the circle does not shrink while busy */
|
|
385
|
+
.button--icon-only .spinner {
|
|
386
|
+
width: var(--bd-button-icon-size);
|
|
387
|
+
height: var(--bd-button-icon-size);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/* ============================================
|
|
391
|
+
VARIANT — primary
|
|
392
|
+
============================================ */
|
|
393
|
+
.button--primary {
|
|
394
|
+
background-color: var(--bd-button-primary-bg);
|
|
395
|
+
color: var(--bd-button-primary-text);
|
|
396
|
+
}
|
|
397
|
+
.button--primary:hover {
|
|
398
|
+
background-color: var(--bd-button-primary-bg-hover);
|
|
399
|
+
}
|
|
400
|
+
.button--primary:active {
|
|
401
|
+
background-color: var(--bd-button-primary-bg-active);
|
|
214
402
|
}
|
|
215
403
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
404
|
+
/* ============================================
|
|
405
|
+
VARIANT — secondary
|
|
406
|
+
============================================ */
|
|
407
|
+
.button--secondary {
|
|
408
|
+
background-color: var(--bd-button-secondary-bg);
|
|
409
|
+
color: var(--bd-button-secondary-text);
|
|
410
|
+
}
|
|
411
|
+
.button--secondary:hover {
|
|
412
|
+
background-color: var(--bd-button-secondary-bg-hover);
|
|
413
|
+
}
|
|
414
|
+
.button--secondary:active {
|
|
415
|
+
background-color: var(--bd-button-secondary-bg-active);
|
|
219
416
|
}
|
|
220
417
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
418
|
+
/* ============================================
|
|
419
|
+
VARIANT — tertiary (blue outline)
|
|
420
|
+
============================================ */
|
|
421
|
+
.button--tertiary {
|
|
422
|
+
background-color: transparent;
|
|
423
|
+
--bd-button-edge: inset 0 0 0 var(--bd-button-border-width) var(--bd-button-tertiary-border);
|
|
424
|
+
color: var(--bd-button-tertiary-text);
|
|
425
|
+
}
|
|
426
|
+
.button--tertiary:hover {
|
|
427
|
+
background-color: var(--bd-button-tertiary-bg-hover);
|
|
428
|
+
--bd-button-edge: inset 0 0 0 var(--bd-button-border-width) var(--bd-button-tertiary-border-hover);
|
|
429
|
+
color: var(--bd-button-tertiary-text-hover);
|
|
430
|
+
}
|
|
431
|
+
.button--tertiary:active {
|
|
432
|
+
background-color: var(--bd-button-tertiary-bg-active);
|
|
433
|
+
--bd-button-edge: inset 0 0 0 var(--bd-button-border-width) var(--bd-button-tertiary-bg-active);
|
|
434
|
+
color: var(--bd-button-tertiary-text-active);
|
|
224
435
|
}
|
|
225
436
|
|
|
226
|
-
|
|
437
|
+
/* ============================================
|
|
438
|
+
VARIANT — ghost (dark outline)
|
|
439
|
+
============================================ */
|
|
440
|
+
.button--ghost {
|
|
227
441
|
background-color: transparent;
|
|
228
|
-
|
|
229
|
-
color: var(--
|
|
442
|
+
--bd-button-edge: inset 0 0 0 var(--bd-button-border-width) var(--bd-button-ghost-border);
|
|
443
|
+
color: var(--bd-button-ghost-text);
|
|
444
|
+
}
|
|
445
|
+
.button--ghost:hover {
|
|
446
|
+
background-color: var(--bd-button-ghost-bg-hover);
|
|
447
|
+
color: var(--bd-button-ghost-text-hover);
|
|
448
|
+
}
|
|
449
|
+
.button--ghost:active {
|
|
450
|
+
background-color: var(--bd-button-ghost-bg-active);
|
|
451
|
+
--bd-button-edge: inset 0 0 0 var(--bd-button-border-width) var(--bd-button-ghost-bg-active);
|
|
452
|
+
color: var(--bd-button-ghost-text-active);
|
|
230
453
|
}
|
|
231
454
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
455
|
+
/* ============================================
|
|
456
|
+
VARIANT — accent
|
|
457
|
+
============================================ */
|
|
458
|
+
.button--accent {
|
|
459
|
+
background-color: var(--bd-button-accent-bg);
|
|
460
|
+
color: var(--bd-button-accent-text);
|
|
461
|
+
--bd-button-edge: inset 0 0 0 var(--bd-button-border-width) var(--bd-button-accent-ring);
|
|
462
|
+
}
|
|
463
|
+
.button--accent:hover {
|
|
464
|
+
background-color: var(--bd-button-accent-bg-hover);
|
|
465
|
+
}
|
|
466
|
+
.button--accent:active {
|
|
467
|
+
background-color: var(--bd-button-accent-bg-active);
|
|
235
468
|
}
|
|
236
469
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
470
|
+
/* ============================================
|
|
471
|
+
SURFACE — dark
|
|
472
|
+
|
|
473
|
+
For a hero or any panel with a full background colour. On a light page
|
|
474
|
+
every variant passes; on a coloured one 21 of 25 variant/surface pairings
|
|
475
|
+
failed, because tertiary and ghost put their ink straight onto the page
|
|
476
|
+
and primary is literally the same colour as a blue-500 hero (1.00:1).
|
|
477
|
+
|
|
478
|
+
The design carries no on-dark set — its axes are Size, Variant and State
|
|
479
|
+
only — so these values are derived from our own palette rather than read
|
|
480
|
+
off a spec, and every one is measured against blue-500, blue-600,
|
|
481
|
+
blue-700, neutral-900 and neutral-950. They need a designer's sign-off.
|
|
482
|
+
|
|
483
|
+
Two notes on what changed shape rather than just colour: ghost drops its
|
|
484
|
+
ring here, because a white ring would make it identical to tertiary, and
|
|
485
|
+
dropping it is what "ghost" conventionally means anyway. accent keeps its
|
|
486
|
+
red so the conversion signal survives, and gains a white ring to give it
|
|
487
|
+
a boundary against blue.
|
|
488
|
+
|
|
489
|
+
WHY THE INK IS A ROLE AND THE GROUNDS ARE NOT, which is what the inline
|
|
490
|
+
no role: markers below point at. check:color-coverage gained sight of
|
|
491
|
+
these declarations on 2026-09-15 and classified twenty-three of them; a
|
|
492
|
+
role of the right CATEGORY exists at the value for nineteen, and exactly
|
|
493
|
+
nine survive the second question, which is whether the role's JOB is this
|
|
494
|
+
declaration's job.
|
|
495
|
+
|
|
496
|
+
The nine that do are all ink, and each one matches a role's own words.
|
|
497
|
+
tertiary and ghost put their label straight onto the hero, and
|
|
498
|
+
--color-text-inverse is defined as the high-emphasis ink on an inverse
|
|
499
|
+
ground. Once a variant inverts and the label sits on the button's own
|
|
500
|
+
light fill, it is ordinary ink again -- --color-text-primary -- or brand
|
|
501
|
+
ink, --color-text-brand. disabled's label is a control the user cannot
|
|
502
|
+
operate, which is --color-text-disabled's whole definition rather than a
|
|
503
|
+
step on the hierarchy. Every one is value-identical, so nothing here
|
|
504
|
+
renders differently.
|
|
505
|
+
|
|
506
|
+
The grounds and hairlines have no role, and the reason is not scarcity.
|
|
507
|
+
--color-surface-default carries this exact white, and its own theme
|
|
508
|
+
clause in Foundations/Surfaces reads "On dark it is the dark ground, not
|
|
509
|
+
white" -- so adopting it here would assert the opposite of what the
|
|
510
|
+
declaration means. surface-subtle is a wash behind a group, not a press
|
|
511
|
+
fill. surface-muted is a state surface and would fit primary's pressed
|
|
512
|
+
step on value and nearly on job, but these three values are one ramp
|
|
513
|
+
measured against the hero rather than three independent choices, and
|
|
514
|
+
binding its last step to a role that can move on its own would break the
|
|
515
|
+
relationship the measurement established. At neutral-700 and neutral-600
|
|
516
|
+
there is no surface or border role at all, and there is no solid white
|
|
517
|
+
border role anywhere: --color-border-container-inverse is white at 12%.
|
|
518
|
+
|
|
519
|
+
So the missing vocabulary is nameable, and it is two entries: a control
|
|
520
|
+
fill on an inverse ground, and a solid hairline on an inverse ground.
|
|
521
|
+
Adding either is a vocabulary decision for the same designer pass this
|
|
522
|
+
block is already waiting on, and token-scales.js is explicit that one
|
|
523
|
+
consumer is not enough to name a role. Recorded, not taken.
|
|
524
|
+
============================================ */
|
|
525
|
+
:host([surface='dark']) {
|
|
526
|
+
/* white fill, brand label — the strongest thing on a coloured hero */
|
|
527
|
+
--bd-button-primary-bg: var(--color-neutral-0); /* no role: on-dark ground; see the block note */
|
|
528
|
+
--bd-button-primary-bg-hover: var(--color-neutral-50); /* no role: on-dark ground; see the block note */
|
|
529
|
+
--bd-button-primary-bg-active: var(--color-neutral-100); /* no role: on-dark ground; see the block note */
|
|
530
|
+
--bd-button-primary-text: var(--color-text-brand);
|
|
531
|
+
|
|
532
|
+
/* neutral-100 rather than a lighter step: it is the lightest fill that
|
|
533
|
+
still clears 3:1 against a blue-500 hero while staying distinguishable
|
|
534
|
+
from primary's pure white */
|
|
535
|
+
--bd-button-secondary-bg: var(--color-neutral-100); /* no role: on-dark ground; see the block note */
|
|
536
|
+
--bd-button-secondary-bg-hover: var(--color-neutral-50); /* no role: on-dark ground; see the block note */
|
|
537
|
+
--bd-button-secondary-bg-active: var(--color-neutral-0); /* no role: on-dark ground; see the block note */
|
|
538
|
+
--bd-button-secondary-text: var(--color-text-primary);
|
|
539
|
+
|
|
540
|
+
/* the outlined one: white ring, white label, inverting on hover */
|
|
541
|
+
--bd-button-tertiary-text: var(--color-text-inverse);
|
|
542
|
+
--bd-button-tertiary-border: var(--color-neutral-0); /* no role: on-dark hairline; see the block note */
|
|
543
|
+
--bd-button-tertiary-bg-hover: var(--color-neutral-0); /* no role: on-dark ground; see the block note */
|
|
544
|
+
--bd-button-tertiary-text-hover: var(--color-text-brand);
|
|
545
|
+
--bd-button-tertiary-border-hover: var(--color-neutral-0); /* no role: on-dark hairline; see the block note */
|
|
546
|
+
--bd-button-tertiary-bg-active: var(--color-neutral-50); /* no role: on-dark ground; see the block note */
|
|
547
|
+
--bd-button-tertiary-text-active: var(--color-text-brand);
|
|
548
|
+
|
|
549
|
+
/* no ring at all, so it stays distinct from tertiary */
|
|
550
|
+
--bd-button-ghost-text: var(--color-text-inverse);
|
|
551
|
+
--bd-button-ghost-border: transparent;
|
|
552
|
+
--bd-button-ghost-bg-hover: var(--color-neutral-0); /* no role: on-dark ground; see the block note */
|
|
553
|
+
--bd-button-ghost-text-hover: var(--color-text-primary);
|
|
554
|
+
--bd-button-ghost-bg-active: var(--color-neutral-50); /* no role: on-dark ground; see the block note */
|
|
555
|
+
--bd-button-ghost-text-active: var(--color-text-primary);
|
|
556
|
+
|
|
557
|
+
/* unchanged red, plus a boundary against the hero */
|
|
558
|
+
--bd-button-accent-ring: var(--color-neutral-0);
|
|
559
|
+
|
|
560
|
+
/* muted downward instead of upward: a neutral-100 fill would read as an
|
|
561
|
+
active control on a dark hero. Exempt from contrast under WCAG 1.4.3. */
|
|
562
|
+
--bd-button-disabled-bg: var(--color-neutral-700); /* no role: on-dark ground; see the block note */
|
|
563
|
+
--bd-button-disabled-text: var(--color-text-disabled);
|
|
564
|
+
--bd-button-disabled-border: var(--color-neutral-600); /* no role: on-dark hairline; see the block note */
|
|
565
|
+
|
|
240
566
|
}
|
|
241
567
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
568
|
+
/* ============================================
|
|
569
|
+
STATE — disabled
|
|
570
|
+
Filled variants go grey; outlined ones keep a transparent fill and take
|
|
571
|
+
the subtle border. Contrast is exempt here under WCAG 1.4.3.
|
|
572
|
+
============================================ */
|
|
573
|
+
.button:disabled,
|
|
574
|
+
.button[aria-disabled="true"] {
|
|
575
|
+
cursor: not-allowed;
|
|
576
|
+
pointer-events: none;
|
|
577
|
+
background-color: var(--bd-button-disabled-bg);
|
|
578
|
+
--bd-button-edge: 0 0 0 0 transparent;
|
|
579
|
+
color: var(--bd-button-disabled-text);
|
|
250
580
|
}
|
|
251
581
|
|
|
252
|
-
.button--
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
min-width: 150px;
|
|
582
|
+
.button--tertiary:disabled,
|
|
583
|
+
.button--ghost:disabled,
|
|
584
|
+
.button--tertiary[aria-disabled="true"],
|
|
585
|
+
.button--ghost[aria-disabled="true"] {
|
|
586
|
+
background-color: transparent;
|
|
587
|
+
--bd-button-edge: inset 0 0 0 var(--bd-button-border-width) var(--bd-button-disabled-border);
|
|
588
|
+
color: var(--bd-button-disabled-text);
|
|
260
589
|
}
|
|
261
590
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
591
|
+
/* ============================================
|
|
592
|
+
STATE — loading
|
|
593
|
+
The variant keeps its own colours, so the spinner is drawn in
|
|
594
|
+
currentColor and sized in em to track the type scale — which is what the
|
|
595
|
+
design's loading widths imply (they exceed the default by exactly one
|
|
596
|
+
font-size plus the gap).
|
|
597
|
+
============================================ */
|
|
598
|
+
.button--loading {
|
|
599
|
+
cursor: progress;
|
|
600
|
+
pointer-events: none;
|
|
270
601
|
}
|
|
271
602
|
|
|
272
|
-
.
|
|
273
|
-
|
|
603
|
+
.spinner {
|
|
604
|
+
width: 1em;
|
|
605
|
+
height: 1em;
|
|
606
|
+
flex: none;
|
|
607
|
+
box-sizing: border-box;
|
|
608
|
+
border: var(--border-width-2) solid currentColor;
|
|
609
|
+
border-top-color: transparent;
|
|
610
|
+
border-radius: var(--radius-full);
|
|
611
|
+
animation: bd-button-spin var(--transition-duration-slower)
|
|
612
|
+
var(--transition-easing-linear) infinite;
|
|
274
613
|
}
|
|
275
614
|
|
|
276
|
-
|
|
277
|
-
|
|
615
|
+
@keyframes bd-button-spin {
|
|
616
|
+
to { transform: rotate(360deg); }
|
|
278
617
|
}
|
|
279
618
|
|
|
280
|
-
/* slot
|
|
281
|
-
.
|
|
619
|
+
/* The slot sits inside .button__label now, not directly in .button. */
|
|
620
|
+
.button__label > ::slotted(*) {
|
|
282
621
|
display: inline-block;
|
|
283
|
-
width: 100%;
|
|
284
622
|
text-align: center;
|
|
285
623
|
}
|
|
286
624
|
|
|
625
|
+
/* box-shadow is not rendered in forced-colors mode, which would leave the
|
|
626
|
+
outlined variants with no visible boundary at all, so a real border comes
|
|
627
|
+
back there. It costs 4px of height, which does not matter when the user
|
|
628
|
+
agent is repainting everything anyway. */
|
|
629
|
+
@media (forced-colors: active) {
|
|
630
|
+
.button--tertiary,
|
|
631
|
+
.button--ghost {
|
|
632
|
+
border: var(--bd-button-border-width) solid currentColor;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
|
|
287
636
|
@media (prefers-reduced-motion: reduce) {
|
|
288
637
|
.button,
|
|
289
638
|
.bd-contact-btn,
|
|
@@ -291,32 +640,53 @@ export default css`
|
|
|
291
640
|
.button__arrow {
|
|
292
641
|
transition: none !important;
|
|
293
642
|
}
|
|
294
|
-
}
|
|
295
643
|
|
|
644
|
+
/* a spinner that cannot spin should still read as busy, so it pulses
|
|
645
|
+
rather than freezing into a static broken ring */
|
|
646
|
+
.spinner {
|
|
647
|
+
animation: bd-button-pulse var(--transition-duration-slower)
|
|
648
|
+
var(--transition-easing-smooth) infinite alternate;
|
|
649
|
+
border-top-color: currentColor;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
@keyframes bd-button-pulse {
|
|
653
|
+
to { opacity: var(--opacity-pulse); }
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
/* ============================================
|
|
657
|
+
VARIANT — white and outline-white
|
|
658
|
+
|
|
659
|
+
Fixed presets for a solid-colour banner, where even a surface="dark"
|
|
660
|
+
primary would sit too close in tone. They ignore surface on purpose —
|
|
661
|
+
see the note on VARIANTS in button.js.
|
|
662
|
+
|
|
663
|
+
These two were appended below the stylesheet's last rule and unindented,
|
|
664
|
+
and they hardcoded their colours instead of going through the aliases
|
|
665
|
+
every other variant uses: 1.5px against the 2px border width the docs
|
|
666
|
+
describe, #ffffff8c, and two rgba() whites. None of it could be rethemed
|
|
667
|
+
and none of it was visible to the lint, which does not read 8-digit hex
|
|
668
|
+
or rgba().
|
|
669
|
+
============================================ */
|
|
296
670
|
.button--white {
|
|
297
|
-
background-color: var(--
|
|
298
|
-
color: var(--
|
|
671
|
+
background-color: var(--bd-button-white-bg);
|
|
672
|
+
color: var(--bd-button-white-text);
|
|
299
673
|
}
|
|
300
|
-
|
|
301
674
|
.button--white:hover {
|
|
302
|
-
background-color: var(--
|
|
675
|
+
background-color: var(--bd-button-white-bg-hover);
|
|
303
676
|
}
|
|
304
|
-
|
|
305
677
|
.button--white:active {
|
|
306
|
-
background-color: var(--
|
|
678
|
+
background-color: var(--bd-button-white-bg-active);
|
|
307
679
|
}
|
|
308
680
|
|
|
309
681
|
.button--outline-white {
|
|
310
682
|
background-color: transparent;
|
|
311
|
-
|
|
312
|
-
color: var(--
|
|
683
|
+
--bd-button-edge: inset 0 0 0 var(--bd-button-border-width) var(--bd-button-outline-white-border);
|
|
684
|
+
color: var(--bd-button-outline-white-text);
|
|
313
685
|
}
|
|
314
|
-
|
|
315
686
|
.button--outline-white:hover {
|
|
316
|
-
background-color:
|
|
687
|
+
background-color: var(--bd-button-outline-white-bg-hover);
|
|
317
688
|
}
|
|
318
|
-
|
|
319
689
|
.button--outline-white:active {
|
|
320
|
-
background-color:
|
|
690
|
+
background-color: var(--bd-button-outline-white-bg-active);
|
|
321
691
|
}
|
|
322
|
-
`;
|
|
692
|
+
`;
|