barua-ui 0.12.1 → 0.13.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/README.md +2 -1
- package/css/barua.css +1 -0
- package/css/base.css +22 -12
- package/css/components/actions.css +22 -17
- package/css/components/auth.css +1 -3
- package/css/components/content.css +78 -21
- package/css/components/feedback.css +2 -2
- package/css/components/forced-colors.css +60 -0
- package/css/components/forms.css +29 -6
- package/css/components/marketing.css +8 -5
- package/css/components/media.css +66 -2
- package/css/components/nav.css +63 -13
- package/css/components/overlays.css +22 -5
- package/css/components/productivity.css +52 -12
- package/css/components/specialized.css +28 -7
- package/css/tokens.css +61 -9
- package/css/utilities.css +16 -3
- package/dist/index.cjs +37 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +769 -184
- package/dist/index.d.ts +769 -184
- package/dist/index.js +40 -15
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -77,7 +77,8 @@ before first paint.
|
|
|
77
77
|
- **Provider** — `BaruaProvider` (theme / `accent` re-tint / Liquid Glass
|
|
78
78
|
`glass` mode / Tier-2 `refraction`), `ThemeScript`, `useToast`
|
|
79
79
|
- **Actions** — `Button`, `ButtonLink`, `Fab`, `Toolbar`
|
|
80
|
-
- **Forms** — `Field`, `Input`, `Textarea`, `
|
|
80
|
+
- **Forms** — `Field`, `Input`, `Textarea`, `NativeSelect` (the platform
|
|
81
|
+
control; product surfaces use `Dropdown variant="select"`), `Checkbox`, `Radio`,
|
|
81
82
|
`Switch`, `Slider`, `OtpInput`
|
|
82
83
|
- **Content** — `Card` family (incl. `StoryCard`, flush iOS-Settings groups),
|
|
83
84
|
`List`/`ListItem`, `Badge`, `Tag`, `Chip`, `Avatar`(+`AvatarGroup`),
|
package/css/barua.css
CHANGED
package/css/base.css
CHANGED
|
@@ -116,17 +116,23 @@
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
/* ---- Focus ring (Focus Ring component) -------------------------------- */
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
119
|
+
/* One ring for everything that can take focus, on the outline channel, at
|
|
120
|
+
zero specificity so a component can restyle it and nothing can cancel it
|
|
121
|
+
by accident: the old box-shadow ring was silently defeated by any
|
|
122
|
+
component that drew its own shadow. */
|
|
123
|
+
:where(:focus-visible, .b-focus-ring:focus-visible) {
|
|
124
|
+
outline: var(--b-focus-ring);
|
|
125
|
+
outline-offset: var(--b-focus-ring-offset);
|
|
126
|
+
}
|
|
127
|
+
/* Inputs whose host draws the ring for them. */
|
|
128
|
+
:where(.b-cmdk__input, .b-multiselect input):focus-visible { outline: none; }
|
|
129
|
+
/* Rows flush inside a clipping container: an outline outside the box is
|
|
130
|
+
cut off by the container's overflow, so these pull it inward. */
|
|
131
|
+
:where(.b-list-item, .b-disclosure > summary, .b-tab, .b-segmented__item,
|
|
132
|
+
.b-btn-group > .b-btn, .b-menu__item, .b-sidebar__item, .b-rail__item,
|
|
133
|
+
.b-bottomnav__item, .b-cmdk__item, .b-stepper-input :is(button, input),
|
|
134
|
+
.b-action-sheet__group button, .b-swipe__actions button) {
|
|
135
|
+
--b-focus-ring-offset: calc(-1 * var(--b-focus-ring-width));
|
|
130
136
|
}
|
|
131
137
|
|
|
132
138
|
/* ---- Interaction-state conventions ------------------------------------
|
|
@@ -138,11 +144,15 @@
|
|
|
138
144
|
.is-dragging — mid-drag
|
|
139
145
|
:disabled / .is-disabled — non-interactive
|
|
140
146
|
------------------------------------------------------------------------- */
|
|
141
|
-
|
|
147
|
+
/* Dim the control, never the group: a disabled <fieldset> already makes
|
|
148
|
+
every control inside it match :disabled, so dimming the group too stacked
|
|
149
|
+
0.4 x 0.4 = 0.16 and greyed the <legend>, which HTML keeps enabled. */
|
|
150
|
+
:disabled:not(fieldset), .is-disabled {
|
|
142
151
|
opacity: var(--b-opacity-disabled);
|
|
143
152
|
cursor: not-allowed !important;
|
|
144
153
|
pointer-events: var(--b-disabled-pointer, auto);
|
|
145
154
|
}
|
|
155
|
+
fieldset:disabled { cursor: not-allowed; }
|
|
146
156
|
.is-dragging { opacity: 0.55; cursor: grabbing !important; }
|
|
147
157
|
|
|
148
158
|
[draggable="true"] { cursor: grab; }
|
|
@@ -13,14 +13,18 @@
|
|
|
13
13
|
justify-content: center;
|
|
14
14
|
gap: var(--b-space-2);
|
|
15
15
|
height: var(--b-control-h-md);
|
|
16
|
-
padding
|
|
16
|
+
/* The border is real and transparent, the padding pays for it, and the
|
|
17
|
+
rendered box does not move by a pixel. Windows High Contrast strips
|
|
18
|
+
backgrounds and shadows; a button that was only a fill became bare
|
|
19
|
+
words on the page. */
|
|
20
|
+
padding-inline: calc(var(--b-space-4) - 1px);
|
|
17
21
|
font-size: var(--b-text-subheadline);
|
|
18
22
|
font-weight: var(--b-weight-semibold);
|
|
19
23
|
line-height: 1;
|
|
20
24
|
white-space: nowrap;
|
|
21
25
|
color: var(--b-text);
|
|
22
26
|
background: var(--b-fill-secondary);
|
|
23
|
-
border:
|
|
27
|
+
border: 1px solid transparent;
|
|
24
28
|
border-radius: var(--b-radius-md);
|
|
25
29
|
cursor: pointer;
|
|
26
30
|
user-select: none;
|
|
@@ -37,11 +41,11 @@
|
|
|
37
41
|
/* Variants */
|
|
38
42
|
.b-btn--primary {
|
|
39
43
|
color: var(--b-color-on-accent);
|
|
40
|
-
background: var(--b-color-accent);
|
|
44
|
+
background: var(--b-color-accent-fill);
|
|
41
45
|
box-shadow: var(--b-shadow-xs);
|
|
42
46
|
}
|
|
43
|
-
.b-btn--primary:hover { background: var(--b-color-accent-hover); }
|
|
44
|
-
.b-btn--primary.is-active { background: var(--b-color-accent-active); }
|
|
47
|
+
.b-btn--primary:hover { background: var(--b-color-accent-fill-hover); }
|
|
48
|
+
.b-btn--primary.is-active { background: var(--b-color-accent-fill-active); }
|
|
45
49
|
|
|
46
50
|
.b-btn--tinted {
|
|
47
51
|
color: var(--b-color-accent-text);
|
|
@@ -56,7 +60,7 @@
|
|
|
56
60
|
color: var(--b-color-on-accent);
|
|
57
61
|
background:
|
|
58
62
|
radial-gradient(120% 140% at 30% 12%, rgba(255, 255, 255, 0.38), transparent 42%),
|
|
59
|
-
var(--b-color-accent);
|
|
63
|
+
var(--b-color-accent-fill);
|
|
60
64
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4),
|
|
61
65
|
inset 0 0 0 1px color-mix(in srgb, var(--b-color-accent) 55%, transparent),
|
|
62
66
|
var(--b-shadow-accent);
|
|
@@ -73,7 +77,7 @@
|
|
|
73
77
|
|
|
74
78
|
.b-btn--outline {
|
|
75
79
|
background: transparent;
|
|
76
|
-
|
|
80
|
+
border-color: var(--b-border-strong);
|
|
77
81
|
}
|
|
78
82
|
.b-btn--outline:hover { background: var(--b-fill-quaternary); }
|
|
79
83
|
|
|
@@ -204,18 +208,18 @@
|
|
|
204
208
|
animation: b-glass-shimmer var(--b-glass-shimmer-duration) var(--b-ease-out) forwards;
|
|
205
209
|
}
|
|
206
210
|
|
|
207
|
-
.b-btn--danger { color: var(--b-color-on-accent); background: var(--b-color-danger); }
|
|
208
|
-
.b-btn--danger:hover { background: color-mix(in srgb, var(--b-color-danger) 85%, black); }
|
|
209
|
-
.b-btn--danger-tinted { color: var(--b-color-danger); background: var(--b-color-danger-soft); }
|
|
211
|
+
.b-btn--danger { color: var(--b-color-on-accent); background: var(--b-color-danger-fill); }
|
|
212
|
+
.b-btn--danger:hover { background: color-mix(in srgb, var(--b-color-danger-fill) 85%, black); }
|
|
213
|
+
.b-btn--danger-tinted { color: var(--b-color-danger-text); background: var(--b-color-danger-soft); }
|
|
210
214
|
.b-btn--danger-tinted:hover { background: color-mix(in srgb, var(--b-color-red) 22%, transparent); }
|
|
211
|
-
.b-btn--success { color: var(--b-color-on-accent); background: var(--b-color-success); }
|
|
215
|
+
.b-btn--success { color: var(--b-color-on-accent); background: var(--b-color-success-fill); }
|
|
212
216
|
.b-btn--success:hover { background: color-mix(in srgb, var(--b-color-success) 85%, black); }
|
|
213
217
|
|
|
214
218
|
/* Sizes */
|
|
215
|
-
.b-btn--xs { height: var(--b-control-h-xs); padding-inline: var(--b-space-2); font-size: var(--b-text-caption); border-radius: var(--b-radius-sm); }
|
|
216
|
-
.b-btn--sm { height: var(--b-control-h-sm); padding-inline: var(--b-space-3); font-size: var(--b-text-footnote); border-radius: var(--b-radius-sm); }
|
|
217
|
-
.b-btn--lg { height: var(--b-control-h-lg); padding-inline: var(--b-space-5); font-size: var(--b-text-callout); border-radius: var(--b-radius-lg); }
|
|
218
|
-
.b-btn--xl { height: var(--b-control-h-xl); padding-inline: var(--b-space-6); font-size: var(--b-text-body); border-radius: var(--b-radius-lg); }
|
|
219
|
+
.b-btn--xs { height: var(--b-control-h-xs); padding-inline: calc(var(--b-space-2) - 1px); font-size: var(--b-text-caption); border-radius: var(--b-radius-sm); }
|
|
220
|
+
.b-btn--sm { height: var(--b-control-h-sm); padding-inline: calc(var(--b-space-3) - 1px); font-size: var(--b-text-footnote); border-radius: var(--b-radius-sm); }
|
|
221
|
+
.b-btn--lg { height: var(--b-control-h-lg); padding-inline: calc(var(--b-space-5) - 1px); font-size: var(--b-text-callout); border-radius: var(--b-radius-lg); }
|
|
222
|
+
.b-btn--xl { height: var(--b-control-h-xl); padding-inline: calc(var(--b-space-6) - 1px); font-size: var(--b-text-body); border-radius: var(--b-radius-lg); }
|
|
219
223
|
.b-btn--pill { border-radius: var(--b-radius-full); }
|
|
220
224
|
.b-btn--block { display: flex; width: 100%; }
|
|
221
225
|
|
|
@@ -255,9 +259,10 @@
|
|
|
255
259
|
inset-inline-end: var(--b-space-6);
|
|
256
260
|
z-index: var(--b-z-sticky);
|
|
257
261
|
width: 3.5rem; height: 3.5rem;
|
|
262
|
+
border: 1px solid transparent;
|
|
258
263
|
border-radius: var(--b-radius-full);
|
|
259
264
|
color: var(--b-color-on-accent);
|
|
260
|
-
background: var(--b-color-accent);
|
|
265
|
+
background: var(--b-color-accent-fill);
|
|
261
266
|
box-shadow: var(--b-shadow-lg), var(--b-shadow-accent);
|
|
262
267
|
}
|
|
263
268
|
.b-fab:hover { background: var(--b-color-accent-hover); translate: 0 -2px; }
|
|
@@ -320,7 +325,7 @@
|
|
|
320
325
|
.b-link:hover { text-decoration: underline; text-underline-offset: 0.2em; }
|
|
321
326
|
.b-link--muted { color: var(--b-text-secondary); }
|
|
322
327
|
.b-link--muted:hover { color: var(--b-text); }
|
|
323
|
-
.b-link--danger { color: var(--b-color-danger); }
|
|
328
|
+
.b-link--danger { color: var(--b-color-danger-text); }
|
|
324
329
|
.b-link svg { width: 1em; height: 1em; }
|
|
325
330
|
.b-link-group {
|
|
326
331
|
display: flex;
|
package/css/components/auth.css
CHANGED
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
margin-inline: auto;
|
|
43
43
|
font-size: 1.4rem;
|
|
44
44
|
color: var(--b-color-on-accent);
|
|
45
|
-
background: linear-gradient(135deg, var(--b-color-accent), var(--b-color-indigo));
|
|
45
|
+
background: linear-gradient(135deg, var(--b-color-accent-fill), var(--b-color-indigo));
|
|
46
46
|
border-radius: var(--b-radius-lg);
|
|
47
47
|
box-shadow: var(--b-shadow-accent);
|
|
48
48
|
}
|
|
@@ -96,8 +96,6 @@
|
|
|
96
96
|
}
|
|
97
97
|
.b-otp input:focus-visible {
|
|
98
98
|
border-color: var(--b-color-accent);
|
|
99
|
-
box-shadow: var(--b-focus-ring);
|
|
100
|
-
outline: none;
|
|
101
99
|
}
|
|
102
100
|
.b-otp input.is-filled { border-color: var(--b-color-accent); }
|
|
103
101
|
.b-otp.is-invalid input { border-color: var(--b-color-danger); animation: b-shake 0.35s var(--b-ease-standard); }
|
|
@@ -381,6 +381,39 @@
|
|
|
381
381
|
border-collapse: collapse;
|
|
382
382
|
font-size: var(--b-text-footnote);
|
|
383
383
|
}
|
|
384
|
+
/* A table with a prose column has no good phone shape: it lays out at
|
|
385
|
+
min-content and scrolls, so a Notes column becomes twelve lines of three
|
|
386
|
+
words each. --stack turns each row into a block under 40rem, with the
|
|
387
|
+
column heading written before every cell from data-label. The cells stay
|
|
388
|
+
table cells for assistive tech; only their display changes. Data grids
|
|
389
|
+
never take this: numbers want columns. */
|
|
390
|
+
/* .b-table.b-table--stack, not .b-table--stack: a docs table is usually
|
|
391
|
+
--compact as well, and --compact's cell padding sits at equal specificity
|
|
392
|
+
later in this file. The phone shape has to win over density by
|
|
393
|
+
specificity, not by where it happens to sit. */
|
|
394
|
+
@media (max-width: 40rem) {
|
|
395
|
+
.b-table.b-table--stack thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
|
|
396
|
+
.b-table.b-table--stack, .b-table.b-table--stack tbody, .b-table.b-table--stack tr, .b-table.b-table--stack td { display: block; }
|
|
397
|
+
.b-table.b-table--stack tr { padding-block: var(--b-space-3); border-block-end: 1px solid var(--b-separator); }
|
|
398
|
+
.b-table.b-table--stack td {
|
|
399
|
+
position: relative;
|
|
400
|
+
padding: var(--b-space-1) 0 var(--b-space-1) var(--b-table-label-w, 34%);
|
|
401
|
+
border: 0;
|
|
402
|
+
min-height: 1.5em;
|
|
403
|
+
}
|
|
404
|
+
.b-table.b-table--stack td::before {
|
|
405
|
+
content: attr(data-label);
|
|
406
|
+
position: absolute;
|
|
407
|
+
inset-inline-start: 0;
|
|
408
|
+
width: calc(var(--b-table-label-w, 34%) - var(--b-space-3));
|
|
409
|
+
font-size: var(--b-text-caption);
|
|
410
|
+
font-weight: var(--b-weight-semibold);
|
|
411
|
+
color: var(--b-text-secondary);
|
|
412
|
+
overflow: hidden;
|
|
413
|
+
text-overflow: ellipsis;
|
|
414
|
+
white-space: nowrap;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
384
417
|
.b-table th {
|
|
385
418
|
padding: var(--b-space-3) var(--b-space-4);
|
|
386
419
|
text-align: start;
|
|
@@ -421,8 +454,19 @@
|
|
|
421
454
|
/* Data grid extras — sticky header + row actions */
|
|
422
455
|
.b-datagrid { max-height: var(--b-datagrid-h, 26rem); overflow: auto; }
|
|
423
456
|
.b-datagrid .b-table th { position: sticky; top: 0; z-index: 1; background: var(--b-surface-2); }
|
|
424
|
-
|
|
425
|
-
|
|
457
|
+
/* Hidden by opacity, not visibility: visibility:hidden drops the buttons
|
|
458
|
+
from the tab order, so a keyboard user could never reach Edit or Delete.
|
|
459
|
+
Revealed by hover or by focus landing anywhere in the row. */
|
|
460
|
+
.b-datagrid .b-table td .b-row-actions {
|
|
461
|
+
opacity: 0;
|
|
462
|
+
transition: opacity var(--b-duration-fast) var(--b-ease-out);
|
|
463
|
+
}
|
|
464
|
+
.b-datagrid .b-table tr:is(:hover, :focus-within) .b-row-actions { opacity: 1; }
|
|
465
|
+
/* No hover on touch, and an opacity-0 button is still tappable, so an
|
|
466
|
+
invisible Delete would be a trap. */
|
|
467
|
+
@media (hover: none) {
|
|
468
|
+
.b-datagrid .b-table td .b-row-actions { opacity: 1; }
|
|
469
|
+
}
|
|
426
470
|
|
|
427
471
|
/* ---- Tree ---------------------------------------------------------------------- */
|
|
428
472
|
.b-tree { list-style: none; margin: 0; padding: 0; font-size: var(--b-text-subheadline); }
|
|
@@ -567,10 +611,10 @@
|
|
|
567
611
|
white-space: nowrap;
|
|
568
612
|
}
|
|
569
613
|
.b-badge--accent { color: var(--b-color-accent-text); background: var(--b-color-accent-soft); }
|
|
570
|
-
.b-badge--success { color: var(--b-color-success); background: var(--b-color-success-soft); }
|
|
571
|
-
.b-badge--warning { color:
|
|
572
|
-
.b-badge--danger { color: var(--b-color-danger);
|
|
573
|
-
.b-badge--solid { color: var(--b-color-on-accent); background: var(--b-color-accent); }
|
|
614
|
+
.b-badge--success { color: var(--b-color-success-text); background: var(--b-color-success-soft); }
|
|
615
|
+
.b-badge--warning { color: var(--b-color-warning-text); background: var(--b-color-warning-soft); }
|
|
616
|
+
.b-badge--danger { color: var(--b-color-danger-text); background: var(--b-color-danger-soft); }
|
|
617
|
+
.b-badge--solid { color: var(--b-color-on-accent); background: var(--b-color-accent-fill); }
|
|
574
618
|
.b-badge--dot::before {
|
|
575
619
|
content: "";
|
|
576
620
|
width: 0.4rem; height: 0.4rem;
|
|
@@ -621,12 +665,12 @@
|
|
|
621
665
|
align-items: center;
|
|
622
666
|
gap: var(--b-space-1);
|
|
623
667
|
height: var(--b-control-h-sm);
|
|
624
|
-
padding-inline: var(--b-space-3);
|
|
668
|
+
padding-inline: calc(var(--b-space-3) - 1px);
|
|
625
669
|
font-size: var(--b-text-footnote);
|
|
626
670
|
font-weight: var(--b-weight-medium);
|
|
627
671
|
color: var(--b-text);
|
|
628
672
|
background: var(--b-fill-tertiary);
|
|
629
|
-
border:
|
|
673
|
+
border: 1px solid transparent;
|
|
630
674
|
border-radius: var(--b-radius-full);
|
|
631
675
|
cursor: pointer;
|
|
632
676
|
transition: background var(--b-duration-fast), color var(--b-duration-fast);
|
|
@@ -634,7 +678,7 @@
|
|
|
634
678
|
.b-chip:hover { background: var(--b-fill-secondary); }
|
|
635
679
|
.b-chip.is-selected, .b-chip[aria-pressed="true"] {
|
|
636
680
|
color: var(--b-color-on-accent);
|
|
637
|
-
background: var(--b-color-accent);
|
|
681
|
+
background: var(--b-color-accent-fill);
|
|
638
682
|
}
|
|
639
683
|
.b-chip__remove {
|
|
640
684
|
display: inline-grid;
|
|
@@ -772,8 +816,12 @@
|
|
|
772
816
|
.b-code__copy {
|
|
773
817
|
padding: 0.2rem var(--b-space-2);
|
|
774
818
|
font-size: var(--b-text-caption);
|
|
775
|
-
|
|
776
|
-
|
|
819
|
+
/* Ink and veil come from the host. A light literal here was right inside
|
|
820
|
+
the always-dark code block and invisible when the docs put the same
|
|
821
|
+
button on a light footer: the copy button was there and nobody could
|
|
822
|
+
see it. */
|
|
823
|
+
color: color-mix(in srgb, currentColor 78%, transparent);
|
|
824
|
+
background: color-mix(in srgb, currentColor 10%, transparent);
|
|
777
825
|
border: none;
|
|
778
826
|
border-radius: var(--b-radius-sm);
|
|
779
827
|
cursor: pointer;
|
|
@@ -818,8 +866,8 @@
|
|
|
818
866
|
font-size: var(--b-text-footnote);
|
|
819
867
|
font-weight: var(--b-weight-semibold);
|
|
820
868
|
}
|
|
821
|
-
.b-stat__delta.is-up { color: var(--b-color-success); }
|
|
822
|
-
.b-stat__delta.is-down { color: var(--b-color-danger); }
|
|
869
|
+
.b-stat__delta.is-up { color: var(--b-color-success-text); }
|
|
870
|
+
.b-stat__delta.is-down { color: var(--b-color-danger-text); }
|
|
823
871
|
|
|
824
872
|
/* ---- Empty State ---------------------------------------------------------------------------------- */
|
|
825
873
|
.b-empty {
|
|
@@ -848,16 +896,24 @@
|
|
|
848
896
|
color: var(--b-text-secondary);
|
|
849
897
|
}
|
|
850
898
|
.b-empty .b-btn { margin-block-start: var(--b-space-3); }
|
|
851
|
-
|
|
899
|
+
|
|
852
900
|
/* A picture behind flat cards is a picture nobody sees. When a wallpaper is
|
|
853
901
|
hanging (Barua.wallpaper adds .b-has-wallpaper), surfaces on the wall
|
|
854
902
|
become the neutral material — derived from whatever is behind them, so it
|
|
855
903
|
holds over any picture. A product that wants opaque surfaces simply never
|
|
856
|
-
hangs one.
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
904
|
+
hangs one.
|
|
905
|
+
|
|
906
|
+
This block lives INSIDE @layer components, so a product's unlayered
|
|
907
|
+
override still wins, which is the contract barua.css states. A closing
|
|
908
|
+
brace had landed above it and the whole block was unlayered: it beat
|
|
909
|
+
every card variant and every product override the moment a wallpaper was
|
|
910
|
+
hung. The class only ever lives on <html>, so :root lifts these to (0,3,0)
|
|
911
|
+
and they beat Liquid Glass's (0,2,0) panes by specificity, not by escaping
|
|
912
|
+
the layer. */
|
|
913
|
+
:root.b-has-wallpaper .b-workspace,
|
|
914
|
+
:root.b-has-wallpaper .b-workspace__main,
|
|
915
|
+
:root.b-has-wallpaper .b-inspector { background: transparent; }
|
|
916
|
+
:root.b-has-wallpaper .b-card {
|
|
861
917
|
background: var(--b-material-neutral-bg);
|
|
862
918
|
-webkit-backdrop-filter: blur(var(--b-blur-lg)) saturate(1.1);
|
|
863
919
|
backdrop-filter: blur(var(--b-blur-lg)) saturate(1.1);
|
|
@@ -867,14 +923,15 @@
|
|
|
867
923
|
material keeps its blur and doubles the veil, so the picture still shows at
|
|
868
924
|
the edges without competing with the ink. The veil follows the wallpaper's
|
|
869
925
|
own scheme, so it lightens on a bright picture and darkens on a dark one. */
|
|
870
|
-
.b-has-wallpaper .b-card--thick {
|
|
926
|
+
:root.b-has-wallpaper .b-card--thick {
|
|
871
927
|
background: var(--b-material-thick-bg);
|
|
872
928
|
}
|
|
873
929
|
|
|
874
930
|
/* A panel inside glass is a fill, never a second material. */
|
|
875
|
-
.b-has-wallpaper .b-card .b-card {
|
|
931
|
+
:root.b-has-wallpaper .b-card .b-card {
|
|
876
932
|
background: var(--b-fill-quaternary);
|
|
877
933
|
-webkit-backdrop-filter: none;
|
|
878
934
|
backdrop-filter: none;
|
|
879
935
|
}
|
|
936
|
+
}
|
|
880
937
|
|
|
@@ -71,9 +71,9 @@
|
|
|
71
71
|
font-weight: var(--b-weight-medium);
|
|
72
72
|
text-align: center;
|
|
73
73
|
color: var(--b-color-on-accent);
|
|
74
|
-
background: linear-gradient(90deg, var(--b-color-accent), color-mix(in srgb, var(--b-color-indigo) 80%, var(--b-color-accent)));
|
|
74
|
+
background: linear-gradient(90deg, var(--b-color-accent-fill), color-mix(in srgb, var(--b-color-indigo) 80%, var(--b-color-accent-fill)));
|
|
75
75
|
}
|
|
76
|
-
.b-banner a { color: inherit; text-decoration: underline; text-underline-offset: 0.2em; }
|
|
76
|
+
.b-banner a:not(.b-btn) { color: inherit; text-decoration: underline; text-underline-offset: 0.2em; }
|
|
77
77
|
.b-banner__close {
|
|
78
78
|
background: none; border: none;
|
|
79
79
|
color: inherit; opacity: 0.8; cursor: pointer;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
@layer components {
|
|
2
|
+
/* ==========================================================================
|
|
3
|
+
Forced colours (Windows High Contrast, and any browser with
|
|
4
|
+
forced-colors: active).
|
|
5
|
+
|
|
6
|
+
The platform strips every background and shadow and repaints the page in
|
|
7
|
+
a handful of system colours. A control whose shape lived only in its fill
|
|
8
|
+
became bare words; a switch became nothing at all; a selected segment and
|
|
9
|
+
an unselected one looked the same. Two rules make a component survive:
|
|
10
|
+
its edge is a real border (transparent in normal mode, painted here) and
|
|
11
|
+
any state that was a fill opts out of the repaint to keep a system fill.
|
|
12
|
+
The system colours are the only literals allowed in a component file.
|
|
13
|
+
========================================================================== */
|
|
14
|
+
@media (forced-colors: active) {
|
|
15
|
+
/* Edges for everything that was shape-by-fill. */
|
|
16
|
+
.b-btn, .b-fab, .b-chip, .b-segmented, .b-segmented__item,
|
|
17
|
+
.b-switch input, .b-switch input::after,
|
|
18
|
+
.b-badge, .b-tag, .b-progress, .b-progress__bar, .b-tab { border-color: ButtonText; }
|
|
19
|
+
.b-switch input { background: Canvas; }
|
|
20
|
+
.b-switch input::after { background: ButtonText; }
|
|
21
|
+
|
|
22
|
+
/* A state that was a fill stays a fill, in the system's own colours. */
|
|
23
|
+
.b-btn--primary, .b-btn--liquid, .b-btn--danger, .b-btn--success,
|
|
24
|
+
.b-segmented__item.is-active, .b-segmented__item[aria-selected="true"],
|
|
25
|
+
.b-tab.is-active, .b-tab[aria-selected="true"],
|
|
26
|
+
.b-chip.is-selected, .b-chip[aria-pressed="true"],
|
|
27
|
+
.b-menu__item.is-active, .b-pagination__item.is-active,
|
|
28
|
+
.b-sidebar__item.is-active, .b-rail__item.is-active,
|
|
29
|
+
.b-switch input:checked,
|
|
30
|
+
.b-checkbox input:checked, .b-checkbox input:indeterminate,
|
|
31
|
+
.b-calendar__day.is-selected, .b-progress__bar, .b-range__fill {
|
|
32
|
+
forced-color-adjust: none;
|
|
33
|
+
background: Highlight;
|
|
34
|
+
color: HighlightText;
|
|
35
|
+
border-color: Highlight;
|
|
36
|
+
}
|
|
37
|
+
.b-switch input:checked::after { forced-color-adjust: none; background: HighlightText; }
|
|
38
|
+
|
|
39
|
+
/* Range inputs: the platform already draws these in system colours. */
|
|
40
|
+
.b-slider, .b-slider::-webkit-slider-thumb,
|
|
41
|
+
.b-range > input[type="range"],
|
|
42
|
+
.b-range > input[type="range"]::-webkit-slider-thumb { appearance: auto; }
|
|
43
|
+
.b-range::before { border: 1px solid ButtonText; }
|
|
44
|
+
|
|
45
|
+
/* Focus and disabled must read as such. */
|
|
46
|
+
:focus-visible { outline-color: Highlight; }
|
|
47
|
+
:disabled, .is-disabled, .b-btn[aria-disabled="true"] { color: GrayText; border-color: GrayText; }
|
|
48
|
+
.b-switch input:disabled { border-color: GrayText; }
|
|
49
|
+
.b-switch input:disabled::after { background: GrayText; }
|
|
50
|
+
|
|
51
|
+
/* Glass has nothing to blur; a translucent veil over Canvas reads as a
|
|
52
|
+
box, and the platform wants Canvas. */
|
|
53
|
+
.b-card, .b-topnav, .b-menu, .b-modal, .b-drawer, .b-sheet, .b-bottom-sheet {
|
|
54
|
+
-webkit-backdrop-filter: none;
|
|
55
|
+
backdrop-filter: none;
|
|
56
|
+
background: Canvas;
|
|
57
|
+
border-color: CanvasText;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
package/css/components/forms.css
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
}
|
|
24
24
|
.b-label--required::after {
|
|
25
25
|
content: " *";
|
|
26
|
-
color: var(--b-color-danger);
|
|
26
|
+
color: var(--b-color-danger-text);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
.b-help {
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
align-items: center;
|
|
36
36
|
gap: var(--b-space-1);
|
|
37
37
|
font-size: var(--b-text-footnote);
|
|
38
|
-
color: var(--b-color-danger);
|
|
38
|
+
color: var(--b-color-danger-text);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
/* ---- Inputs ------------------------------------------------------------ */
|
|
@@ -56,8 +56,6 @@
|
|
|
56
56
|
.b-input:hover, .b-textarea:hover, .b-select:hover { border-color: var(--b-border-strong); }
|
|
57
57
|
.b-input:focus-visible, .b-textarea:focus-visible, .b-select:focus-visible {
|
|
58
58
|
border-color: var(--b-color-accent);
|
|
59
|
-
box-shadow: var(--b-focus-ring);
|
|
60
|
-
outline: none;
|
|
61
59
|
}
|
|
62
60
|
.b-input--filled { background: var(--b-fill-tertiary); border-color: transparent; }
|
|
63
61
|
.b-input--filled:hover { background: var(--b-fill-secondary); }
|
|
@@ -81,7 +79,7 @@
|
|
|
81
79
|
}
|
|
82
80
|
.b-field.is-invalid .b-input:focus-visible,
|
|
83
81
|
.b-input.is-invalid:focus-visible, .b-input:user-invalid:focus-visible {
|
|
84
|
-
|
|
82
|
+
--b-focus-ring-color: var(--b-color-danger);
|
|
85
83
|
}
|
|
86
84
|
.b-field.is-valid .b-input, .b-input.is-valid { border-color: var(--b-color-success); }
|
|
87
85
|
|
|
@@ -237,6 +235,9 @@
|
|
|
237
235
|
margin: 0;
|
|
238
236
|
flex: none;
|
|
239
237
|
background: var(--b-fill);
|
|
238
|
+
/* Painted only by forced colours: the track was a fill and the thumb a
|
|
239
|
+
shadow, and both vanish in Windows High Contrast. */
|
|
240
|
+
border: 1.5px solid transparent;
|
|
240
241
|
border-radius: var(--b-radius-full);
|
|
241
242
|
position: relative;
|
|
242
243
|
cursor: pointer;
|
|
@@ -250,6 +251,7 @@
|
|
|
250
251
|
translate: 0 -50%;
|
|
251
252
|
width: 1.3rem; height: 1.3rem;
|
|
252
253
|
background: #fff;
|
|
254
|
+
border: 1px solid transparent;
|
|
253
255
|
border-radius: 50%;
|
|
254
256
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), 0 0 0 0.5px rgba(0, 0, 0, 0.06);
|
|
255
257
|
transition: inset-inline-start var(--b-duration-normal) var(--b-ease-spring);
|
|
@@ -387,6 +389,7 @@
|
|
|
387
389
|
|
|
388
390
|
/* ---- File Upload ------------------------------------------------------- */
|
|
389
391
|
.b-upload {
|
|
392
|
+
position: relative;
|
|
390
393
|
display: flex;
|
|
391
394
|
flex-direction: column;
|
|
392
395
|
align-items: center;
|
|
@@ -407,7 +410,27 @@
|
|
|
407
410
|
background: var(--b-color-accent-soft);
|
|
408
411
|
color: var(--b-color-accent-text);
|
|
409
412
|
}
|
|
410
|
-
|
|
413
|
+
/* Keyboard focus on the wrapped input lights the zone, like a multiselect. */
|
|
414
|
+
.b-upload:focus-within {
|
|
415
|
+
border-color: var(--b-color-accent);
|
|
416
|
+
outline: var(--b-focus-ring);
|
|
417
|
+
outline-offset: var(--b-focus-ring-offset);
|
|
418
|
+
}
|
|
419
|
+
/* Hidden visually but still focusable and in the accessibility tree, the
|
|
420
|
+
.b-sr-only recipe. display:none took the only focusable thing in the
|
|
421
|
+
label out of the tab order, so the picker could not be opened without a
|
|
422
|
+
mouse. */
|
|
423
|
+
.b-upload input[type="file"] {
|
|
424
|
+
position: absolute;
|
|
425
|
+
width: 1px;
|
|
426
|
+
height: 1px;
|
|
427
|
+
padding: 0;
|
|
428
|
+
margin: -1px;
|
|
429
|
+
overflow: hidden;
|
|
430
|
+
clip-path: inset(50%);
|
|
431
|
+
white-space: nowrap;
|
|
432
|
+
border: 0;
|
|
433
|
+
}
|
|
411
434
|
.b-upload svg { width: 2rem; height: 2rem; opacity: 0.7; }
|
|
412
435
|
.b-upload__hint { font-size: var(--b-text-footnote); color: var(--b-text-tertiary); }
|
|
413
436
|
|
|
@@ -52,10 +52,13 @@
|
|
|
52
52
|
}
|
|
53
53
|
.b-marketing-nav--lg .b-marketing-nav__brand { font-size: var(--b-text-title3); }
|
|
54
54
|
.b-marketing-nav--lg .b-marketing-nav__links { gap: clamp(var(--b-space-4), 2.4vw, var(--b-space-8)); }
|
|
55
|
-
.b-marketing-nav--lg a { font-weight: var(--b-weight-medium); }
|
|
55
|
+
.b-marketing-nav--lg a:not(.b-btn) { font-weight: var(--b-weight-medium); }
|
|
56
56
|
.b-marketing-nav__links { display: flex; gap: var(--b-space-5); margin-inline: auto; }
|
|
57
|
-
.b-
|
|
58
|
-
|
|
57
|
+
/* Bare links only. A .b-btn dropped in the bar keeps its own ink: an element
|
|
58
|
+
selector inside a container is (0,1,1) and quietly beat .b-btn--primary's
|
|
59
|
+
(0,1,0), which left the landing page's call to action grey on blue. */
|
|
60
|
+
.b-marketing-nav a:not(.b-btn) { color: var(--b-text-secondary); text-decoration: none; }
|
|
61
|
+
.b-marketing-nav a:not(.b-btn):hover { color: var(--b-text); }
|
|
59
62
|
|
|
60
63
|
/* ---- Chapter: one idea, centred, with room around it --------------------- */
|
|
61
64
|
.b-chapter {
|
|
@@ -278,7 +281,7 @@
|
|
|
278
281
|
gap: var(--b-space-6);
|
|
279
282
|
padding: clamp(var(--b-space-6), 4vw, var(--b-space-10));
|
|
280
283
|
color: var(--b-color-on-accent);
|
|
281
|
-
background: var(--b-color-accent);
|
|
284
|
+
background: var(--b-color-accent-fill);
|
|
282
285
|
border-radius: var(--b-radius-2xl);
|
|
283
286
|
color-scheme: dark;
|
|
284
287
|
}
|
|
@@ -779,7 +782,7 @@
|
|
|
779
782
|
font-weight: var(--b-weight-semibold);
|
|
780
783
|
color: var(--b-text);
|
|
781
784
|
}
|
|
782
|
-
.b-site-footer__group a { display: block; padding-block: 0.2rem; color: var(--b-text-secondary); text-decoration: none; }
|
|
785
|
+
.b-site-footer__group a:not(.b-btn) { display: block; padding-block: 0.2rem; color: var(--b-text-secondary); text-decoration: none; }
|
|
783
786
|
.b-site-footer__group a:hover { color: var(--b-text); text-decoration: underline; }
|
|
784
787
|
.b-site-footer__legal {
|
|
785
788
|
max-width: var(--b-container-xl);
|
package/css/components/media.css
CHANGED
|
@@ -235,7 +235,7 @@
|
|
|
235
235
|
.b-poster:hover .b-poster__frame { translate: 0 -2px; box-shadow: var(--b-elevation-3); }
|
|
236
236
|
}
|
|
237
237
|
.b-poster:focus-visible { outline: none; }
|
|
238
|
-
.b-poster:focus-visible .b-poster__frame
|
|
238
|
+
.b-poster:focus-visible .b-poster__frame { outline: var(--b-focus-ring); outline-offset: 2px; }
|
|
239
239
|
.b-poster.is-selected .b-poster__frame { outline: 2px solid var(--b-color-accent); outline-offset: 2px; }
|
|
240
240
|
|
|
241
241
|
/* A wall of posters: as many across as fit — three on a phone, eight on a
|
|
@@ -264,7 +264,9 @@
|
|
|
264
264
|
opacity: 0;
|
|
265
265
|
transition: opacity var(--b-duration-normal);
|
|
266
266
|
}
|
|
267
|
-
.b-video:hover .b-video__overlay,
|
|
267
|
+
.b-video:hover .b-video__overlay,
|
|
268
|
+
.b-video:focus-within .b-video__overlay,
|
|
269
|
+
.b-video.is-paused .b-video__overlay { opacity: 1; }
|
|
268
270
|
.b-video__play {
|
|
269
271
|
display: grid;
|
|
270
272
|
place-items: center;
|
|
@@ -281,6 +283,68 @@
|
|
|
281
283
|
}
|
|
282
284
|
.b-video__play:hover { scale: 1.08; }
|
|
283
285
|
|
|
286
|
+
/* ---- Film player controls -------------------------------------------------------
|
|
287
|
+
`.b-media-controls` is the generic bar. A film needs its controls over the
|
|
288
|
+
picture rather than beside it, and needs them gone while someone watches.
|
|
289
|
+
These four existed only in the player's markup — the classes were used and
|
|
290
|
+
never defined, so the bar sat unstyled below the video with browser-default
|
|
291
|
+
buttons and full-size glyphs. */
|
|
292
|
+
.b-video__bar {
|
|
293
|
+
position: absolute;
|
|
294
|
+
inset-inline: 0;
|
|
295
|
+
inset-block-end: 0;
|
|
296
|
+
display: flex;
|
|
297
|
+
align-items: center;
|
|
298
|
+
gap: var(--b-space-2);
|
|
299
|
+
padding: var(--b-space-3);
|
|
300
|
+
color: #fff;
|
|
301
|
+
color-scheme: dark;
|
|
302
|
+
background: linear-gradient(transparent, rgba(0, 0, 0, 0.72));
|
|
303
|
+
opacity: 0;
|
|
304
|
+
transition: opacity var(--b-duration-normal) var(--b-ease-out);
|
|
305
|
+
}
|
|
306
|
+
.b-video:hover .b-video__bar,
|
|
307
|
+
.b-video:focus-within .b-video__bar,
|
|
308
|
+
.b-video.is-paused .b-video__bar { opacity: 1; }
|
|
309
|
+
/* A touch screen has no hover, so the bar would otherwise appear only by
|
|
310
|
+
pausing — which is exactly when someone full screen cannot reach it. */
|
|
311
|
+
@media (hover: none) {
|
|
312
|
+
.b-video__bar { opacity: 1; }
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
.b-video__btn {
|
|
316
|
+
flex: none;
|
|
317
|
+
display: inline-flex;
|
|
318
|
+
align-items: center;
|
|
319
|
+
justify-content: center;
|
|
320
|
+
width: 2.25rem;
|
|
321
|
+
height: 2.25rem;
|
|
322
|
+
padding: 0;
|
|
323
|
+
border: 0;
|
|
324
|
+
border-radius: var(--b-radius-full);
|
|
325
|
+
background: transparent;
|
|
326
|
+
color: inherit;
|
|
327
|
+
cursor: pointer;
|
|
328
|
+
transition: background var(--b-duration-fast) var(--b-ease-out);
|
|
329
|
+
}
|
|
330
|
+
.b-video__btn:hover { background: rgb(255 255 255 / 0.18); }
|
|
331
|
+
.b-video__btn svg { width: 1.5rem; height: 1.5rem; fill: currentColor; }
|
|
332
|
+
|
|
333
|
+
.b-video__time {
|
|
334
|
+
flex: none;
|
|
335
|
+
font-size: var(--b-text-caption);
|
|
336
|
+
font-variant-numeric: tabular-nums;
|
|
337
|
+
opacity: 0.9;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
.b-video__seek {
|
|
341
|
+
flex: 1;
|
|
342
|
+
min-width: 0;
|
|
343
|
+
height: 1.5rem;
|
|
344
|
+
accent-color: var(--b-color-accent);
|
|
345
|
+
cursor: pointer;
|
|
346
|
+
}
|
|
347
|
+
|
|
284
348
|
/* ---- Media Controls (shared control bar) --------------------------------------- */
|
|
285
349
|
.b-media-controls {
|
|
286
350
|
position: absolute;
|