@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
|
@@ -1,11 +1,26 @@
|
|
|
1
1
|
import { html } from 'lit';
|
|
2
|
-
import
|
|
2
|
+
import {
|
|
3
|
+
INK,
|
|
4
|
+
PAPER,
|
|
5
|
+
contrast,
|
|
6
|
+
copyToken,
|
|
7
|
+
discoverConsumers,
|
|
8
|
+
docsPage,
|
|
9
|
+
levelBadge,
|
|
10
|
+
readAllCssText,
|
|
11
|
+
refSection,
|
|
12
|
+
resolve,
|
|
13
|
+
toHex,
|
|
14
|
+
usageCell
|
|
15
|
+
} from './story-chrome.js';
|
|
3
16
|
|
|
4
17
|
export default {
|
|
5
|
-
title: '
|
|
18
|
+
title: 'Foundations/Colors',
|
|
19
|
+
tags : ['autodocs']
|
|
6
20
|
};
|
|
7
21
|
|
|
8
|
-
|
|
22
|
+
/** Only used if the stylesheets cannot be read (e.g. cross-origin). */
|
|
23
|
+
const FALLBACK_FAMILIES = {
|
|
9
24
|
blue : ['50', '100', '200', '300', '400', '500', '600', '700', '800', '900', '950'],
|
|
10
25
|
red : ['50', '100', '200', '300', '400', '500', '600', '700', '800', '900', '950'],
|
|
11
26
|
green : ['50', '100', '200', '300', '400', '500', '600', '700', '800', '900', '950'],
|
|
@@ -13,56 +28,131 @@ const colorGroups = {
|
|
|
13
28
|
neutral: ['0', '25', '50', '100', '200', '300', '400', '500', '600', '700', '800', '900', '950', '1000']
|
|
14
29
|
};
|
|
15
30
|
|
|
16
|
-
|
|
31
|
+
function discoverFamilies(cssText) {
|
|
32
|
+
const families = new Map();
|
|
33
|
+
for (const [, family, shade] of cssText.matchAll(/--color-([a-z]+)-(\d+)\s*:/g)) {
|
|
34
|
+
if (!families.has(family)) families.set(family, new Set());
|
|
35
|
+
families.get(family).add(shade);
|
|
36
|
+
}
|
|
37
|
+
if (!families.size) {
|
|
38
|
+
for (const [family, shades] of Object.entries(FALLBACK_FAMILIES)) {
|
|
39
|
+
families.set(family, new Set(shades));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return [...families].map(([family, shades]) => ({
|
|
43
|
+
family,
|
|
44
|
+
shades: [...shades].sort((a, b) => Number(a) - Number(b))
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const swatchStyles = html`
|
|
17
49
|
<style>
|
|
18
|
-
|
|
19
|
-
|
|
50
|
+
/* Full-bleed swatch column: no padding and no row border, so consecutive
|
|
51
|
+
rows read as one continuous ramp. */
|
|
52
|
+
.docs th.col-swatch {
|
|
53
|
+
padding-left: 0;
|
|
54
|
+
padding-right: 0;
|
|
20
55
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
text-transform: capitalize;
|
|
56
|
+
|
|
57
|
+
.docs td.cell-swatch {
|
|
58
|
+
padding: 0;
|
|
59
|
+
width: 104px;
|
|
60
|
+
border-bottom: 0;
|
|
27
61
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
62
|
+
|
|
63
|
+
.swatch {
|
|
64
|
+
min-height: var(--touch-target-size);
|
|
65
|
+
height: 100%;
|
|
66
|
+
display: flex;
|
|
31
67
|
align-items: center;
|
|
32
68
|
justify-content: center;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
border-radius: 8px;
|
|
37
|
-
box-shadow: 0 0 4px rgba(0,0,0,0.1);
|
|
38
|
-
color: white;
|
|
39
|
-
font-family: var(--font-family-mono);
|
|
40
|
-
font-size: 12px;
|
|
41
|
-
text-align: center;
|
|
42
|
-
user-select: none;
|
|
69
|
+
gap: var(--spacing-10);
|
|
70
|
+
/* keeps --color-neutral-0 distinguishable from the page */
|
|
71
|
+
box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.1);
|
|
43
72
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
font-
|
|
49
|
-
font-size:
|
|
50
|
-
|
|
73
|
+
|
|
74
|
+
/* Both text colours drawn straight on the swatch, so an illegible
|
|
75
|
+
pairing genuinely looks illegible. */
|
|
76
|
+
.probe-aa {
|
|
77
|
+
font-weight: var(--typography-fontWeight-semibold);
|
|
78
|
+
font-size: var(--typography-fontSize-sm);
|
|
79
|
+
line-height: var(--typography-lineHeight-none);
|
|
51
80
|
}
|
|
52
81
|
</style>
|
|
82
|
+
`;
|
|
83
|
+
|
|
84
|
+
function renderRow(family, shade, consumers) {
|
|
85
|
+
const token = `--color-${family}-${shade}`;
|
|
86
|
+
const value = resolve(token);
|
|
87
|
+
if (!value) return html``;
|
|
53
88
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
89
|
+
const onPaper = contrast(value, PAPER);
|
|
90
|
+
const onInk = contrast(value, INK);
|
|
91
|
+
|
|
92
|
+
return html`
|
|
93
|
+
<tr>
|
|
94
|
+
<td class="cell-swatch">
|
|
95
|
+
<div class="swatch" style="background-color: var(${token})">
|
|
96
|
+
<span class="probe-aa" style="color: ${PAPER}">Aa</span>
|
|
97
|
+
<span class="probe-aa" style="color: ${INK}">Aa</span>
|
|
98
|
+
</div>
|
|
99
|
+
</td>
|
|
100
|
+
<td class="num">${shade}</td>
|
|
101
|
+
<td>${copyToken(token)}</td>
|
|
102
|
+
<td class="mono muted">${toHex(value).toUpperCase()}</td>
|
|
103
|
+
<td class="num">${onPaper.toFixed(2)}${levelBadge(onPaper)}</td>
|
|
104
|
+
<td class="num">${onInk.toFixed(2)}${levelBadge(onInk)}</td>
|
|
105
|
+
<td>${usageCell(consumers.get(token))}</td>
|
|
106
|
+
</tr>
|
|
107
|
+
`;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export const Colors = () => {
|
|
111
|
+
const cssText = readAllCssText();
|
|
112
|
+
const families = discoverFamilies(cssText);
|
|
113
|
+
const consumers = discoverConsumers(cssText);
|
|
114
|
+
|
|
115
|
+
return html`
|
|
116
|
+
${swatchStyles}
|
|
117
|
+
${docsPage({
|
|
118
|
+
title: 'Colour palette',
|
|
119
|
+
lede : html`Every ramp is read out of the loaded token CSS at render time, so this page
|
|
120
|
+
always matches <code>src/tokens/tokens.css</code>. Click a token name to copy its
|
|
121
|
+
<code>var()</code> reference.`,
|
|
122
|
+
note: html`The two <b>Aa</b> marks on each swatch are white and
|
|
123
|
+
<code>--color-neutral-900</code> text drawn straight onto that colour, so an illegible
|
|
124
|
+
pairing looks illegible. The contrast columns give the measured ratio and the WCAG level
|
|
125
|
+
it reaches for body text: <b>AAA</b> 7.0, <b>AA</b> 4.5, <b>18pt</b> 3.0 (large text and
|
|
126
|
+
UI edges only), <b>fail</b> below 3.0.`,
|
|
127
|
+
children: families.map(({ family, shades }) => {
|
|
128
|
+
const referenced = shades.filter(shade => consumers.has(`--color-${family}-${shade}`)).length;
|
|
129
|
+
|
|
130
|
+
return refSection({
|
|
131
|
+
name : family,
|
|
132
|
+
meta : `${shades.length} steps · ${referenced} referenced by other tokens`,
|
|
133
|
+
children: html`
|
|
134
|
+
<div class="table-scroll">
|
|
135
|
+
<table>
|
|
136
|
+
<caption>${family} colour ramp</caption>
|
|
137
|
+
<thead>
|
|
138
|
+
<tr>
|
|
139
|
+
<th class="col-swatch" scope="col">Swatch</th>
|
|
140
|
+
<th scope="col">Step</th>
|
|
141
|
+
<th scope="col">Token</th>
|
|
142
|
+
<th scope="col">Hex</th>
|
|
143
|
+
<th scope="col">On white</th>
|
|
144
|
+
<th scope="col">On neutral-900</th>
|
|
145
|
+
<th scope="col">Used by</th>
|
|
146
|
+
</tr>
|
|
147
|
+
</thead>
|
|
148
|
+
<tbody>
|
|
149
|
+
${shades.map(shade => renderRow(family, shade, consumers))}
|
|
150
|
+
</tbody>
|
|
151
|
+
</table>
|
|
152
|
+
</div>
|
|
153
|
+
`
|
|
154
|
+
});
|
|
155
|
+
})
|
|
156
|
+
})}
|
|
157
|
+
`;
|
|
158
|
+
};
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The word sample the type ceilings are measured against.
|
|
3
|
+
*
|
|
4
|
+
* WHY WORDS AND NOT STRINGS. For large type the binding constraint is the
|
|
5
|
+
* longest UNBREAKABLE WORD, not the length of the sentence -- a word wider
|
|
6
|
+
* than its column overflows or hyphenates, and neither is a size anyone chose.
|
|
7
|
+
* So this file holds words.
|
|
8
|
+
*
|
|
9
|
+
* NOTHING HERE CARRIES A MEASURED WIDTH. Foundations/Typography -> Why These
|
|
10
|
+
* Sizes measures every entry live in the browser, because a width measured
|
|
11
|
+
* once and written down is a width that goes stale -- and the browser and the
|
|
12
|
+
* Figma file already disagree by about 3.5% on the same word.
|
|
13
|
+
*
|
|
14
|
+
* WHERE THESE WORDS COME FROM, as of 2026-09-17: shipped copy. Every entry
|
|
15
|
+
* marked `production` was harvested from a live localized bitdefender.com
|
|
16
|
+
* page, and carries the page it came from and the size that page renders it
|
|
17
|
+
* at. The `representative` compounds this file started with are gone -- they
|
|
18
|
+
* indicated an order of magnitude and were the reason the ladder could only
|
|
19
|
+
* ever be provisional. See `harvest` below for the method.
|
|
20
|
+
*
|
|
21
|
+
* A JS module rather than the JSON registry it started as: the story needs it
|
|
22
|
+
* at build time, and a bare JSON import needs an import attribute under Node,
|
|
23
|
+
* which would break the per-file parse check without breaking the Vite build.
|
|
24
|
+
* One source, no attributes.
|
|
25
|
+
*/
|
|
26
|
+
export const ceilingWords = {
|
|
27
|
+
"about" : "The word sample the type ceilings are measured against. For large type the binding constraint is the longest UNBREAKABLE WORD, not the length of the sentence, so this file holds words rather than strings. Foundations/Typography -> Why These Sizes reads it and measures every entry live in the browser; nothing here carries a measured width, because a width measured once and written down is a width that goes stale.",
|
|
28
|
+
"howToUpdate" : "The ask that stood here -- one longest unbreakable token per language from the translation memory -- was answered another way, by harvesting the rendered copy instead of the TM that produced it. To re-run it, follow `harvest` below: it is one script against nine locale URLs and takes minutes. Re-run it when the marketing copy is rewritten, when a language is added to localeMap.js, or before changing any fontSizeMin token.",
|
|
29
|
+
"sourceVocabulary": {
|
|
30
|
+
"production" : "Harvested from a live localized bitdefender.com page: a token that really renders at 24px or larger in that market's copy. Carries `page` and `observedAt`. Stronger evidence than a TM extract, because it is what actually renders rather than a string that might.",
|
|
31
|
+
"tm" : "A string from the translation memory. None left -- `production` superseded the ask. Kept in the vocabulary because a TM entry would still be valid evidence for copy that has not shipped yet.",
|
|
32
|
+
"representative": "A plausible compound written for the study. NONE REMAIN: every one was replaced on 2026-09-17 by a production token in the same language. Kept in the vocabulary so a future gap can be filled honestly rather than silently.",
|
|
33
|
+
"outlier" : "Deliberately extreme, kept to show the shape of the failure rather than to set a ceiling. Excluded from the worst case the ladder is calibrated against."
|
|
34
|
+
},
|
|
35
|
+
"tiers": {
|
|
36
|
+
"note" : "Two tiers, because the question is not only how wide the longest token is but whether it can land in the role that would break. The size a token renders at on bitdefender.com is not our role -- their site, their scale -- but it does classify the COPY: a word set at 40px+ there is headline copy, a word set at 24-32px is feature or subhead copy.",
|
|
37
|
+
"headline": "observedAt >= 40. Copy that plays the part heading-h1 plays. This is the tier the h1 mobile size has to survive.",
|
|
38
|
+
"feature" : "observedAt 24-39. Subheads and feature lists. On a phone this copy lands in h3 and below, where the ladder has room -- but it is included in the all-tier worst case, because nothing stops a writer from promoting one of these words into a headline."
|
|
39
|
+
},
|
|
40
|
+
"shippingLanguages": {
|
|
41
|
+
"source" : "Derived from src/components/footer/localeMap.js, the only locale list in this monorepo. It is the footer's country selector, so treat it as the best available evidence rather than a declared locale contract.",
|
|
42
|
+
"languages": [
|
|
43
|
+
"en",
|
|
44
|
+
"es",
|
|
45
|
+
"de",
|
|
46
|
+
"nl",
|
|
47
|
+
"fr",
|
|
48
|
+
"pt",
|
|
49
|
+
"zh",
|
|
50
|
+
"it",
|
|
51
|
+
"ro",
|
|
52
|
+
"sv",
|
|
53
|
+
"ja"
|
|
54
|
+
],
|
|
55
|
+
"note": "46 locales, 11 languages. Two languages are deliberately absent. Finnish: there is no fi-FI locale at all -- see the `retired` note on the fi entries below. Hungarian: Hungary is served in ENGLISH, at /en-hu/, so the locale is en-HU and Hungarian is not a language this product sells in. That was established 2026-09-17 after the footer was found pointing at /hu-hu/, which 404s; the footer says en-HU now and all 46 roots resolve."
|
|
56
|
+
},
|
|
57
|
+
"wrappingCaveats": {
|
|
58
|
+
"zh": "Chinese wraps between characters, so the longest-word constraint barely applies. The relevant question there is characters per line at ~1em per glyph, which this study does not model.",
|
|
59
|
+
"ja": "Same as zh, with kinsoku line-breaking rules on top. Not modelled."
|
|
60
|
+
},
|
|
61
|
+
"harvest": {
|
|
62
|
+
"date" : "2026-09-17",
|
|
63
|
+
"method": "In a browser on each locale URL below: walk every element, keep the ones whose computed font-size is >= 24px and are not hidden, take their direct text nodes, split on whitespace AND on hyphen, slash, en/em dash and punctuation -- all of them are line-break opportunities, so a hyphenated compound is not one unbreakable token -- strip anything that is not a letter or digit, and keep tokens of 9 characters or more with the largest size each was seen at. Then measure each candidate in IBM Plex Sans 700 at 100px in this package's own token scope and rank by width, not by character count.",
|
|
64
|
+
"pages" : [
|
|
65
|
+
"https://www.bitdefender.com/<locale>/consumer/total-security",
|
|
66
|
+
"https://www.bitdefender.com/<locale>/consumer/ultimate-security"
|
|
67
|
+
],
|
|
68
|
+
"locales": [
|
|
69
|
+
"en-us",
|
|
70
|
+
"nl-nl",
|
|
71
|
+
"de-de",
|
|
72
|
+
"sv-se",
|
|
73
|
+
"ro-ro",
|
|
74
|
+
"fr-fr",
|
|
75
|
+
"it-it",
|
|
76
|
+
"es-es",
|
|
77
|
+
"pt-pt"
|
|
78
|
+
],
|
|
79
|
+
"whyNotCharacterCount": "Character count is a prefilter, not the measurement. Plex is proportional: Romanian `Confidentialitate` and Dutch `Gepersonaliseerde` are both 17 characters and differ by 12% in width, and a 15-character Swedish compound outruns a 17-character Romanian one.",
|
|
80
|
+
"caveat" : "These are marketing pages rendered by bitdefender.com's own design system, not by this package. The TOKEN TEXT is the evidence; the size it renders at there is used only to classify the copy into the two tiers above."
|
|
81
|
+
},
|
|
82
|
+
"words": [
|
|
83
|
+
{
|
|
84
|
+
"lang" : "en",
|
|
85
|
+
"word" : "Recommended",
|
|
86
|
+
"source" : "production",
|
|
87
|
+
"page" : "en-us/consumer/total-security",
|
|
88
|
+
"observedAt": 40
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"lang" : "en",
|
|
92
|
+
"word" : "Personalized",
|
|
93
|
+
"source" : "production",
|
|
94
|
+
"page" : "en-us/consumer/total-security",
|
|
95
|
+
"observedAt": 24
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"lang" : "en",
|
|
99
|
+
"word" : "Performance",
|
|
100
|
+
"source" : "production",
|
|
101
|
+
"page" : "en-us/consumer/total-security",
|
|
102
|
+
"observedAt": 32
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"lang" : "sv",
|
|
106
|
+
"word" : "kalenderinbjudningar",
|
|
107
|
+
"source" : "production",
|
|
108
|
+
"page" : "sv-se/consumer/ultimate-security",
|
|
109
|
+
"observedAt": 24,
|
|
110
|
+
"note" : "The widest token in the whole sample. Swedish was in `alsoMissing` as a low-priority gap; it turned out to set the worst case."
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"lang" : "sv",
|
|
114
|
+
"word" : "bedrägeriaviseringar",
|
|
115
|
+
"source" : "production",
|
|
116
|
+
"page" : "sv-se/consumer/ultimate-security",
|
|
117
|
+
"observedAt": 24
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"lang" : "sv",
|
|
121
|
+
"word" : "Rekommenderas",
|
|
122
|
+
"source" : "production",
|
|
123
|
+
"page" : "sv-se/consumer/total-security",
|
|
124
|
+
"observedAt": 40,
|
|
125
|
+
"note" : "Swedish's widest HEADLINE-tier token, which is the one h1 has to survive."
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"lang" : "nl",
|
|
129
|
+
"word" : "oplichtingsmeldingen",
|
|
130
|
+
"source" : "production",
|
|
131
|
+
"page" : "nl-nl/consumer/ultimate-security",
|
|
132
|
+
"observedAt": 24
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"lang" : "nl",
|
|
136
|
+
"word" : "oplichtingspatronen",
|
|
137
|
+
"source" : "production",
|
|
138
|
+
"page" : "nl-nl/consumer/ultimate-security",
|
|
139
|
+
"observedAt": 24
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"lang" : "nl",
|
|
143
|
+
"word" : "Gepersonaliseerde",
|
|
144
|
+
"source" : "production",
|
|
145
|
+
"page" : "nl-nl/consumer/total-security",
|
|
146
|
+
"observedAt": 24
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"lang" : "nl",
|
|
150
|
+
"word" : "Aanbevolen",
|
|
151
|
+
"source" : "production",
|
|
152
|
+
"page" : "nl-nl/consumer/total-security",
|
|
153
|
+
"observedAt": 40,
|
|
154
|
+
"note" : "Dutch's widest headline-tier token -- and narrower than English `Recommended`, which is the same word doing the same job. Compounding does not reach the headline here."
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"lang" : "de",
|
|
158
|
+
"word" : "Kalendereinladungen",
|
|
159
|
+
"source" : "production",
|
|
160
|
+
"page" : "de-de/consumer/ultimate-security",
|
|
161
|
+
"observedAt": 24
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"lang" : "de",
|
|
165
|
+
"word" : "Kalenderereignissen",
|
|
166
|
+
"source" : "production",
|
|
167
|
+
"page" : "de-de/consumer/ultimate-security",
|
|
168
|
+
"observedAt": 24
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"lang" : "de",
|
|
172
|
+
"word" : "Benachrichtigungen",
|
|
173
|
+
"source" : "production",
|
|
174
|
+
"page" : "de-de/consumer/ultimate-security",
|
|
175
|
+
"observedAt": 24
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"lang" : "de",
|
|
179
|
+
"word" : "Gründungsmitglied",
|
|
180
|
+
"source" : "production",
|
|
181
|
+
"page" : "de-de/consumer/ultimate-security",
|
|
182
|
+
"observedAt": 44,
|
|
183
|
+
"note" : "The widest headline-tier token in the sample, in any language, and therefore the word the h1 mobile size is really calibrated against."
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"lang" : "ro",
|
|
187
|
+
"word" : "Confidențialitate",
|
|
188
|
+
"source" : "production",
|
|
189
|
+
"page" : "ro-ro/consumer/total-security",
|
|
190
|
+
"observedAt": 32,
|
|
191
|
+
"note" : "Was in this file as a `representative` compound and turned out to be real copy, at 32px."
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"lang" : "ro",
|
|
195
|
+
"word" : "abonamentele",
|
|
196
|
+
"source" : "production",
|
|
197
|
+
"page" : "ro-ro/consumer/ultimate-security",
|
|
198
|
+
"observedAt": 40
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
"lang" : "fr",
|
|
202
|
+
"word" : "Confidentialité",
|
|
203
|
+
"source" : "production",
|
|
204
|
+
"page" : "fr-fr/consumer/total-security",
|
|
205
|
+
"observedAt": 32
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"lang" : "fr",
|
|
209
|
+
"word" : "performances",
|
|
210
|
+
"source" : "production",
|
|
211
|
+
"page" : "fr-fr/consumer/total-security",
|
|
212
|
+
"observedAt": 40
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
"lang" : "it",
|
|
216
|
+
"word" : "personalizzata",
|
|
217
|
+
"source" : "production",
|
|
218
|
+
"page" : "it-it/consumer/total-security",
|
|
219
|
+
"observedAt": 32
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
"lang" : "it",
|
|
223
|
+
"word" : "disposizione",
|
|
224
|
+
"source" : "production",
|
|
225
|
+
"page" : "it-it/consumer/total-security",
|
|
226
|
+
"observedAt": 40
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
"lang" : "es",
|
|
230
|
+
"word" : "tranquilamente",
|
|
231
|
+
"source" : "production",
|
|
232
|
+
"page" : "es-es/consumer/total-security",
|
|
233
|
+
"observedAt": 32
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
"lang" : "es",
|
|
237
|
+
"word" : "Recomendado",
|
|
238
|
+
"source" : "production",
|
|
239
|
+
"page" : "es-es/consumer/total-security",
|
|
240
|
+
"observedAt": 40
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"lang" : "pt",
|
|
244
|
+
"word" : "independência",
|
|
245
|
+
"source" : "production",
|
|
246
|
+
"page" : "pt-pt/consumer/total-security",
|
|
247
|
+
"observedAt": 24
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
"lang" : "pt",
|
|
251
|
+
"word" : "preocupação",
|
|
252
|
+
"source" : "production",
|
|
253
|
+
"page" : "pt-pt/consumer/total-security",
|
|
254
|
+
"observedAt": 40
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
"lang" : "fi",
|
|
258
|
+
"word" : "Tietoturvaratkaisu",
|
|
259
|
+
"source" : "representative",
|
|
260
|
+
"retired": "Finnish does not ship -- there is no fi-FI locale in localeMap.js. Kept only because the ladder committed in 723aa111 was calibrated against the widest of these, so removing them would erase the record of what it was calibrated against. Do not use them to set a new ceiling."
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
"lang" : "fi",
|
|
264
|
+
"word" : "Käyttäjätunnukset",
|
|
265
|
+
"source" : "representative",
|
|
266
|
+
"retired": "see the note on Tietoturvaratkaisu"
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
"lang" : "fi",
|
|
270
|
+
"word" : "Henkilöllisyyssuoja",
|
|
271
|
+
"source" : "representative",
|
|
272
|
+
"retired": "see the note on Tietoturvaratkaisu. THIS is the word the mobile ladder was sized against -- and the production harvest has since found three real tokens WIDER than it, in Swedish, Dutch and German."
|
|
273
|
+
}
|
|
274
|
+
],
|
|
275
|
+
"missing": {
|
|
276
|
+
"note" : "NOTHING, as of 2026-09-17. Every shipping language the longest-word model applies to now has a production sample. `unsampledLanguages` below derives to an empty array, and it should stay that way: if a language is added to localeMap.js, this file is one of the places that has to grow with it.",
|
|
277
|
+
"hungarian" : "Was the one gap, and it turned out not to be a gap. The study could find no Hungarian copy because THERE IS NONE: Hungary is an English market, served at /en-hu/. The footer had it as hu-HU, which is why /hu-hu/ 404ed and why this file recorded Hungarian as an untested compounding language. Corrected in localeMap.js; Hungarian is no longer claimed as a shipping language.",
|
|
278
|
+
"notApplicable": [
|
|
279
|
+
"zh",
|
|
280
|
+
"ja"
|
|
281
|
+
]
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
/** Live-sampled languages -- everything not marked `retired`. */
|
|
286
|
+
export const sampledLanguages = [...new Set(
|
|
287
|
+
ceilingWords.words.filter(w => !w.retired).map(w => w.lang)
|
|
288
|
+
)].sort();
|
|
289
|
+
|
|
290
|
+
/** Shipping languages with no live sample, minus the two that wrap per character. */
|
|
291
|
+
export const unsampledLanguages = ceilingWords.shippingLanguages.languages
|
|
292
|
+
.filter(l => !sampledLanguages.includes(l))
|
|
293
|
+
.filter(l => !Object.keys(ceilingWords.wrappingCaveats).includes(l))
|
|
294
|
+
.sort();
|
|
295
|
+
|
|
296
|
+
/** The tier a word's copy belongs to; see `ceilingWords.tiers`. */
|
|
297
|
+
export const tierOf = word => (word.observedAt >= 40 ? 'headline' : 'feature');
|
|
298
|
+
|
|
299
|
+
export default ceilingWords;
|