@repobit/dex-system-design 0.25.12 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +204 -0
- package/README.md +131 -8
- package/package.json +96 -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
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
import './switch.js';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title : 'Atoms/Switch',
|
|
6
|
+
tags : ['autodocs'],
|
|
7
|
+
parameters: {
|
|
8
|
+
docs: {
|
|
9
|
+
description: {
|
|
10
|
+
component: `
|
|
11
|
+
**BdSwitch** turns something on or off, taking effect immediately. If the
|
|
12
|
+
change only applies once a form is submitted, use \`<bd-checkbox>\` instead —
|
|
13
|
+
that difference is the whole reason both exist.
|
|
14
|
+
|
|
15
|
+
### Usage
|
|
16
|
+
\`\`\`html
|
|
17
|
+
<bd-switch label="Autopilot"></bd-switch>
|
|
18
|
+
<bd-switch label="Scam alerts" checked></bd-switch>
|
|
19
|
+
<bd-switch label="Unavailable" disabled></bd-switch>
|
|
20
|
+
|
|
21
|
+
<bd-switch @bd-change=\${e => console.log(e.detail)}>Autopilot</bd-switch>
|
|
22
|
+
\`\`\`
|
|
23
|
+
|
|
24
|
+
### Props
|
|
25
|
+
| Prop | Values | Default |
|
|
26
|
+
|---|---|---|
|
|
27
|
+
| \`checked\` | boolean, on or off | \`false\` |
|
|
28
|
+
| \`disabled\` | boolean | \`false\` |
|
|
29
|
+
| \`label\` | label text | \`''\` |
|
|
30
|
+
| \`name\` | carried for your own use | \`''\` |
|
|
31
|
+
|
|
32
|
+
Content can also come from the default slot, which renders after \`label\` — so
|
|
33
|
+
set one or the other, not both.
|
|
34
|
+
|
|
35
|
+
### Events
|
|
36
|
+
\`bd-change\` — fires on toggle with \`detail\` set to the new boolean.
|
|
37
|
+
|
|
38
|
+
### Accessibility
|
|
39
|
+
It is a real \`<input type="checkbox">\` with \`role="switch"\`, inside a
|
|
40
|
+
\`<label>\`, so it is keyboard-operable and announced as a switch with an on/off
|
|
41
|
+
state rather than checked/unchecked.
|
|
42
|
+
|
|
43
|
+
### Not form-associated
|
|
44
|
+
The input lives in this element's shadow root, and a native input inside a
|
|
45
|
+
shadow root does not participate in an outer \`<form>\`. **\`name\` is carried but
|
|
46
|
+
nothing is submitted** — read the state from \`bd-change\` or the \`checked\`
|
|
47
|
+
property.
|
|
48
|
+
`
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
argTypes: {
|
|
53
|
+
checked: {
|
|
54
|
+
control : 'boolean',
|
|
55
|
+
description: 'On or off. Takes effect immediately, which is what separates a switch from a checkbox.',
|
|
56
|
+
table : { type: { summary: 'boolean' }, defaultValue: { summary: "false" }, category: 'State' }
|
|
57
|
+
},
|
|
58
|
+
disabled: {
|
|
59
|
+
control : 'boolean',
|
|
60
|
+
description: 'Blocks interaction.',
|
|
61
|
+
table : { type: { summary: 'boolean' }, defaultValue: { summary: "false" }, category: 'State' }
|
|
62
|
+
},
|
|
63
|
+
label: {
|
|
64
|
+
control : 'text',
|
|
65
|
+
description: 'Label text, rendered before any slotted content.',
|
|
66
|
+
table : { type: { summary: 'string' }, defaultValue: { summary: "" }, category: 'Content' }
|
|
67
|
+
},
|
|
68
|
+
name: {
|
|
69
|
+
control : 'text',
|
|
70
|
+
description: 'Carried for your own use. NOT submitted with a form — see the notes.',
|
|
71
|
+
table : { type: { summary: 'string' }, defaultValue: { summary: "" }, category: 'Data' }
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const Default = () => html`
|
|
77
|
+
<bd-switch label="Automatic updates"></bd-switch>
|
|
78
|
+
`;
|
|
79
|
+
|
|
80
|
+
export const Checked = () => html`
|
|
81
|
+
<bd-switch checked label="Real-time protection"></bd-switch>
|
|
82
|
+
`;
|
|
83
|
+
|
|
84
|
+
export const Disabled = () => html`
|
|
85
|
+
<bd-switch disabled label="Unavailable on this plan"></bd-switch>
|
|
86
|
+
`;
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { html } from "lit";
|
|
2
|
+
import "./tab-list.js";
|
|
3
|
+
import { contentSwitcherCSS, tabListCSS } from "./tab-list.css.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The Content Switcher is `bd-tab-list` wearing `appearance="switcher"`, so it
|
|
7
|
+
* renders into light DOM like the strip does and needs both sheets in scope —
|
|
8
|
+
* see the note in tab-list.js. Inside a real component you add them to that
|
|
9
|
+
* component's own `static styles` instead of doing this.
|
|
10
|
+
*/
|
|
11
|
+
const withStyles = template => html`
|
|
12
|
+
<style>${tabListCSS.cssText}${contentSwitcherCSS.cssText}</style>
|
|
13
|
+
<div style="font-family: var(--typography-fontFamily-sans);">${template}</div>
|
|
14
|
+
`;
|
|
15
|
+
|
|
16
|
+
export default {
|
|
17
|
+
title : "Components/Content Switcher",
|
|
18
|
+
tags : ["autodocs"],
|
|
19
|
+
parameters: {
|
|
20
|
+
docs: {
|
|
21
|
+
description: {
|
|
22
|
+
component: `
|
|
23
|
+
**The Content Switcher** is a pill track of mutually exclusive options with the
|
|
24
|
+
selected one on a white pill. Designed in Figma as *Content switcher*
|
|
25
|
+
(node \`311:931\`).
|
|
26
|
+
|
|
27
|
+
### It is an appearance, not its own element
|
|
28
|
+
|
|
29
|
+
It is \`<bd-tab-list appearance="switcher">\`. Everything underneath —
|
|
30
|
+
\`role="tablist"\`, \`role="tab"\`, \`aria-selected\`, the roving \`tabindex\` and the
|
|
31
|
+
Arrow/Home/End pattern with automatic activation — is the same control the
|
|
32
|
+
underlined strip uses, so a second element would have meant a second copy of
|
|
33
|
+
that keyboard pattern to keep in step. CLAUDE.md's own rule: *when two
|
|
34
|
+
components implement the same visual role, prefer extracting the role over
|
|
35
|
+
spelling it twice.*
|
|
36
|
+
|
|
37
|
+
### Both options are as wide as the longer label
|
|
38
|
+
|
|
39
|
+
This is the part the design is built around: a translation cannot make one
|
|
40
|
+
option wider than the other, because every option is as wide as the **longest**
|
|
41
|
+
label.
|
|
42
|
+
|
|
43
|
+
**CSS alone cannot express that**, and the two obvious declarations were both
|
|
44
|
+
tried and measured on the *Unequal labels* story below:
|
|
45
|
+
|
|
46
|
+
| | result |
|
|
47
|
+
|---|---|
|
|
48
|
+
| \`grid-auto-columns: 1fr\` | 127.21px and 141.79px — unequal, and both narrower than their content, so the labels wrapped to four lines |
|
|
49
|
+
| \`grid-auto-columns: minmax(max-content, 1fr)\` | 78.35px and 248.77px — no wrapping, still unequal |
|
|
50
|
+
|
|
51
|
+
An \`fr\` track needs definite free space to equalise and a shrink-to-fit
|
|
52
|
+
container has none; once the width *is* definite, \`fr\` splits it evenly rather
|
|
53
|
+
than matching the widest. Hug, equal, and equal-to-the-widest cannot all come
|
|
54
|
+
from one grid declaration.
|
|
55
|
+
|
|
56
|
+
So the width is measured. \`_sizeSwitcherOptions\` in tab-list.js reads the
|
|
57
|
+
widest option after each render and publishes it as
|
|
58
|
+
\`--bd-switcher-option-width\`, which \`grid-auto-columns\` consumes; it clears
|
|
59
|
+
the property before measuring, so the track can shrink again when labels get
|
|
60
|
+
shorter, and it re-measures once \`document.fonts.ready\` settles, because a
|
|
61
|
+
width measured on a fallback face does not match IBM Plex.
|
|
62
|
+
|
|
63
|
+
Figma cannot express it either: in the file one option hugs and the other is
|
|
64
|
+
fixed at the same width, which is equal at this text and stops being equal as
|
|
65
|
+
soon as a label changes length. The code carries the rule; the file carries a
|
|
66
|
+
snapshot of it.
|
|
67
|
+
|
|
68
|
+
### Usage
|
|
69
|
+
|
|
70
|
+
\`\`\`js
|
|
71
|
+
import "@repobit/dex-system-design/tab-list";
|
|
72
|
+
import { tabListCSS, contentSwitcherCSS } from "@repobit/dex-system-design/tab-list-css";
|
|
73
|
+
|
|
74
|
+
static styles = [tabListCSS, contentSwitcherCSS, myComponentCSS];
|
|
75
|
+
\`\`\`
|
|
76
|
+
|
|
77
|
+
\`\`\`js
|
|
78
|
+
html\`
|
|
79
|
+
<bd-tab-list
|
|
80
|
+
appearance="switcher"
|
|
81
|
+
label="Plan type"
|
|
82
|
+
.tabs=\${[{ label: "Individual" }, { label: "Family" }]}
|
|
83
|
+
.selected=\${0}
|
|
84
|
+
@bd-tab-select=\${e => (this.plan = e.detail.index)}
|
|
85
|
+
></bd-tab-list>
|
|
86
|
+
\`
|
|
87
|
+
\`\`\`
|
|
88
|
+
|
|
89
|
+
### Accessibility
|
|
90
|
+
|
|
91
|
+
\`label\` becomes the \`aria-label\` on the \`tablist\` and is not optional in
|
|
92
|
+
practice — without it a screen reader announces a tab list with no name. The
|
|
93
|
+
selected option is the only one in the tab order; arrow keys move between them
|
|
94
|
+
and select in one step.
|
|
95
|
+
|
|
96
|
+
The unselected label is white on \`--color-action-primary\`, which measures
|
|
97
|
+
**4.53:1** — it passes the 4.5:1 minimum for 16px/500 text with very little to
|
|
98
|
+
spare. CLAUDE.md names blue-500 as the step with no headroom, so if this track
|
|
99
|
+
ever needs to sit on a tint, re-measure before assuming it still passes.
|
|
100
|
+
`
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const switcher = (tabs, selected = 0, label = "Plan type") => withStyles(html`
|
|
107
|
+
<bd-tab-list
|
|
108
|
+
appearance="switcher"
|
|
109
|
+
label=${label}
|
|
110
|
+
.tabs=${tabs}
|
|
111
|
+
.selected=${selected}
|
|
112
|
+
></bd-tab-list>
|
|
113
|
+
`);
|
|
114
|
+
|
|
115
|
+
export const Default = {
|
|
116
|
+
name : "Default",
|
|
117
|
+
render : () => switcher([{ label: "Individual" }, { label: "Family" }], 0),
|
|
118
|
+
parameters: {
|
|
119
|
+
docs: { description: { story: "The design as drawn: the first option selected." } }
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export const SecondSelected = {
|
|
124
|
+
name : "Second selected",
|
|
125
|
+
render : () => switcher([{ label: "Individual" }, { label: "Family" }], 1),
|
|
126
|
+
parameters: {
|
|
127
|
+
docs: {
|
|
128
|
+
description: {
|
|
129
|
+
story: "The other variant in the Figma set. Only the pill and the ink move — "
|
|
130
|
+
+ "both labels stay at the action-label weight, so nothing reflows on switch."
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
export const UnequalLabels = {
|
|
137
|
+
name : "Unequal labels",
|
|
138
|
+
render : () => switcher([{ label: "One" }, { label: "A considerably longer label" }], 0),
|
|
139
|
+
parameters: {
|
|
140
|
+
docs: {
|
|
141
|
+
description: {
|
|
142
|
+
story: "The equal-width rule under load. \"One\" is far shorter than its "
|
|
143
|
+
+ "sibling and still occupies exactly the same width, which is what makes "
|
|
144
|
+
+ "the control safe to translate. Measure both options in this story rather "
|
|
145
|
+
+ "than the one above — in Default the two labels are close enough that a "
|
|
146
|
+
+ "plain flex row would look almost the same."
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
export const ThreeOptions = {
|
|
153
|
+
name : "Three options",
|
|
154
|
+
render : () => switcher([{ label: "Monthly" }, { label: "Yearly" }, { label: "Lifetime" }], 1),
|
|
155
|
+
parameters: {
|
|
156
|
+
docs: {
|
|
157
|
+
description: {
|
|
158
|
+
story: "Nothing in the control assumes two. The Figma component is drawn with "
|
|
159
|
+
+ "two because that is what pricing needs; the grid adds a column per option "
|
|
160
|
+
+ "and they all stay equal."
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
export const LongestLabelDrivesBoth = {
|
|
167
|
+
name : "In a narrow container",
|
|
168
|
+
render: () => withStyles(html`
|
|
169
|
+
<div style="width: 320px; outline: 1px dashed var(--color-border-subtle); padding: var(--spacing-16);">
|
|
170
|
+
<bd-tab-list
|
|
171
|
+
appearance="switcher"
|
|
172
|
+
label="Plan type"
|
|
173
|
+
.tabs=${[{ label: "Individual" }, { label: "Family" }]}
|
|
174
|
+
.selected=${0}
|
|
175
|
+
></bd-tab-list>
|
|
176
|
+
</div>
|
|
177
|
+
`),
|
|
178
|
+
parameters: {
|
|
179
|
+
docs: {
|
|
180
|
+
description: {
|
|
181
|
+
story: "The track hugs its content rather than filling its parent, so it does "
|
|
182
|
+
+ "not stretch in a wide column. At 320px both options plus the track "
|
|
183
|
+
+ "padding still fit — measured, the pair comes to 256px — which is why the "
|
|
184
|
+
+ "switcher holds its 12/24 option padding below `sm` instead of taking the "
|
|
185
|
+
+ "strip's narrower step."
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
};
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { css, unsafeCSS } from "lit";
|
|
2
|
+
/* unsafeCSS is how a Lit css`` template accepts a computed string. The
|
|
3
|
+
value is not arbitrary: below() resolves a name from the closed
|
|
4
|
+
breakpoint set and throws on anything else, so the only strings that
|
|
5
|
+
reach here are the ones the scale produced. */
|
|
6
|
+
import { below } from "../shared/token-scales.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Base styling for <bd-tab-list>.
|
|
10
|
+
*
|
|
11
|
+
* The element renders into light DOM (see tab-list.js), so this sheet is not
|
|
12
|
+
* applied automatically — a consumer adds it to its own `static styles` ahead
|
|
13
|
+
* of its overrides:
|
|
14
|
+
*
|
|
15
|
+
* static styles = [tabListCSS, myComponentCSS];
|
|
16
|
+
*
|
|
17
|
+
* Everything that varies between the sections that use a tab strip is a custom
|
|
18
|
+
* property, so an override is a token change rather than a re-declaration of
|
|
19
|
+
* the whole button.
|
|
20
|
+
*/
|
|
21
|
+
export const tabListCSS = css`
|
|
22
|
+
/* The element is a pass-through wrapper: the strip itself stays the flex/grid
|
|
23
|
+
item it was before the extraction, so surrounding layout is unaffected. */
|
|
24
|
+
bd-tab-list {
|
|
25
|
+
display: contents;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.bd-tabs-container {
|
|
29
|
+
display: inline-flex;
|
|
30
|
+
justify-content: center;
|
|
31
|
+
flex-wrap: wrap;
|
|
32
|
+
border-bottom: var(--border-width-1) solid var(--bd-tab-border-color, var(--color-border-container));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.bd-tab-button {
|
|
36
|
+
display: inline-flex;
|
|
37
|
+
align-items: center;
|
|
38
|
+
justify-content: center;
|
|
39
|
+
gap: var(--bd-tab-gap, var(--spacing-8));
|
|
40
|
+
background: none;
|
|
41
|
+
border: none;
|
|
42
|
+
padding: var(--bd-tab-padding, var(--spacing-10) var(--spacing-16));
|
|
43
|
+
cursor: pointer;
|
|
44
|
+
position: relative;
|
|
45
|
+
color: var(--bd-tab-color, var(--color-text-brand));
|
|
46
|
+
font-family: var(--typography-fontFamily-sans);
|
|
47
|
+
/* body-regular, the same role bd-anchor-nav's and bd-page-switcher's items
|
|
48
|
+
resolve through.
|
|
49
|
+
|
|
50
|
+
This was body-large at semibold -- 18px/600 -- with no leading declared
|
|
51
|
+
at all, on the argument that a tab's type is a control's rather than a
|
|
52
|
+
text role's. The wayfinding family review settled it the other way: all
|
|
53
|
+
three of these components are labels with an action attached, they mark
|
|
54
|
+
the current one the same way, and there was no reason for one of them to
|
|
55
|
+
be a size and a weight apart. At 16/1.5 the tab box is 10 + 24 + 10, so
|
|
56
|
+
all three now measure 44px.
|
|
57
|
+
|
|
58
|
+
The leading is declared either way, and that part was a defect on its
|
|
59
|
+
own. An 18px label sat on IBM Plex Sans's own metric while the nav bars
|
|
60
|
+
beside it sat on a declared 24px -- and a leading nobody declares is the
|
|
61
|
+
blind spot neither gate can see: lint:tokens needs a DECLARED value to
|
|
62
|
+
report, and verify:typography only fails on multi-line text, which a
|
|
63
|
+
single-line tab label never is. */
|
|
64
|
+
font-size: var(--bd-tab-font-size, var(--typography-body-regular-fontSize));
|
|
65
|
+
line-height: var(--bd-tab-line-height, var(--typography-body-regular-lineHeight));
|
|
66
|
+
font-weight: var(--bd-tab-font-weight, var(--typography-body-regular-fontWeight));
|
|
67
|
+
transition: color var(--transition-duration-fast) var(--transition-easing-smooth);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.bd-tab-button::after {
|
|
71
|
+
content: "";
|
|
72
|
+
height: var(--bd-tab-underline-height, var(--indicator-underline-height));
|
|
73
|
+
background: var(--bd-tab-underline-color, var(--indicator-color));
|
|
74
|
+
position: absolute;
|
|
75
|
+
left: 0;
|
|
76
|
+
bottom: 0;
|
|
77
|
+
width: 0;
|
|
78
|
+
transition: width var(--bd-tab-underline-duration, var(--indicator-underline-duration))
|
|
79
|
+
var(--indicator-underline-easing);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* The transition two rules up had nothing to animate on pointer: this sheet
|
|
83
|
+
declared a colour transition and then no :hover rule anywhere, so a tab
|
|
84
|
+
was the one control in the package that gave no feedback under the
|
|
85
|
+
cursor.
|
|
86
|
+
|
|
87
|
+
action/primary-active is the step this system already uses for an
|
|
88
|
+
interactive element under the pointer -- bd-link's :hover and the anchor
|
|
89
|
+
nav's engaged dropdown option both resolve to it -- and it is a step
|
|
90
|
+
darker than the resting --color-text-brand, so the change is visible
|
|
91
|
+
without becoming the selected ink. Excluding .bd-selected keeps the
|
|
92
|
+
selected tab's text/primary from moving under the cursor. */
|
|
93
|
+
.bd-tab-button:hover:not(.bd-selected) {
|
|
94
|
+
color: var(--color-action-primary-active);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.bd-tab-button.bd-selected::after {
|
|
98
|
+
width: 100%;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.bd-tab-button.bd-selected {
|
|
102
|
+
color: var(--bd-tab-color-selected, var(--color-text-primary));
|
|
103
|
+
/* no role: the weight that marks the current item -- a state or modifier
|
|
104
|
+
weight, not a text-content type. See button.css.js's .button--bold for
|
|
105
|
+
the argument, and bd-link's .bd-link--active, which is the same 700 on
|
|
106
|
+
the same job in the other two components of this family. The tab used to
|
|
107
|
+
carry semibold at rest AND selected, so its weight said nothing about
|
|
108
|
+
which item you were on -- colour and the indicator carried it alone. */
|
|
109
|
+
font-weight: var(--bd-tab-font-weight-selected, var(--typography-fontWeight-bold));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.bd-tab-button:focus-visible {
|
|
113
|
+
/* the one focus ring — see Foundations/Focus */
|
|
114
|
+
outline: none;
|
|
115
|
+
box-shadow: var(--focus-outline-primary);
|
|
116
|
+
border-radius: var(--focus-outline-radius);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/* Icon sizing is deliberately not defaulted here: the two sections that use
|
|
120
|
+
icons size them differently and neither value has a dimension token, so
|
|
121
|
+
each keeps its own rule rather than this atom inventing a size. */
|
|
122
|
+
|
|
123
|
+
.bd-tab-label {
|
|
124
|
+
pointer-events: none;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
@media (prefers-reduced-motion: reduce) {
|
|
128
|
+
.bd-tab-button,
|
|
129
|
+
.bd-tab-button::after {
|
|
130
|
+
transition: none;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/* Narrower than sm. A media condition cannot read a custom property, so
|
|
135
|
+
below() interpolates the value; 600px was on no scale at all, and the
|
|
136
|
+
576px that replaced it still matched at exactly 576px, where sm begins. */
|
|
137
|
+
@media ${unsafeCSS(below('sm'))} {
|
|
138
|
+
.bd-tabs-container {
|
|
139
|
+
gap: var(--spacing-4);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.bd-tab-button {
|
|
143
|
+
padding: var(--bd-tab-padding-mobile, var(--spacing-8) var(--spacing-12));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
`;
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
/* ---- appearance="switcher": the Content Switcher --------------------------
|
|
150
|
+
Figma: Content switcher, node 311:931. Every value below is the one the
|
|
151
|
+
component carries there, and the geometry reconciles: label 24 tall + 12/24
|
|
152
|
+
padding = a 48px option, + 4px track padding top and bottom = 56, which is
|
|
153
|
+
the frame height. "Individual" at 16/500 measures 75, + 24 + 24 = the 123px
|
|
154
|
+
option, and 4 + 123 + 4 + 123 + 4 = the 258px track.
|
|
155
|
+
|
|
156
|
+
THE EQUAL-WIDTH RULE IS THE POINT, and CSS expresses it where Figma cannot.
|
|
157
|
+
The design asks for both options to be as wide as the LONGER label so a
|
|
158
|
+
translation cannot make one tab bigger than the other. In the file one
|
|
159
|
+
option HUGs and the other is FIXED at the same width, which is equal at this
|
|
160
|
+
text and stops being equal the moment a label changes length. An auto-sized
|
|
161
|
+
inline grid whose columns are 1fr sizes every column to the widest column's
|
|
162
|
+
max-content, so the track still hugs its content AND the two options stay
|
|
163
|
+
identical -- which is the stated intent rather than a snapshot of it.
|
|
164
|
+
|
|
165
|
+
The selected option is marked by the white pill alone. The base sheet moves
|
|
166
|
+
the selected tab to bold, and that is right for an underlined strip where
|
|
167
|
+
weight and the indicator carry the state together; here the fill carries it,
|
|
168
|
+
so both weights stay at the action-label step and the label does not reflow
|
|
169
|
+
when you switch. That is also why every override here goes through the
|
|
170
|
+
--bd-tab-* custom properties the base sheet exposes rather than
|
|
171
|
+
re-declaring the button. */
|
|
172
|
+
export const contentSwitcherCSS = css`
|
|
173
|
+
.bd-tabs-container--switcher {
|
|
174
|
+
display: inline-grid;
|
|
175
|
+
grid-auto-flow: column;
|
|
176
|
+
/* minmax(max-content, 1fr), NOT 1fr. Measured on the Unequal labels story:
|
|
177
|
+
a bare 1fr gave 127.21px and 141.79px -- two unequal columns, both
|
|
178
|
+
narrower than their content, so the labels wrapped to four lines. An fr
|
|
179
|
+
track under a shrink-to-fit container does not equalise to the widest
|
|
180
|
+
sibling, which is the assumption that was wrong.
|
|
181
|
+
.
|
|
182
|
+
minmax(max-content, 1fr) was the next attempt and gave 78.35 and 248.77
|
|
183
|
+
-- each column at its own max-content, still unequal. Once the width IS
|
|
184
|
+
definite an fr track splits it evenly instead, which is a different
|
|
185
|
+
wrong answer. There is no grid declaration that gives all three of hug,
|
|
186
|
+
equal, and equal-to-the-widest.
|
|
187
|
+
.
|
|
188
|
+
So the width arrives measured: _sizeSwitcherOptions in tab-list.js
|
|
189
|
+
publishes the widest option's width and this reads it. max-content is
|
|
190
|
+
the fallback for the frame before the first measurement, which is also
|
|
191
|
+
what keeps the geometry right if the property is ever absent -- and it
|
|
192
|
+
is a component-local property, the one place CLAUDE.md allows a
|
|
193
|
+
fallback. */
|
|
194
|
+
grid-auto-columns: var(--bd-switcher-option-width, max-content);
|
|
195
|
+
gap: var(--spacing-4);
|
|
196
|
+
padding: var(--spacing-4);
|
|
197
|
+
border-bottom: none;
|
|
198
|
+
border-radius: var(--radius-full);
|
|
199
|
+
background: var(--color-action-primary);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.bd-tabs-container--switcher .bd-tab-button {
|
|
203
|
+
/* the action-label step, which is what a button's label carries */
|
|
204
|
+
--bd-tab-font-weight: var(--typography-control-label-large-fontWeight);
|
|
205
|
+
--bd-tab-font-weight-selected: var(--typography-control-label-large-fontWeight);
|
|
206
|
+
--bd-tab-color: var(--color-text-inverse);
|
|
207
|
+
--bd-tab-color-selected: var(--color-text-primary);
|
|
208
|
+
--bd-tab-padding: var(--spacing-12) var(--spacing-24);
|
|
209
|
+
/* held at the same padding below sm: the base sheet drops to 8/12 there,
|
|
210
|
+
which would take the pill off the 48px option the design specifies, and
|
|
211
|
+
two 123px options plus the track padding still fit a 375px viewport. */
|
|
212
|
+
--bd-tab-padding-mobile: var(--spacing-12) var(--spacing-24);
|
|
213
|
+
border-radius: var(--radius-full);
|
|
214
|
+
/* An option is a control label, so it is one line by definition. The base
|
|
215
|
+
sheet lets a tab wrap, which is right for a strip that reflows; here a
|
|
216
|
+
wrap would break the pill geometry the design specifies. */
|
|
217
|
+
white-space: nowrap;
|
|
218
|
+
transition: color var(--transition-duration-fast) var(--transition-easing-smooth),
|
|
219
|
+
background-color var(--transition-duration-fast) var(--transition-easing-smooth);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.bd-tabs-container--switcher .bd-tab-button.bd-selected {
|
|
223
|
+
background: var(--color-surface-default);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/* The underline belongs to the other appearance. Left as display:none rather
|
|
227
|
+
than content:none so the base rule's width transition has nothing to
|
|
228
|
+
animate either. */
|
|
229
|
+
.bd-tabs-container--switcher .bd-tab-button::after {
|
|
230
|
+
display: none;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/* The base hover goes to action/primary-active, a darker blue, which on this
|
|
234
|
+
blue track would be close to invisible and is the wrong direction anyway.
|
|
235
|
+
The unselected option is already white, so the pointer affordance is the
|
|
236
|
+
pill appearing under it -- white at 12%, which reads on blue-500 without
|
|
237
|
+
competing with the selected option's solid white. */
|
|
238
|
+
.bd-tabs-container--switcher .bd-tab-button:hover:not(.bd-selected) {
|
|
239
|
+
color: var(--color-text-inverse);
|
|
240
|
+
background: var(--color-border-container-inverse);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
@media (prefers-reduced-motion: reduce) {
|
|
244
|
+
.bd-tabs-container--switcher .bd-tab-button {
|
|
245
|
+
transition: none;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
`;
|
|
249
|
+
|
|
250
|
+
export default tabListCSS;
|