@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
|
@@ -14,7 +14,7 @@ export default css`
|
|
|
14
14
|
border: none;
|
|
15
15
|
background: none;
|
|
16
16
|
cursor: pointer;
|
|
17
|
-
border-radius: var(--radius-lg
|
|
17
|
+
border-radius: var(--radius-lg);
|
|
18
18
|
overflow: hidden;
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -22,8 +22,8 @@ export default css`
|
|
|
22
22
|
width: 100%;
|
|
23
23
|
height: auto;
|
|
24
24
|
display: block;
|
|
25
|
-
border-radius: var(--radius-lg
|
|
26
|
-
transition: transform
|
|
25
|
+
border-radius: var(--radius-lg);
|
|
26
|
+
transition: transform var(--transition-duration-slow) var(--transition-easing-ease);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
.bd-video-thumb:hover img {
|
|
@@ -39,7 +39,7 @@ export default css`
|
|
|
39
39
|
height: 64px;
|
|
40
40
|
pointer-events: none;
|
|
41
41
|
filter: drop-shadow(0 4px 12px rgba(0,0,0,0.3));
|
|
42
|
-
transition: transform
|
|
42
|
+
transition: transform var(--transition-duration-slow) var(--transition-easing-ease);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
.bd-video-thumb:hover .bd-video-play-btn {
|
|
@@ -55,9 +55,12 @@ export default css`
|
|
|
55
55
|
position: relative;
|
|
56
56
|
width: 100%;
|
|
57
57
|
padding-bottom: 56.25%;
|
|
58
|
-
border-radius: var(--radius-lg
|
|
58
|
+
border-radius: var(--radius-lg);
|
|
59
59
|
overflow: hidden;
|
|
60
|
-
|
|
60
|
+
/* The media frame, --color-surface-media: around a video, dark in every theme.
|
|
61
|
+
This read --color-surface-inverse until dark mode decision 15 -- the
|
|
62
|
+
polarity flip, which would turn a letterbox light in a dark theme. */
|
|
63
|
+
background: var(--color-surface-media);
|
|
61
64
|
}
|
|
62
65
|
|
|
63
66
|
.bd-video-player iframe,
|
|
@@ -78,18 +81,71 @@ export default css`
|
|
|
78
81
|
height: 32px;
|
|
79
82
|
border-radius: 50%;
|
|
80
83
|
border: none;
|
|
81
|
-
|
|
82
|
-
|
|
84
|
+
/* no role: NOT a scrim, though it looks like one next to the modal's. This
|
|
85
|
+
is the close button's own ground -- a 32px circle that has to carry a
|
|
86
|
+
white glyph over whatever frame the video happens to be showing, so the
|
|
87
|
+
darkness is doing contrast work for the icon rather than dimming content
|
|
88
|
+
behind a dialog. Two declarations, one control, no role.
|
|
89
|
+
.
|
|
90
|
+
Mixed over the palette rather than written as a raw rgba, for the same
|
|
91
|
+
reason as the modal's scrim: this follows --color-neutral-1000 where a
|
|
92
|
+
literal black follows nothing. Pixel-identical to the rgba it replaces. */
|
|
93
|
+
background: color-mix(in srgb, var(--color-neutral-1000) 60%, transparent);
|
|
94
|
+
color: var(--color-text-on-media);
|
|
83
95
|
font-size: 16px;
|
|
84
96
|
cursor: pointer;
|
|
85
97
|
display: flex;
|
|
86
98
|
align-items: center;
|
|
87
99
|
justify-content: center;
|
|
88
|
-
|
|
89
|
-
|
|
100
|
+
/* Above the video surface it sits on; nothing else in this shadow root
|
|
101
|
+
is positioned. */
|
|
102
|
+
z-index: var(--z-raised);
|
|
103
|
+
transition: background var(--transition-duration-fast) var(--transition-easing-ease);
|
|
90
104
|
}
|
|
91
105
|
|
|
92
106
|
.bd-video-close:hover {
|
|
93
|
-
|
|
107
|
+
/* no role: the same control ground at 90% under the pointer -- it gets more
|
|
108
|
+
opaque rather than changing hue. Same reasoning as the rest state above,
|
|
109
|
+
and no role for the same reason. Pixel-identical to the rgba it
|
|
110
|
+
replaces. */
|
|
111
|
+
background: color-mix(in srgb, var(--color-neutral-1000) 90%, transparent);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* The one focus ring, on both controls. This sheet had no :focus-visible
|
|
115
|
+
rule at all, so the two buttons fell back to the browser's outline:
|
|
116
|
+
measured on the thumbnail with a real Tab, outline 1px auto
|
|
117
|
+
rgb(0, 95, 204) and box-shadow none, where every other control in this
|
|
118
|
+
package draws --focus-outline-primary. The two-colour ring also matters
|
|
119
|
+
more here than most places -- the close button sits on video, so a
|
|
120
|
+
single-colour outline has no guaranteed ground to contrast against, and
|
|
121
|
+
the white inner band is what makes it visible on any frame.
|
|
122
|
+
|
|
123
|
+
The ring follows each control's own shape: the thumbnail keeps its
|
|
124
|
+
--radius-lg corner and the close button is a circle. */
|
|
125
|
+
.bd-video-thumb:focus-visible,
|
|
126
|
+
.bd-video-close:focus-visible {
|
|
127
|
+
outline: none;
|
|
128
|
+
box-shadow: var(--focus-outline-primary);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/* The thumbnail lifts on hover and the play mark grows. Measured before
|
|
132
|
+
this: with prefers-reduced-motion: reduce both still reported a 0.3s
|
|
133
|
+
transition, so the scale ran for a reader who asked for less motion.
|
|
134
|
+
The transform is dropped as well as the transition -- a scale that
|
|
135
|
+
arrives instantly is still motion the reader did not ask for. */
|
|
136
|
+
@media (prefers-reduced-motion: reduce) {
|
|
137
|
+
.bd-video-thumb img,
|
|
138
|
+
.bd-video-play-btn,
|
|
139
|
+
.bd-video-close {
|
|
140
|
+
transition: none;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.bd-video-thumb:hover img {
|
|
144
|
+
transform: none;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.bd-video-thumb:hover .bd-video-play-btn {
|
|
148
|
+
transform: translate(-50%, -50%);
|
|
149
|
+
}
|
|
94
150
|
}
|
|
95
151
|
`;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { LitElement, html } from "lit";
|
|
2
|
-
|
|
2
|
+
// Installs the design tokens into document scope; see src/tokens/tokens.js
|
|
3
|
+
import "../../tokens/tokens.js";
|
|
4
|
+
import "../icons/close-icon.js";
|
|
3
5
|
import videoPlayerCSS from "./video-player.css.js";
|
|
4
6
|
|
|
5
7
|
class BdVideoPlayer extends LitElement {
|
|
@@ -10,7 +12,7 @@ class BdVideoPlayer extends LitElement {
|
|
|
10
12
|
_open : { state: true }
|
|
11
13
|
};
|
|
12
14
|
|
|
13
|
-
static styles = [
|
|
15
|
+
static styles = [videoPlayerCSS];
|
|
14
16
|
|
|
15
17
|
constructor() {
|
|
16
18
|
super();
|
|
@@ -24,12 +26,39 @@ class BdVideoPlayer extends LitElement {
|
|
|
24
26
|
return this.src.includes("youtube.com") || this.src.includes("youtu.be");
|
|
25
27
|
}
|
|
26
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Opening replaces the thumbnail button with the player, which destroys the
|
|
31
|
+
* element that had focus. Measured with a real keyboard: Tab to the
|
|
32
|
+
* thumbnail, Enter, and document.activeElement was body -- the keyboard user
|
|
33
|
+
* was dropped to the top of the document by the act of pressing Play.
|
|
34
|
+
*
|
|
35
|
+
* Focus goes to the close button, which is the one control this component
|
|
36
|
+
* owns once the player is up. That also answers a reachability problem it
|
|
37
|
+
* would otherwise have: the close button follows the iframe in DOM order, so
|
|
38
|
+
* reaching it by Tab means traversing the embedded player's own tab stops
|
|
39
|
+
* first -- measured, six Tabs after opening never left the iframe. Landing on
|
|
40
|
+
* it directly means the way out is the first thing the keyboard has.
|
|
41
|
+
*
|
|
42
|
+
* Only when there is a thumbnail: without one the component renders the
|
|
43
|
+
* player immediately, owns no close button, and nothing has been displaced.
|
|
44
|
+
*/
|
|
27
45
|
_openVideo() {
|
|
28
46
|
this._open = true;
|
|
47
|
+
if (!this.thumb) return;
|
|
48
|
+
this.updateComplete.then(() => {
|
|
49
|
+
this.renderRoot?.querySelector(".bd-video-close")?.focus();
|
|
50
|
+
});
|
|
29
51
|
}
|
|
30
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Closing destroys the close button the same way, so focus returns to the
|
|
55
|
+
* thumbnail it came from.
|
|
56
|
+
*/
|
|
31
57
|
_closeVideo() {
|
|
32
58
|
this._open = false;
|
|
59
|
+
this.updateComplete.then(() => {
|
|
60
|
+
this.renderRoot?.querySelector(".bd-video-thumb")?.focus();
|
|
61
|
+
});
|
|
33
62
|
}
|
|
34
63
|
|
|
35
64
|
render() {
|
|
@@ -61,7 +90,9 @@ class BdVideoPlayer extends LitElement {
|
|
|
61
90
|
class="bd-video-close"
|
|
62
91
|
@click=${this._closeVideo}
|
|
63
92
|
aria-label="Close video"
|
|
64
|
-
|
|
93
|
+
>
|
|
94
|
+
<bd-close-icon size="xs" aria-hidden="true"></bd-close-icon>
|
|
95
|
+
</button>
|
|
65
96
|
`
|
|
66
97
|
: ""}
|
|
67
98
|
</div>
|
|
@@ -82,7 +113,7 @@ class BdVideoPlayer extends LitElement {
|
|
|
82
113
|
<span class="bd-video-play-btn" aria-hidden="true">
|
|
83
114
|
<svg viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
84
115
|
<circle cx="32" cy="32" r="32" fill="white" fill-opacity="0.9"/>
|
|
85
|
-
<path d="M26 20L46 32L26 44V20Z" fill="
|
|
116
|
+
<path d="M26 20L46 32L26 44V20Z" fill="var(--color-blue-500)"/>
|
|
86
117
|
</svg>
|
|
87
118
|
</span>
|
|
88
119
|
</button>
|
|
@@ -136,7 +136,7 @@ export const YouTubeAutoplayVideo = {
|
|
|
136
136
|
export const DifferentThumbnails = {
|
|
137
137
|
name : 'Different Thumbnails',
|
|
138
138
|
render: () => html`
|
|
139
|
-
<div style="display:grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 24px; max-width: 1200px; margin: 0 auto; padding: 20px;">
|
|
139
|
+
<div style="display:grid; grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr)); gap: 24px; max-width: 1200px; margin: 0 auto; padding: 20px;">
|
|
140
140
|
<div>
|
|
141
141
|
<h4 style="margin-bottom: 8px;">Thumbnail 1</h4>
|
|
142
142
|
<bd-video-player
|
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
|
|
3
|
+
import './alert/alert.js';
|
|
4
|
+
import './anchor/anchor-nav.js';
|
|
5
|
+
import './back/back.js';
|
|
6
|
+
import './badge/badge.js';
|
|
7
|
+
import './bento-grid/bento-item.js';
|
|
8
|
+
import './breadcrumb/breadcrumb.js';
|
|
9
|
+
import './card-features/card-features.js';
|
|
10
|
+
import './cards/card.js';
|
|
11
|
+
import './carousel/carousel.js';
|
|
12
|
+
import './compare/compare.js';
|
|
13
|
+
import './divider/divider-vertical.js';
|
|
14
|
+
import './footer/footer-nav-menu.js';
|
|
15
|
+
import './heading/heading.js';
|
|
16
|
+
import './light-carousel/light-carousel.js';
|
|
17
|
+
import './page-switcher/page-switcher.js';
|
|
18
|
+
import './paragraph/paragraph.js';
|
|
19
|
+
import './tab-list/tab-list.js';
|
|
20
|
+
import './tag/tag.js';
|
|
21
|
+
import { tabListCSS } from './tab-list/tab-list.css.js';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Composed components rendered next to the components they are supposed to
|
|
25
|
+
* agree with.
|
|
26
|
+
*
|
|
27
|
+
* `Atoms/Control Alignment` does this for atoms and says why: the lint can
|
|
28
|
+
* prove every value came from a token and still cannot prove two components
|
|
29
|
+
* ended up looking the same. The same gap exists a layer up, and it is where
|
|
30
|
+
* the section title came to mean 48, 36, 32 and 24 at once, and where one card
|
|
31
|
+
* in the family kept a corner the other five had stopped using.
|
|
32
|
+
*
|
|
33
|
+
* These exist to be looked at. Nothing here is a usage example — do not copy
|
|
34
|
+
* these compositions into a page.
|
|
35
|
+
*/
|
|
36
|
+
export default {
|
|
37
|
+
title : 'Foundations/Visual Alignment',
|
|
38
|
+
tags : ['autodocs'],
|
|
39
|
+
parameters: {
|
|
40
|
+
layout: 'padded',
|
|
41
|
+
docs : {
|
|
42
|
+
description: {
|
|
43
|
+
component: `
|
|
44
|
+
Cross-component comparisons. Each story puts components that share a visual
|
|
45
|
+
role in one frame, so the system can be judged as a system.
|
|
46
|
+
|
|
47
|
+
Read each one by asking whether these look like they came from the same place.
|
|
48
|
+
Where they do not, the difference is either a decision or a finding — and the
|
|
49
|
+
point of the story is that you can tell which.
|
|
50
|
+
`
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const label = text => html`
|
|
57
|
+
<p style="margin:0 0 var(--spacing-8);font:var(--typography-fontWeight-semibold) var(--typography-fontSize-xs)/1.4 var(--typography-fontFamily-mono);color:var(--color-text-muted)">
|
|
58
|
+
${text}
|
|
59
|
+
</p>`;
|
|
60
|
+
|
|
61
|
+
/* Several of these components carry their own fixed width -- the carousel item
|
|
62
|
+
is 350px -- so a row of them is wider than a phone no matter how it wraps.
|
|
63
|
+
It scrolls inside its own container rather than taking the page with it,
|
|
64
|
+
which is what this package already does for wide reference tables. */
|
|
65
|
+
const row = children => html`
|
|
66
|
+
<div style="overflow-x:auto">
|
|
67
|
+
<div style="display:flex;flex-wrap:wrap;gap:var(--spacing-24);align-items:flex-start;min-width:min-content">
|
|
68
|
+
${children}
|
|
69
|
+
</div>
|
|
70
|
+
</div>`;
|
|
71
|
+
|
|
72
|
+
const cell = (name, node) => html`
|
|
73
|
+
<div style="flex:0 1 auto;min-width:0">${label(name)}${node}</div>`;
|
|
74
|
+
|
|
75
|
+
/* ---------------------------------------------------------------- cards --- */
|
|
76
|
+
|
|
77
|
+
export const CardFamily = {
|
|
78
|
+
name : 'Card family',
|
|
79
|
+
render: () => html`
|
|
80
|
+
<p style="max-width:70ch;color:var(--color-text-secondary)">
|
|
81
|
+
Every card in the family sits on <code>--color-surface-container</code> with
|
|
82
|
+
32px of padding and no resting shadow, and none of them draws an edge. Every
|
|
83
|
+
cell below measures the same at desktop width: 16px corner, no border, 32px
|
|
84
|
+
inset. This page used to exist because they differed.
|
|
85
|
+
</p>
|
|
86
|
+
<p style="max-width:70ch;color:var(--color-text-secondary)">
|
|
87
|
+
<b>The inset holds at every width.</b> LightCarousel used to be the one exception,
|
|
88
|
+
dropping its padding to 1.5em at 1024 and 1em at 480 while every other card held
|
|
89
|
+
<code>--spacing-32</code> — so at this page's own default viewport that cell
|
|
90
|
+
measured 24px, not 32. It was never a decision, just two em literals carried
|
|
91
|
+
forward, and it is gone. A card in a narrowing track is still a card: the track
|
|
92
|
+
gives way, not the card's own breathing room.
|
|
93
|
+
</p>
|
|
94
|
+
<p style="max-width:70ch;color:var(--color-text-secondary)">
|
|
95
|
+
Whether a card has an edge is no longer a component decision. It follows from
|
|
96
|
+
what the card sits on — no edge on the page ground, where the tonal step is the
|
|
97
|
+
separation; an edge on a tinted section, where no tonal step is available. See
|
|
98
|
+
<i>A card's ground and its edge</i> in the package README, and
|
|
99
|
+
<code>Foundations/Surfaces</code>. The two cards that drew an edge on the page
|
|
100
|
+
ground — Bento and the Carousel item — dropped it under that rule. Interactivity
|
|
101
|
+
never predicted an edge and still does not.
|
|
102
|
+
</p>
|
|
103
|
+
${row(html`
|
|
104
|
+
${cell('bd-card-item · 16px, no border', html`
|
|
105
|
+
<bd-card-item title="Machine Learning">
|
|
106
|
+
<bd-p variant="small">Behaviour learned from millions of daily threats.</bd-p>
|
|
107
|
+
</bd-card-item>`)}
|
|
108
|
+
${cell('bd-card-features-item · 16px, no border', html`
|
|
109
|
+
<bd-card-features-item title="Scam Copilot">
|
|
110
|
+
<bd-p variant="small">Behaviour learned from millions of daily threats.</bd-p>
|
|
111
|
+
</bd-card-features-item>`)}
|
|
112
|
+
${cell('bd-light-carousel-item · 16px, no border', html`
|
|
113
|
+
<bd-light-carousel-item title="Machine Learning">
|
|
114
|
+
<bd-p variant="small">Behaviour learned from millions of daily threats.</bd-p>
|
|
115
|
+
</bd-light-carousel-item>`)}
|
|
116
|
+
${cell('bd-bento-item · 16px, no border — was 1px', html`
|
|
117
|
+
<bd-bento-item title="Machine Learning">
|
|
118
|
+
<bd-p variant="small">Behaviour learned from millions of daily threats.</bd-p>
|
|
119
|
+
</bd-bento-item>`)}
|
|
120
|
+
${cell('bd-carousel-item · 16px, no border — was 24px and 2px', html`
|
|
121
|
+
<bd-carousel-item title="Machine Learning" modalText="Opens a modal.">
|
|
122
|
+
<bd-p variant="small">Behaviour learned from millions of daily threats.</bd-p>
|
|
123
|
+
</bd-carousel-item>`)}
|
|
124
|
+
${cell('compare-card · 16px, no border — was 24px', html`
|
|
125
|
+
<compare-card
|
|
126
|
+
title="Best Protection"
|
|
127
|
+
description="Scale of 0-6. Higher is better."
|
|
128
|
+
></compare-card>`)}
|
|
129
|
+
`)}`,
|
|
130
|
+
parameters: {
|
|
131
|
+
docs: {
|
|
132
|
+
description: {
|
|
133
|
+
story: `Nothing differs any more, and the two that used to are worth keeping
|
|
134
|
+
on the page for the reasons they gave.
|
|
135
|
+
|
|
136
|
+
The compare card had no argument: same surface, same inset, no elevation,
|
|
137
|
+
no card-level interaction, no recorded reason. It went first.
|
|
138
|
+
|
|
139
|
+
The carousel item did have one — it is draggable and its plus button opens
|
|
140
|
+
a modal, where the others are static — and it went anyway. Behaviour earns
|
|
141
|
+
a state, a cue or a control; it does not earn a different corner. The
|
|
142
|
+
question the two of them settle is what counts as a reason to leave a
|
|
143
|
+
family, and behaving differently turned out not to be enough on its own.`
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
/* ----------------------------------------------------------- section titles - */
|
|
150
|
+
|
|
151
|
+
export const SectionTitles = {
|
|
152
|
+
name : 'Section title roles',
|
|
153
|
+
render: () => html`
|
|
154
|
+
<p style="max-width:70ch;color:var(--color-text-secondary)">
|
|
155
|
+
Two roles, and the question that picks between them: would the page still make
|
|
156
|
+
sense with this title deleted and its content left in place? If not it is
|
|
157
|
+
anchoring a region, and it is a page section.
|
|
158
|
+
</p>
|
|
159
|
+
<div style="display:grid;gap:var(--spacing-40);max-width:80ch">
|
|
160
|
+
<div>
|
|
161
|
+
${label('PAGE SECTION · bd-h visual-level="h2" · 36/700')}
|
|
162
|
+
<bd-h as="h2" visual-level="h2">What is AI Guardian?</bd-h>
|
|
163
|
+
<bd-p variant="small">Overview, Process Steps, Trust Panel, Comparison Panel.</bd-p>
|
|
164
|
+
</div>
|
|
165
|
+
<div>
|
|
166
|
+
${label('COMPONENT SECTION · bd-h visual-level="h3" · 32/600')}
|
|
167
|
+
<bd-h as="h2" visual-level="h3">Need help? We have answers.</bd-h>
|
|
168
|
+
<bd-p variant="small">LightCarousel, CardFeatures, Awards, Tabs, Terms.</bd-p>
|
|
169
|
+
</div>
|
|
170
|
+
<div>
|
|
171
|
+
${label('ITEM TITLE · bd-h visual-level="h5" fontWeight="bold" · 20/700')}
|
|
172
|
+
<bd-h as="h3" visual-level="h5" fontWeight="bold">Machine Learning</bd-h>
|
|
173
|
+
<bd-p variant="small">The title of one card inside a collection.</bd-p>
|
|
174
|
+
</div>
|
|
175
|
+
<div>
|
|
176
|
+
${label('LONG TITLE · the component section, wrapping')}
|
|
177
|
+
<bd-h as="h2" visual-level="h3">
|
|
178
|
+
A section title long enough to wrap onto a second and very probably a third line
|
|
179
|
+
</bd-h>
|
|
180
|
+
</div>
|
|
181
|
+
</div>`,
|
|
182
|
+
parameters: {
|
|
183
|
+
docs: {
|
|
184
|
+
description: {
|
|
185
|
+
story: `The level and the size are separate: every heading here is semantically
|
|
186
|
+
what its position requires, and visually what its responsibility requires.
|
|
187
|
+
Two components render a section title at 48/700 — the card section and the
|
|
188
|
+
hero — and both are recorded P4 exceptions rather than a third role.`
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
/* -------------------------------------------------------------- navigation - */
|
|
195
|
+
|
|
196
|
+
const NAV_ITEMS = [
|
|
197
|
+
{ title: 'AI Guardian', href: '#one', active: true },
|
|
198
|
+
{ title: 'Skill Scanner', href: '#two' }
|
|
199
|
+
];
|
|
200
|
+
|
|
201
|
+
export const NavigationStates = {
|
|
202
|
+
name : 'Navigation current state',
|
|
203
|
+
render: () => html`
|
|
204
|
+
<p style="max-width:70ch;color:var(--color-text-secondary)">
|
|
205
|
+
Two models, and they are not the same question. The link navigations mark where
|
|
206
|
+
you are; the tab list marks which panel is showing. Every one of them carries a
|
|
207
|
+
cue that is not colour.
|
|
208
|
+
</p>
|
|
209
|
+
<div style="display:grid;gap:var(--spacing-40)">
|
|
210
|
+
<div>
|
|
211
|
+
${label('bd-page-switcher · current is heavier and darker')}
|
|
212
|
+
<bd-page-switcher .items=${NAV_ITEMS}></bd-page-switcher>
|
|
213
|
+
</div>
|
|
214
|
+
<div>
|
|
215
|
+
${label('bd-breadcrumb · current is heavier, larger and darker')}
|
|
216
|
+
<bd-breadcrumb>
|
|
217
|
+
<bd-breadcrumb-item href="/">Home</bd-breadcrumb-item>
|
|
218
|
+
<bd-breadcrumb-item href="/products">Products</bd-breadcrumb-item>
|
|
219
|
+
<bd-breadcrumb-item current>Total Security</bd-breadcrumb-item>
|
|
220
|
+
</bd-breadcrumb>
|
|
221
|
+
</div>
|
|
222
|
+
</div>`,
|
|
223
|
+
parameters: {
|
|
224
|
+
docs: {
|
|
225
|
+
description: {
|
|
226
|
+
story: `Tabs used to run the opposite way and be left alone here, on the argument
|
|
227
|
+
that its items are buttons with role="tab" and aria-selected inside a
|
|
228
|
+
tablist rather than links. The ARIA contract is still exactly that and does
|
|
229
|
+
not change. What changed is the ink: a label with an action behind it is
|
|
230
|
+
painted like a link in this package, whatever element carries it, so the
|
|
231
|
+
unselected tabs are brand blue and the selected one settles to plain text
|
|
232
|
+
at bold — the same three-step contract the link navigations use. Measured
|
|
233
|
+
across all three: resting is blue-600 at 400, current is text-primary at
|
|
234
|
+
700, both at 16px. Its underline carries the state either way.
|
|
235
|
+
|
|
236
|
+
The two rows above read alike, and measurement is why. The page
|
|
237
|
+
switcher's current item is darker and heavier than its neighbours, which
|
|
238
|
+
are brand blue rather than muted — the sizes match at 16px. The
|
|
239
|
+
breadcrumb's current item is the same 14px as its links and one weight
|
|
240
|
+
step above them, which is a change P6C.2 made: the links asked bd-link for
|
|
241
|
+
\`size="small"\`, a property bd-link does not have, so they rendered 16px
|
|
242
|
+
against a 14px current item, and the current item's medium weight was
|
|
243
|
+
declared on a span whose text lives inside bd-p and never arrived.`
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
/* The whole family in one frame, grouped by what each member is responsible for
|
|
250
|
+
rather than by what it looks like. The point of the grouping is that two of
|
|
251
|
+
these are not supposed to converge with the others.
|
|
252
|
+
|
|
253
|
+
bd-footer-nav sits on the masthead blue it is always used on. It is the one
|
|
254
|
+
member whose links are the consumer's own anchors rather than bd-link, which
|
|
255
|
+
is why it is the only one that had to be given the focus ring explicitly —
|
|
256
|
+
tab through it here and the ring should be the same two-colour ring as
|
|
257
|
+
everywhere else, white band inside blue. */
|
|
258
|
+
const FAMILY_TABS = [
|
|
259
|
+
{ label: 'Windows' }, { label: 'macOS' }, { label: 'iOS' }
|
|
260
|
+
];
|
|
261
|
+
|
|
262
|
+
const group = (title, note, node) => html`
|
|
263
|
+
<section style="display:grid;gap:var(--spacing-8)">
|
|
264
|
+
<h3 style="margin:0;font:var(--typography-fontWeight-semibold) var(--typography-fontSize-base)/var(--typography-lineHeight-tight) var(--typography-fontFamily-sans);color:var(--color-text-primary)">
|
|
265
|
+
${title}
|
|
266
|
+
</h3>
|
|
267
|
+
<p style="margin:0;max-width:74ch;font:var(--typography-fontWeight-normal) var(--typography-fontSize-sm)/var(--typography-lineHeight-normal) var(--typography-fontFamily-sans);color:var(--color-text-secondary)">
|
|
268
|
+
${note}
|
|
269
|
+
</p>
|
|
270
|
+
<div style="padding-top:var(--spacing-8)">${node}</div>
|
|
271
|
+
</section>`;
|
|
272
|
+
|
|
273
|
+
export const NavigationFamily = {
|
|
274
|
+
name : 'Navigation family',
|
|
275
|
+
render: () => html`
|
|
276
|
+
<style>${tabListCSS.cssText}</style>
|
|
277
|
+
<p style="max-width:74ch;color:var(--color-text-secondary)">
|
|
278
|
+
Seven components, five responsibilities. They share a vocabulary — one focus ring,
|
|
279
|
+
one selected-underline role, one ink scale — and they are not meant to share an
|
|
280
|
+
appearance: a breadcrumb answers "where am I", a tab list answers "which panel is
|
|
281
|
+
showing", and a back control answers neither.
|
|
282
|
+
</p>
|
|
283
|
+
<div style="display:grid;gap:var(--spacing-48)">
|
|
284
|
+
${group(
|
|
285
|
+
'1 · Current location, in a set of pages',
|
|
286
|
+
'bd-page-switcher. aria-current="page". The current item is the darkest and the heaviest and carries the 3px selected underline; the others are brand blue, because they are links. Three cues, none of them colour alone.',
|
|
287
|
+
html`<bd-page-switcher .items=${NAV_ITEMS}></bd-page-switcher>`
|
|
288
|
+
)}
|
|
289
|
+
${group(
|
|
290
|
+
'2 · Current location, inside one page',
|
|
291
|
+
'bd-anchor-nav. aria-current="location" — a different claim from "page", and the reason the two do not share the attribute value. Below md the same nav becomes a disclosure: the trigger takes a control edge and the expanded panel and its chevron take the one blue that means expanded.',
|
|
292
|
+
html`<bd-anchor-nav .items=${NAV_ITEMS.map(i => ({ title: i.title, href: i.href }))}></bd-anchor-nav>`
|
|
293
|
+
)}
|
|
294
|
+
${group(
|
|
295
|
+
'3 · Path to the current location',
|
|
296
|
+
'bd-breadcrumb. aria-current="page" on the last item, which is text rather than a link. One type size across the row; the links are brand blue and the current item is default ink one weight step up. Hover adds an underline — the cue that is not colour — and at mobile widths the row becomes a stack of full-width targets.',
|
|
297
|
+
html`
|
|
298
|
+
<bd-breadcrumb>
|
|
299
|
+
<bd-breadcrumb-item href="/">Home</bd-breadcrumb-item>
|
|
300
|
+
<bd-breadcrumb-item href="/products">Products</bd-breadcrumb-item>
|
|
301
|
+
<bd-breadcrumb-item current>Total Security</bd-breadcrumb-item>
|
|
302
|
+
</bd-breadcrumb>`
|
|
303
|
+
)}
|
|
304
|
+
${group(
|
|
305
|
+
'4 · Selection, not location',
|
|
306
|
+
'bd-tab-list. role="tablist", aria-selected, roving tabindex, arrow keys. The polarity is deliberately the other way round: the unselected tabs are the actionable ones and read as brand blue, and the selected one settles to plain ink. It shares the underline role with 1 and 2 and shares nothing else, because it is not saying where you are.',
|
|
307
|
+
html`<bd-tab-list .tabs=${FAMILY_TABS} .selected=${0} label="Platform"></bd-tab-list>`
|
|
308
|
+
)}
|
|
309
|
+
${group(
|
|
310
|
+
'5 · Leaving, rather than arriving',
|
|
311
|
+
'bd-back. A button, not a link — it may call history.back() and have no href at all — so it has no current state to show and takes a control shape instead: a filled hover, a pressed state, and its own 8px corner that the focus ring follows. Below md it steps up a type size and gains vertical padding, which is the touch target growing where fingers are.',
|
|
312
|
+
html`<bd-back label="Back"></bd-back>`
|
|
313
|
+
)}
|
|
314
|
+
${group(
|
|
315
|
+
'6 · Global navigation, on the masthead',
|
|
316
|
+
'bd-footer-nav. The links here are the page\'s own anchors, slotted in, with bd-divider-vertical between them — so the composed rhythm is 33px in a row (16 either side of a 1px divider) and 16px stacked, where the declared gap is 16 at both. Tab into it: the ring is the same one, which it was not before P6C.2.',
|
|
317
|
+
html`
|
|
318
|
+
<div style="background:var(--color-blue-600);padding:var(--spacing-24) var(--spacing-16)">
|
|
319
|
+
<bd-footer-nav>
|
|
320
|
+
<a href="/legal">Legal Information</a>
|
|
321
|
+
<bd-divider-vertical></bd-divider-vertical>
|
|
322
|
+
<a href="/privacy">Privacy Policy</a>
|
|
323
|
+
<bd-divider-vertical></bd-divider-vertical>
|
|
324
|
+
<a href="/cookies">Cookies</a>
|
|
325
|
+
</bd-footer-nav>
|
|
326
|
+
</div>`
|
|
327
|
+
)}
|
|
328
|
+
</div>`,
|
|
329
|
+
parameters: {
|
|
330
|
+
layout: 'padded',
|
|
331
|
+
docs : {
|
|
332
|
+
description: {
|
|
333
|
+
story: `Read this at 375 and at 1440. Four of the six change shape between those
|
|
334
|
+
widths and each change is a different mechanism: the anchor nav swaps a row
|
|
335
|
+
of links for a disclosure, the breadcrumb swaps a row for a stack of
|
|
336
|
+
full-width targets, the footer nav drops its dividers and stacks, and the
|
|
337
|
+
back control changes type size. The page switcher and the tab list both
|
|
338
|
+
simply wrap.
|
|
339
|
+
|
|
340
|
+
What should NOT differ across the six: the focus ring, the 3px underline
|
|
341
|
+
where there is one, and the ink scale. What should: everything that follows
|
|
342
|
+
from the responsibility — whether there is a current state at all, whether
|
|
343
|
+
the item is a link or a button, and whether hover is an invitation or a
|
|
344
|
+
no-op.`
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
/* ------------------------------------------------------- feedback & status - */
|
|
351
|
+
|
|
352
|
+
const TONES = ['info', 'success', 'warning', 'error'];
|
|
353
|
+
|
|
354
|
+
export const StatusFamily = {
|
|
355
|
+
name : 'Status Family',
|
|
356
|
+
render: () => html`
|
|
357
|
+
<p style="max-width:74ch;color:var(--color-text-secondary)">
|
|
358
|
+
One message surface, one filled chip and one outlined label, carrying the same four
|
|
359
|
+
tones. Every value here is read from the shared --status-* roles rather than from the
|
|
360
|
+
palette steps those roles happen to point at today.
|
|
361
|
+
</p>
|
|
362
|
+
<div style="display:grid;gap:var(--spacing-32)">
|
|
363
|
+
<div>
|
|
364
|
+
${label('bd-alert · the feedback message: neutral ink, a 4px tone rule, --radius-md')}
|
|
365
|
+
<div style="display:grid;gap:var(--spacing-12)">
|
|
366
|
+
${TONES.map(tone => html`
|
|
367
|
+
<bd-alert tone=${tone} heading="Heading.">A message that explains what happened.</bd-alert>
|
|
368
|
+
`)}
|
|
369
|
+
</div>
|
|
370
|
+
</div>
|
|
371
|
+
<div>
|
|
372
|
+
${label('bd-badge · the filled status chip, above bd-tag · the outlined label')}
|
|
373
|
+
<div style="display:flex;flex-wrap:wrap;align-items:center;gap:var(--spacing-12)">
|
|
374
|
+
${TONES.map(tone => html`<bd-badge tone=${tone}>${tone}</bd-badge>`)}
|
|
375
|
+
</div>
|
|
376
|
+
<div style="display:flex;flex-wrap:wrap;align-items:center;gap:var(--spacing-12);margin-top:var(--spacing-12)">
|
|
377
|
+
${TONES.map(tone => html`<bd-tag tone=${tone}>${tone}</bd-tag>`)}
|
|
378
|
+
</div>
|
|
379
|
+
</div>
|
|
380
|
+
</div>`,
|
|
381
|
+
parameters: {
|
|
382
|
+
layout: 'padded',
|
|
383
|
+
docs : {
|
|
384
|
+
description: {
|
|
385
|
+
story: `Three components, four tones, one semantic system. Read down a column rather
|
|
386
|
+
than across a row: the info surface under bd-alert and the info tint under
|
|
387
|
+
bd-tag are the same value because both name \`--status-info-surface\`, not
|
|
388
|
+
because someone matched two palette steps by eye.
|
|
389
|
+
|
|
390
|
+
bd-badge and bd-tag are deliberately not identical, and P7C left both alone.
|
|
391
|
+
A tag is an outlined label — 1px \`--status-*-border\` around the plain tint.
|
|
392
|
+
A badge is a filled chip — no border, the stronger tint. Measured at 1440
|
|
393
|
+
they stand 24px and 23px tall, which is arithmetic rather than drift: the tag
|
|
394
|
+
spends its extra pixel on the border it draws. The difference you can see
|
|
395
|
+
maps to a difference that is real.
|
|
396
|
+
|
|
397
|
+
This story replaced a Banner vs Alert comparison that P6C.3 left here to put
|
|
398
|
+
a decision in front of a person. P7C answered it, and bd-banner was retired.
|
|
399
|
+
It was not in \`package.json\` exports and not in the component manifest, so
|
|
400
|
+
it was never part of the published surface; it had no consumer anywhere in
|
|
401
|
+
this repository outside its own stories; its first commit is titled "banner
|
|
402
|
+
component for testing"; and it drew the same four tinted surfaces as bd-alert
|
|
403
|
+
by naming \`--color-blue-50\` and its neighbours directly. That last point is
|
|
404
|
+
what made it worth removing rather than polishing. Retinting
|
|
405
|
+
\`--status-info-surface\` would have moved bd-alert, bd-tag and bd-badge and
|
|
406
|
+
left bd-banner behind, so the duplication was not only visual — it was
|
|
407
|
+
invisible to the token system that is supposed to hold this family together.`
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
|
|
3
|
+
/** Styled entirely from design tokens — see npm run lint:tokens. */
|
|
4
|
+
export const visuallyHiddenCSS = css`
|
|
5
|
+
/* Removed from view but kept in the accessibility tree. Not display:none,
|
|
6
|
+
which would remove it from the tree as well. */
|
|
7
|
+
:host {
|
|
8
|
+
position: absolute;
|
|
9
|
+
/* no token: 1px is the clip idiom's own measure, not a border. It was
|
|
10
|
+
spelled --border-width-1, which resolves to the same pixel and reads as
|
|
11
|
+
a category error — the lint already sanctions the literal here, as it
|
|
12
|
+
does the -1px below. */
|
|
13
|
+
width: 1px;
|
|
14
|
+
height: 1px;
|
|
15
|
+
margin: -1px;
|
|
16
|
+
padding: 0;
|
|
17
|
+
overflow: hidden;
|
|
18
|
+
clip-path: inset(50%);
|
|
19
|
+
white-space: nowrap;
|
|
20
|
+
border: 0;
|
|
21
|
+
}
|
|
22
|
+
`;
|
|
23
|
+
|
|
24
|
+
export default visuallyHiddenCSS;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { LitElement, html } from 'lit';
|
|
2
|
+
// Installs the design tokens into document scope; see src/tokens/tokens.js
|
|
3
|
+
import '../../tokens/tokens.js';
|
|
4
|
+
import { visuallyHiddenCSS } from './visually-hidden.css.js';
|
|
5
|
+
|
|
6
|
+
export class BdVisuallyHidden extends LitElement {
|
|
7
|
+
static styles = [visuallyHiddenCSS];
|
|
8
|
+
|
|
9
|
+
render() {
|
|
10
|
+
return html`
|
|
11
|
+
<slot></slot>
|
|
12
|
+
`;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
customElements.define('bd-visually-hidden', BdVisuallyHidden);
|