@repobit/dex-system-design 1.0.1 → 2.0.1
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 +89 -0
- package/README.md +43 -12
- package/package.json +6 -4
- package/schemas/component-manifest.json +207 -49
- package/schemas/manifest-omissions.json +2 -0
- package/src/components/accordion/accordion.css.js +12 -1
- package/src/components/agent-endpoints/agent-endpoints.js +1 -1
- package/src/components/alert/alert.css.js +22 -1
- package/src/components/anchor/anchor-nav.css.js +6 -1
- package/src/components/annotation/annotation.css.js +6 -1
- package/src/components/architecture.stories.js +6 -4
- package/src/components/avatar/avatar.js +37 -11
- package/src/components/avatar/avatar.stories.js +10 -6
- package/src/components/awards/awards-flex.css.js +31 -129
- package/src/components/awards/awards-flex.js +66 -116
- package/src/components/awards/awards-flex.stories.js +8 -6
- package/src/components/back/back.css.js +6 -1
- package/src/components/back/back.js +24 -12
- package/src/components/back/back.stories.js +3 -3
- package/src/components/badge/badge.js +6 -3
- package/src/components/badge/badge.stories.js +13 -9
- package/src/components/bento-grid/bento-grid.js +1 -1
- package/src/components/blockquote/blockquote.css.js +12 -3
- package/src/components/blockquote/blockquote.js +12 -5
- package/src/components/blockquote/blockquote.stories.js +6 -4
- package/src/components/button/button.css.js +46 -25
- package/src/components/button/button.js +44 -43
- package/src/components/button/button.stories.js +2 -2
- package/src/components/caption/caption.css.js +10 -0
- package/src/components/caption/caption.stories.js +4 -4
- package/src/components/carousel/carousel.css.js +19 -116
- package/src/components/carousel/carousel.js +70 -74
- package/src/components/carousel/carousel.stories.js +9 -8
- package/src/components/checkbox/checkbox.css.js +6 -1
- package/src/components/code/code.css.js +6 -1
- package/src/components/code/code.js +48 -7
- package/src/components/code/code.stories.js +7 -4
- package/src/components/divider/divider-horizontal.js +11 -3
- package/src/components/divider/divider-vertical.js +12 -5
- package/src/components/divider/divider.css.js +4 -1
- package/src/components/divider/divider.stories.js +6 -6
- package/src/components/dropdown/dropdown.js +67 -13
- package/src/components/dropdown/dropdown.stories.js +15 -14
- package/src/components/fieldset/fieldset.stories.js +41 -16
- package/src/components/footer/footer-nav-menu.css.js +6 -1
- package/src/components/footer/footer.css.js +6 -1
- package/src/components/header/header-code.js +1 -1
- package/src/components/header/header.css.js +9 -4
- package/src/components/heading/heading.stories.js +64 -31
- package/src/components/highlight/highlight.js +74 -34
- package/src/components/highlight/highlight.stories.js +5 -4
- package/src/components/icons/icon-element.js +49 -6
- package/src/components/icons/icons.stories.js +7 -0
- package/src/components/image/image.css.js +9 -98
- package/src/components/image/image.js +7 -2
- package/src/components/input/custom-form.stories.js +14 -19
- package/src/components/input/input-clipboard.css.js +6 -1
- package/src/components/input/input-clipboard.js +56 -8
- package/src/components/input/input.js +19 -2
- package/src/components/label/label.js +87 -1
- package/src/components/label/label.stories.js +21 -12
- package/src/components/link/link.css.js +52 -3
- package/src/components/link/link.js +52 -17
- package/src/components/link/link.stories.js +114 -3
- package/src/components/list/list-item/list-item.css.js +4 -6
- package/src/components/list/list-item/list-item.js +53 -5
- package/src/components/list/list-item/list-item.stories.js +22 -0
- package/src/components/list/list.js +27 -0
- package/src/components/modal/modal.css.js +6 -1
- package/src/components/pagination-dots/pagination-dots.css.js +161 -0
- package/src/components/pagination-dots/pagination-dots.js +202 -0
- package/src/components/pagination-dots/pagination-dots.stories.js +171 -0
- package/src/components/paragraph/paragraph.css.js +37 -1
- package/src/components/paragraph/paragraph.js +19 -2
- package/src/components/paragraph/paragraph.stories.js +40 -6
- package/src/components/picture/picture.css.js +8 -67
- package/src/components/picture/picture.js +15 -8
- package/src/components/pricing-cards/pricing-card.css.js +12 -2
- package/src/components/pricing-cards/pricing-card.js +4 -4
- package/src/components/progress/progress.js +24 -4
- package/src/components/progress/progress.stories.js +8 -6
- package/src/components/radio/radio.css.js +6 -1
- package/src/components/radio/radio.js +48 -3
- package/src/components/radio/radio.stories.js +1 -1
- package/src/components/shared/form-field.css.js +30 -4
- package/src/components/shared/token-scales.js +16 -0
- package/src/components/spinner/spinner.css.js +31 -4
- package/src/components/spinner/spinner.js +26 -4
- package/src/components/spinner/spinner.stories.js +10 -7
- package/src/components/switch/switch.css.js +21 -3
- package/src/components/switch/switch.js +8 -1
- package/src/components/switch/switch.stories.js +2 -1
- package/src/components/tab-list/tab-list.css.js +6 -1
- package/src/components/terminal/terminal-cursor.js +11 -0
- package/src/components/terminal/terminal-message.js +1 -1
- package/src/components/termsOfUse/terms.css.js +6 -1
- package/src/components/textarea/textarea.stories.js +23 -0
- package/src/components/tooltip/tooltip.css.js +24 -1
- package/src/components/tooltip/tooltip.js +135 -5
- package/src/components/tooltip/tooltip.stories.js +20 -14
- package/src/components/trust-panel/trust-panel.js +2 -2
- package/src/components/video/video.js +38 -3
- package/src/components/video/video.stories.js +10 -5
- package/src/components/video-player/video-player.css.js +6 -1
- package/src/tokens/elevation.stories.js +2 -3
- package/src/tokens/focus.stories.js +81 -15
- package/src/tokens/motion.stories.js +0 -6
- package/src/tokens/tokens.css +174 -97
- package/src/tokens/tokens.js +174 -97
- package/src/tokens/vertical-rhythm.stories.js +1 -1
- package/src/stories/Button.js +0 -20
- package/src/stories/Button.stories.js +0 -46
- package/src/stories/Configure.mdx +0 -364
- package/src/stories/Header.js +0 -45
- package/src/stories/Header.stories.js +0 -24
- package/src/stories/Page.js +0 -62
- package/src/stories/Page.stories.js +0 -20
- package/src/stories/assets/accessibility.png +0 -0
- package/src/stories/assets/accessibility.svg +0 -1
- package/src/stories/assets/addon-library.png +0 -0
- package/src/stories/assets/assets.png +0 -0
- package/src/stories/assets/avif-test-image.avif +0 -0
- package/src/stories/assets/context.png +0 -0
- package/src/stories/assets/discord.svg +0 -1
- package/src/stories/assets/docs.png +0 -0
- package/src/stories/assets/figma-plugin.png +0 -0
- package/src/stories/assets/github.svg +0 -1
- package/src/stories/assets/share.png +0 -0
- package/src/stories/assets/styling.png +0 -0
- package/src/stories/assets/testing.png +0 -0
- package/src/stories/assets/theming.png +0 -0
- package/src/stories/assets/tutorials.svg +0 -1
- package/src/stories/assets/youtube.svg +0 -1
- package/src/stories/button.css +0 -30
- package/src/stories/header.css +0 -32
- package/src/stories/page.css +0 -68
package/src/tokens/tokens.js
CHANGED
|
@@ -81,8 +81,11 @@ const declarations = `
|
|
|
81
81
|
t-comma, -0.275em in Bold, a third deeper than g -- and the tallest
|
|
82
82
|
are grave and acute capitals at +0.977em. Measured per weight, ink
|
|
83
83
|
spans 1.174 Light, 1.194 Regular, 1.219 Medium, 1.235 SemiBold,
|
|
84
|
-
1.252 Bold.
|
|
85
|
-
|
|
84
|
+
1.252 Bold. Tight, 1.25, sits 0.002 under the Bold floor -- the
|
|
85
|
+
tallest accented capital and the deepest comma-below letter would
|
|
86
|
+
have to fall in consecutive lines, one above the other, to touch --
|
|
87
|
+
which is why the display roles stay at tight and are never tightened
|
|
88
|
+
further.
|
|
86
89
|
Foundations/Typography/Vertical Rhythm reaches 1.231 for 48px Bold
|
|
87
90
|
from canvas metrics; this is the same number from outline bounds. */
|
|
88
91
|
--typography-lineHeight-130: 1.3;
|
|
@@ -243,13 +246,12 @@ const declarations = `
|
|
|
243
246
|
/* The CSS default curve. It was missing, and its absence was the single
|
|
244
247
|
reason eleven component transitions could not be expressed in tokens:
|
|
245
248
|
ease is not ease-in-out — it front-loads, and swapping one for the
|
|
246
|
-
other is a visible change. Named after the keyword, as linear
|
|
247
|
-
ease-
|
|
248
|
-
|
|
249
|
+
other is a visible change. Named after the keyword, as linear and
|
|
250
|
+
ease-out beside it are; smooth is the outlier that aliases a keyword
|
|
251
|
+
rather than naming it. ease-in and a bounce curve stood here too and
|
|
252
|
+
went on 2026-10-15, because nothing read either. */
|
|
249
253
|
--transition-easing-ease: ease;
|
|
250
|
-
--transition-easing-ease-in: ease-in;
|
|
251
254
|
--transition-easing-ease-out: ease-out;
|
|
252
|
-
--transition-easing-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
|
253
255
|
|
|
254
256
|
/* ================================
|
|
255
257
|
CORE SHADOW TOKENS
|
|
@@ -261,37 +263,62 @@ const declarations = `
|
|
|
261
263
|
0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
262
264
|
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1),
|
|
263
265
|
0 8px 10px -6px rgb(0 0 0 / 0.1);
|
|
264
|
-
--shadow-2xl
|
|
265
|
-
|
|
266
|
+
/* The ladder stops at xl. --shadow-2xl and the inset --shadow-inner
|
|
267
|
+
stood beside it until 2026-10-15, and nothing read either. */
|
|
266
268
|
|
|
267
|
-
/*
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
269
|
+
/* The focus glow: --color-blue-500 at 15%, mixed from the palette. It
|
|
270
|
+
was rgba(6, 109, 255, 0.15) -- a blue one unit off blue-500 -- with a
|
|
271
|
+
red and a green beside it that were Tailwind's red-500 and green-500,
|
|
272
|
+
in no palette here. Nothing read the red or the green, so they went;
|
|
273
|
+
--form-input-focus-boxShadow reads this one. */
|
|
274
|
+
--shadow-focus-outline-blue: 0 0 0 3px color-mix(in srgb, var(--color-blue-500) 15%, transparent);
|
|
271
275
|
|
|
272
276
|
/* Focus Outlines - Two-Color System for Universal Visibility */
|
|
273
277
|
--focus-outline-primary: 0 0 0 2px var(--color-neutral-0),
|
|
274
278
|
0 0 0 4px var(--color-blue-500);
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
keeps them visible on a coloured hero. That fails on a control which
|
|
279
|
+
|
|
280
|
+
/* Secondary, error and success rings stood here until 2026-10-15.
|
|
281
|
+
Nothing read them -- every component rings with primary -- and the
|
|
282
|
+
success ring was green-500, 2.39:1 against white, under the 3:1 a
|
|
283
|
+
focus indicator needs. */
|
|
284
|
+
|
|
285
|
+
/* The one above puts the WHITE band against the control, which is what
|
|
286
|
+
keeps it visible on a coloured hero. That fails on a control which
|
|
284
287
|
is itself white: bd-button-link variant="white" measured 1.00:1 for
|
|
285
288
|
the inner band against its own fill and 2.38:1 for the blue band
|
|
286
289
|
against a blue hero, so neither band reached the 3:1 WCAG 2.4.11
|
|
287
290
|
asks of a focus indicator. This one inverts the pair -- dark band
|
|
288
291
|
against the control, white band against the ground -- so the inner
|
|
289
|
-
band carries the contrast whatever the control is sitting on.
|
|
292
|
+
band carries the contrast whatever the control is sitting on.
|
|
293
|
+
|
|
294
|
+
This is also what the Figma library draws around a filled or
|
|
295
|
+
bordered button on a dark or brand ground (focus/ring-inverse).
|
|
296
|
+
Figma builds a ring from spread shadows, so every band in it is a
|
|
297
|
+
painted colour, and the band between control and ring has to be
|
|
298
|
+
chosen per surface. On a brand hero that painted neutral-900 band
|
|
299
|
+
reads as a black outline. bd-button does not use this one; it draws
|
|
300
|
+
the outline below, whose gap is not painted at all. */
|
|
290
301
|
--focus-outline-inverse: 0 0 0 2px var(--color-neutral-900),
|
|
291
302
|
0 0 0 4px var(--color-neutral-0);
|
|
292
303
|
|
|
293
|
-
/*
|
|
304
|
+
/* The CTA ring in code: one band, held off the control by
|
|
305
|
+
--focus-outline-offset. The offset leaves the gap TRANSPARENT, so it
|
|
306
|
+
is always the surface the control sits on -- white on a light page,
|
|
307
|
+
neutral-900 on a dark hero, blue on a brand one -- and never merges
|
|
308
|
+
into a white fill or a white border, which is the job the painted
|
|
309
|
+
inner band of every two-band ring above does by hand. Figma has no
|
|
310
|
+
offset outline, which is why its rings paint that gap and need one
|
|
311
|
+
style per surface; code does not.
|
|
312
|
+
|
|
313
|
+
Only the band's colour follows the ground. Blue on light, 4.53:1
|
|
314
|
+
against white. White on dark and brand, the one colour that clears
|
|
315
|
+
3:1 on both: 4.53:1 on blue-500, 6.18 on blue-600, 8.56 on blue-700,
|
|
316
|
+
17.97 on neutral-900. A blue band on a brand hero is 1.00:1.
|
|
317
|
+
|
|
318
|
+
An outline also survives forced-colors mode, where a box-shadow ring
|
|
319
|
+
is not drawn at all. bd-button reads these; see its FOCUS block. */
|
|
294
320
|
--focus-outline-traditional: 2px solid var(--color-blue-500);
|
|
321
|
+
--focus-outline-traditional-inverse: 2px solid var(--color-neutral-0);
|
|
295
322
|
--focus-outline-offset: 2px;
|
|
296
323
|
|
|
297
324
|
/* The ring is a box-shadow, so it already follows the radius of the
|
|
@@ -441,7 +468,7 @@ const declarations = `
|
|
|
441
468
|
/* Subordinate text on an inverse surface. --color-text-inverse is the
|
|
442
469
|
high-emphasis step there; this is the one below it, and until now the
|
|
443
470
|
system had no such step at all -- the light-side -secondary, -muted and
|
|
444
|
-
-subtle roles invert to 1.91, 2.73 and 3.
|
|
471
|
+
-subtle roles invert to 1.91, 2.73 and 3.74 against
|
|
445
472
|
--color-surface-inverse and cannot be used.
|
|
446
473
|
|
|
447
474
|
Two components had already invented it independently and spelled it
|
|
@@ -482,6 +509,14 @@ const declarations = `
|
|
|
482
509
|
the link it borrowed falls to 2.27:1. */
|
|
483
510
|
--color-text-brand-hover: var(--color-blue-700);
|
|
484
511
|
--color-text-success: var(--color-green-800);
|
|
512
|
+
/* Warning text sits on the page, a card, surface-subtle (5.16) or its
|
|
513
|
+
own tint (--color-surface-warning, 5.59) -- not on surface-muted,
|
|
514
|
+
where it measures 4.49:1, a hair under 4.5. The same rule as
|
|
515
|
+
-subtle above: the role is right and the ground is wrong, so the
|
|
516
|
+
fix is the ground. Nothing in the package draws the pair today:
|
|
517
|
+
bd-tag and bd-badge draw this yellow through --status-warning-text,
|
|
518
|
+
on --status-warning-surface. The way a page reaches it is the
|
|
519
|
+
color="warning" value the text atoms take (token-scales.js). */
|
|
485
520
|
--color-text-warning: var(--color-yellow-800);
|
|
486
521
|
--color-text-error: var(--color-red-700);
|
|
487
522
|
|
|
@@ -541,7 +576,18 @@ const declarations = `
|
|
|
541
576
|
-subtle is a decorative hairline between things that already belong
|
|
542
577
|
together, not the edge of anything actionable, and disabled controls
|
|
543
578
|
are exempt under 1.4.3. Do not reach for -subtle to outline a
|
|
544
|
-
control.
|
|
579
|
+
control.
|
|
580
|
+
|
|
581
|
+
-default's 3.23 holds on white and nowhere darker: on a band it is
|
|
582
|
+
2.88 (surface-subtle) and 2.51 (surface-muted), and on the brand
|
|
583
|
+
tint 2.99. So a control drawn in it carries a fill of its own --
|
|
584
|
+
surface-default, the ground it was measured on -- and its edge is
|
|
585
|
+
read against that fill wherever it is placed. A field already does
|
|
586
|
+
(--form-input-default-backgroundColor). A control with no fill, or
|
|
587
|
+
whose fill IS this colour (the switch's off track), belongs on the
|
|
588
|
+
page or a card, not on a band. The rule is where it goes; a darker
|
|
589
|
+
-default would move every field edge in the system to fix a case
|
|
590
|
+
nothing in the package draws. */
|
|
545
591
|
--color-border-subtle: var(--color-neutral-200);
|
|
546
592
|
--color-border-default: var(--color-neutral-400);
|
|
547
593
|
--color-border-strong: var(--color-neutral-900);
|
|
@@ -605,7 +651,9 @@ const declarations = `
|
|
|
605
651
|
this theme, which is why the borrowing never showed -- and both must
|
|
606
652
|
flip to near-black in a dark one, which would turn every label and
|
|
607
653
|
mark dark on its blue or red fill. White clears every action fill:
|
|
608
|
-
4.53 to 10.51:1
|
|
654
|
+
4.53 to 10.51:1 on the blue and red ones, 13.28 to 21:1 on the
|
|
655
|
+
near-black secondary ones. Measured in the Figma Dark mode study,
|
|
656
|
+
and re-measured on the live tokens 2026-10-15. */
|
|
609
657
|
--color-action-on-fill: var(--color-neutral-0);
|
|
610
658
|
|
|
611
659
|
/* ================================
|
|
@@ -734,10 +782,14 @@ const declarations = `
|
|
|
734
782
|
takes, it is whether the longest UNBREAKABLE WORD fits the column.
|
|
735
783
|
The column is the viewport minus twice --grid-padding-*, so a 320px
|
|
736
784
|
phone gives type 288px -- 10% of the screen is gutter. Against that
|
|
737
|
-
column the
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
785
|
+
column, the widest real words in the nine shipping languages --
|
|
786
|
+
harvested from live localized copy, see type-ceiling-words.js and
|
|
787
|
+
plans/LATER.md entry 8 -- set two ceilings: 28px for any copy
|
|
788
|
+
(Swedish "kalenderinbjudningar", 10.16px of width per px of size)
|
|
789
|
+
and 31px for headline copy (German "Gründungsmitglied", 9.05).
|
|
790
|
+
heading-h1 is 48. It overflowed at 375 as well as at 320. (This
|
|
791
|
+
rested on a Finnish word once; Finnish is not a market, and three
|
|
792
|
+
real words beat it.)
|
|
741
793
|
|
|
742
794
|
WHY NOT A BREAKPOINT STEP. Tried first and abandoned, measured:
|
|
743
795
|
stepping h1 to 36 below sm still overflows at 320 (needs 327 of
|
|
@@ -779,20 +831,24 @@ const declarations = `
|
|
|
779
831
|
numbers: 30 27 24 21 18 16 for h1 through h6. Its ratios are 1.11,
|
|
780
832
|
1.13, 1.14, 1.17, 1.13 -- near-even, against the desktop ladder's
|
|
781
833
|
irregular 1.33, 1.13, 1.33, 1.20, 1.11. A phone has less range to
|
|
782
|
-
spend (16 to the 31px ceiling, a factor of 1.94, where
|
|
783
|
-
18 to 48, a factor of 2.67), so the ladder has to
|
|
784
|
-
compressing it evenly is what keeps six levels
|
|
785
|
-
Measured: h1 at 30
|
|
786
|
-
|
|
834
|
+
spend (16 to the 31px headline ceiling, a factor of 1.94, where
|
|
835
|
+
desktop has 18 to 48, a factor of 2.67), so the ladder has to
|
|
836
|
+
compress, and compressing it evenly is what keeps six levels
|
|
837
|
+
distinguishable. Measured on the harvest: h1 at 30 sets the widest
|
|
838
|
+
headline word in 272px of a 288px column. The widest word of any
|
|
839
|
+
tier would need 305, so a headline word wider than 960px per 100px
|
|
840
|
+
of size is a stated copy constraint (LATER.md entry 8) rather than
|
|
841
|
+
a margin the ladder holds -- none of the five such words is a
|
|
842
|
+
headline today.
|
|
787
843
|
|
|
788
844
|
WHAT IS DELIBERATELY NOT FLUID.
|
|
789
845
|
- Every role at 24px and below except body-lead. Nothing that small
|
|
790
846
|
overflows, and the small end's own failure is measure, not
|
|
791
847
|
overflow -- see below.
|
|
792
848
|
- display-lg, display-xl, display-2xl, display-3xl (60 to 128px).
|
|
793
|
-
Above display-md the family has NO mobile identity
|
|
794
|
-
|
|
795
|
-
|
|
849
|
+
Above display-md the family has NO mobile identity to give it:
|
|
850
|
+
four roles would all have to squeeze between 30 and the 31px
|
|
851
|
+
headline ceiling. They are desktop-only, and a component that
|
|
796
852
|
needs one of them on a phone should reach for a heading role
|
|
797
853
|
instead. Recorded rather than papered over.
|
|
798
854
|
- body-regular at 16px. It runs 40 characters per line on a 288px
|
|
@@ -1024,6 +1080,11 @@ const declarations = `
|
|
|
1024
1080
|
--typography-caption-default-fontFamily: var(--typography-fontFamily-sans);
|
|
1025
1081
|
--typography-caption-default-color: var(--color-text-muted);
|
|
1026
1082
|
|
|
1083
|
+
/* "small" is not smaller. It is caption-default with the tracking
|
|
1084
|
+
opened to wide -- 0.025em, which is the design's caption/small at
|
|
1085
|
+
2.5% -- and every other axis equal. The repeated axes are the role
|
|
1086
|
+
being complete, as every role is, not a second copy to remove;
|
|
1087
|
+
bd-caption size="sm" reads all five. */
|
|
1027
1088
|
--typography-caption-small-fontSize: var(--typography-fontSize-xs);
|
|
1028
1089
|
--typography-caption-small-fontWeight: var(--typography-fontWeight-normal);
|
|
1029
1090
|
--typography-caption-small-lineHeight: var(--typography-lineHeight-normal);
|
|
@@ -1125,28 +1186,43 @@ const declarations = `
|
|
|
1125
1186
|
COMPONENT TOKENS - FORM
|
|
1126
1187
|
================================ */
|
|
1127
1188
|
|
|
1128
|
-
/* Form Label Tokens
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1189
|
+
/* Form Label Tokens
|
|
1190
|
+
|
|
1191
|
+
The type of a field's label is the label role's, read through: the
|
|
1192
|
+
default and small rungs were the same five values as
|
|
1193
|
+
--typography-label-default-* and -small-*, written out a second time,
|
|
1194
|
+
so a change to the role would have reached bd-text and missed every
|
|
1195
|
+
form. Colour and margin stay here; they are the form's own and no
|
|
1196
|
+
role carries them.
|
|
1197
|
+
|
|
1198
|
+
Large differs on one axis. Its size is 18px where label-large is
|
|
1199
|
+
16px, set to the large field's own text (--form-input-large-fontSize)
|
|
1200
|
+
so the label and the value read at the same step; a field's own
|
|
1201
|
+
label at size lg, bd-label size=lg and the bd-fieldset legend all
|
|
1202
|
+
render it. That size stays a
|
|
1203
|
+
primitive -- no label role sits at 18px -- and the other four axes
|
|
1204
|
+
are label-large's. */
|
|
1205
|
+
--form-label-default-fontSize: var(--typography-label-default-fontSize);
|
|
1206
|
+
--form-label-default-fontWeight: var(--typography-label-default-fontWeight);
|
|
1207
|
+
--form-label-default-lineHeight: var(--typography-label-default-lineHeight);
|
|
1208
|
+
--form-label-default-letterSpacing: var(--typography-label-default-letterSpacing);
|
|
1209
|
+
--form-label-default-fontFamily: var(--typography-label-default-fontFamily);
|
|
1134
1210
|
--form-label-default-color: var(--color-text-primary);
|
|
1135
1211
|
--form-label-default-marginBottom: var(--spacing-4);
|
|
1136
1212
|
|
|
1137
1213
|
--form-label-large-fontSize: var(--typography-fontSize-lg);
|
|
1138
|
-
--form-label-large-fontWeight: var(--typography-fontWeight
|
|
1139
|
-
--form-label-large-lineHeight: var(--typography-lineHeight
|
|
1140
|
-
--form-label-large-letterSpacing: var(--typography-letterSpacing
|
|
1141
|
-
--form-label-large-fontFamily: var(--typography-fontFamily
|
|
1214
|
+
--form-label-large-fontWeight: var(--typography-label-large-fontWeight);
|
|
1215
|
+
--form-label-large-lineHeight: var(--typography-label-large-lineHeight);
|
|
1216
|
+
--form-label-large-letterSpacing: var(--typography-label-large-letterSpacing);
|
|
1217
|
+
--form-label-large-fontFamily: var(--typography-label-large-fontFamily);
|
|
1142
1218
|
--form-label-large-color: var(--color-text-primary);
|
|
1143
1219
|
--form-label-large-marginBottom: var(--spacing-8);
|
|
1144
1220
|
|
|
1145
|
-
--form-label-small-fontSize: var(--typography-fontSize
|
|
1146
|
-
--form-label-small-fontWeight: var(--typography-fontWeight
|
|
1147
|
-
--form-label-small-lineHeight: var(--typography-lineHeight
|
|
1148
|
-
--form-label-small-letterSpacing: var(--typography-letterSpacing
|
|
1149
|
-
--form-label-small-fontFamily: var(--typography-fontFamily
|
|
1221
|
+
--form-label-small-fontSize: var(--typography-label-small-fontSize);
|
|
1222
|
+
--form-label-small-fontWeight: var(--typography-label-small-fontWeight);
|
|
1223
|
+
--form-label-small-lineHeight: var(--typography-label-small-lineHeight);
|
|
1224
|
+
--form-label-small-letterSpacing: var(--typography-label-small-letterSpacing);
|
|
1225
|
+
--form-label-small-fontFamily: var(--typography-label-small-fontFamily);
|
|
1150
1226
|
--form-label-small-color: var(--color-text-primary);
|
|
1151
1227
|
--form-label-small-marginBottom: var(--spacing-4);
|
|
1152
1228
|
|
|
@@ -1169,11 +1245,14 @@ const declarations = `
|
|
|
1169
1245
|
three times. Changing them changes no pixel; it changes what the
|
|
1170
1246
|
package tells a consumer the height is.
|
|
1171
1247
|
|
|
1172
|
-
The
|
|
1173
|
-
the
|
|
1174
|
-
|
|
1175
|
-
line and paints into the padding
|
|
1176
|
-
|
|
1248
|
+
The derivation counts padding but not the 1px border on each edge,
|
|
1249
|
+
and the box is border-box, so these heights leave the line box 2px
|
|
1250
|
+
taller than the content box. An input hides that -- it centres its
|
|
1251
|
+
line and paints into the padding -- but a select clips at the
|
|
1252
|
+
content box, and at md its descenders lost their bottoms.
|
|
1253
|
+
Correcting the height would move a field off its button, so the
|
|
1254
|
+
border comes out of the block padding instead: see the note after
|
|
1255
|
+
the size rules in shared/form-field.css.js. */
|
|
1177
1256
|
--form-input-small-height: calc(
|
|
1178
1257
|
var(--spacing-8) * 2 + var(--typography-fontSize-sm) * var(--typography-lineHeight-tight)
|
|
1179
1258
|
);
|
|
@@ -1220,16 +1299,13 @@ const declarations = `
|
|
|
1220
1299
|
|
|
1221
1300
|
--form-input-error-backgroundColor: var(--status-error-surface);
|
|
1222
1301
|
--form-input-error-borderColor: var(--status-error-accent);
|
|
1223
|
-
--form-input-error-placeholderColor: var(--color-red-600);
|
|
1224
1302
|
|
|
1225
1303
|
--form-input-success-backgroundColor: var(--status-success-surface);
|
|
1226
1304
|
--form-input-success-borderColor: var(--color-green-600);
|
|
1227
|
-
--form-input-success-placeholderColor: var(--color-green-700);
|
|
1228
1305
|
|
|
1229
1306
|
--form-input-disabled-backgroundColor: var(--color-surface-disabled);
|
|
1230
1307
|
--form-input-disabled-borderColor: var(--color-border-disabled);
|
|
1231
1308
|
--form-input-disabled-color: var(--color-text-subtle);
|
|
1232
|
-
--form-input-disabled-placeholderColor: var(--color-neutral-400);
|
|
1233
1309
|
|
|
1234
1310
|
/* Form Help Text Tokens */
|
|
1235
1311
|
--form-help-text-default-fontSize: var(--typography-fontSize-xs);
|
|
@@ -1267,9 +1343,6 @@ const declarations = `
|
|
|
1267
1343
|
32, which is what a form actually wants and what the value is set to
|
|
1268
1344
|
here. */
|
|
1269
1345
|
--form-fieldSpacing: var(--spacing-24);
|
|
1270
|
-
--form-sectionSpacing: var(--spacing-32);
|
|
1271
|
-
--form-labelSpacing: var(--spacing-4);
|
|
1272
|
-
--form-helpTextSpacing: var(--spacing-4);
|
|
1273
1346
|
|
|
1274
1347
|
/* ================================
|
|
1275
1348
|
COMPONENT TOKENS - BUTTON
|
|
@@ -1299,15 +1372,14 @@ const declarations = `
|
|
|
1299
1372
|
--button-large-gap: var(--spacing-8);
|
|
1300
1373
|
--button-large-borderRadius: var(--radius-lg);
|
|
1301
1374
|
|
|
1302
|
-
/*
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1375
|
+
/* Removed 2026-10-15, because nothing read them: the seven
|
|
1376
|
+
--button-default-* (a state no variant draws), and
|
|
1377
|
+
--button-shared-focus-boxShadow, -disabled-opacity and
|
|
1378
|
+
-disabled-cursor (the button draws focus with the outline below and
|
|
1379
|
+
disabled through its own rules). Likewise the three
|
|
1380
|
+
--form-input-*-placeholderColor tokens, the --form-section-,
|
|
1381
|
+
-label- and -helpTextSpacing trio, and two --layout-awards- widths.
|
|
1382
|
+
None was mirrored in Figma, which carries no component tokens. */
|
|
1311
1383
|
/* Button Shared Tokens */
|
|
1312
1384
|
--button-shared-fontFamily: var(--typography-fontFamily-sans);
|
|
1313
1385
|
--button-shared-fontWeight: var(--typography-fontWeight-medium);
|
|
@@ -1320,9 +1392,6 @@ const declarations = `
|
|
|
1320
1392
|
--button-shared-transition-easing: var(--transition-easing-smooth);
|
|
1321
1393
|
--button-shared-focus-outline: var(--focus-outline-traditional);
|
|
1322
1394
|
--button-shared-focus-outlineOffset: var(--focus-outline-offset);
|
|
1323
|
-
--button-shared-focus-boxShadow: var(--focus-outline-primary);
|
|
1324
|
-
--button-shared-disabled-opacity: 0.6;
|
|
1325
|
-
--button-shared-disabled-cursor: not-allowed;
|
|
1326
1395
|
|
|
1327
1396
|
/* ---- variant colours -------------------------------------------
|
|
1328
1397
|
Named for the kind attribute they serve, because that is the public
|
|
@@ -1343,10 +1412,12 @@ const declarations = `
|
|
|
1343
1412
|
wiring them up unchanged would have moved pixels.
|
|
1344
1413
|
|
|
1345
1414
|
The per-variant -focus and -disabled sets are gone. The component
|
|
1346
|
-
draws
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1415
|
+
draws its focus ring as an offset outline -- the blue one through
|
|
1416
|
+
--button-shared-focus-outline by default, the white one from
|
|
1417
|
+
--focus-outline-traditional-inverse under surface="dark" and on
|
|
1418
|
+
white and outline-white -- and one shared disabled treatment;
|
|
1419
|
+
thirty tokens described per-variant versions of both that nothing
|
|
1420
|
+
rendered. --button-empty-* went with them: there is no empty kind. */
|
|
1350
1421
|
|
|
1351
1422
|
/* primary: blue fill */
|
|
1352
1423
|
--button-primary-background-default: var(--color-action-primary);
|
|
@@ -1561,8 +1632,11 @@ const declarations = `
|
|
|
1561
1632
|
/* Accessibility Spacing Tokens
|
|
1562
1633
|
-----------------------------------------------*/
|
|
1563
1634
|
/* Touch Target Sizes - WCAG 2.1 Success Criterion 2.5.5 (AAA) and 2.5.8 (AA) */
|
|
1564
|
-
|
|
1565
|
-
|
|
1635
|
+
/* The dimension steps that carry these values, rather than px
|
|
1636
|
+
literals beside them: a target is matched to a finger, not to the
|
|
1637
|
+
reader's text size, so it is px, which --dimension-* is. */
|
|
1638
|
+
--touch-target-size: var(--dimension-44); /* Minimum touch target size (44px × 44px) */
|
|
1639
|
+
--touch-target-spacing: var(--dimension-8); /* Minimum space between touch targets */
|
|
1566
1640
|
|
|
1567
1641
|
/* Readable Line Lengths - For optimal readability */
|
|
1568
1642
|
--content-width-readable: 70ch; /* Approximately 70 characters per line */
|
|
@@ -1570,18 +1644,21 @@ const declarations = `
|
|
|
1570
1644
|
|
|
1571
1645
|
/** GRID AND BREAKPOINT TOKENS
|
|
1572
1646
|
|
|
1573
|
-
|
|
1574
|
-
A media condition cannot read a custom property — @media
|
|
1647
|
+
The breakpoint tokens have no consumer in this package and are kept
|
|
1648
|
+
deliberately. A media condition cannot read a custom property — @media
|
|
1575
1649
|
(max-width: var(--breakpoint-sm)) is not valid CSS — so a breakpoint
|
|
1576
1650
|
token can never be referenced the way a colour is. It exists so the
|
|
1577
1651
|
six values have one place to be read from, by the lint that checks
|
|
1578
1652
|
media queries against them and by anything generating CSS. The grid
|
|
1579
|
-
tokens are
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1653
|
+
tokens below are read: --grid-container-max-* and --grid-padding-*
|
|
1654
|
+
are the page column, through shared/ensemble.css.js and layout.css,
|
|
1655
|
+
and the header and compare read them too. --grid-gutter-* has no
|
|
1656
|
+
reader outside the blog's own token copy, and carries the same
|
|
1657
|
+
values as --grid-padding-*.
|
|
1658
|
+
|
|
1659
|
+
The breakpoints are the exception. Everything else here that nothing
|
|
1660
|
+
references is dead weight, and the OLD VALUES and FONT TOKENS blocks
|
|
1661
|
+
that used to sit below were removed for exactly that reason.
|
|
1585
1662
|
*/
|
|
1586
1663
|
/* Grid container max widths */
|
|
1587
1664
|
--grid-container-max-xs: 100%; /* mobile full width */
|
|
@@ -1630,18 +1707,18 @@ const declarations = `
|
|
|
1630
1707
|
|
|
1631
1708
|
/* Awards section — Orbit Frame 14 (node 1882:9342) */
|
|
1632
1709
|
--layout-awards-section-background: var(--color-blue-50);
|
|
1633
|
-
--layout-awards-banner-max-width: 37.5rem; /* legacy narrow cap; prefer cluster */
|
|
1634
1710
|
--layout-awards-cluster-max-width: 49.5625rem; /* 793px — trust banner column */
|
|
1635
1711
|
--layout-awards-intro-max-width: 39.4375rem; /* 631px — headline stack */
|
|
1636
|
-
/*
|
|
1637
|
-
|
|
1638
|
-
|
|
1712
|
+
/* The page column has no width token of its own. --content-width-max,
|
|
1713
|
+
above, is a 1200px cap that no component reads; only the blog's own
|
|
1714
|
+
token copy aliases it. The page column is an implementation --
|
|
1639
1715
|
src/components/shared/ensemble.css.js -- on the grid container scale
|
|
1640
1716
|
above (--grid-container-max-* with --grid-padding-*), which is what
|
|
1641
1717
|
Foundations/Grid System documented and nothing had built. A width token
|
|
1642
1718
|
here is how six ensembles came to hold one literal each and seven other
|
|
1643
|
-
modules a different one. This padding step stays
|
|
1644
|
-
|
|
1719
|
+
modules a different one. This padding step stays because bd-features
|
|
1720
|
+
reads it for its inline padding; the blog declares its own copy and
|
|
1721
|
+
does not read this one. */
|
|
1645
1722
|
--layout-ensemble-inline-padding: var(--spacing-24);
|
|
1646
1723
|
|
|
1647
1724
|
`;
|
|
@@ -32,7 +32,7 @@ const ROLES = [
|
|
|
32
32
|
['label-small', 'label', 'A small label: a badge, a tag, a field hint.'],
|
|
33
33
|
['label-extra-small', 'label', 'The smallest label step, 11px.'],
|
|
34
34
|
['caption-default', 'caption', 'Text under an image or a figure.'],
|
|
35
|
-
['caption-small', 'caption', 'The same,
|
|
35
|
+
['caption-small', 'caption', 'The same size, tracked wider: 0.025em against none.'],
|
|
36
36
|
['link-standalone', 'link', 'A link that is not inside a sentence.'],
|
|
37
37
|
['code-block', 'code', 'A block of monospaced code.']
|
|
38
38
|
];
|
package/src/stories/Button.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { html } from 'lit';
|
|
2
|
-
import { styleMap } from 'lit/directives/style-map.js';
|
|
3
|
-
|
|
4
|
-
import './button.css';
|
|
5
|
-
|
|
6
|
-
/** Primary UI component for user interaction */
|
|
7
|
-
export const Button = ({ primary, backgroundColor = null, size, label, onClick }) => {
|
|
8
|
-
const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
|
|
9
|
-
|
|
10
|
-
return html`
|
|
11
|
-
<button
|
|
12
|
-
type="button"
|
|
13
|
-
class=${['storybook-button', `storybook-button--${size || 'medium'}`, mode].join(' ')}
|
|
14
|
-
style=${styleMap({ backgroundColor })}
|
|
15
|
-
@click=${onClick}
|
|
16
|
-
>
|
|
17
|
-
${label}
|
|
18
|
-
</button>
|
|
19
|
-
`;
|
|
20
|
-
};
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { fn } from '@storybook/test';
|
|
2
|
-
|
|
3
|
-
import { Button } from './Button';
|
|
4
|
-
|
|
5
|
-
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
|
|
6
|
-
export default {
|
|
7
|
-
title : 'Example/Button',
|
|
8
|
-
tags : ['autodocs'],
|
|
9
|
-
render : (args) => Button(args),
|
|
10
|
-
argTypes: {
|
|
11
|
-
backgroundColor: { control: 'color' },
|
|
12
|
-
size : {
|
|
13
|
-
control: { type: 'select' },
|
|
14
|
-
options: ['small', 'medium', 'large']
|
|
15
|
-
}
|
|
16
|
-
},
|
|
17
|
-
args: { onClick: fn() }
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
|
|
21
|
-
export const Primary = {
|
|
22
|
-
args: {
|
|
23
|
-
primary: true,
|
|
24
|
-
label : 'Button'
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export const Secondary = {
|
|
29
|
-
args: {
|
|
30
|
-
label: 'Button'
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export const Large = {
|
|
35
|
-
args: {
|
|
36
|
-
size : 'large',
|
|
37
|
-
label: 'Button'
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export const Small = {
|
|
42
|
-
args: {
|
|
43
|
-
size : 'small',
|
|
44
|
-
label: 'Button'
|
|
45
|
-
}
|
|
46
|
-
};
|