@fluixi-ui/skin-material 0.3.0-alpha.5 → 0.3.0-alpha.7
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/material.css +429 -34
- package/package.json +1 -1
package/material.css
CHANGED
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
/* ---- Button: pill shape, state layer, filled/tonal/outlined/text ---------- */
|
|
43
|
-
[data-ui='material'] :where([data-variant]) {
|
|
43
|
+
[data-ui='material'] :where([data-variant]:not([data-badge])) {
|
|
44
44
|
position: relative;
|
|
45
45
|
overflow: hidden;
|
|
46
46
|
border-radius: 9999px;
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
/* The Material "state layer": a currentColor overlay that fades in on interaction.
|
|
57
57
|
On a filled button currentColor is the on-primary ink (white) → a subtle
|
|
58
58
|
lightening; on outlined/text/tonal it's the primary colour. */
|
|
59
|
-
[data-ui='material'] :where([data-variant])::before {
|
|
59
|
+
[data-ui='material'] :where([data-variant]:not([data-badge]))::before {
|
|
60
60
|
content: '';
|
|
61
61
|
position: absolute;
|
|
62
62
|
inset: 0;
|
|
@@ -68,35 +68,28 @@
|
|
|
68
68
|
pointer-events: none;
|
|
69
69
|
transition: opacity var(--flx-ui-duration-fast) var(--flx-ui-ease-standard);
|
|
70
70
|
}
|
|
71
|
-
[data-ui='material'] :where([data-variant]:hover)::before { opacity: 0.08; }
|
|
72
|
-
[data-ui='material'] :where([data-variant]:focus-visible)::before { opacity: 0.12; }
|
|
73
|
-
[data-ui='material'] :where([data-variant]:active)::before { opacity: 0.16; }
|
|
74
|
-
[data-ui='material'] :where([data-variant]:focus-visible) { box-shadow: none; outline: none; }
|
|
75
|
-
[data-ui='material'] :where([data-variant][disabled], [data-variant]:disabled) {
|
|
71
|
+
[data-ui='material'] :where([data-variant]:not([data-badge]):hover)::before { opacity: 0.08; }
|
|
72
|
+
[data-ui='material'] :where([data-variant]:not([data-badge]):focus-visible)::before { opacity: 0.12; }
|
|
73
|
+
[data-ui='material'] :where([data-variant]:not([data-badge]):active)::before { opacity: 0.16; }
|
|
74
|
+
[data-ui='material'] :where([data-variant]:not([data-badge]):focus-visible) { box-shadow: none; outline: none; }
|
|
75
|
+
[data-ui='material'] :where([data-variant]:not([data-badge])[disabled], [data-variant]:not([data-badge]):disabled) {
|
|
76
76
|
box-shadow: none;
|
|
77
77
|
opacity: 0.38;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
/* Filled (solid) = the classic contained button: rests on elevation, lifts
|
|
81
81
|
further on hover. Elevation is per-variant — outlined/text/tonal stay flat. */
|
|
82
|
-
[data-ui='material'] :where([data-variant='solid']) { box-shadow: var(--flx-ui-shadow-sm); }
|
|
83
|
-
[data-ui='material'] :where([data-variant='solid']:hover) { box-shadow: var(--flx-ui-shadow-md); }
|
|
84
|
-
[data-ui='material'] :where([data-variant='solid']:active) { box-shadow: var(--flx-ui-shadow-sm); }
|
|
82
|
+
[data-ui='material'] :where([data-variant='solid']:not([data-badge])) { box-shadow: var(--flx-ui-shadow-sm); }
|
|
83
|
+
[data-ui='material'] :where([data-variant='solid']:not([data-badge]):hover) { box-shadow: var(--flx-ui-shadow-md); }
|
|
84
|
+
[data-ui='material'] :where([data-variant='solid']:not([data-badge]):active) { box-shadow: var(--flx-ui-shadow-sm); }
|
|
85
85
|
/* Tonal (soft): secondary-container feel. */
|
|
86
|
-
[data-ui='material'] :where([data-variant='soft']) { background: var(--flx-ui-color-primary-subtle); color: var(--flx-ui-color-primary-active); }
|
|
86
|
+
[data-ui='material'] :where([data-variant='soft']:not([data-badge])) { background: var(--flx-ui-color-primary-subtle); color: var(--flx-ui-color-primary-active); }
|
|
87
87
|
/* Outlined: 1px hairline, no fill. */
|
|
88
|
-
[data-ui='material'] :where([data-variant='outline']) { border: 1px solid var(--flx-ui-color-border-strong); }
|
|
88
|
+
[data-ui='material'] :where([data-variant='outline']:not([data-badge])) { border: 1px solid var(--flx-ui-color-border-strong); }
|
|
89
89
|
/* Text: tighter padding, no border. */
|
|
90
|
-
[data-ui='material'] :where([data-variant='ghost']) { padding: 0 12px; }
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
not buttons): restore size, keep the pill, drop the state layer. */
|
|
94
|
-
[data-ui='material'] :where(.flx-ui-badge[data-variant]) {
|
|
95
|
-
height: auto;
|
|
96
|
-
padding: 2px 10px;
|
|
97
|
-
box-shadow: none;
|
|
98
|
-
}
|
|
99
|
-
[data-ui='material'] :where(.flx-ui-badge[data-variant])::before { content: none; }
|
|
90
|
+
[data-ui='material'] :where([data-variant='ghost']:not([data-badge])) { padding: 0 12px; }
|
|
91
|
+
/* Badges carry [data-variant] too, but every button rule above excludes
|
|
92
|
+
[data-badge], so a badge is never treated as a button — no guard needed. */
|
|
100
93
|
|
|
101
94
|
/* ---- Switch: M3 geometry (52×32 track, growing thumb) --------------------- */
|
|
102
95
|
[data-ui='material'] :where([role='switch']) {
|
|
@@ -132,9 +125,26 @@
|
|
|
132
125
|
border-width: 2px;
|
|
133
126
|
border-radius: 2px;
|
|
134
127
|
}
|
|
128
|
+
/* The check (rotated border) and indeterminate bar are flex items; the tighter
|
|
129
|
+
2px-border box lets flex shrink them to a sliver on the main axis. Pin them. */
|
|
130
|
+
[data-ui='material'] :where([role='checkbox'][data-state='checked'])::after,
|
|
131
|
+
[data-ui='material'] :where([role='checkbox'][data-state='indeterminate'])::after {
|
|
132
|
+
flex: none;
|
|
133
|
+
}
|
|
134
|
+
[data-ui='material'] :where([role='checkbox'][data-state='checked'])::after {
|
|
135
|
+
width: 4px;
|
|
136
|
+
height: 8px;
|
|
137
|
+
margin-top: -3px;
|
|
138
|
+
}
|
|
139
|
+
/* Multi-select listbox/select indicator box → match the material checkbox. */
|
|
140
|
+
[data-ui='material'] :where([data-select-item-indicator]) {
|
|
141
|
+
box-sizing: border-box;
|
|
142
|
+
border-width: 2px;
|
|
143
|
+
border-radius: 2px;
|
|
144
|
+
}
|
|
135
145
|
|
|
136
146
|
/* ---- Slider: M3 filled thumb -------------------------------------------- */
|
|
137
|
-
[data-ui='material'] :where([role='slider']) {
|
|
147
|
+
[data-ui='material'] :where([data-slider] [role='slider']) {
|
|
138
148
|
width: 20px;
|
|
139
149
|
height: 20px;
|
|
140
150
|
background: var(--flx-ui-color-primary);
|
|
@@ -149,18 +159,48 @@
|
|
|
149
159
|
border-top-right-radius: 3px;
|
|
150
160
|
}
|
|
151
161
|
|
|
152
|
-
/* ----
|
|
153
|
-
|
|
162
|
+
/* ---- Text field / select / combobox appearance --------------------------
|
|
163
|
+
Baseline (no data-field-variant) and the explicit `filled` variant → M3
|
|
164
|
+
filled underline; `outlined` → M3 outlined box. 4px M3 radius (the tokens'
|
|
165
|
+
radius-md is 12px here). */
|
|
166
|
+
[data-ui='material'] :where(
|
|
167
|
+
[data-input]:not([data-field-variant]),
|
|
168
|
+
[data-combobox-control]:not([data-field-variant]),
|
|
169
|
+
button[role='combobox']:not([data-field-variant]),
|
|
170
|
+
[data-field-variant='filled']) {
|
|
154
171
|
background: var(--flx-ui-color-bg-muted);
|
|
155
|
-
border:
|
|
172
|
+
border: 1px solid transparent;
|
|
156
173
|
border-bottom: 1px solid var(--flx-ui-color-border-strong);
|
|
157
174
|
border-radius: 4px 4px 0 0;
|
|
158
175
|
}
|
|
159
|
-
[data-ui='material'] :where(
|
|
176
|
+
[data-ui='material'] :where(
|
|
177
|
+
[data-input]:not([data-field-variant]):focus,
|
|
178
|
+
[data-combobox-control]:not([data-field-variant]):focus-within,
|
|
179
|
+
button[role='combobox']:not([data-field-variant]):focus-visible,
|
|
180
|
+
button[role='combobox']:not([data-field-variant])[data-state='open'],
|
|
181
|
+
[data-field-variant='filled']:focus,
|
|
182
|
+
[data-field-variant='filled']:focus-visible,
|
|
183
|
+
[data-field-variant='filled']:focus-within) {
|
|
160
184
|
border-bottom: 2px solid var(--flx-ui-color-primary);
|
|
161
185
|
box-shadow: none;
|
|
162
186
|
outline: none;
|
|
163
187
|
}
|
|
188
|
+
/* Outlined → M3 outlined box (4px), 2px primary border on focus. */
|
|
189
|
+
[data-ui='material'] :where([data-field-variant='outlined']) {
|
|
190
|
+
background: transparent;
|
|
191
|
+
border: 1px solid var(--flx-ui-color-border-strong);
|
|
192
|
+
border-radius: 4px;
|
|
193
|
+
}
|
|
194
|
+
[data-ui='material'] :where([data-field-variant='outlined']:focus, [data-field-variant='outlined']:focus-visible, [data-field-variant='outlined']:focus-within) {
|
|
195
|
+
border: 2px solid var(--flx-ui-color-primary);
|
|
196
|
+
box-shadow: none;
|
|
197
|
+
outline: none;
|
|
198
|
+
}
|
|
199
|
+
/* The combobox's inner input must stay bare — the wrapper carries the field. */
|
|
200
|
+
[data-ui='material'] :where([data-combobox-control] [role='combobox']) {
|
|
201
|
+
background: transparent;
|
|
202
|
+
border: none;
|
|
203
|
+
}
|
|
164
204
|
|
|
165
205
|
/* ---- Menus & lists: full-bleed M3 rows, roomier padding ------------------- */
|
|
166
206
|
[data-ui='material'] :where([role='menuitem'], [role='option']) {
|
|
@@ -348,7 +388,7 @@
|
|
|
348
388
|
}
|
|
349
389
|
|
|
350
390
|
/* ---- Linear progress: 4dp fully-rounded track, tonal remainder ---------- */
|
|
351
|
-
[data-ui='material'] :where([role='progressbar']) {
|
|
391
|
+
[data-ui='material'] :where([role='progressbar']:not([data-circular])) {
|
|
352
392
|
height: 4px;
|
|
353
393
|
border-radius: 9999px;
|
|
354
394
|
background: var(--flx-ui-color-primary-subtle);
|
|
@@ -406,9 +446,31 @@
|
|
|
406
446
|
}
|
|
407
447
|
|
|
408
448
|
/* ---- Breadcrumb: state-layer link affordance ---------------------------- */
|
|
449
|
+
/* Padded pill targets so the state-layer has room to breathe (M3). */
|
|
450
|
+
[data-ui='material'] :where([data-breadcrumb-link]) {
|
|
451
|
+
padding: 2px 8px;
|
|
452
|
+
margin: 0 -2px;
|
|
453
|
+
border-radius: 999px;
|
|
454
|
+
}
|
|
409
455
|
[data-ui='material'] :where([data-breadcrumb-link]:hover) {
|
|
410
456
|
background: color-mix(in oklab, var(--flx-ui-color-fg) 8%, transparent);
|
|
411
|
-
|
|
457
|
+
color: var(--flx-ui-color-fg);
|
|
458
|
+
}
|
|
459
|
+
[data-ui='material'] :where([data-breadcrumb-page]) {
|
|
460
|
+
padding: 2px 8px;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/* ---- Toolbar: M3 surface + pill state-layer buttons ---------------------- */
|
|
464
|
+
[data-ui='material'] :where([role='toolbar']) {
|
|
465
|
+
border-radius: 8px;
|
|
466
|
+
gap: 2px;
|
|
467
|
+
}
|
|
468
|
+
[data-ui='material'] :where([role='toolbar'] > button:not([aria-pressed])) {
|
|
469
|
+
border-radius: 999px;
|
|
470
|
+
}
|
|
471
|
+
[data-ui='material'] :where([role='toolbar'] > button:not([aria-pressed]):hover) {
|
|
472
|
+
background: color-mix(in oklab, var(--flx-ui-color-fg) 8%, transparent);
|
|
473
|
+
color: var(--flx-ui-color-fg);
|
|
412
474
|
}
|
|
413
475
|
|
|
414
476
|
/* ---- Navigation menu & menubar: state-layer triggers, rounded ----------- */
|
|
@@ -423,12 +485,41 @@
|
|
|
423
485
|
background: color-mix(in oklab, var(--flx-ui-color-fg) 8%, transparent);
|
|
424
486
|
}
|
|
425
487
|
|
|
426
|
-
/* ---- Table:
|
|
488
|
+
/* ---- Table: flat M3 data table — no frame, divider-only rows, sentence-case
|
|
489
|
+
header (no all-caps), state-layer hover/selection, comfortable density -- */
|
|
490
|
+
[data-ui='material'] :where([data-table]) {
|
|
491
|
+
border: none;
|
|
492
|
+
border-radius: 0;
|
|
493
|
+
}
|
|
427
494
|
[data-ui='material'] :where([data-table-head]) {
|
|
495
|
+
background: transparent;
|
|
496
|
+
color: var(--flx-ui-color-fg-muted);
|
|
497
|
+
font-size: var(--flx-ui-font-size-sm);
|
|
428
498
|
font-weight: 500;
|
|
499
|
+
letter-spacing: normal;
|
|
500
|
+
text-transform: none;
|
|
501
|
+
padding: var(--flx-ui-space-3);
|
|
502
|
+
border-bottom: var(--flx-ui-border-width-thin) solid var(--flx-ui-color-border);
|
|
503
|
+
}
|
|
504
|
+
[data-ui='material'] :where([data-table-cell]) {
|
|
505
|
+
padding: var(--flx-ui-space-3);
|
|
429
506
|
}
|
|
430
|
-
[data-ui='material'] :where([data-table-row]:hover) {
|
|
431
|
-
background: color-mix(in oklab, var(--flx-ui-color-fg)
|
|
507
|
+
[data-ui='material'] :where([data-table-body] > [data-table-row]:hover) {
|
|
508
|
+
background: color-mix(in oklab, var(--flx-ui-color-fg) 5%, transparent);
|
|
509
|
+
}
|
|
510
|
+
[data-ui='material'] :where([data-table-row][data-selected]),
|
|
511
|
+
[data-ui='material'] :where([data-table-row][data-selected]:hover) {
|
|
512
|
+
background: color-mix(in oklab, var(--flx-ui-color-primary) 10%, transparent);
|
|
513
|
+
}
|
|
514
|
+
/* Header is transparent now, so pinned cells need an opaque surface fill. */
|
|
515
|
+
[data-ui='material'] :where([data-table-cell][data-pinned]),
|
|
516
|
+
[data-ui='material'] :where([data-table-head][data-pinned]) {
|
|
517
|
+
background: var(--flx-ui-color-bg);
|
|
518
|
+
}
|
|
519
|
+
/* Compact density under Material. */
|
|
520
|
+
[data-ui='material'] :where([data-table][data-density='compact'] [data-table-head]),
|
|
521
|
+
[data-ui='material'] :where([data-table][data-density='compact'] [data-table-cell]) {
|
|
522
|
+
padding: var(--flx-ui-space-1) var(--flx-ui-space-2);
|
|
432
523
|
}
|
|
433
524
|
|
|
434
525
|
/* ---- Toast: M3 snackbar shape + elevation (keeps the type accent) -------- */
|
|
@@ -443,13 +534,13 @@
|
|
|
443
534
|
}
|
|
444
535
|
|
|
445
536
|
/* ---- Click-origin ripple (installed by the ripple primitive) ------------- */
|
|
446
|
-
[data-ui='material'] :where([data-variant], [role='menuitem'], [role='option'], [role='tab']) {
|
|
537
|
+
[data-ui='material'] :where([data-variant]:not([data-badge]), [role='menuitem'], [role='option'], [role='tab']) {
|
|
447
538
|
position: relative;
|
|
448
539
|
overflow: hidden;
|
|
449
540
|
}
|
|
450
541
|
/* A glow button draws its ring on ::after at the border edge; the ripple's
|
|
451
542
|
overflow:hidden would clip it, so let a glow button overflow. */
|
|
452
|
-
[data-ui='material'] :where([data-variant][data-glow]) {
|
|
543
|
+
[data-ui='material'] :where([data-variant]:not([data-badge])[data-glow]) {
|
|
453
544
|
overflow: visible;
|
|
454
545
|
}
|
|
455
546
|
[data-ui='material'] .flx-mat-ripple {
|
|
@@ -478,4 +569,308 @@
|
|
|
478
569
|
opacity: 0;
|
|
479
570
|
}
|
|
480
571
|
}
|
|
572
|
+
|
|
573
|
+
/* ---- Progress: M3 linear (4px, tonal track) ------------------------------- */
|
|
574
|
+
[data-ui='material'] :where([role='progressbar']:not([data-circular])) {
|
|
575
|
+
height: 4px;
|
|
576
|
+
background: var(--flx-ui-color-primary-subtle);
|
|
577
|
+
}
|
|
578
|
+
[data-ui='material'] :where([role='progressbar']:not([data-circular]))::after {
|
|
579
|
+
background: var(--flx-ui-color-primary);
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/* ---- Slider: M3 (thin tonal track, filled active range) ------------------- */
|
|
583
|
+
[data-ui='material'] :where([data-slider-track]) {
|
|
584
|
+
height: 4px;
|
|
585
|
+
background: var(--flx-ui-color-primary-subtle);
|
|
586
|
+
}
|
|
587
|
+
[data-ui='material'] :where([data-slider-range]) {
|
|
588
|
+
background: var(--flx-ui-color-primary);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
/* ---- Badge: M3 label (medium weight, subtle tracking) --------------------- */
|
|
592
|
+
[data-ui='material'] :where([data-badge]) {
|
|
593
|
+
font-weight: var(--flx-ui-font-weight-medium);
|
|
594
|
+
letter-spacing: 0.02em;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/* ---- Avatar: M3 rounded-square option stays circular; add tonal ring ------ */
|
|
598
|
+
[data-ui='material'] :where([data-avatar]) {
|
|
599
|
+
font-weight: var(--flx-ui-font-weight-medium);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
/* ---- Statistic: M3 display number (tighter tracking) ---------------------- */
|
|
603
|
+
[data-ui='material'] :where([data-statistic-value]) {
|
|
604
|
+
font-weight: var(--flx-ui-font-weight-semibold);
|
|
605
|
+
letter-spacing: -0.01em;
|
|
606
|
+
}
|
|
607
|
+
[data-ui='material'] :where([data-statistic-label]) {
|
|
608
|
+
letter-spacing: 0.06em;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
/* ---- Empty: M3 icon tile (rounded-large, tonal) --------------------------- */
|
|
612
|
+
[data-ui='material'] :where([data-empty-icon]) {
|
|
613
|
+
width: 48px;
|
|
614
|
+
height: 48px;
|
|
615
|
+
border-radius: 16px;
|
|
616
|
+
background: var(--flx-ui-color-primary-subtle);
|
|
617
|
+
color: var(--flx-ui-color-primary);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
/* ---- Timeline: M3 dot state-layer ---------------------------------------- */
|
|
621
|
+
[data-ui='material'] :where([data-timeline-indicator]:empty)::before {
|
|
622
|
+
box-shadow: 0 0 0 4px color-mix(in srgb, var(--flx-timeline-dot) 14%, transparent);
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
/* ---- Descriptions: M3 term (medium, tracked) ------------------------------ */
|
|
626
|
+
[data-ui='material'] :where([data-descriptions-term]) {
|
|
627
|
+
font-weight: var(--flx-ui-font-weight-medium);
|
|
628
|
+
letter-spacing: 0.04em;
|
|
629
|
+
text-transform: uppercase;
|
|
630
|
+
font-size: var(--flx-ui-font-size-2xs, 11px);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/* ---- Switch: Material (thin track, prominent thumb, ripple state-layer) ---- */
|
|
634
|
+
[data-ui='material'] :where([role='switch']) {
|
|
635
|
+
width: 34px;
|
|
636
|
+
height: 14px;
|
|
637
|
+
padding: 0;
|
|
638
|
+
border: none;
|
|
639
|
+
overflow: visible;
|
|
640
|
+
position: relative;
|
|
641
|
+
border-radius: 999px;
|
|
642
|
+
background: color-mix(in srgb, var(--flx-ui-color-fg) 26%, transparent);
|
|
643
|
+
}
|
|
644
|
+
[data-ui='material'] :where([role='switch'][data-state='checked']) {
|
|
645
|
+
background: color-mix(in srgb, var(--flx-ui-color-primary) 50%, transparent);
|
|
646
|
+
filter: none;
|
|
647
|
+
}
|
|
648
|
+
[data-ui='material'] :where([role='switch']:hover:not([data-disabled])) {
|
|
649
|
+
filter: none;
|
|
650
|
+
}
|
|
651
|
+
/* Thumb — 20px circle, larger than the 14px track so it overlaps it. */
|
|
652
|
+
[data-ui='material'] :where([role='switch'])::after {
|
|
653
|
+
content: '';
|
|
654
|
+
position: absolute;
|
|
655
|
+
top: 50%;
|
|
656
|
+
left: 0;
|
|
657
|
+
width: 20px;
|
|
658
|
+
height: 20px;
|
|
659
|
+
margin: 0;
|
|
660
|
+
border-radius: 50%;
|
|
661
|
+
background: #fff;
|
|
662
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
|
|
663
|
+
transform: translate(-2px, -50%);
|
|
664
|
+
transition:
|
|
665
|
+
transform var(--flx-ui-duration-normal) var(--flx-ui-ease-emphasized),
|
|
666
|
+
background var(--flx-ui-duration-fast) var(--flx-ui-ease-standard);
|
|
667
|
+
}
|
|
668
|
+
[data-ui='material'] :where([role='switch'][data-state='checked'])::after {
|
|
669
|
+
background: var(--flx-ui-color-primary);
|
|
670
|
+
transform: translate(16px, -50%);
|
|
671
|
+
}
|
|
672
|
+
/* Ripple / state-layer — a translucent disc behind the thumb, following it. */
|
|
673
|
+
[data-ui='material'] :where([role='switch'])::before {
|
|
674
|
+
content: '';
|
|
675
|
+
position: absolute;
|
|
676
|
+
top: 50%;
|
|
677
|
+
left: 0;
|
|
678
|
+
width: 40px;
|
|
679
|
+
height: 40px;
|
|
680
|
+
border-radius: 50%;
|
|
681
|
+
background: var(--flx-ui-color-fg);
|
|
682
|
+
opacity: 0;
|
|
683
|
+
pointer-events: none;
|
|
684
|
+
transform: translate(-12px, -50%) scale(0.7);
|
|
685
|
+
transition:
|
|
686
|
+
opacity var(--flx-ui-duration-fast) var(--flx-ui-ease-standard),
|
|
687
|
+
transform var(--flx-ui-duration-normal) var(--flx-ui-ease-emphasized);
|
|
688
|
+
}
|
|
689
|
+
[data-ui='material'] :where([role='switch'][data-state='checked'])::before {
|
|
690
|
+
background: var(--flx-ui-color-primary);
|
|
691
|
+
transform: translate(6px, -50%) scale(0.7);
|
|
692
|
+
}
|
|
693
|
+
[data-ui='material'] :where([role='switch']:hover:not([data-disabled]))::before {
|
|
694
|
+
opacity: 0.09;
|
|
695
|
+
transform: translate(-12px, -50%) scale(1);
|
|
696
|
+
}
|
|
697
|
+
[data-ui='material'] :where([role='switch'][data-state='checked']:hover:not([data-disabled]))::before {
|
|
698
|
+
transform: translate(6px, -50%) scale(1);
|
|
699
|
+
}
|
|
700
|
+
[data-ui='material'] :where([role='switch']:active:not([data-disabled]))::before {
|
|
701
|
+
opacity: 0.18;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
/* ---- Slider thumb: Material filled handle + ripple state-layer ------------- */
|
|
705
|
+
[data-ui='material'] :where([data-slider] [role='slider']) {
|
|
706
|
+
background: var(--flx-ui-color-primary);
|
|
707
|
+
border-color: var(--flx-ui-color-primary);
|
|
708
|
+
}
|
|
709
|
+
[data-ui='material'] :where([data-slider] [role='slider'])::before {
|
|
710
|
+
content: '';
|
|
711
|
+
position: absolute;
|
|
712
|
+
top: 50%;
|
|
713
|
+
left: 50%;
|
|
714
|
+
width: 40px;
|
|
715
|
+
height: 40px;
|
|
716
|
+
border-radius: 50%;
|
|
717
|
+
background: var(--flx-ui-color-primary);
|
|
718
|
+
opacity: 0;
|
|
719
|
+
pointer-events: none;
|
|
720
|
+
transform: translate(-50%, -50%) scale(0.4);
|
|
721
|
+
transition:
|
|
722
|
+
opacity var(--flx-ui-duration-fast) var(--flx-ui-ease-standard),
|
|
723
|
+
transform var(--flx-ui-duration-normal) var(--flx-ui-ease-emphasized);
|
|
724
|
+
}
|
|
725
|
+
[data-ui='material'] :where([data-slider] [role='slider']:hover:not([data-disabled]))::before {
|
|
726
|
+
opacity: 0.12;
|
|
727
|
+
transform: translate(-50%, -50%) scale(1);
|
|
728
|
+
}
|
|
729
|
+
[data-ui='material'] :where([data-slider] [role='slider']:active)::before,
|
|
730
|
+
[data-ui='material'] :where([data-slider] [role='slider']:focus-visible)::before {
|
|
731
|
+
opacity: 0.2;
|
|
732
|
+
transform: translate(-50%, -50%) scale(1);
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
/* ---- Popup surfaces: one consistent M3 shape (small radius, tight elevation)
|
|
736
|
+
* Unifies every floating surface — menus, listboxes, datepicker, command,
|
|
737
|
+
* hovercard, nav-menu — which previously ranged from radius-md (12px) to
|
|
738
|
+
* radius-lg (16px) with a heavy shadow-lg. Tooltip already matches at 4px. */
|
|
739
|
+
[data-ui='material'] :where(
|
|
740
|
+
[role='menu'],
|
|
741
|
+
[role='listbox'],
|
|
742
|
+
[data-date-picker-content],
|
|
743
|
+
[data-navigation-menu-content],
|
|
744
|
+
[data-command],
|
|
745
|
+
[data-hovercard-content]
|
|
746
|
+
) {
|
|
747
|
+
border-radius: 4px;
|
|
748
|
+
box-shadow:
|
|
749
|
+
0 2px 6px rgba(0, 0, 0, 0.16),
|
|
750
|
+
0 1px 3px rgba(0, 0, 0, 0.1);
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
/* ---- Checkbox & radio: M3 state-layer ripple -------------------------------
|
|
754
|
+
* The ripple lives on ::before at z-index:-1 so it paints ABOVE the control's
|
|
755
|
+
* background but BELOW its content (the base check/dot on ::after). This leaves
|
|
756
|
+
* the base marks completely untouched — do NOT restyle ::after here, the base
|
|
757
|
+
* check is a flex-centred rotated border and the radio dot is position:absolute;
|
|
758
|
+
* inset:3px, both of which break if position/box-sizing is overridden. */
|
|
759
|
+
[data-ui='material'] :where([role='checkbox']),
|
|
760
|
+
[data-ui='material'] :where([role='radio']) {
|
|
761
|
+
position: relative;
|
|
762
|
+
overflow: visible;
|
|
763
|
+
}
|
|
764
|
+
[data-ui='material'] :where([role='checkbox'])::before,
|
|
765
|
+
[data-ui='material'] :where([role='radio'])::before {
|
|
766
|
+
content: '';
|
|
767
|
+
position: absolute;
|
|
768
|
+
z-index: -1;
|
|
769
|
+
top: 50%;
|
|
770
|
+
left: 50%;
|
|
771
|
+
width: 40px;
|
|
772
|
+
height: 40px;
|
|
773
|
+
border-radius: 50%;
|
|
774
|
+
background: var(--flx-ui-color-primary);
|
|
775
|
+
opacity: 0;
|
|
776
|
+
pointer-events: none;
|
|
777
|
+
transform: translate(-50%, -50%) scale(0.5);
|
|
778
|
+
transition:
|
|
779
|
+
opacity var(--flx-ui-duration-fast) var(--flx-ui-ease-standard),
|
|
780
|
+
transform var(--flx-ui-duration-normal) var(--flx-ui-ease-emphasized);
|
|
781
|
+
}
|
|
782
|
+
[data-ui='material'] :where([role='checkbox']:hover:not([data-disabled]))::before,
|
|
783
|
+
[data-ui='material'] :where([role='radio']:hover:not([data-disabled]))::before {
|
|
784
|
+
opacity: 0.1;
|
|
785
|
+
transform: translate(-50%, -50%) scale(1);
|
|
786
|
+
}
|
|
787
|
+
[data-ui='material'] :where([role='checkbox']:active:not([data-disabled]))::before,
|
|
788
|
+
[data-ui='material'] :where([role='radio']:active:not([data-disabled]))::before,
|
|
789
|
+
[data-ui='material'] :where([role='checkbox']:focus-visible)::before,
|
|
790
|
+
[data-ui='material'] :where([role='radio']:focus-visible)::before {
|
|
791
|
+
opacity: 0.18;
|
|
792
|
+
transform: translate(-50%, -50%) scale(1);
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
/* ---- Circular progress: 4dp tonal track, round cap (matches linear) ------ */
|
|
796
|
+
[data-ui='material'] :where([data-progress-track]) {
|
|
797
|
+
stroke: var(--flx-ui-color-primary-subtle);
|
|
798
|
+
}
|
|
799
|
+
[data-ui='material'] :where([data-progress-indicator]) {
|
|
800
|
+
stroke-linecap: round;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
/* ---- Avatar group: tonal secondary-container overflow chip --------------- */
|
|
804
|
+
[data-ui='material'] :where([data-avatar-group-overflow]) {
|
|
805
|
+
background: var(--flx-ui-color-primary-subtle);
|
|
806
|
+
color: var(--flx-ui-color-primary-active);
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
/* ---- Rating: filled primary stars, roomier M3 spacing ------------------- */
|
|
810
|
+
[data-ui='material'] :where([data-rating]) {
|
|
811
|
+
--flx-ui-rating-gap: 4px;
|
|
812
|
+
--flx-ui-rating-color: var(--flx-ui-color-primary);
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
/* ---- PIN input: M3 filled cells with the shared underline treatment ------ */
|
|
816
|
+
[data-ui='material'] :where([data-pin-input-field]) {
|
|
817
|
+
background: var(--flx-ui-color-bg-muted);
|
|
818
|
+
border: none;
|
|
819
|
+
border-bottom: 1px solid var(--flx-ui-color-border-strong);
|
|
820
|
+
border-radius: 4px 4px 0 0;
|
|
821
|
+
}
|
|
822
|
+
[data-ui='material'] :where([data-pin-input-field]:focus, [data-pin-input-field]:focus-visible) {
|
|
823
|
+
border-bottom: 2px solid var(--flx-ui-color-primary);
|
|
824
|
+
box-shadow: none;
|
|
825
|
+
outline: none;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
/* ---- Icon button: M3 round, size-aware (overrides the fixed 40px pill) ---- */
|
|
829
|
+
[data-ui='material'] :where([data-icon-button]) {
|
|
830
|
+
padding: 0;
|
|
831
|
+
width: var(--flx-ui-size-md);
|
|
832
|
+
height: var(--flx-ui-size-md);
|
|
833
|
+
border-radius: 9999px;
|
|
834
|
+
}
|
|
835
|
+
[data-ui='material'] :where([data-icon-button][data-size='sm']) {
|
|
836
|
+
width: var(--flx-ui-size-sm);
|
|
837
|
+
height: var(--flx-ui-size-sm);
|
|
838
|
+
}
|
|
839
|
+
[data-ui='material'] :where([data-icon-button][data-size='lg']) {
|
|
840
|
+
width: var(--flx-ui-size-lg);
|
|
841
|
+
height: var(--flx-ui-size-lg);
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
/* ---- FAB: M3 primary-container, resting elevation, larger radius. Re-assert
|
|
845
|
+
the FAB geometry the fixed-40px button rule above would otherwise impose. */
|
|
846
|
+
[data-ui='material'] :where([data-fab]) {
|
|
847
|
+
width: 56px;
|
|
848
|
+
height: 56px;
|
|
849
|
+
padding: 0;
|
|
850
|
+
border-radius: 16px;
|
|
851
|
+
background: var(--flx-ui-color-primary-subtle);
|
|
852
|
+
color: var(--flx-ui-color-primary-active);
|
|
853
|
+
box-shadow: var(--flx-ui-shadow-md);
|
|
854
|
+
}
|
|
855
|
+
[data-ui='material'] :where([data-fab]:hover:not([data-disabled])) {
|
|
856
|
+
box-shadow: var(--flx-ui-shadow-lg);
|
|
857
|
+
}
|
|
858
|
+
[data-ui='material'] :where([data-fab][data-fab-size='sm']) { width: 40px; height: 40px; border-radius: 12px; }
|
|
859
|
+
[data-ui='material'] :where([data-fab][data-fab-size='lg']) { width: 64px; height: 64px; border-radius: 28px; }
|
|
860
|
+
[data-ui='material'] :where([data-fab][data-fab-extended]) {
|
|
861
|
+
width: auto;
|
|
862
|
+
height: 56px;
|
|
863
|
+
padding: 0 20px;
|
|
864
|
+
border-radius: 16px;
|
|
865
|
+
}
|
|
866
|
+
/* A solid-toned FAB keeps the primary fill instead of the tonal container. */
|
|
867
|
+
[data-ui='material'] :where([data-fab][data-variant='solid']) {
|
|
868
|
+
background: var(--flx-ui-color-primary);
|
|
869
|
+
color: var(--flx-ui-color-primary-fg);
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
/* ---- Speed dial: elevated action buttons -------------------------------- */
|
|
873
|
+
[data-ui='material'] :where([data-speed-dial-action]) {
|
|
874
|
+
box-shadow: var(--flx-ui-shadow-sm);
|
|
875
|
+
}
|
|
481
876
|
}
|