@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
|
@@ -79,6 +79,11 @@ export default css`
|
|
|
79
79
|
boundary, so the value is switched rather than the rule */
|
|
80
80
|
--bd-button-accent-ring: var(--button-accent-ring-default);
|
|
81
81
|
|
|
82
|
+
/* the focus ring is switched the same way: surface="dark" swaps the blue
|
|
83
|
+
outline for a white one. white and outline-white do not read this; see
|
|
84
|
+
FOCUS. */
|
|
85
|
+
--bd-button-focus-ring: var(--button-shared-focus-outline);
|
|
86
|
+
|
|
82
87
|
--bd-button-border-width: var(--border-width-2);
|
|
83
88
|
}
|
|
84
89
|
|
|
@@ -121,14 +126,29 @@ export default css`
|
|
|
121
126
|
FOCUS
|
|
122
127
|
The design specifies no focus state, but 2.4.7 requires one.
|
|
123
128
|
|
|
129
|
+
The ring is an outline held 2px off the control, and the 2px between is
|
|
130
|
+
left transparent, so it is whatever surface the button sits on. That is
|
|
131
|
+
the one thing code can do here that Figma cannot, and it is why the two
|
|
132
|
+
differ. Figma builds a ring from spread shadows, every band of which is a
|
|
133
|
+
painted colour, so its library paints the gap and keeps one ring per
|
|
134
|
+
surface: focus/ring-primary on light, focus/ring-inverse on dark and
|
|
135
|
+
brand. Painted in code, that gap is what went wrong twice: a white band
|
|
136
|
+
merged into a white fill on surface="dark", and the neutral-900 band
|
|
137
|
+
that replaced it drew a black outline round every button on a brand
|
|
138
|
+
hero. A transparent gap cannot do either, on any surface.
|
|
139
|
+
|
|
140
|
+
So only the colour switches: blue on light, white under surface="dark",
|
|
141
|
+
which covers a brand hero and a neutral one alike; the numbers are on
|
|
142
|
+
--focus-outline-traditional. Every variant takes the same ring, ghost
|
|
143
|
+
included. An outline is also kept in forced-colors mode, where a
|
|
144
|
+
box-shadow ring is not drawn at all.
|
|
145
|
+
|
|
146
|
+
The rule leaves box-shadow alone, so an outlined variant's own boundary
|
|
147
|
+
in --bd-button-edge stays put while focused.
|
|
148
|
+
|
|
124
149
|
This used to be driven from JavaScript: two requestAnimationFrame hops
|
|
125
150
|
checked :focus-visible and set a data attribute the CSS then styled.
|
|
126
|
-
:focus-visible does that natively
|
|
127
|
-
is the shared one from Foundations/Focus — a two-colour ring whose white
|
|
128
|
-
inner band keeps it visible on a coloured hero, which the old
|
|
129
|
-
single-colour outline could not do. It is composed with
|
|
130
|
-
--bd-button-edge rather than replacing it, so an outlined variant keeps
|
|
131
|
-
its own boundary while focused; see the note on that property.
|
|
151
|
+
:focus-visible does that natively.
|
|
132
152
|
============================================ */
|
|
133
153
|
button:focus,
|
|
134
154
|
a:focus {
|
|
@@ -136,21 +156,17 @@ export default css`
|
|
|
136
156
|
}
|
|
137
157
|
|
|
138
158
|
.button:focus-visible {
|
|
139
|
-
outline:
|
|
140
|
-
|
|
159
|
+
outline: var(--bd-button-focus-ring);
|
|
160
|
+
outline-offset: var(--button-shared-focus-outlineOffset);
|
|
141
161
|
}
|
|
142
162
|
|
|
143
|
-
/*
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
against the button's own fill and the blue band 2.38:1 against the hero
|
|
148
|
-
(1.75:1 at the gradient's light end), so neither reached the 3:1 WCAG
|
|
149
|
-
2.4.11 asks. outline-white is here too because restoring its boundary
|
|
150
|
-
above puts a white border where the white band used to sit on the hero. */
|
|
163
|
+
/* white and outline-white are presets for a coloured banner and ignore
|
|
164
|
+
surface, so they take the white ring on their own: 4.53:1 on blue-500,
|
|
165
|
+
7.95:1 at the light end of the banner gradient. A blue ring there was
|
|
166
|
+
2.38:1, and 1.75:1 at that end. */
|
|
151
167
|
.button--white:focus-visible,
|
|
152
168
|
.button--outline-white:focus-visible {
|
|
153
|
-
|
|
169
|
+
outline: var(--focus-outline-traditional-inverse);
|
|
154
170
|
}
|
|
155
171
|
|
|
156
172
|
a.button {
|
|
@@ -175,14 +191,14 @@ export default css`
|
|
|
175
191
|
vertical-align: middle;
|
|
176
192
|
box-sizing: border-box;
|
|
177
193
|
|
|
178
|
-
/* The variant's own boundary, held in a custom property so
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
a
|
|
194
|
+
/* The variant's own boundary, held in a custom property so each state can
|
|
195
|
+
switch it. It was introduced while the focus ring was a box-shadow, so
|
|
196
|
+
the ring could COMPOSE with it: box-shadow is a single list, not
|
|
197
|
+
additive, and .button:focus-visible (0,2,0) outranks .button--ghost
|
|
198
|
+
(0,1,0) -- so a focus rule that declared box-shadow directly erased the
|
|
199
|
+
border of every outlined variant, and a focused ghost button read as a
|
|
200
|
+
tertiary one. The ring is an outline now and does not touch box-shadow;
|
|
201
|
+
a focus rule that goes back to declaring it brings that defect back. */
|
|
186
202
|
--bd-button-edge: 0 0 0 0 transparent;
|
|
187
203
|
box-shadow: var(--bd-button-edge);
|
|
188
204
|
|
|
@@ -557,6 +573,11 @@ export default css`
|
|
|
557
573
|
/* unchanged red, plus a boundary against the hero */
|
|
558
574
|
--bd-button-accent-ring: var(--color-neutral-0);
|
|
559
575
|
|
|
576
|
+
/* a white ring, the one colour that clears 3:1 on a brand hero and a
|
|
577
|
+
neutral one alike, which this surface has to cover without knowing
|
|
578
|
+
which it is on. The gap inside it is the hero itself; see FOCUS. */
|
|
579
|
+
--bd-button-focus-ring: var(--focus-outline-traditional-inverse);
|
|
580
|
+
|
|
560
581
|
/* muted downward instead of upward: a neutral-100 fill would read as an
|
|
561
582
|
active control on a dark hero. Exempt from contrast under WCAG 1.4.3. */
|
|
562
583
|
--bd-button-disabled-bg: var(--color-neutral-700); /* no role: on-dark ground; see the block note */
|
|
@@ -29,6 +29,14 @@ const SIZE_CLASS = { sm: "button--small", md: "button--medium", lg: "button--lar
|
|
|
29
29
|
const SURFACES = ["light", "dark"];
|
|
30
30
|
const SHAPES = ["default", "rounded"];
|
|
31
31
|
|
|
32
|
+
/* custom-click bubbles and is composed, like every sibling event in the
|
|
33
|
+
package -- bd-checkbox's and bd-radio's change, bd-switch's and
|
|
34
|
+
bd-custom-input's bd-change. It was a plain Event, which does not bubble,
|
|
35
|
+
so it reached a listener on the button itself and nothing above it: a form
|
|
36
|
+
or a card delegating from a wrapper heard nothing. composed carries it out
|
|
37
|
+
of any shadow root the button is rendered inside, too. */
|
|
38
|
+
const clickEvent = () => new CustomEvent("custom-click", { bubbles: true, composed: true });
|
|
39
|
+
|
|
32
40
|
/**
|
|
33
41
|
* Everything bd-button and bd-button-link share.
|
|
34
42
|
*
|
|
@@ -42,31 +50,37 @@ class BdButtonBase extends LitElement {
|
|
|
42
50
|
static styles = [buttonsCSS];
|
|
43
51
|
|
|
44
52
|
static properties = {
|
|
45
|
-
label
|
|
46
|
-
size
|
|
47
|
-
variant
|
|
53
|
+
label : { type: String },
|
|
54
|
+
size : { type: String },
|
|
55
|
+
variant : { type: String, reflect: true },
|
|
48
56
|
/** @deprecated pass `variant`. kind meant four different things across the
|
|
49
57
|
atoms; on this one it always meant appearance. */
|
|
50
|
-
kind
|
|
51
|
-
fullWidth
|
|
52
|
-
strong
|
|
53
|
-
disabled
|
|
54
|
-
loading
|
|
55
|
-
fontSize
|
|
56
|
-
fontWeight: { type: String, attribute: "font-weight" },
|
|
57
|
-
align
|
|
58
|
-
surface
|
|
58
|
+
kind : { type: String },
|
|
59
|
+
fullWidth : { type: Boolean, attribute: "fullwidth" },
|
|
60
|
+
strong : { type: Boolean },
|
|
61
|
+
disabled : { type: Boolean, reflect: true },
|
|
62
|
+
loading : { type: Boolean, reflect: true },
|
|
63
|
+
fontSize : { type: String, attribute: "font-size" },
|
|
64
|
+
fontWeight : { type: String, attribute: "font-weight" },
|
|
65
|
+
align : { type: String },
|
|
66
|
+
surface : { type: String, reflect: true },
|
|
59
67
|
/** "rounded" takes the pill corner; see .button--rounded. */
|
|
60
|
-
shape
|
|
68
|
+
shape : { type: String, reflect: true },
|
|
61
69
|
/** The accent variant reveals a trailing arrow on hover; this opts out. */
|
|
62
|
-
noArrow
|
|
70
|
+
noArrow : { type: Boolean, attribute: "no-arrow" },
|
|
63
71
|
/* A circle holding one icon instead of a label: the homepage's audience
|
|
64
72
|
cards and the mobile menu toggle. A mode, not a variant, because every
|
|
65
73
|
variant, size, surface and state applies to it unchanged -- which is how
|
|
66
74
|
the Button icon sets in the foundation Figma file are drawn. With no
|
|
67
75
|
visible text there is nothing to name the control, so label becomes
|
|
68
76
|
required rather than optional. */
|
|
69
|
-
iconOnly
|
|
77
|
+
iconOnly : { type: Boolean, attribute: "icon-only", reflect: true },
|
|
78
|
+
/* Extra text a screen reader reads after the name, through
|
|
79
|
+
aria-describedby on the inner control. It has to be carried in here:
|
|
80
|
+
the control is in this shadow root, so an aria-describedby written on
|
|
81
|
+
the host, or pointing at an id outside, never reaches it. bd-tooltip
|
|
82
|
+
sets it on a bd-button trigger; a page can set it directly. */
|
|
83
|
+
description: { type: String }
|
|
70
84
|
};
|
|
71
85
|
|
|
72
86
|
constructor() {
|
|
@@ -90,6 +104,7 @@ class BdButtonBase extends LitElement {
|
|
|
90
104
|
this.shape = "default";
|
|
91
105
|
this.noArrow = false;
|
|
92
106
|
this.iconOnly = false;
|
|
107
|
+
this.description = "";
|
|
93
108
|
}
|
|
94
109
|
|
|
95
110
|
willUpdate(changed) {
|
|
@@ -162,6 +177,14 @@ class BdButtonBase extends LitElement {
|
|
|
162
177
|
* lg 24 against padding 8, 12 and 16 -- so the size passes straight through
|
|
163
178
|
* and the circle comes out 32, 44 and 56.
|
|
164
179
|
*/
|
|
180
|
+
get _describedBy() {
|
|
181
|
+
return this.description ? "description" : nothing;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
get _description() {
|
|
185
|
+
return this.description ? html`<span id="description" hidden>${this.description}</span>` : nothing;
|
|
186
|
+
}
|
|
187
|
+
|
|
165
188
|
get _iconContent() {
|
|
166
189
|
if (this.loading) return html`<span class="spinner" aria-hidden="true"></span>`;
|
|
167
190
|
return html`<slot><bd-arrow-icon size="${this.size}" aria-hidden="true"></bd-arrow-icon></slot>`;
|
|
@@ -173,7 +196,7 @@ class BdButtonBase extends LitElement {
|
|
|
173
196
|
e.stopPropagation();
|
|
174
197
|
return;
|
|
175
198
|
}
|
|
176
|
-
this.dispatchEvent(
|
|
199
|
+
this.dispatchEvent(clickEvent());
|
|
177
200
|
}
|
|
178
201
|
}
|
|
179
202
|
|
|
@@ -186,10 +209,11 @@ class Button extends BdButtonBase {
|
|
|
186
209
|
class="${this._classes}"
|
|
187
210
|
aria-label="${this.label || nothing}"
|
|
188
211
|
aria-busy="${this.loading ? "true" : nothing}"
|
|
212
|
+
aria-describedby="${this._describedBy}"
|
|
189
213
|
?disabled="${this.disabled}"
|
|
190
214
|
style="${this._inlineStyle}"
|
|
191
215
|
@click=${this._handleClick}
|
|
192
|
-
>${this._content}</button
|
|
216
|
+
>${this._content}</button>${this._description}
|
|
193
217
|
`;
|
|
194
218
|
}
|
|
195
219
|
}
|
|
@@ -211,35 +235,11 @@ class ButtonLink extends BdButtonBase {
|
|
|
211
235
|
super();
|
|
212
236
|
this.href = "";
|
|
213
237
|
this.buyLink = false;
|
|
214
|
-
this.shadow = true;
|
|
215
238
|
this.align = "left";
|
|
216
239
|
this.target = "";
|
|
217
240
|
this.rel = "";
|
|
218
241
|
}
|
|
219
242
|
|
|
220
|
-
_onFocusin(e) {
|
|
221
|
-
const el = e.currentTarget;
|
|
222
|
-
requestAnimationFrame(() =>
|
|
223
|
-
requestAnimationFrame(() => {
|
|
224
|
-
if (el.matches(':focus-visible')) {
|
|
225
|
-
this.setAttribute('data-bd-button-focus', '');
|
|
226
|
-
}
|
|
227
|
-
})
|
|
228
|
-
);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
_onFocusout() {
|
|
232
|
-
this.removeAttribute('data-bd-button-focus');
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
get fullWidthClass() {
|
|
236
|
-
return this.fullWidth ? "max--width" : "";
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
get strongClass() {
|
|
240
|
-
return this.strong ? "button--bold" : "";
|
|
241
|
-
}
|
|
242
|
-
|
|
243
243
|
/* Reverse tabnabbing is the reason rather than convention: a new tab opened
|
|
244
244
|
from here keeps a window.opener handle back unless rel says otherwise. An
|
|
245
245
|
explicit rel always wins, so a consumer can still opt out deliberately. */
|
|
@@ -265,11 +265,12 @@ class ButtonLink extends BdButtonBase {
|
|
|
265
265
|
aria-label="${this.label || nothing}"
|
|
266
266
|
aria-busy="${this.loading ? "true" : nothing}"
|
|
267
267
|
aria-disabled="${this.disabled ? "true" : nothing}"
|
|
268
|
+
aria-describedby="${this._describedBy}"
|
|
268
269
|
style="${this._inlineStyle}"
|
|
269
270
|
@click=${this._handleClick}
|
|
270
271
|
?data-store-render="${this.buyLink}"
|
|
271
272
|
?data-store-buy-link="${this.buyLink}"
|
|
272
|
-
>${this._content}</a
|
|
273
|
+
>${this._content}</a>${this._description}
|
|
273
274
|
`;
|
|
274
275
|
}
|
|
275
276
|
}
|
|
@@ -297,7 +298,7 @@ class ContactButton extends LitElement {
|
|
|
297
298
|
}
|
|
298
299
|
|
|
299
300
|
_handleClick() {
|
|
300
|
-
this.dispatchEvent(
|
|
301
|
+
this.dispatchEvent(clickEvent());
|
|
301
302
|
}
|
|
302
303
|
|
|
303
304
|
render() {
|
|
@@ -100,7 +100,7 @@ variant, so every \`variant\`, \`size\`, \`surface\` and state applies unchanged
|
|
|
100
100
|
| \`right\` | Aligns button to the right |
|
|
101
101
|
|
|
102
102
|
### Events
|
|
103
|
-
- \`custom-click\` — dispatched on click or Enter/Space keypress
|
|
103
|
+
- \`custom-click\` — dispatched on click or Enter/Space keypress. It bubbles and is composed, so a wrapper can listen for it
|
|
104
104
|
`
|
|
105
105
|
}
|
|
106
106
|
}
|
|
@@ -430,7 +430,7 @@ export const ButtonKeyboard = {
|
|
|
430
430
|
<p style="font-size:14px; margin-bottom:8px;">Tab to focus, press Enter or Space to trigger.</p>
|
|
431
431
|
<bd-button variant="primary" size="md" label="Keyboard test">Press me</bd-button>
|
|
432
432
|
`,
|
|
433
|
-
parameters: { docs: { description: { story: 'Demonstrates keyboard activation. Enter
|
|
433
|
+
parameters: { docs: { description: { story: 'Demonstrates keyboard activation. Enter and Space trigger `custom-click`.' } } }
|
|
434
434
|
};
|
|
435
435
|
|
|
436
436
|
// ─── bd-button-link Stories ────────────────────────────────────────────────
|
|
@@ -13,7 +13,17 @@ export const captionCSS = css`
|
|
|
13
13
|
color: var(--typography-caption-default-color);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
/* sm takes the caption-small role whole. Today it differs from
|
|
17
|
+
caption-default in tracking alone -- 0.025em against 0, the design's
|
|
18
|
+
caption/small -- so reading only letter-spacing drew the same thing, but
|
|
19
|
+
left the role's other four axes unread, and a change to any of them would
|
|
20
|
+
never have reached the element. The colour stays the default's: the role
|
|
21
|
+
carries none of its own. */
|
|
16
22
|
:host([size='sm']) figcaption {
|
|
23
|
+
font-family: var(--typography-caption-small-fontFamily);
|
|
24
|
+
font-size: var(--typography-caption-small-fontSize);
|
|
25
|
+
font-weight: var(--typography-caption-small-fontWeight);
|
|
26
|
+
line-height: var(--typography-caption-small-lineHeight);
|
|
17
27
|
letter-spacing: var(--typography-caption-small-letterSpacing);
|
|
18
28
|
}
|
|
19
29
|
`;
|
|
@@ -23,11 +23,11 @@ export default {
|
|
|
23
23
|
### Props
|
|
24
24
|
| Prop | Values | Default |
|
|
25
25
|
|---|---|---|
|
|
26
|
-
| \`size\` | \`
|
|
26
|
+
| \`size\` | \`md\`, \`sm\` — \`sm\` is the same size tracked wider (\`caption-small\`); \`default\` / \`small\` still resolve | \`md\` |
|
|
27
27
|
|
|
28
28
|
### Contrast
|
|
29
29
|
The caption is \`--color-neutral-600\`, which is 6.59:1 on white and stays above
|
|
30
|
-
4.5:1 at the \`
|
|
30
|
+
4.5:1 at the \`sm\` size too. Caption text is the most common place a design
|
|
31
31
|
system slips below AA, because it is both small and grey — anything lighter
|
|
32
32
|
than \`neutral-600\` would not clear it.
|
|
33
33
|
|
|
@@ -46,9 +46,9 @@ and reach for this only where the styling alone is wanted.
|
|
|
46
46
|
argTypes: {
|
|
47
47
|
size: {
|
|
48
48
|
control : { type: 'select' },
|
|
49
|
-
options : ['
|
|
49
|
+
options : ['md', 'sm'],
|
|
50
50
|
description: 'Type size of the caption.',
|
|
51
|
-
table : { type: { summary: 'string' }, defaultValue: { summary:
|
|
51
|
+
table : { type: { summary: 'string' }, defaultValue: { summary: 'md' }, category: 'Appearance' }
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
};
|
|
@@ -12,7 +12,10 @@ export default css`
|
|
|
12
12
|
display: block;
|
|
13
13
|
align-items: center;
|
|
14
14
|
position: relative;
|
|
15
|
-
|
|
15
|
+
/* 100px used to stand here, room for two arrows positioned absolutely
|
|
16
|
+
65px below the track. The dots are in the flow now, so the space below
|
|
17
|
+
the track is their margin, their 24px and this: 96. */
|
|
18
|
+
margin-bottom: var(--spacing-48);
|
|
16
19
|
max-width: 100%;
|
|
17
20
|
flex-direction: column;
|
|
18
21
|
}
|
|
@@ -27,17 +30,16 @@ export default css`
|
|
|
27
30
|
hand while leaving its line-height unset, which is how the title came to
|
|
28
31
|
render at the browser's default leading and with the browser's default h2
|
|
29
32
|
margins. LightCarousel and CardFeatures declare no such rule either. */
|
|
30
|
-
div.bd-arrow {
|
|
31
|
-
padding: var(--spacing-2);
|
|
32
|
-
visibility: visible;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
33
|
.bd-box:focus-visible,
|
|
36
|
-
.bd-arrow:focus-visible,
|
|
37
34
|
.bd-plus-button:focus-visible,
|
|
38
35
|
.bd-modal-content button:focus-visible {
|
|
39
36
|
/* the one focus ring — see Foundations/Focus */
|
|
40
|
-
|
|
37
|
+
/* forced-colors mode does not paint box-shadow, so the ring
|
|
38
|
+
vanishes there; it does paint an outline, in a system colour. This one
|
|
39
|
+
is transparent everywhere else, and the offset lands it on the ring's
|
|
40
|
+
outer band. */
|
|
41
|
+
outline: var(--border-width-2) solid transparent;
|
|
42
|
+
outline-offset: var(--focus-outline-offset);
|
|
41
43
|
box-shadow: var(--focus-outline-primary);
|
|
42
44
|
}
|
|
43
45
|
|
|
@@ -59,90 +61,16 @@ export default css`
|
|
|
59
61
|
gap: 1rem;
|
|
60
62
|
padding: 1rem;
|
|
61
63
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
/* The dots: bd-pagination-dots, the package's one set of slide controls.
|
|
65
|
+
Two <img role="button"> arrows stood here, painted by eight data-URI SVGs
|
|
66
|
+
with the blues and the disabled grey baked in as hex -- invisible to every
|
|
67
|
+
colour check -- and positioned absolutely 65px under the track. Where they
|
|
68
|
+
sat, the dots sit now: under the track, at its end. */
|
|
69
|
+
.bd-carousel-controls {
|
|
66
70
|
display: flex;
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
box-shadow: var(--spacing-0) var(--spacing-2) var(--spacing-4) rgba(0, 0, 0, 0.1);
|
|
71
|
-
position: absolute;
|
|
72
|
-
bottom: -65px;
|
|
73
|
-
background: var(--color-surface-brand);
|
|
74
|
-
color: var(--color-text-inverse);
|
|
75
|
-
/* no role: .bd-arrow is an <img> -- left-arrow.svg / right-arrow.svg in
|
|
76
|
-
carousel.js. It renders no text, so this styles nothing but the alt
|
|
77
|
-
text a browser shows when the SVG fails to load. Fallback typography
|
|
78
|
-
is not a role decision. */
|
|
79
|
-
font-size: var(--typography-fontSize-xl);
|
|
80
|
-
/* no role: .bd-arrow is an <img> -- left-arrow.svg / right-arrow.svg in
|
|
81
|
-
carousel.js. It renders no text, so this styles nothing but the alt
|
|
82
|
-
text a browser shows when the SVG fails to load. Fallback typography
|
|
83
|
-
is not a role decision. */
|
|
84
|
-
line-height: var(--typography-lineHeight-none);
|
|
85
|
-
text-align: center;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
.bd-left-arrow {
|
|
89
|
-
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><circle cx="20" cy="20" r="20" transform="matrix(-1 0 0 1 40 0)" fill="%23006DFF"/><path d="M23.3431 14.4142L21.9289 13L14.8579 20.071L16.2721 21.4853L23.3431 14.4142Z" fill="white"/><path d="M16.2721 18.6568L14.8579 20.071L21.9289 27.1421L23.3431 25.7279L16.2721 18.6568Z" fill="white"/></svg>');
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
.bd-left-arrow:hover {
|
|
94
|
-
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><circle cx="20" cy="20" r="20" transform="matrix(-1 0 0 1 40 0)" fill="%230059D6"/><path d="M23.3431 14.4142L21.9289 13L14.8579 20.071L16.2721 21.4853L23.3431 14.4142Z" fill="white"/><path d="M16.2721 18.6568L14.8579 20.071L21.9289 27.1421L23.3431 25.7279L16.2721 18.6568Z" fill="white"/></svg>');
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
.bd-left-arrow:active {
|
|
98
|
-
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><circle cx="20" cy="20" r="20" transform="matrix(-1 0 0 1 40 0)" fill="%230045AD"/><path d="M23.3431 14.4142L21.9289 13L14.8579 20.071L16.2721 21.4853L23.3431 14.4142Z" fill="white"/><path d="M16.2721 18.6568L14.8579 20.071L21.9289 27.1421L23.3431 25.7279L16.2721 18.6568Z" fill="white"/></svg>');
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
.bd-left-arrow:disabled {
|
|
103
|
-
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><circle cx="20" cy="20" r="20" fill="%23F1F2F3"/><path d="M23.3431 14.4142L21.9289 13L14.8579 20.071L16.2721 21.4853L23.3431 14.4142Z" fill="%23A6ADB4"/><path d="M16.2721 18.6568L14.8579 20.071L21.9289 27.1421L23.3431 25.7279L16.2721 18.6568Z" fill="%23A6ADB4"/></svg>');
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
.bd-right-arrow {
|
|
107
|
-
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><circle cx="20" cy="20" r="20" fill="%23006DFF"/><path d="M16.6569 14.4142L18.0711 13L25.1421 20.071L23.7279 21.4853L16.6569 14.4142Z" fill="white"/><path d="M23.7279 18.6568L25.1421 20.071L18.0711 27.1421L16.6569 25.7279L23.7279 18.6568Z" fill="white"/></svg>');
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
.bd-right-arrow:hover {
|
|
112
|
-
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><circle cx="20" cy="20" r="20" fill="%230059D6"/><path d="M16.6569 14.4142L18.0711 13L25.1421 20.071L23.7279 21.4853L16.6569 14.4142Z" fill="white"/><path d="M23.7279 18.6568L25.1421 20.071L18.0711 27.1421L16.6569 25.7279L23.7279 18.6568Z" fill="white"/></svg>');
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
.bd-right-arrow:active {
|
|
117
|
-
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><circle cx="20" cy="20" r="20" fill="%230045AD"/><path d="M16.6569 14.4142L18.0711 13L25.1421 20.071L23.7279 21.4853L16.6569 14.4142Z" fill="white"/><path d="M23.7279 18.6568L25.1421 20.071L18.0711 27.1421L16.6569 25.7279L23.7279 18.6568Z" fill="white"/></svg>');
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
.bd-right-arrow:disabled {
|
|
122
|
-
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><circle cx="20" cy="20" r="20" fill="%23F1F2F3"/><path d="M16.6569 14.4142L18.0711 13L25.1421 20.071L23.7279 21.4853L16.6569 14.4142Z" fill="%23A6ADB4"/><path d="M23.7279 18.6568L25.1421 20.071L18.0711 27.1421L16.6569 25.7279L23.7279 18.6568Z" fill="%23A6ADB4"/></svg>');
|
|
123
|
-
}
|
|
124
|
-
.bd-right-arrow.bd-disabled {
|
|
125
|
-
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><circle cx="20" cy="20" r="20" fill="%23F1F2F3"/><path d="M16.6569 14.4142L18.0711 13L25.1421 20.071L23.7279 21.4853L16.6569 14.4142Z" fill="%23A6ADB4"/><path d="M23.7279 18.6568L25.1421 20.071L18.0711 27.1421L16.6569 25.7279L23.7279 18.6568Z" fill="%23A6ADB4"/></svg>');
|
|
126
|
-
cursor: not-allowed;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
.bd-left-arrow.bd-disabled {
|
|
130
|
-
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><circle cx="20" cy="20" r="20" fill="%23F1F2F3"/><path d="M23.3431 14.4142L21.9289 13L14.8579 20.071L16.2721 21.4853L23.3431 14.4142Z" fill="%23A6ADB4"/><path d="M16.2721 18.6568L14.8579 20.071L21.9289 27.1421L23.3431 25.7279L16.2721 18.6568Z" fill="%23A6ADB4"/></svg>');
|
|
131
|
-
cursor: not-allowed;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
.bd-disabled {
|
|
135
|
-
background: var(--color-neutral-50);
|
|
136
|
-
color: var(--color-text-muted-inverse);
|
|
137
|
-
cursor: not-allowed;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
.bd-arrow:first-of-type {
|
|
141
|
-
right: 60px;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
.bd-arrow:last-of-type {
|
|
145
|
-
right: var(--spacing-10);
|
|
71
|
+
justify-content: flex-end;
|
|
72
|
+
margin-top: var(--spacing-24);
|
|
73
|
+
padding-inline: var(--spacing-10);
|
|
146
74
|
}
|
|
147
75
|
|
|
148
76
|
.bd-carousel-track {
|
|
@@ -259,14 +187,6 @@ export default css`
|
|
|
259
187
|
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40" fill="none"><circle cx="20" cy="20" r="19" fill="%23006DFF" stroke="%23006DFF" stroke-width="2"/><path d="M19 11H21V29H19V11Z" fill="white"/><path d="M29 19V21L11 21L11 19L29 19Z" fill="white"/></svg>');
|
|
260
188
|
}
|
|
261
189
|
|
|
262
|
-
.bd-left-arrow {
|
|
263
|
-
margin-right: var(--spacing-6);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
.bd-right-arrow {
|
|
267
|
-
margin-left: var(--spacing-6);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
190
|
@media ${unsafeCSS(below('md'))} {
|
|
271
191
|
.bd-carousel-track {
|
|
272
192
|
flex-wrap: nowrap;
|
|
@@ -284,23 +204,6 @@ export default css`
|
|
|
284
204
|
max-width: 90%;
|
|
285
205
|
padding: 1.5em;
|
|
286
206
|
}
|
|
287
|
-
|
|
288
|
-
.bd-arrow {
|
|
289
|
-
bottom: -75px;
|
|
290
|
-
/* no role: .bd-arrow is an <img> -- left-arrow.svg / right-arrow.svg in
|
|
291
|
-
carousel.js. It renders no text, so this styles nothing but the alt
|
|
292
|
-
text a browser shows when the SVG fails to load. Fallback typography
|
|
293
|
-
is not a role decision. */
|
|
294
|
-
font-size: var(--typography-fontSize-base);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
.bd-arrow:first-of-type {
|
|
298
|
-
right: 50px;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
.bd-arrow:last-of-type {
|
|
302
|
-
right: var(--spacing-6);
|
|
303
|
-
}
|
|
304
207
|
}
|
|
305
208
|
|
|
306
209
|
@media (max-width: 480px) {
|