@repobit/dex-system-design 0.25.11 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +195 -0
- package/README.md +131 -8
- package/package.json +95 -13
- package/schemas/component-manifest.json +3294 -405
- package/schemas/manifest-omissions.json +173 -0
- package/src/blog/src/breakpoints.js +6 -6
- package/src/blog/src/content/blog-atoms-showcase.js +1 -1
- package/src/blog/src/content/blog-page-layout.js +2 -2
- package/src/blog/src/lib/article-toc.js +7 -7
- package/src/blog/src/shell/blog-shell.js +1 -1
- package/src/blog/src/tokens/blog.js +2 -2
- package/src/blog/src/tokens/core.js +34 -35
- package/src/blog/src/tokens/legacy.js +0 -9
- package/src/blog/tokens/blog.js +2 -2
- package/src/blog/tokens/core.js +34 -35
- package/src/blog/tokens/legacy.js +0 -9
- package/src/blog/tokens.css +36 -46
- package/src/components/accordion/accordion-bg.css.js +83 -59
- package/src/components/accordion/accordion-bg.js +29 -10
- package/src/components/accordion/accordion-bg.stories.js +67 -67
- package/src/components/accordion/accordion-keyboard.js +80 -0
- package/src/components/accordion/accordion.css.js +142 -80
- package/src/components/accordion/accordion.js +37 -10
- package/src/components/accordion/accordion.stories.js +7 -7
- package/src/components/agent-endpoints/agent-endpoints.css.js +36 -39
- package/src/components/agent-endpoints/agent-endpoints.js +30 -20
- package/src/components/agent-endpoints/agent-endpoints.stories.js +1 -1
- package/src/components/ai-guardian-demo.stories.js +91 -91
- package/src/components/alert/alert.css.js +198 -0
- package/src/components/alert/alert.js +103 -0
- package/src/components/alert/alert.stories.js +206 -0
- package/src/components/anchor/anchor-nav.css.js +213 -101
- package/src/components/anchor/anchor-nav.js +26 -40
- package/src/components/anchor/anchor.stories.js +22 -12
- package/src/components/annotation/annotation.css.js +58 -0
- package/src/components/annotation/annotation.js +67 -0
- package/src/components/annotation/annotation.stories.js +63 -0
- package/src/components/architecture.stories.js +285 -0
- package/src/components/atoms.stories.js +342 -0
- package/src/components/avatar/avatar.css.js +67 -0
- package/src/components/avatar/avatar.js +42 -0
- package/src/components/avatar/avatar.stories.js +95 -0
- package/src/components/awards/awards-flex.css.js +209 -23
- package/src/components/awards/awards-flex.js +66 -7
- package/src/components/awards/awards-flex.stories.js +1 -1
- package/src/components/awards/{awards-light.stories.js → awards-summary.stories.js} +54 -64
- package/src/components/awards/awards.css.js +116 -58
- package/src/components/awards/awards.js +102 -28
- package/src/components/awards/awards.stories.js +1 -1
- package/src/components/back/back.css.js +51 -22
- package/src/components/back/back.js +28 -7
- package/src/components/back/back.stories.js +9 -3
- package/src/components/badge/badge.css.js +158 -46
- package/src/components/badge/badge.js +62 -74
- package/src/components/badge/badge.stories.js +176 -248
- package/src/components/bento-grid/bento-grid.css.js +21 -16
- package/src/components/bento-grid/bento-grid.js +16 -4
- package/src/components/bento-grid/bento-grid.stories.js +19 -18
- package/src/components/bento-grid/bento-item.css.js +52 -28
- package/src/components/bento-grid/bento-item.js +2 -2
- package/src/components/blockquote/blockquote.css.js +47 -0
- package/src/components/blockquote/blockquote.js +29 -0
- package/src/components/blockquote/blockquote.stories.js +62 -0
- package/src/components/breadcrumb/breadcrumb.css.js +92 -22
- package/src/components/breadcrumb/breadcrumb.js +56 -11
- package/src/components/button/button.css.js +531 -161
- package/src/components/button/button.js +206 -214
- package/src/components/button/button.stories.js +322 -174
- package/src/components/caption/caption.css.js +21 -0
- package/src/components/caption/caption.js +31 -0
- package/src/components/caption/caption.stories.js +62 -0
- package/src/components/card-features/card-features.css.js +14 -22
- package/src/components/card-features/card-features.js +68 -9
- package/src/components/card-features/card-features.stories.js +11 -11
- package/src/components/cards/card.css.js +60 -81
- package/src/components/cards/card.js +56 -25
- package/src/components/cards/card.stories.js +39 -39
- package/src/components/carousel/carousel.css.js +93 -99
- package/src/components/carousel/carousel.js +32 -4
- package/src/components/checkbox/checkbox.css.js +111 -93
- package/src/components/checkbox/checkbox.js +64 -90
- package/src/components/checkbox/checkbox.stories.js +96 -29
- package/src/components/code/code.css.js +70 -0
- package/src/components/code/code.js +40 -0
- package/src/components/code/code.stories.js +73 -0
- package/src/components/compare/compare.css.js +179 -43
- package/src/components/compare/compare.js +52 -25
- package/src/components/compare/compare.stories.js +61 -4
- package/src/components/comparison-panel/comparison-panel.css.js +38 -51
- package/src/components/comparison-panel/comparison-panel.js +5 -4
- package/src/components/comparison-panel/comparison-panel.stories.js +1 -1
- package/src/components/compatibility-table/compatibility-table.css.js +180 -80
- package/src/components/compatibility-table/compatibility-table.js +37 -9
- package/src/components/control-alignment.stories.js +393 -0
- package/src/components/cta-banner/cta-banner.css.js +41 -13
- package/src/components/cta-banner/cta-banner.js +6 -5
- package/src/components/cta-banner/cta-banner.stories.js +43 -98
- package/src/components/display/display.css.js +25 -1
- package/src/components/display/display.js +46 -13
- package/src/components/display/display.stories.js +270 -40
- package/src/components/divider/divider-horizontal.js +21 -5
- package/src/components/divider/divider-vertical.js +15 -7
- package/src/components/divider/divider.css.js +2 -2
- package/src/components/divider/divider.stories.js +38 -34
- package/src/components/dropdown/dropdown.css.js +93 -126
- package/src/components/dropdown/dropdown.js +114 -34
- package/src/components/dropdown/dropdown.stories.js +56 -24
- package/src/components/features/features.css.js +24 -11
- package/src/components/features/features.js +7 -3
- package/src/components/features/features.stories.js +37 -37
- package/src/components/features-tab/features-tab.css.js +19 -8
- package/src/components/features-tab/features-tab.js +6 -5
- package/src/components/features-tab/features-tab.stories.js +23 -23
- package/src/components/fieldset/fieldset.css.js +30 -0
- package/src/components/fieldset/fieldset.js +28 -0
- package/src/components/fieldset/fieldset.stories.js +84 -0
- package/src/components/footer/footer-links-group.css.js +10 -14
- package/src/components/footer/footer-links-group.js +4 -3
- package/src/components/footer/footer-lp.css.js +59 -30
- package/src/components/footer/footer-lp.js +17 -12
- package/src/components/footer/footer-lp.stories.js +63 -75
- package/src/components/footer/footer-nav-menu.css.js +26 -4
- package/src/components/footer/footer-nav-menu.js +3 -2
- package/src/components/footer/footer.css.js +146 -264
- package/src/components/footer/footer.js +176 -106
- package/src/components/footer/footer.stories.js +9 -9
- package/src/components/footer/localeMap.js +1 -1
- package/src/components/grid/grid.css.js +1 -1
- package/src/components/grid/grid.js +49 -7
- package/src/components/grid/grid.stories.js +111 -0
- package/src/components/header/header-code.css.js +61 -51
- package/src/components/header/header-code.js +28 -14
- package/src/components/header/header-code.stories.js +5 -5
- package/src/components/header/header.css.js +655 -176
- package/src/components/header/header.js +269 -36
- package/src/components/header/header.stories.js +841 -18
- package/src/components/heading/heading.css.js +14 -17
- package/src/components/heading/heading.js +48 -33
- package/src/components/heading/heading.stories.js +27 -25
- package/src/components/help-text/help-text.css.js +21 -0
- package/src/components/help-text/help-text.js +25 -0
- package/src/components/help-text/help-text.stories.js +66 -0
- package/src/components/highlight/highlight.css.js +86 -64
- package/src/components/highlight/highlight.js +18 -27
- package/src/components/highlight/highlight.stories.js +14 -3
- package/src/components/icons/analysis-icon.js +6 -16
- package/src/components/icons/arrow-down-icon.js +6 -19
- package/src/components/icons/arrow-icon.js +44 -0
- package/src/components/icons/arrow-right-icon.js +30 -23
- package/src/components/icons/arrow-up-icon.js +19 -18
- package/src/components/icons/bd-ai-icon.js +1 -1
- package/src/components/icons/brand-marks.stories.js +279 -0
- package/src/components/icons/brand-signature-icon.js +42 -0
- package/src/components/icons/check-icon.js +27 -0
- package/src/components/icons/circle-info-icon.js +33 -0
- package/src/components/icons/close-icon.js +6 -18
- package/src/components/icons/family-icon.js +8 -20
- package/src/components/icons/globe-icon.js +6 -18
- package/src/components/icons/guide-icon.js +6 -18
- package/src/components/icons/icon-element.js +99 -0
- package/src/components/icons/icons.js +36 -0
- package/src/components/icons/icons.stories.js +184 -52
- package/src/components/icons/individual-icon.js +6 -18
- package/src/components/icons/laurel-icon.js +9 -19
- package/src/components/icons/machine-learning-icon.js +6 -17
- package/src/components/icons/marks.js +41 -0
- package/src/components/icons/minus-icon.js +7 -21
- package/src/components/icons/missing-icon.js +52 -0
- package/src/components/icons/plus-icon.js +7 -21
- package/src/components/icons/quote-icon.js +19 -19
- package/src/components/image/image.css.js +72 -25
- package/src/components/image/image.js +11 -6
- package/src/components/image/image.stories.js +2 -2
- package/src/components/input/custom-form.stories.js +214 -62
- package/src/components/input/input-clipboard.css.js +51 -144
- package/src/components/input/input-clipboard.js +31 -15
- package/src/components/input/input.css.js +8 -146
- package/src/components/input/input.js +93 -38
- package/src/components/install-options/install-options.css.js +84 -77
- package/src/components/install-options/install-options.js +33 -30
- package/src/components/install-options/install-options.stories.js +3 -3
- package/src/components/label/label.css.js +35 -0
- package/src/components/label/label.js +38 -0
- package/src/components/label/label.stories.js +82 -0
- package/src/components/light-carousel/light-carousel.css.js +111 -63
- package/src/components/light-carousel/light-carousel.js +85 -11
- package/src/components/light-carousel/light-carousel.stories.js +126 -82
- package/src/components/link/link.css.js +150 -99
- package/src/components/link/link.js +86 -11
- package/src/components/link/link.stories.js +124 -30
- package/src/components/list/list-item/list-item.css.js +74 -22
- package/src/components/list/list-item/list-item.js +32 -10
- package/src/components/list/list-item/list-item.stories.js +23 -23
- package/src/components/list/list.css.js +8 -2
- package/src/components/list/list.js +3 -2
- package/src/components/list/list.stories.js +222 -0
- package/src/components/modal/modal.css.js +114 -24
- package/src/components/modal/modal.js +83 -7
- package/src/components/modal/modal.stories.js +9 -9
- package/src/components/overview/overview.css.js +19 -14
- package/src/components/overview/overview.js +6 -5
- package/src/components/overview/overview.stories.js +10 -10
- package/src/components/page-switcher/page-switcher.css.js +97 -40
- package/src/components/page-switcher/page-switcher.js +28 -5
- package/src/components/page-switcher/page-switcher.stories.js +95 -0
- package/src/components/paragraph/paragraph.css.js +15 -10
- package/src/components/paragraph/paragraph.js +41 -44
- package/src/components/paragraph/paragraph.stories.js +56 -21
- package/src/components/picture/picture.css.js +103 -44
- package/src/components/picture/picture.js +100 -30
- package/src/components/picture/picture.stories.js +1 -1
- package/src/components/pricing-cards/new-pricing-card.js +3 -3
- package/src/components/pricing-cards/new-pricing.css.js +24 -15
- package/src/components/pricing-cards/pricing-card-actions.css.js +1 -1
- package/src/components/pricing-cards/pricing-card-actions.js +3 -4
- package/src/components/pricing-cards/pricing-card-container.css.js +3 -3
- package/src/components/pricing-cards/pricing-card-container.js +3 -2
- package/src/components/pricing-cards/pricing-card-header.css.js +10 -8
- package/src/components/pricing-cards/pricing-card-header.js +6 -7
- package/src/components/pricing-cards/pricing-card-pricing.css.js +16 -9
- package/src/components/pricing-cards/pricing-card-pricing.js +8 -6
- package/src/components/pricing-cards/pricing-card-show-more.css.js +11 -3
- package/src/components/pricing-cards/pricing-card-show-more.js +8 -3
- package/src/components/pricing-cards/pricing-card.css.js +244 -190
- package/src/components/pricing-cards/pricing-card.js +54 -70
- package/src/components/pricing-cards/pricing-feature-item.css.js +25 -8
- package/src/components/pricing-cards/pricing-feature-item.js +8 -3
- package/src/components/process-steps/process-steps.css.js +26 -14
- package/src/components/process-steps/process-steps.js +23 -6
- package/src/components/process-steps/process-steps.stories.js +1 -1
- package/src/components/progress/progress.css.js +80 -0
- package/src/components/progress/progress.js +42 -0
- package/src/components/progress/progress.stories.js +79 -0
- package/src/components/quick-answer/quick-answer.css.js +75 -13
- package/src/components/quick-answer/quick-answer.js +8 -3
- package/src/components/radio/radio.css.js +92 -128
- package/src/components/radio/radio.js +106 -127
- package/src/components/radio/radio.stories.js +54 -19
- package/src/components/review/review-grid.css.js +5 -6
- package/src/components/review/review-grid.js +14 -11
- package/src/components/review/review.css.js +11 -6
- package/src/components/review/review.js +3 -8
- package/src/components/shared/ensemble.css.js +93 -0
- package/src/components/shared/form-field.css.js +206 -0
- package/src/components/shared/prop-vocabulary.js +48 -0
- package/src/components/shared/token-scales.js +306 -0
- package/src/components/skeleton/skeleton.css.js +34 -0
- package/src/components/skeleton/skeleton.js +32 -0
- package/src/components/skeleton/skeleton.stories.js +70 -0
- package/src/components/spinner/spinner.css.js +62 -0
- package/src/components/spinner/spinner.js +38 -0
- package/src/components/spinner/spinner.stories.js +92 -0
- package/src/components/spotlight-section/spotlight-section.css.js +14 -13
- package/src/components/spotlight-section/spotlight-section.js +42 -39
- package/src/components/switch/switch.css.js +103 -0
- package/src/components/switch/switch.js +44 -0
- package/src/components/switch/switch.stories.js +86 -0
- package/src/components/tab-list/content-switcher.stories.js +189 -0
- package/src/components/tab-list/tab-list.css.js +250 -0
- package/src/components/tab-list/tab-list.js +184 -0
- package/src/components/tab-list/tab-list.stories.js +221 -0
- package/src/components/tabs/tabs.css.js +14 -123
- package/src/components/tabs/tabs.js +16 -19
- package/src/components/tabs/tabs.stories.js +95 -95
- package/src/components/tag/tag.css.js +54 -0
- package/src/components/tag/tag.js +32 -0
- package/src/components/tag/tag.stories.js +126 -0
- package/src/components/terminal/terminal-message.css.js +164 -60
- package/src/components/terminal/terminal-message.js +5 -5
- package/src/components/terminal/terminal-message.stories.js +70 -1
- package/src/components/termsOfUse/terms.css.js +25 -20
- package/src/components/termsOfUse/terms.js +13 -9
- package/src/components/termsOfUse/terms.stories.js +1 -1
- package/src/components/textarea/textarea.css.js +51 -0
- package/src/components/textarea/textarea.js +136 -0
- package/src/components/textarea/textarea.stories.js +191 -0
- package/src/components/tooltip/tooltip.css.js +75 -0
- package/src/components/tooltip/tooltip.js +156 -0
- package/src/components/tooltip/tooltip.stories.js +161 -0
- package/src/components/trust-panel/trust-panel.css.js +85 -33
- package/src/components/trust-panel/trust-panel.js +18 -10
- package/src/components/trust-panel/trust-panel.stories.js +1 -1
- package/src/components/ultimate-security-demo.stories.js +431 -0
- package/src/components/video/video.css.js +17 -0
- package/src/components/video/video.js +40 -0
- package/src/components/video/video.stories.js +106 -0
- package/src/components/video-player/video-player.css.js +67 -11
- package/src/components/video-player/video-player.js +35 -4
- package/src/components/video-player/video-player.stories.js +1 -1
- package/src/components/visual-alignment.stories.js +411 -0
- package/src/components/visually-hidden/visually-hidden.css.js +24 -0
- package/src/components/visually-hidden/visually-hidden.js +16 -0
- package/src/components/visually-hidden/visually-hidden.stories.js +56 -0
- package/src/stories/Button.stories.js +17 -17
- package/src/stories/Header.stories.js +10 -10
- package/src/stories/Page.js +1 -1
- package/src/stories/Page.stories.js +6 -6
- package/src/tokens/borders.stories.js +339 -0
- package/src/tokens/color-responsibilities.stories.js +227 -0
- package/src/tokens/dark-derivation.js +309 -0
- package/src/tokens/dark-findings.js +197 -0
- package/src/tokens/dark-mode.stories.js +207 -0
- package/src/tokens/dimension.stories.js +251 -0
- package/src/tokens/elevation.stories.js +143 -0
- package/src/tokens/focus.stories.js +276 -0
- package/src/tokens/fonts.css +20 -20
- package/src/tokens/fonts.stories.js +354 -374
- package/src/tokens/layout.css +25 -11
- package/src/tokens/motion.stories.js +231 -0
- package/src/tokens/shape.stories.js +272 -0
- package/src/tokens/spacing-rhythm.stories.js +359 -0
- package/src/tokens/spacing.stories.js +208 -703
- package/src/tokens/story-chrome.js +503 -0
- package/src/tokens/surfaces.stories.js +224 -0
- package/src/tokens/text-on-surface.stories.js +164 -0
- package/src/tokens/token-map.js +220 -0
- package/src/tokens/token-map.stories.js +257 -0
- package/src/tokens/token-purposes.js +266 -0
- package/src/tokens/tokens-grid.stories.js +388 -900
- package/src/tokens/tokens.css +1633 -1045
- package/src/tokens/tokens.js +1130 -492
- package/src/tokens/tokens.stories.js +137 -47
- package/src/tokens/type-ceiling-words.js +299 -0
- package/src/tokens/typography.stories.js +1003 -965
- package/src/tokens/vertical-rhythm.stories.js +224 -0
- package/src/components/awards/awards-icon.js +0 -56
- package/src/components/awards/awards-light.js +0 -240
- package/src/components/banner/banner.js +0 -60
- package/src/components/banner/banner.stories.js +0 -51
- package/src/components/button/icons.js +0 -24
- package/src/components/input/index.js +0 -0
- package/src/components/light-carousel/light-carousel-simple.css.js +0 -183
- package/src/components/light-carousel/light-carousel-simple.js +0 -74
- package/src/tokens/colors.js +0 -121
- package/src/tokens/typography.css.js +0 -207
- package/src/tokens/typography.js +0 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Styled entirely from design tokens -- see npm run lint:tokens.
|
|
5
|
+
*
|
|
6
|
+
* Reshaped 2026-09-14 to the Eclipse Alert banner (Figma yzCimjlQG7RzokkgVpjfnZ
|
|
7
|
+
* node 5021:11630), using this package's roles rather than that file's
|
|
8
|
+
* variables. The two systems turn out to share ancestry: three of the five
|
|
9
|
+
* tints matched byte-for-byte (blue f0f7ff, green edfdf1, red fff0f0), the type
|
|
10
|
+
* size matched at 14px, and the radius, gaps and padding all landed on our
|
|
11
|
+
* existing scales -- radius/small 8px IS --radius-lg, and 16/12/8 are
|
|
12
|
+
* --spacing-16/12/8.
|
|
13
|
+
*
|
|
14
|
+
* Two places the design and this package disagree, both resolved our way
|
|
15
|
+
* because our tokens are the brief:
|
|
16
|
+
*
|
|
17
|
+
* warning tint the design is fff6f0, an orange; --status-warning-surface is
|
|
18
|
+
* fffbf0, a yellow. Ours. Worth knowing that warning is the
|
|
19
|
+
* tightest of the six: its accent reads 3.49:1 on its own
|
|
20
|
+
* tint where every other tone clears 4.2, so a future change
|
|
21
|
+
* to either half has least room here.
|
|
22
|
+
* actions ink the design is 0045ad; --color-text-brand is blue-600
|
|
23
|
+
* 0059d6. Ours, and blue-600 is the documented choice for ink
|
|
24
|
+
* on a tint -- CLAUDE.md records blue-500 as failing there.
|
|
25
|
+
*
|
|
26
|
+
* THE LEFT ACCENT RULE IS GONE. This atom carried a 4px border-left in the
|
|
27
|
+
* tone's accent colour; the design is tint-only, with a full border on the
|
|
28
|
+
* outline variant instead. That is a visible change to a shipped atom and it
|
|
29
|
+
* was asked for. The invariant the old rule existed to keep -- that an alert
|
|
30
|
+
* and a bd-badge of the same tone are the same colour by construction, because
|
|
31
|
+
* both read --status-<tone>-accent -- survives, because the icon now carries
|
|
32
|
+
* it.
|
|
33
|
+
*
|
|
34
|
+
* EVERY COMBINATION WAS MEASURED, not assumed: title and description
|
|
35
|
+
* (--color-text-primary) run 16.03 to 17.97:1 across the six grounds, the
|
|
36
|
+
* actions ink 5.51 to 6.18, and the tone accents 3.49 to 8.39 against the 3:1
|
|
37
|
+
* non-text bar. No pair needed a compromise.
|
|
38
|
+
*/
|
|
39
|
+
export const alertCSS = css`
|
|
40
|
+
:host {
|
|
41
|
+
display: block;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* The native hidden attribute has to beat the display above, or a consumer
|
|
45
|
+
writing <bd-alert hidden> gets a visible alert. Same fix as
|
|
46
|
+
icons/icon-element.js. */
|
|
47
|
+
:host([hidden]) {
|
|
48
|
+
display: none;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.alert {
|
|
52
|
+
display: flex;
|
|
53
|
+
align-items: flex-start;
|
|
54
|
+
gap: var(--spacing-12);
|
|
55
|
+
padding: var(--spacing-16);
|
|
56
|
+
border-radius: var(--radius-lg);
|
|
57
|
+
font-family: var(--typography-fontFamily-sans);
|
|
58
|
+
/* Set ONCE, here. The title differs from the description by weight only,
|
|
59
|
+
which is what the design does too -- Body/medium/semibold over
|
|
60
|
+
Body/medium/regular, both 14px -- so nothing below re-declares a size.
|
|
61
|
+
.
|
|
62
|
+
THE LEADING IS DELIBERATELY NOT THE DESIGN'S. The design specifies 20px;
|
|
63
|
+
this resolves to 1.45, which computes to 20.3px at 14px. Confirmed 2026-09-14
|
|
64
|
+
to stay as it is: a unitless ratio is the first rule of this package's
|
|
65
|
+
typography contract, because an absolute 20px stops scaling when a reader
|
|
66
|
+
enlarges their text, which is the defect the rule exists to prevent. The
|
|
67
|
+
0.3px is the price of keeping it. 1.45 also clears the Plex leading floor
|
|
68
|
+
that Romanian diacritics need, so there is no clipping risk in dropping
|
|
69
|
+
toward the design's figure -- but there is no reason to. */
|
|
70
|
+
font-size: var(--typography-body-small-fontSize);
|
|
71
|
+
line-height: var(--typography-body-small-lineHeight);
|
|
72
|
+
color: var(--color-text-primary);
|
|
73
|
+
background: var(--status-info-surface);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* The tone sets the ground and the icon's ink in one place, so the two cannot
|
|
77
|
+
drift apart. The icon reads currentColor from .icon, which is the rule the
|
|
78
|
+
icon atoms already follow. */
|
|
79
|
+
.icon {
|
|
80
|
+
flex: none;
|
|
81
|
+
display: flex;
|
|
82
|
+
color: var(--status-info-accent);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
:host([tone='success']) .alert {
|
|
86
|
+
background: var(--status-success-surface);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
:host([tone='success']) .icon {
|
|
90
|
+
color: var(--status-success-accent);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
:host([tone='warning']) .alert {
|
|
94
|
+
background: var(--status-warning-surface);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
:host([tone='warning']) .icon {
|
|
98
|
+
color: var(--status-warning-accent);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
:host([tone='error']) .alert {
|
|
102
|
+
background: var(--status-error-surface);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
:host([tone='error']) .icon {
|
|
106
|
+
color: var(--status-error-accent);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
:host([tone='neutral']) .alert {
|
|
110
|
+
background: var(--status-neutral-surface);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
:host([tone='neutral']) .icon {
|
|
114
|
+
color: var(--status-neutral-accent);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/* The outline variant is a SURFACE treatment, not a tone: it keeps whichever
|
|
118
|
+
tone's icon is set and drops the tint for the page ground plus an edge.
|
|
119
|
+
That is why it is its own attribute rather than a sixth tone -- the design
|
|
120
|
+
models both axes in one enum, and folding a surface choice into the status
|
|
121
|
+
vocabulary is the category error CLAUDE.md names.
|
|
122
|
+
.
|
|
123
|
+
The edge takes --color-border-container, the role for a self-contained
|
|
124
|
+
object's boundary, which is what this is. The design spells it
|
|
125
|
+
rgba(0,0,0,0.1); the role is neutral-100 and within a shade of it. */
|
|
126
|
+
:host([variant='outline']) .alert {
|
|
127
|
+
background: var(--color-surface-default);
|
|
128
|
+
border: var(--border-width-1) solid var(--color-border-container);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.content {
|
|
132
|
+
flex: 1 1 auto;
|
|
133
|
+
min-width: 0;
|
|
134
|
+
display: flex;
|
|
135
|
+
flex-direction: column;
|
|
136
|
+
gap: var(--spacing-8);
|
|
137
|
+
overflow-wrap: break-word;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/* no role: the title's weight. Semibold at 14px is not a role this package
|
|
141
|
+
has -- body-small is 400, label-default and control-label-default are 500 --
|
|
142
|
+
and the element is doing the work a role would name. It stays a strong so
|
|
143
|
+
the emphasis is in the markup rather than in a class, which is the same
|
|
144
|
+
argument button.css.js's .button--bold makes.
|
|
145
|
+
.
|
|
146
|
+
The value is deliberate and not the UA default: strong renders at bolder
|
|
147
|
+
(700), and semibold keeps an alert title from shouting inside a status
|
|
148
|
+
strip. The design agrees -- Body/medium/semibold. */
|
|
149
|
+
.title { font-weight: var(--typography-fontWeight-semibold); }
|
|
150
|
+
|
|
151
|
+
/* The design gives the description a 24px floor so a one-line alert has the
|
|
152
|
+
same height as the icon beside it and the row does not look top-heavy. */
|
|
153
|
+
.body {
|
|
154
|
+
min-height: var(--icon-lg-size);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/* Each action is its own flex item, so the gap needs each one slotted
|
|
158
|
+
separately -- wrapping several in one span makes them a single item and
|
|
159
|
+
they run together with no space. The stories show the right shape.
|
|
160
|
+
.
|
|
161
|
+
The colour here is a DEFAULT, not the source of the action ink: bd-link
|
|
162
|
+
and bd-button both set their own, so in normal use this never paints. It
|
|
163
|
+
is kept so a bare anchor or a run of text slotted here gets brand ink
|
|
164
|
+
rather than the UA's blue, which is the only case it applies to. Do not go
|
|
165
|
+
looking here for why an action is the colour it is -- look at the atom. */
|
|
166
|
+
.actions {
|
|
167
|
+
display: flex;
|
|
168
|
+
flex-wrap: wrap;
|
|
169
|
+
align-items: center;
|
|
170
|
+
gap: var(--spacing-12);
|
|
171
|
+
color: var(--color-text-brand);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/* Rendered only when something is slotted in, so an alert without actions
|
|
175
|
+
does not carry an empty row and the gap above it. */
|
|
176
|
+
.actions[hidden] {
|
|
177
|
+
display: none;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.dismiss {
|
|
181
|
+
flex: none;
|
|
182
|
+
display: flex;
|
|
183
|
+
padding: var(--spacing-0);
|
|
184
|
+
border: none;
|
|
185
|
+
background: none;
|
|
186
|
+
color: var(--color-text-muted);
|
|
187
|
+
border-radius: var(--focus-outline-radius);
|
|
188
|
+
cursor: pointer;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/* One token, one painter -- the same invariant accordion.css.js records. */
|
|
192
|
+
.dismiss:focus-visible {
|
|
193
|
+
outline: none;
|
|
194
|
+
box-shadow: var(--focus-outline-primary);
|
|
195
|
+
}
|
|
196
|
+
`;
|
|
197
|
+
|
|
198
|
+
export default alertCSS;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { LitElement, html, nothing } from 'lit';
|
|
2
|
+
// Installs the design tokens into document scope; see src/tokens/tokens.js
|
|
3
|
+
import '../../tokens/tokens.js';
|
|
4
|
+
import '../icons/circle-info-icon.js';
|
|
5
|
+
import '../icons/close-icon.js';
|
|
6
|
+
import { alertCSS } from './alert.css.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A status banner: an icon, a title, a description, optional actions, and an
|
|
10
|
+
* optional dismiss.
|
|
11
|
+
*
|
|
12
|
+
* Shaped to the Eclipse Alert banner (Figma yzCimjlQG7RzokkgVpjfnZ node
|
|
13
|
+
* 5021:11630) with this package's roles. See alert.css.js for what the two
|
|
14
|
+
* systems agreed on and the two places they did not.
|
|
15
|
+
*
|
|
16
|
+
* TWO AXES, NOT ONE. The design models six values of a single `type` enum:
|
|
17
|
+
* Information, Success, Danger, Warning, Neutral and Outline. Five of those are
|
|
18
|
+
* statuses and one is a surface treatment, so this element keeps them apart --
|
|
19
|
+
* `tone` for the status, `variant` for the treatment. An outline alert still
|
|
20
|
+
* has a tone, and folding the two into one attribute would mean
|
|
21
|
+
* tone="outline", which says nothing about what the alert is telling you.
|
|
22
|
+
*
|
|
23
|
+
* THE LEADING ICON. bd-circle-info-icon, the glyph the design asked for. It
|
|
24
|
+
* was a bd-missing-icon placeholder from the day this component was built --
|
|
25
|
+
* a visible dashed box that check:icons reported as owed -- which is the
|
|
26
|
+
* recorded process for an icon we need and have not drawn: no font glyph, no
|
|
27
|
+
* inline path, no silent omission. The artwork arrived from Eclipse and the
|
|
28
|
+
* placeholder is gone. Pass your own through the icon slot to override it.
|
|
29
|
+
*/
|
|
30
|
+
export class BdAlert extends LitElement {
|
|
31
|
+
static styles = [alertCSS];
|
|
32
|
+
|
|
33
|
+
static properties = {
|
|
34
|
+
/** info | success | warning | error | neutral */
|
|
35
|
+
tone : { type: String, reflect: true },
|
|
36
|
+
/** tint (default) | outline */
|
|
37
|
+
variant : { type: String, reflect: true },
|
|
38
|
+
heading : { type: String },
|
|
39
|
+
dismissible : { type: Boolean, reflect: true },
|
|
40
|
+
/** The dismiss button's accessible name, overridable per context. */
|
|
41
|
+
dismisslabel: { type: String },
|
|
42
|
+
_hasActions : { state: true }
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
constructor() {
|
|
46
|
+
super();
|
|
47
|
+
this.tone = 'info';
|
|
48
|
+
this.variant = 'tint';
|
|
49
|
+
this.heading = '';
|
|
50
|
+
this.dismissible = false;
|
|
51
|
+
this.dismisslabel = 'Dismiss alert';
|
|
52
|
+
this._hasActions = false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* The actions row is only rendered when something is slotted into it, so an
|
|
56
|
+
alert without actions does not carry an empty row and the gap above it.
|
|
57
|
+
Read from the slot rather than from a querySelector at render time, so it
|
|
58
|
+
stays right when a consumer adds or removes actions later. */
|
|
59
|
+
_onActionsSlotChange(event) {
|
|
60
|
+
this._hasActions = event.target.assignedNodes({ flatten: true })
|
|
61
|
+
.some(n => n.nodeType === Node.ELEMENT_NODE || n.textContent.trim());
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
_onDismiss() {
|
|
65
|
+
/* The element does not remove itself: what should happen to the space it
|
|
66
|
+
occupied is the page's decision, not the atom's. */
|
|
67
|
+
this.dispatchEvent(new CustomEvent('bd-dismiss', { bubbles: true, composed: true }));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
render() {
|
|
71
|
+
return html`
|
|
72
|
+
<div class="alert" role=${this.tone === 'error' ? 'alert' : 'status'}>
|
|
73
|
+
<span class="icon">
|
|
74
|
+
<slot name="icon">
|
|
75
|
+
<bd-circle-info-icon size="lg"></bd-circle-info-icon>
|
|
76
|
+
</slot>
|
|
77
|
+
</span>
|
|
78
|
+
|
|
79
|
+
<div class="content">
|
|
80
|
+
${this.heading ? html`<strong class="title">${this.heading}</strong>` : nothing}
|
|
81
|
+
<div class="body"><slot></slot></div>
|
|
82
|
+
<div class="actions" ?hidden=${!this._hasActions}>
|
|
83
|
+
<slot name="actions" @slotchange=${this._onActionsSlotChange}></slot>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
${this.dismissible
|
|
88
|
+
? html`
|
|
89
|
+
<button
|
|
90
|
+
class="dismiss"
|
|
91
|
+
type="button"
|
|
92
|
+
aria-label=${this.dismisslabel}
|
|
93
|
+
@click=${this._onDismiss}
|
|
94
|
+
>
|
|
95
|
+
<bd-close-icon size="sm"></bd-close-icon>
|
|
96
|
+
</button>`
|
|
97
|
+
: nothing}
|
|
98
|
+
</div>
|
|
99
|
+
`;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
customElements.define('bd-alert', BdAlert);
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
import './alert.js';
|
|
3
|
+
import '../link/link.js';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
title : 'Atoms/Alert',
|
|
7
|
+
tags : ['autodocs'],
|
|
8
|
+
parameters: {
|
|
9
|
+
docs: {
|
|
10
|
+
description: {
|
|
11
|
+
component: `
|
|
12
|
+
**BdAlert** is an inline message about the state of something on the page. It
|
|
13
|
+
belongs in the flow, next to whatever it describes — it is not a toast or a
|
|
14
|
+
dialog.
|
|
15
|
+
|
|
16
|
+
### Usage
|
|
17
|
+
\`\`\`html
|
|
18
|
+
<bd-alert>Your subscription renews on 12 March.</bd-alert>
|
|
19
|
+
<bd-alert tone="success" heading="Payment received">A receipt is on its way.</bd-alert>
|
|
20
|
+
<bd-alert tone="error" heading="Card declined">Check the expiry date and try again.</bd-alert>
|
|
21
|
+
|
|
22
|
+
<bd-alert variant="outline" heading="On a tinted page">
|
|
23
|
+
Drops the tint for the page ground and an edge.
|
|
24
|
+
</bd-alert>
|
|
25
|
+
|
|
26
|
+
<bd-alert tone="warning" heading="Two devices are out of date." dismissible>
|
|
27
|
+
Windows Defender is still handling protection on them.
|
|
28
|
+
<bd-link inline slot="actions" href="#">Review devices</bd-link>
|
|
29
|
+
</bd-alert>
|
|
30
|
+
\`\`\`
|
|
31
|
+
|
|
32
|
+
### Props
|
|
33
|
+
| Prop | Values | Default |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| \`tone\` | \`info\`, \`success\`, \`warning\`, \`error\`, \`neutral\` | \`info\` |
|
|
36
|
+
| \`variant\` | \`tint\`, \`outline\` | \`tint\` |
|
|
37
|
+
| \`heading\` | any string — omit for a description-only alert | \`''\` |
|
|
38
|
+
| \`dismissible\` | boolean — adds a close button | \`false\` |
|
|
39
|
+
| \`dismisslabel\` | the close button's accessible name | \`Dismiss alert\` |
|
|
40
|
+
|
|
41
|
+
### Slots
|
|
42
|
+
| Slot | For |
|
|
43
|
+
|---|---|
|
|
44
|
+
| *(default)* | the description. Carries markup, such as a link |
|
|
45
|
+
| \`icon\` | replaces the leading icon |
|
|
46
|
+
| \`actions\` | one or more actions under the description. Collapses when empty. **Each action is its own slotted element** — wrapping several in one span makes them a single flex item and they lose the gap between them |
|
|
47
|
+
|
|
48
|
+
### Slotted links need \`inline\`
|
|
49
|
+
A \`bd-link\` without \`inline\` is a **standalone** link and sets its own size:
|
|
50
|
+
\`--typography-link-standalone-fontSize\` is \`1rem\`, where this alert's prose is
|
|
51
|
+
\`body-small\` at \`0.875rem\`. Dropped into an alert it renders 16px inside 14px
|
|
52
|
+
text, with a taller line box that pushes the surrounding line apart.
|
|
53
|
+
|
|
54
|
+
\`inline\` selects \`--typography-link-default-*\`, which is \`inherit\` for both
|
|
55
|
+
size and leading — deliberately, per typography rule 10 in CLAUDE.md: a link
|
|
56
|
+
inside a sentence sits in that sentence's line box. The same applies to an
|
|
57
|
+
action, which should match the alert it belongs to rather than assert a size of
|
|
58
|
+
its own.
|
|
59
|
+
|
|
60
|
+
The alert **cannot** fix this for you. \`::slotted(bd-link)\` sets properties on
|
|
61
|
+
the host, and the link's own shadow rule sets \`font-size\` on the element
|
|
62
|
+
inside it, so the host never wins. The attribute is the only lever.
|
|
63
|
+
|
|
64
|
+
### Two axes, not one
|
|
65
|
+
The Figma source models six values of a single \`type\`: five statuses plus
|
|
66
|
+
\`Outline\`. Outline is a **surface treatment**, not a status — an outline alert
|
|
67
|
+
still needs to say whether it is an error — so the two are separate attributes
|
|
68
|
+
here. \`tone="outline"\` would tell a reader nothing about what the alert means.
|
|
69
|
+
|
|
70
|
+
### The leading icon is a placeholder
|
|
71
|
+
The design's glyph is a circle-info, which this package has not drawn. The
|
|
72
|
+
default is therefore \`bd-missing-icon\` — a visible dashed box that
|
|
73
|
+
\`npm run check:icons\` reports as owed. Pass real artwork through the \`icon\`
|
|
74
|
+
slot to override it.
|
|
75
|
+
|
|
76
|
+
### Accessibility
|
|
77
|
+
Only \`error\` gets \`role="alert"\`, which interrupts a screen reader. Every other
|
|
78
|
+
tone gets \`role="status"\`, announced politely when the user is idle.
|
|
79
|
+
|
|
80
|
+
That means **\`warning\` is announced politely, not urgently.** If a warning in
|
|
81
|
+
your context is time-critical, that is worth revisiting — the split is
|
|
82
|
+
currently error-only.
|
|
83
|
+
|
|
84
|
+
The tone is never the only signal: the heading and the description carry the
|
|
85
|
+
meaning too, so the alert still works for anyone who cannot distinguish the
|
|
86
|
+
tint. Every pairing was measured rather than assumed — the ink runs 16.03 to
|
|
87
|
+
17.97:1 across the six grounds, the actions ink 5.51 to 6.18, and the tone
|
|
88
|
+
accents 3.49 to 8.39 against the 3:1 non-text bar.
|
|
89
|
+
|
|
90
|
+
\`dismissible\` emits \`bd-dismiss\` and does **not** remove the element: what
|
|
91
|
+
happens to the space it occupied is the page's decision, not the atom's.
|
|
92
|
+
`
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
argTypes: {
|
|
97
|
+
tone: {
|
|
98
|
+
control : { type: 'select' },
|
|
99
|
+
options : ['info', 'success', 'warning', 'error', 'neutral'],
|
|
100
|
+
description: 'Which kind of message this is. Only `error` announces urgently.',
|
|
101
|
+
table : { type: { summary: 'string' }, defaultValue: { summary: 'info' }, category: 'Appearance' }
|
|
102
|
+
},
|
|
103
|
+
variant: {
|
|
104
|
+
control : { type: 'select' },
|
|
105
|
+
options : ['tint', 'outline'],
|
|
106
|
+
description: 'A surface treatment, independent of the tone. `outline` drops the tint for the page ground and an edge.',
|
|
107
|
+
table : { type: { summary: 'string' }, defaultValue: { summary: 'tint' }, category: 'Appearance' }
|
|
108
|
+
},
|
|
109
|
+
heading: {
|
|
110
|
+
control : 'text',
|
|
111
|
+
description: 'Optional title, on its own line above the description.',
|
|
112
|
+
table : { type: { summary: 'string' }, defaultValue: { summary: '' }, category: 'Content' }
|
|
113
|
+
},
|
|
114
|
+
dismissible: {
|
|
115
|
+
control : 'boolean',
|
|
116
|
+
description: 'Adds a close button that emits `bd-dismiss`. The element does not remove itself.',
|
|
117
|
+
table : { type: { summary: 'boolean' }, defaultValue: { summary: 'false' }, category: 'Behaviour' }
|
|
118
|
+
},
|
|
119
|
+
dismisslabel: {
|
|
120
|
+
control : 'text',
|
|
121
|
+
description: "The close button's accessible name.",
|
|
122
|
+
table : { type: { summary: 'string' }, defaultValue: { summary: 'Dismiss alert' }, category: 'Accessibility' }
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export const Tones = () => html`
|
|
128
|
+
<div style="display:grid; gap:1rem">
|
|
129
|
+
<bd-alert heading="Heads up.">Your licence renews in 14 days.</bd-alert>
|
|
130
|
+
<bd-alert tone="success" heading="Done.">Your device is protected.</bd-alert>
|
|
131
|
+
<bd-alert tone="warning" heading="Check this.">Two devices are out of date.</bd-alert>
|
|
132
|
+
<bd-alert tone="error" heading="Blocked.">We could not reach the update server.</bd-alert>
|
|
133
|
+
<bd-alert tone="neutral" heading="For reference.">Scans run weekly on this plan.</bd-alert>
|
|
134
|
+
</div>
|
|
135
|
+
`;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* The `outline` variant is a surface treatment and keeps its tone. Both alerts
|
|
139
|
+
* below are still `info` and `error` respectively — the icon says so, and the
|
|
140
|
+
* error one still carries `role="alert"`. Use it where the page already has a
|
|
141
|
+
* tint of its own and a second one would read as dirt.
|
|
142
|
+
*/
|
|
143
|
+
export const Outline = () => html`
|
|
144
|
+
<div style="display:grid; gap:1rem">
|
|
145
|
+
<bd-alert variant="outline" heading="Heads up.">Your licence renews in 14 days.</bd-alert>
|
|
146
|
+
<bd-alert variant="outline" tone="error" heading="Blocked.">We could not reach the update server.</bd-alert>
|
|
147
|
+
</div>
|
|
148
|
+
`;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* `heading` is optional, and without it the alert is description only. Worth
|
|
152
|
+
* its own snapshot because it is the shape most inline alerts actually take.
|
|
153
|
+
*/
|
|
154
|
+
export const WithoutHeading = () => html`
|
|
155
|
+
<div style="display:grid; gap:1rem">
|
|
156
|
+
<bd-alert>Your licence renews in 14 days.</bd-alert>
|
|
157
|
+
<bd-alert tone="success">Your device is protected.</bd-alert>
|
|
158
|
+
<bd-alert tone="error">We could not reach the update server.</bd-alert>
|
|
159
|
+
</div>
|
|
160
|
+
`;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* The `actions` slot takes one or more actions under the description. It
|
|
164
|
+
* collapses entirely when nothing is slotted into it, so the three alerts above
|
|
165
|
+
* carry no empty row — compare their heights with these.
|
|
166
|
+
*/
|
|
167
|
+
export const WithActions = () => html`
|
|
168
|
+
<bd-alert tone="warning" heading="Two devices are out of date.">
|
|
169
|
+
Windows Defender is still handling real-time protection on them.
|
|
170
|
+
<bd-link inline slot="actions" href="#">Review devices</bd-link>
|
|
171
|
+
<bd-link inline slot="actions" href="#">Remind me later</bd-link>
|
|
172
|
+
</bd-alert>
|
|
173
|
+
`;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* `dismissible` adds the close button. It emits `bd-dismiss` and deliberately
|
|
177
|
+
* does not remove the element — whether the space collapses, animates out, or
|
|
178
|
+
* is replaced is the page's call. This story logs the event rather than acting
|
|
179
|
+
* on it, which is the honest demonstration.
|
|
180
|
+
*/
|
|
181
|
+
export const Dismissible = () => html`
|
|
182
|
+
<bd-alert
|
|
183
|
+
tone="success"
|
|
184
|
+
heading="Payment received."
|
|
185
|
+
dismissible
|
|
186
|
+
@bd-dismiss=${e => e.target.setAttribute('hidden', '')}
|
|
187
|
+
>
|
|
188
|
+
A receipt is on its way. This story hides the alert on dismiss, which is
|
|
189
|
+
one of several things a page might reasonably do.
|
|
190
|
+
</bd-alert>
|
|
191
|
+
`;
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* The description is slotted, so it can carry markup — and it wraps. This is
|
|
195
|
+
* the story that shows the icon staying pinned to the first line while the
|
|
196
|
+
* text runs on, which is what `align-items: flex-start` on the row is for.
|
|
197
|
+
*/
|
|
198
|
+
export const LongMessage = () => html`
|
|
199
|
+
<div style="max-width: 46ch">
|
|
200
|
+
<bd-alert tone="warning" heading="Two devices are out of date." dismissible>
|
|
201
|
+
Windows Defender is still handling real-time protection on them. Open
|
|
202
|
+
<bd-link inline href="#">Device overview</bd-link> to finish setting up, or
|
|
203
|
+
remove the devices you no longer use.
|
|
204
|
+
</bd-alert>
|
|
205
|
+
</div>
|
|
206
|
+
`;
|