@repobit/dex-system-design 1.0.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +81 -0
- package/README.md +43 -12
- package/package.json +4 -2
- 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
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"bd-compare-section: component declares \"scoreLabel\" but the manifest omits it",
|
|
52
52
|
"bd-compare-section: component declares \"variant\" but the manifest omits it",
|
|
53
53
|
"bd-contact-button: component declares \"buyLink\" but the manifest omits it",
|
|
54
|
+
"bd-contact-button: component declares \"description\" but the manifest omits it",
|
|
54
55
|
"bd-contact-button: component declares \"disabled\" but the manifest omits it",
|
|
55
56
|
"bd-contact-button: component declares \"fontSize\" but the manifest omits it",
|
|
56
57
|
"bd-contact-button: component declares \"fontWeight\" but the manifest omits it",
|
|
@@ -64,6 +65,7 @@
|
|
|
64
65
|
"bd-contact-button: component declares \"strong\" but the manifest omits it",
|
|
65
66
|
"bd-contact-button: component declares \"surface\" but the manifest omits it",
|
|
66
67
|
"bd-contact-button: component declares \"target\" but the manifest omits it",
|
|
68
|
+
"bd-contact-button: component declares \"variant\" but the manifest omits it",
|
|
67
69
|
"bd-feature-col is registered by ./features but absent from the manifest",
|
|
68
70
|
"bd-features is registered by ./features but absent from the manifest",
|
|
69
71
|
"bd-features-tab is registered by ./features-tab but absent from the manifest",
|
|
@@ -58,6 +58,12 @@ export const accordionItem = css`
|
|
|
58
58
|
position: relative;
|
|
59
59
|
z-index: var(--z-base);
|
|
60
60
|
box-shadow: var(--focus-outline-primary);
|
|
61
|
+
/* forced-colors mode does not paint box-shadow, so the ring
|
|
62
|
+
vanishes there; it does paint an outline, in a system colour. This one
|
|
63
|
+
is transparent everywhere else, and the offset lands it on the ring's
|
|
64
|
+
outer band. */
|
|
65
|
+
outline: var(--border-width-2) solid transparent;
|
|
66
|
+
outline-offset: var(--focus-outline-offset);
|
|
61
67
|
}
|
|
62
68
|
|
|
63
69
|
:host(:last-child) {
|
|
@@ -367,7 +373,12 @@ export const accordionSection = css`
|
|
|
367
373
|
}
|
|
368
374
|
|
|
369
375
|
.user-guide-link a:focus-visible {
|
|
370
|
-
|
|
376
|
+
/* forced-colors mode does not paint box-shadow, so the ring
|
|
377
|
+
vanishes there; it does paint an outline, in a system colour. This one
|
|
378
|
+
is transparent everywhere else, and the offset lands it on the ring's
|
|
379
|
+
outer band. */
|
|
380
|
+
outline: var(--border-width-2) solid transparent;
|
|
381
|
+
outline-offset: var(--focus-outline-offset);
|
|
371
382
|
box-shadow: var(--focus-outline-primary);
|
|
372
383
|
border-radius: var(--focus-outline-radius);
|
|
373
384
|
}
|
|
@@ -31,7 +31,7 @@ class AgentEndpoints extends LitElement {
|
|
|
31
31
|
return html`
|
|
32
32
|
<div class="bd-ensemble bd-agentendpoints-wrapper">
|
|
33
33
|
${this.eyebrow
|
|
34
|
-
? html`<bd-p variant="
|
|
34
|
+
? html`<bd-p variant="eyebrow" class="bd-agentendpoints-eyebrow"><slot name="eyebrow">${this.eyebrow}</slot></bd-p>`
|
|
35
35
|
: nothing}
|
|
36
36
|
|
|
37
37
|
${this.title
|
|
@@ -177,7 +177,17 @@ export const alertCSS = css`
|
|
|
177
177
|
display: none;
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
+
/* A 24px target around the 16px icon. The button was the icon and
|
|
181
|
+
nothing else, 16x16, under the 24px WCAG 2.5.8 asks of a pointer target
|
|
182
|
+
-- and an alert's close button is the one control on it a reader is
|
|
183
|
+
trying to hit. The ::before below is that target: it reaches
|
|
184
|
+
--spacing-4 past the button on each side, and a click on it is a click
|
|
185
|
+
on the button -- 24x24 at the default text size, and larger, never
|
|
186
|
+
smaller, for a reader who enlarges their text, since the reach is rem.
|
|
187
|
+
The button's own box is unchanged, so the icon sits exactly where it did
|
|
188
|
+
and the alert is no taller. */
|
|
180
189
|
.dismiss {
|
|
190
|
+
position: relative;
|
|
181
191
|
flex: none;
|
|
182
192
|
display: flex;
|
|
183
193
|
padding: var(--spacing-0);
|
|
@@ -188,9 +198,20 @@ export const alertCSS = css`
|
|
|
188
198
|
cursor: pointer;
|
|
189
199
|
}
|
|
190
200
|
|
|
201
|
+
.dismiss::before {
|
|
202
|
+
content: "";
|
|
203
|
+
position: absolute;
|
|
204
|
+
inset: calc(-1 * var(--spacing-4));
|
|
205
|
+
}
|
|
206
|
+
|
|
191
207
|
/* One token, one painter -- the same invariant accordion.css.js records. */
|
|
192
208
|
.dismiss:focus-visible {
|
|
193
|
-
|
|
209
|
+
/* forced-colors mode does not paint box-shadow, so the ring
|
|
210
|
+
vanishes there; it does paint an outline, in a system colour. This one
|
|
211
|
+
is transparent everywhere else, and the offset lands it on the ring's
|
|
212
|
+
outer band. */
|
|
213
|
+
outline: var(--border-width-2) solid transparent;
|
|
214
|
+
outline-offset: var(--focus-outline-offset);
|
|
194
215
|
box-shadow: var(--focus-outline-primary);
|
|
195
216
|
}
|
|
196
217
|
`;
|
|
@@ -54,7 +54,12 @@ export const anchorNavStyles = css`
|
|
|
54
54
|
.bd-anchor-nav__dropdown-toggle:focus-visible,
|
|
55
55
|
.bd-anchor-nav__dropdown-option:focus-visible {
|
|
56
56
|
/* the one focus ring — see Foundations/Focus */
|
|
57
|
-
|
|
57
|
+
/* forced-colors mode does not paint box-shadow, so the ring
|
|
58
|
+
vanishes there; it does paint an outline, in a system colour. This one
|
|
59
|
+
is transparent everywhere else, and the offset lands it on the ring's
|
|
60
|
+
outer band. */
|
|
61
|
+
outline: var(--border-width-2) solid transparent;
|
|
62
|
+
outline-offset: var(--focus-outline-offset);
|
|
58
63
|
box-shadow: var(--focus-outline-primary);
|
|
59
64
|
/* No border-radius here, for the reason back.css.js records: the ring is a
|
|
60
65
|
box-shadow and already follows the shape of what it sits on, and both of
|
|
@@ -33,7 +33,12 @@ export const annotationCSS = css`
|
|
|
33
33
|
/* the one focus ring — see Foundations/Focus. A two-colour ring whose
|
|
34
34
|
white inner band keeps it visible on a coloured or dark surface, which
|
|
35
35
|
a single-colour outline cannot do. */
|
|
36
|
-
|
|
36
|
+
/* forced-colors mode does not paint box-shadow, so the ring
|
|
37
|
+
vanishes there; it does paint an outline, in a system colour. This one
|
|
38
|
+
is transparent everywhere else, and the offset lands it on the ring's
|
|
39
|
+
outer band. */
|
|
40
|
+
outline: var(--border-width-2) solid transparent;
|
|
41
|
+
outline-offset: var(--focus-outline-offset);
|
|
37
42
|
box-shadow: var(--focus-outline-primary);
|
|
38
43
|
border-radius: var(--focus-outline-radius);
|
|
39
44
|
}
|
|
@@ -146,10 +146,12 @@ export const LayerModel = () =>
|
|
|
146
146
|
lede : 'Foundations, Atoms, Components, Modules, Layout, and internal primitives — what each one owns in ' +
|
|
147
147
|
'this repository, with the rules for adding to them. Derived from the library as it stands, not from a ' +
|
|
148
148
|
'textbook hierarchy.',
|
|
149
|
-
note: html`This page is documentation
|
|
150
|
-
<code>lint:tokens</code>
|
|
151
|
-
<code>
|
|
152
|
-
<code>
|
|
149
|
+
note: html`This page is documentation, and where it is filed changes nothing the gates
|
|
150
|
+
believe. <code>lint:tokens</code> and <code>verify:typography</code> read each unit’s layer
|
|
151
|
+
from <code>scripts/architecture.json</code>, keyed on its source path — not from a story’s
|
|
152
|
+
<code>title</code>, which is what they used to read — so a page can be moved between groups
|
|
153
|
+
without changing what is enforced. This one is recorded there as <code>FOUNDATION</code>; see
|
|
154
|
+
<em>Where classification lives</em> below.`,
|
|
153
155
|
children: html`
|
|
154
156
|
${refSection({ name: 'The six layers', meta: 'what belongs where', children: layerTable() })}
|
|
155
157
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LitElement, html } from 'lit';
|
|
1
|
+
import { LitElement, html, nothing } from 'lit';
|
|
2
2
|
// Installs the design tokens into document scope; see src/tokens/tokens.js
|
|
3
3
|
import '../../tokens/tokens.js';
|
|
4
4
|
import { avatarCSS } from './avatar.css.js';
|
|
@@ -8,9 +8,10 @@ export class BdAvatar extends LitElement {
|
|
|
8
8
|
static styles = [avatarCSS];
|
|
9
9
|
|
|
10
10
|
static properties = {
|
|
11
|
-
src
|
|
12
|
-
name: { type: String },
|
|
13
|
-
size: { type: String, reflect: true }
|
|
11
|
+
src : { type: String },
|
|
12
|
+
name : { type: String },
|
|
13
|
+
size : { type: String, reflect: true },
|
|
14
|
+
_failed: { state: true }
|
|
14
15
|
};
|
|
15
16
|
|
|
16
17
|
constructor() {
|
|
@@ -23,17 +24,42 @@ export class BdAvatar extends LitElement {
|
|
|
23
24
|
willUpdate(changed) {
|
|
24
25
|
// small / default / large still resolve; see shared/prop-vocabulary.js
|
|
25
26
|
if (changed.has('size')) this.size = resolveSize(this.size, 'md');
|
|
27
|
+
// a new image gets its own chance to load
|
|
28
|
+
if (changed.has('src')) this._failed = false;
|
|
26
29
|
}
|
|
27
30
|
|
|
31
|
+
/* The first letter of each word, at most two, upper-cased. name can be
|
|
32
|
+
null -- a removed attribute sets it so -- and used to throw on split. */
|
|
33
|
+
get _initials() {
|
|
34
|
+
return (this.name ?? '').trim()
|
|
35
|
+
.split(/\s+/)
|
|
36
|
+
.map(w => w[0] || '')
|
|
37
|
+
.join('')
|
|
38
|
+
.slice(0, 2)
|
|
39
|
+
.toUpperCase();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* THE FALLBACKS.
|
|
43
|
+
An image that fails to load used to stay on screen as an empty circle;
|
|
44
|
+
it now falls back to the initials, as having no src does.
|
|
45
|
+
|
|
46
|
+
With no name there is nothing to say, so the avatar is hidden from
|
|
47
|
+
assistive technology instead of being announced: it used to be an img
|
|
48
|
+
named "Avatar", which tells a screen reader user only that a picture is
|
|
49
|
+
there, on every avatar in a list. */
|
|
28
50
|
render() {
|
|
51
|
+
const name = (this.name ?? '').trim();
|
|
52
|
+
const showImage = this.src && !this._failed;
|
|
29
53
|
return html`
|
|
30
|
-
<span
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
54
|
+
<span
|
|
55
|
+
class="avatar"
|
|
56
|
+
role=${name ? 'img' : nothing}
|
|
57
|
+
aria-label=${name || nothing}
|
|
58
|
+
aria-hidden=${name ? nothing : 'true'}
|
|
59
|
+
>
|
|
60
|
+
${showImage
|
|
61
|
+
? html`<img src=${this.src} alt="" @error=${() => { this._failed = true; }} />`
|
|
62
|
+
: this._initials}
|
|
37
63
|
</span>
|
|
38
64
|
`;
|
|
39
65
|
}
|
|
@@ -23,7 +23,7 @@ there is no image.
|
|
|
23
23
|
|---|---|---|
|
|
24
24
|
| \`src\` | image URL — omit to fall back to initials | \`''\` |
|
|
25
25
|
| \`name\` | the person's name | \`''\` |
|
|
26
|
-
| \`size\` | \`
|
|
26
|
+
| \`size\` | \`sm\`, \`md\`, \`lg\` — \`small\` / \`default\` / \`large\` still resolve | \`md\` |
|
|
27
27
|
|
|
28
28
|
### Always pass a name
|
|
29
29
|
\`name\` does two jobs. It is the source of the initials when there is no \`src\`,
|
|
@@ -31,9 +31,13 @@ and it is the accessible name in both cases — the wrapper carries
|
|
|
31
31
|
\`role="img"\` with \`aria-label\` from \`name\`, and the inner image is given an
|
|
32
32
|
empty \`alt\` so it is not announced twice.
|
|
33
33
|
|
|
34
|
-
Without a \`name\` the
|
|
35
|
-
|
|
36
|
-
an image.
|
|
34
|
+
Without a \`name\` the avatar has nothing to say, so it is hidden from assistive
|
|
35
|
+
technology rather than announced — it used to be an image named "Avatar", which
|
|
36
|
+
tells a screen reader user nothing. Pass one even when you have an image.
|
|
37
|
+
|
|
38
|
+
### When the image does not load
|
|
39
|
+
A \`src\` that fails to load falls back to the initials, the same as no \`src\`
|
|
40
|
+
at all. A new \`src\` gets its own chance to load.
|
|
37
41
|
|
|
38
42
|
### How the initials are derived
|
|
39
43
|
The first letter of each whitespace-separated word, capped at two characters
|
|
@@ -57,9 +61,9 @@ first and last.
|
|
|
57
61
|
},
|
|
58
62
|
size: {
|
|
59
63
|
control : { type: 'select' },
|
|
60
|
-
options : ['
|
|
64
|
+
options : ['sm', 'md', 'lg'],
|
|
61
65
|
description: 'Diameter of the avatar.',
|
|
62
|
-
table : { type: { summary: 'string' }, defaultValue: { summary:
|
|
66
|
+
table : { type: { summary: 'string' }, defaultValue: { summary: 'md' }, category: 'Appearance' }
|
|
63
67
|
}
|
|
64
68
|
}
|
|
65
69
|
};
|
|
@@ -203,136 +203,21 @@ export const awardsFlexCSS = css`
|
|
|
203
203
|
margin: 0;
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
-
/* ===
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
.bd-awardsflex-dots {
|
|
216
|
-
display: flex;
|
|
217
|
-
/* The buttons below carry their own 24px of target, so the space between
|
|
218
|
-
two dots now comes from the boxes rather than from a gap. Adding one on
|
|
219
|
-
top would push them apart without making either easier to hit. */
|
|
220
|
-
gap: 0;
|
|
206
|
+
/* === SLIDE CONTROLS ===
|
|
207
|
+
bd-pagination-dots, which also runs the autoplay clock. This file used to
|
|
208
|
+
draw its own dots and pause button -- a dot row that called itself a
|
|
209
|
+
tablist with no tabpanels, resting dots at neutral-300 (2.10:1 on the
|
|
210
|
+
tint, under the 3:1 a control needs), and a setInterval the dots knew
|
|
211
|
+
nothing about. The atom owns all of that now; the margin is all that is
|
|
212
|
+
left to decide here. */
|
|
213
|
+
bd-pagination-dots {
|
|
221
214
|
margin-top: var(--spacing-8);
|
|
222
215
|
}
|
|
223
216
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
border: var(--border-width-1) solid var(--color-border-default);
|
|
229
|
-
border-radius: var(--radius-full);
|
|
230
|
-
color: var(--color-text-muted);
|
|
231
|
-
font-family: var(--typography-fontFamily-sans);
|
|
232
|
-
/* no role: four roles sit at this size and each fails differently, so the
|
|
233
|
-
size stays a primitive. Note the weight is not declared here at all --
|
|
234
|
-
it inherits 400 -- which is why two of these are about what adopting a
|
|
235
|
-
role would ADD.
|
|
236
|
-
.
|
|
237
|
-
caption-default matches every value exactly, including the colour token:
|
|
238
|
-
xs / 400 / 1.5 / tracking 0 / sans, and its own colour axis is
|
|
239
|
-
--color-text-muted, which is what this rule already declares two lines
|
|
240
|
-
up. It renders as the same pixels. It is declined anyway, because
|
|
241
|
-
vertical-rhythm.stories.js documents it as "text under an image or a
|
|
242
|
-
figure" and this is the visible label of a toggle button. A
|
|
243
|
-
five-axis-plus-colour identity is the most seductive form of choosing a
|
|
244
|
-
role by its value rather than its meaning -- not an exemption from
|
|
245
|
-
CLAUDE.md's rule against that, but the case the rule is for.
|
|
246
|
-
.
|
|
247
|
-
caption-small carries the same wrong meaning and adds
|
|
248
|
-
letterSpacing-wide, which has no job on a five-letter word.
|
|
249
|
-
.
|
|
250
|
-
label-small is the right family -- "a small label: a badge, a tag, a
|
|
251
|
-
field hint" -- but the wrong result: it would declare a weight of 500
|
|
252
|
-
where nothing is declared today, and add wide tracking, making the
|
|
253
|
-
control bolder and 2.2px wider. This control is deliberately recessive:
|
|
254
|
-
muted, 2px of vertical padding, sitting beside the carousel dots as
|
|
255
|
-
chrome whose job is not to compete with the quote cards. Adopting a role
|
|
256
|
-
should not invert that.
|
|
257
|
-
.
|
|
258
|
-
control-label-small is the right meaning -- built for the name of a
|
|
259
|
-
control -- and fails on the leading. See the line below. */
|
|
260
|
-
font-size: var(--typography-fontSize-xs);
|
|
261
|
-
/* no role: and this leading in particular cannot move. The line box is
|
|
262
|
-
18px, which with 2px of padding and a 1px border makes the button
|
|
263
|
-
exactly 24px -- the same 24px as the .bd-awardsflex-dot buttons it shares
|
|
264
|
-
a row with, which are 24 square deliberately for the WCAG 2.5.8 target
|
|
265
|
-
size the comment further down explains.
|
|
266
|
-
.
|
|
267
|
-
control-label-small would take the line box to 15px and the button to
|
|
268
|
-
21px, misaligning it from the dots. Its tight leading exists for controls
|
|
269
|
-
whose height is DERIVED from padding + fontSize x lineHeight, the way
|
|
270
|
-
form-field computes one. This button's height is not derived -- it is
|
|
271
|
-
matched to a sibling. So the constraint is a pixel alignment between two
|
|
272
|
-
controls in one row, and nothing else in this file says so: a later pass
|
|
273
|
-
adopting control-label-small on meaning alone would quietly break the
|
|
274
|
-
row. */
|
|
275
|
-
line-height: var(--typography-lineHeight-normal);
|
|
276
|
-
cursor: pointer;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
.bd-awardsflex-autoplay-toggle:hover {
|
|
280
|
-
color: var(--color-text-primary);
|
|
281
|
-
border-color: var(--color-border-strong);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
.bd-awardsflex-autoplay-toggle:focus-visible {
|
|
285
|
-
/* the one focus ring — see Foundations/Focus */
|
|
286
|
-
outline: none;
|
|
287
|
-
box-shadow: var(--focus-outline-primary);
|
|
288
|
-
border-radius: var(--focus-outline-radius);
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
/* An 8px dot was an 8px target, which is a third of what WCAG 2.5.8 asks and
|
|
292
|
-
close enough to its neighbour that the 24px circles would have overlapped
|
|
293
|
-
as well. The button is the target and the dot is only what you see, so the
|
|
294
|
-
button is 24 square and the dot is drawn inside it at the size it always
|
|
295
|
-
was. Nothing about the component looks bigger; the part you can hit does. */
|
|
296
|
-
.bd-awardsflex-dot {
|
|
297
|
-
width: var(--dimension-24);
|
|
298
|
-
height: var(--dimension-24);
|
|
299
|
-
display: grid;
|
|
300
|
-
place-items: center;
|
|
301
|
-
border: none;
|
|
302
|
-
background: transparent;
|
|
303
|
-
padding: 0;
|
|
304
|
-
cursor: pointer;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
.bd-awardsflex-dot::before {
|
|
308
|
-
content: "";
|
|
309
|
-
width: var(--spacing-8);
|
|
310
|
-
height: var(--spacing-8);
|
|
311
|
-
border-radius: 50%;
|
|
312
|
-
background: var(--color-neutral-300);
|
|
313
|
-
transition: background var(--transition-duration-normal) var(--transition-easing-ease),
|
|
314
|
-
transform var(--transition-duration-normal) var(--transition-easing-ease);
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
.bd-awardsflex-dot.active::before {
|
|
318
|
-
/* The current slide's mark, and it takes the indicator role now that the
|
|
319
|
-
role is not named for a shape. --indicator-color IS blue-500, so nothing
|
|
320
|
-
moves; what changes is that this dot and the tab/nav underlines can no
|
|
321
|
-
longer drift apart, which is the reason the role exists.
|
|
322
|
-
.
|
|
323
|
-
The geometry stays local on purpose: an underline slides its width, a dot
|
|
324
|
-
scales, so --indicator-underline-height and its transition are not this
|
|
325
|
-
component's to borrow. */
|
|
326
|
-
background: var(--indicator-color);
|
|
327
|
-
transform: scale(1.2);
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
.bd-awardsflex-dot:focus-visible {
|
|
331
|
-
/* the one focus ring — see Foundations/Focus. It follows the target, not
|
|
332
|
-
the dot, so keyboard focus is visible at the size the button really is. */
|
|
333
|
-
outline: none;
|
|
334
|
-
box-shadow: var(--focus-outline-primary);
|
|
335
|
-
border-radius: var(--radius-full);
|
|
217
|
+
@media (prefers-reduced-motion: reduce) {
|
|
218
|
+
.bd-awardsflex-carousel-track {
|
|
219
|
+
transition: none;
|
|
220
|
+
}
|
|
336
221
|
}
|
|
337
222
|
|
|
338
223
|
@media ${unsafeCSS(below('sm'))} {
|
|
@@ -342,12 +227,29 @@ export const awardsFlexCSS = css`
|
|
|
342
227
|
min-height: var(--bd-awardsflex-min-height-mobile, 280px);
|
|
343
228
|
}
|
|
344
229
|
|
|
345
|
-
.
|
|
346
|
-
|
|
230
|
+
/* The static row stacks. The carousel slide does not: below sm it holds
|
|
231
|
+
one card, and in a column the card's 200px flex-basis became its
|
|
232
|
+
height. In the row it fills the width and takes its own height. */
|
|
233
|
+
.bd-awardsflex-quotes-row {
|
|
347
234
|
flex-direction: column;
|
|
348
235
|
align-items: center;
|
|
349
236
|
}
|
|
350
237
|
|
|
238
|
+
/* A stacked card is as tall as what it holds. In the column, the card's
|
|
239
|
+
200px flex-basis became its height and the 160px min-height had nothing
|
|
240
|
+
left to do -- it keeps cards that stand side by side the same height,
|
|
241
|
+
and stacked cards stand side by side with nothing. Measured at 390:
|
|
242
|
+
200px cards whose content ended at 111 and 132. The width is the
|
|
243
|
+
column's, so a short quote no longer hugs its source line.
|
|
244
|
+
.
|
|
245
|
+
The carousel slide keeps the min-height: there it stops the section
|
|
246
|
+
jumping in height from one slide to the next. */
|
|
247
|
+
.bd-awardsflex-quotes-row .bd-awardsflex-quote-card {
|
|
248
|
+
flex: none;
|
|
249
|
+
width: 100%;
|
|
250
|
+
min-height: 0;
|
|
251
|
+
}
|
|
252
|
+
|
|
351
253
|
.bd-awardsflex-quote-card {
|
|
352
254
|
max-width: none;
|
|
353
255
|
}
|