@cahyo-dimas/freeday 3.6.0 → 3.8.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 +139 -0
- package/COMPONENTS.md +119 -6
- package/README.id.md +19 -6
- package/README.md +17 -5
- package/USAGE.md +42 -0
- package/adapters/blazor/FdyDatepicker.razor +3 -1
- package/adapters/blazor/FdyDatepicker.razor.cs +22 -1
- package/adapters/blazor/FdyTableFooter.razor +6 -6
- package/adapters/blazor/FdyTableFooter.razor.cs +36 -0
- package/adapters/react/components/FdyDatepicker.tsx +122 -42
- package/adapters/react/components/FdyTableFooter.tsx +37 -6
- package/adapters/react/index.d.ts +1 -1
- package/adapters/vue/components/FdyDatepicker.vue +119 -34
- package/adapters/vue/components/FdyTableFooter.vue +39 -6
- package/dist/freeday-datepicker.js +68 -14
- package/dist/freeday-menu.js +15 -1
- package/dist/freeday-popover.js +33 -11
- package/dist/freeday-tabs.js +21 -2
- package/dist/freeday.bundle.css +493 -117
- package/dist/freeday.css +190 -113
- package/dist/freeday.js +137 -28
- package/dist/freeday.tokens.css +303 -4
- package/docs/getting-started.md +1 -1
- package/package.json +2 -2
- package/src/base.css +1 -1
- package/src/components/accordion.css +1 -1
- package/src/components/alert.css +5 -5
- package/src/components/app-shell.css +2 -2
- package/src/components/appbar.css +3 -3
- package/src/components/avatar.css +15 -9
- package/src/components/badge.css +18 -14
- package/src/components/breadcrumb.css +1 -1
- package/src/components/button.css +21 -13
- package/src/components/carousel.css +3 -3
- package/src/components/cascade.css +4 -4
- package/src/components/chip.css +33 -15
- package/src/components/combo.css +5 -5
- package/src/components/datepicker.css +8 -8
- package/src/components/file-upload.css +9 -4
- package/src/components/input-group.css +2 -2
- package/src/components/input.css +2 -2
- package/src/components/menu.css +3 -3
- package/src/components/pagination.css +1 -1
- package/src/components/selection.css +2 -2
- package/src/components/skeleton.css +1 -1
- package/src/components/stepper.css +1 -1
- package/src/components/table.css +12 -7
- package/src/components/tabs.css +32 -1
- package/src/components/timepicker.css +3 -3
- package/src/components/toast.css +1 -1
- package/src/components/tree.css +1 -1
- package/tokens/tokens.json +57 -4
package/dist/freeday.css
CHANGED
|
@@ -12,7 +12,7 @@ body {
|
|
|
12
12
|
-webkit-font-smoothing: antialiased;
|
|
13
13
|
}
|
|
14
14
|
h1, h2, h3, h4 { font-family: var(--font-display); font-weight: var(--weight-bold); letter-spacing: var(--tracking-tighter); line-height: var(--leading-snug); margin: 0; }
|
|
15
|
-
a { color: var(--color-primary); }
|
|
15
|
+
a { color: var(--color-primary-strong); }
|
|
16
16
|
:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: var(--focus-ring-width); border-radius: var(--radius-xs); }
|
|
17
17
|
:where(button, input, select, textarea) { font: inherit; }
|
|
18
18
|
/* Hidden from sight, kept for assistive tech. `clip` hides PAINTING, not LAYOUT: the box still
|
|
@@ -52,7 +52,7 @@ a { color: var(--color-primary); }
|
|
|
52
52
|
.fdy-accordion__item > summary::after{content:"";margin-left:auto;margin-top:-.15rem;flex:none;width:.5rem;height:.5rem;border-right:2px solid var(--color-text-subtle);border-bottom:2px solid var(--color-text-subtle);transform:rotate(45deg);transition:transform var(--dur-fast) var(--ease-standard);}
|
|
53
53
|
.fdy-accordion__item[open] > summary::after{transform:rotate(225deg);margin-top:.1rem;}
|
|
54
54
|
.fdy-accordion__item > summary:hover{background:var(--color-surface-2);}
|
|
55
|
-
.fdy-accordion__item > summary:focus-visible{outline:none;box-shadow:inset 0 0 0 2px
|
|
55
|
+
.fdy-accordion__item > summary:focus-visible{outline:none;box-shadow:inset 0 0 0 2px rgba(var(--color-primary-rgb),.45);}
|
|
56
56
|
.fdy-accordion__panel{padding:0 var(--space-4) var(--space-4);color:var(--color-text-muted);font-size:var(--text-sm);line-height:var(--leading-normal);}
|
|
57
57
|
/* Content reveal on open (fade + rise). Native <details> can't animate its own height cross-
|
|
58
58
|
* browser without JS, so we animate the revealed panel instead, cheap, safe, reduced-motion gated. */
|
|
@@ -67,14 +67,14 @@ a { color: var(--color-primary); }
|
|
|
67
67
|
.fdy-alert__text{color:var(--color-text);line-height:var(--leading-normal);}
|
|
68
68
|
.fdy-alert__close{flex:none;align-self:flex-start;border:0;background:transparent;color:var(--color-text-muted);cursor:pointer;font-size:var(--text-lg);line-height:1;padding:0 var(--space-1);border-radius:var(--radius-sm);}
|
|
69
69
|
.fdy-alert__close:hover{color:var(--color-text);}
|
|
70
|
-
.fdy-alert__close:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
71
|
-
.fdy-alert--info{background:var(--color-info-soft);border-color:
|
|
70
|
+
.fdy-alert__close:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
71
|
+
.fdy-alert--info{background:var(--color-info-soft);border-color:rgba(var(--color-info-rgb),.26);}
|
|
72
72
|
.fdy-alert--info .fdy-alert__title,.fdy-alert--info .fdy-alert__icon{color:var(--color-info-strong);}
|
|
73
|
-
.fdy-alert--success{background:var(--color-success-soft);border-color:
|
|
73
|
+
.fdy-alert--success{background:var(--color-success-soft);border-color:rgba(var(--color-success-rgb),.26);}
|
|
74
74
|
.fdy-alert--success .fdy-alert__title,.fdy-alert--success .fdy-alert__icon{color:var(--color-success-strong);}
|
|
75
|
-
.fdy-alert--warning{background:var(--color-warning-soft);border-color:
|
|
75
|
+
.fdy-alert--warning{background:var(--color-warning-soft);border-color:rgba(var(--color-warning-rgb),.26);}
|
|
76
76
|
.fdy-alert--warning .fdy-alert__title,.fdy-alert--warning .fdy-alert__icon{color:var(--color-warning-strong);}
|
|
77
|
-
.fdy-alert--danger{background:var(--color-danger-soft);border-color:
|
|
77
|
+
.fdy-alert--danger{background:var(--color-danger-soft);border-color:rgba(var(--color-danger-rgb),.26);}
|
|
78
78
|
.fdy-alert--danger .fdy-alert__title,.fdy-alert--danger .fdy-alert__icon{color:var(--color-danger-strong);}
|
|
79
79
|
|
|
80
80
|
/* Freeday. App Shell.
|
|
@@ -123,7 +123,7 @@ a { color: var(--color-primary); }
|
|
|
123
123
|
.fdy-nav__item:hover{background:var(--color-surface-2);color:var(--color-text);}
|
|
124
124
|
/* Active indicator stays in the primary ramp so it never clashes with a re-themed accent. */
|
|
125
125
|
.fdy-nav__item[aria-current="page"]{background:var(--color-primary-soft);color:var(--color-primary-strong);font-weight:var(--weight-semibold);}
|
|
126
|
-
.fdy-nav__item:focus-visible{outline:none;box-shadow:0 0 0 2px
|
|
126
|
+
.fdy-nav__item:focus-visible{outline:none;box-shadow:0 0 0 2px rgba(var(--color-primary-rgb),.45);}
|
|
127
127
|
/* Sidebar-menu extras: per-node icon (leading), count badge (trailing), and a
|
|
128
128
|
* text label that truncates. Any of these are optional, a bare text item works. */
|
|
129
129
|
.fdy-nav__icon{flex:none;display:inline-flex;width:1.15rem;height:1.15rem;}
|
|
@@ -141,7 +141,7 @@ a { color: var(--color-primary); }
|
|
|
141
141
|
.fdy-nav__grouplabel{list-style:none;cursor:pointer;display:flex;align-items:center;justify-content:space-between;gap:var(--space-2);padding:var(--space-3) var(--space-3) var(--space-1);font-size:var(--text-xs);text-transform:uppercase;letter-spacing:var(--tracking-wide);font-weight:var(--weight-semibold);color:var(--color-text-muted);}
|
|
142
142
|
.fdy-nav__grouplabel::-webkit-details-marker{display:none;}
|
|
143
143
|
.fdy-nav__grouplabel:hover{color:var(--color-text-muted);}
|
|
144
|
-
.fdy-nav__grouplabel:focus-visible{outline:none;border-radius:var(--radius-sm);box-shadow:0 0 0 2px
|
|
144
|
+
.fdy-nav__grouplabel:focus-visible{outline:none;border-radius:var(--radius-sm);box-shadow:0 0 0 2px rgba(var(--color-primary-rgb),.45);}
|
|
145
145
|
.fdy-nav__grouplabel::after{content:"";flex:none;width:.45rem;height:.45rem;margin-right:var(--space-1);border-right:2px solid currentColor;border-bottom:2px solid currentColor;transform:rotate(-45deg);transition:transform var(--dur-fast) var(--ease-standard);opacity:.7;}
|
|
146
146
|
.fdy-nav__group[open] > .fdy-nav__grouplabel::after{transform:rotate(45deg);}
|
|
147
147
|
/* --flat: calmer, non-collapsible grouped nav, hide the caret, drop the
|
|
@@ -242,13 +242,13 @@ a { color: var(--color-primary); }
|
|
|
242
242
|
is the same component whether the nav is a sidebar column or a top row. */
|
|
243
243
|
/* Controls on a coloured app bar go on-colour (icons stay legible, hover is a light wash) */
|
|
244
244
|
.fdy-appbar--primary .fdy-btn--ghost{background:transparent;border-color:transparent;color:var(--color-on-primary);box-shadow:none;}
|
|
245
|
-
.fdy-appbar--primary .fdy-btn--ghost:hover{background:
|
|
245
|
+
.fdy-appbar--primary .fdy-btn--ghost:hover{background:rgba(var(--color-on-primary-rgb),.16);color:var(--color-on-primary);transform:none;}
|
|
246
246
|
/* Nav links on a coloured bar: full on-colour ink in every state (a dimmed variant would trade away
|
|
247
247
|
the contrast the bar's own token pair guarantees). The current page is carried by the background
|
|
248
248
|
wash plus the semibold weight the base rule already applies, and by `aria-current` itself. */
|
|
249
249
|
.fdy-appbar--primary .fdy-nav__item{color:var(--color-on-primary);}
|
|
250
|
-
.fdy-appbar--primary .fdy-nav__item:hover{background:
|
|
251
|
-
.fdy-appbar--primary .fdy-nav__item[aria-current="page"]{background:
|
|
250
|
+
.fdy-appbar--primary .fdy-nav__item:hover{background:rgba(var(--color-on-primary-rgb),.16);color:var(--color-on-primary);}
|
|
251
|
+
.fdy-appbar--primary .fdy-nav__item[aria-current="page"]{background:rgba(var(--color-on-primary-rgb),.24);color:var(--color-on-primary);}
|
|
252
252
|
|
|
253
253
|
/* Freeday. Autocomplete (text input + filtered suggestion listbox, APG editable combobox).
|
|
254
254
|
* Enhanced by freeday-autocomplete.js. */
|
|
@@ -282,22 +282,28 @@ a { color: var(--color-primary); }
|
|
|
282
282
|
* text-leaning foreground so initials keep WCAG AA (verified >=4.5:1 in light & dark by
|
|
283
283
|
* test/contrast.test.mjs). Use to disambiguate same-initial avatars (e.g. many "PT …" names):
|
|
284
284
|
* hash a stable 1..8 index off the FULL name in your app, then apply .fdy-avatar--tone-<n>. */
|
|
285
|
-
.
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
.
|
|
291
|
-
.
|
|
292
|
-
.fdy-avatar--tone-
|
|
293
|
-
.fdy-avatar--tone-
|
|
285
|
+
/* One flat token per half, computed in advance by tokens/build.mjs: --tone-N-bg is 18% of the
|
|
286
|
+
* tone over --color-surface, --tone-N-ink is 50% of it toward --color-text, both per theme.
|
|
287
|
+
* They USED to be mixed here, with the hue injected per element through a private custom
|
|
288
|
+
* property — which put var() inside color-mix(), the one shape that cannot be rescued: valid at
|
|
289
|
+
* parse time, invalid at computed-value time, and there `background` and `color` drop to their
|
|
290
|
+
* INITIAL values, not to any fallback. @supports answered it for exactly as long as somebody
|
|
291
|
+
* remembered to write the counterpart; a precomputed token removes the question. */
|
|
292
|
+
.fdy-avatar--tone-1{background:var(--tone-1-bg);color:var(--tone-1-ink);}
|
|
293
|
+
.fdy-avatar--tone-2{background:var(--tone-2-bg);color:var(--tone-2-ink);}
|
|
294
|
+
.fdy-avatar--tone-3{background:var(--tone-3-bg);color:var(--tone-3-ink);}
|
|
295
|
+
.fdy-avatar--tone-4{background:var(--tone-4-bg);color:var(--tone-4-ink);}
|
|
296
|
+
.fdy-avatar--tone-5{background:var(--tone-5-bg);color:var(--tone-5-ink);}
|
|
297
|
+
.fdy-avatar--tone-6{background:var(--tone-6-bg);color:var(--tone-6-ink);}
|
|
298
|
+
.fdy-avatar--tone-7{background:var(--tone-7-bg);color:var(--tone-7-ink);}
|
|
299
|
+
.fdy-avatar--tone-8{background:var(--tone-8-bg);color:var(--tone-8-ink);}
|
|
294
300
|
|
|
295
301
|
/* Freeday. Badge */
|
|
296
|
-
.fdy-badge{display:inline-flex;align-items:center;gap:var(--space-1);font-family:var(--font-body);font-size:var(--text-xs);font-weight:var(--weight-semibold);line-height:1;white-space:nowrap;padding:.35em .7em;border-radius:var(--radius-full);color:var(--color-primary-strong);background:var(--color-primary-soft);border:var(--bw) solid
|
|
297
|
-
.fdy-badge--success{color:var(--color-success-strong);background:var(--color-success-soft);border-color:
|
|
298
|
-
.fdy-badge--warning{color:var(--color-warning-strong);background:var(--color-warning-soft);border-color:
|
|
299
|
-
.fdy-badge--danger{color:var(--color-danger-strong);background:var(--color-danger-soft);border-color:
|
|
300
|
-
.fdy-badge--info{color:var(--color-info-strong);background:var(--color-info-soft);border-color:
|
|
302
|
+
.fdy-badge{display:inline-flex;align-items:center;gap:var(--space-1);font-family:var(--font-body);font-size:var(--text-xs);font-weight:var(--weight-semibold);line-height:1;white-space:nowrap;padding:.35em .7em;border-radius:var(--radius-full);color:var(--color-primary-strong);background:var(--color-primary-soft);border:var(--bw) solid rgba(var(--color-primary-rgb),.22);box-shadow:0 1px 1.5px rgba(16,14,30,.05);}
|
|
303
|
+
.fdy-badge--success{color:var(--color-success-strong);background:var(--color-success-soft);border-color:rgba(var(--color-success-rgb),.26);}
|
|
304
|
+
.fdy-badge--warning{color:var(--color-warning-strong);background:var(--color-warning-soft);border-color:rgba(var(--color-warning-rgb),.26);}
|
|
305
|
+
.fdy-badge--danger{color:var(--color-danger-strong);background:var(--color-danger-soft);border-color:rgba(var(--color-danger-rgb),.26);}
|
|
306
|
+
.fdy-badge--info{color:var(--color-info-strong);background:var(--color-info-soft);border-color:rgba(var(--color-info-rgb),.26);}
|
|
301
307
|
.fdy-badge--outline{background:transparent;border-color:var(--color-border-strong);color:var(--color-text-muted);box-shadow:none;}
|
|
302
308
|
|
|
303
309
|
/* Categorical tone badges, a status vocabulary larger than the semantic palette, from the
|
|
@@ -309,15 +315,19 @@ a { color: var(--color-primary); }
|
|
|
309
315
|
* cannot. A back-office document list carrying Draft, Submitted, Approved, Completed, Settled,
|
|
310
316
|
* Closed, Transferred, InDeclaration, Open and Rejected in ONE column collapsed to three colours,
|
|
311
317
|
* which is the report this shipped for. */
|
|
312
|
-
|
|
313
|
-
.
|
|
314
|
-
|
|
315
|
-
.
|
|
316
|
-
.
|
|
317
|
-
.fdy-badge--tone-
|
|
318
|
-
.fdy-badge--tone-
|
|
319
|
-
.fdy-badge--tone-
|
|
320
|
-
.fdy-badge--tone-
|
|
318
|
+
/* Precomputed tone tokens, the same --tone-N-bg / --tone-N-ink the avatar and the chip read, so
|
|
319
|
+
* one contrast assertion still covers all three. --tone-N-border-soft is the badge's own edge:
|
|
320
|
+
* 26% of the tone over transparent, which is a translucent colour and therefore stays rgba()
|
|
321
|
+
* rather than flattening to a hex. See avatar.css for why none of this is mixed in the
|
|
322
|
+
* component any more, and tokens/build.mjs for where the mixing moved to. */
|
|
323
|
+
.fdy-badge--tone-1{background:var(--tone-1-bg);color:var(--tone-1-ink);border-color:var(--tone-1-border-soft);}
|
|
324
|
+
.fdy-badge--tone-2{background:var(--tone-2-bg);color:var(--tone-2-ink);border-color:var(--tone-2-border-soft);}
|
|
325
|
+
.fdy-badge--tone-3{background:var(--tone-3-bg);color:var(--tone-3-ink);border-color:var(--tone-3-border-soft);}
|
|
326
|
+
.fdy-badge--tone-4{background:var(--tone-4-bg);color:var(--tone-4-ink);border-color:var(--tone-4-border-soft);}
|
|
327
|
+
.fdy-badge--tone-5{background:var(--tone-5-bg);color:var(--tone-5-ink);border-color:var(--tone-5-border-soft);}
|
|
328
|
+
.fdy-badge--tone-6{background:var(--tone-6-bg);color:var(--tone-6-ink);border-color:var(--tone-6-border-soft);}
|
|
329
|
+
.fdy-badge--tone-7{background:var(--tone-7-bg);color:var(--tone-7-ink);border-color:var(--tone-7-border-soft);}
|
|
330
|
+
.fdy-badge--tone-8{background:var(--tone-8-bg);color:var(--tone-8-ink);border-color:var(--tone-8-border-soft);}
|
|
321
331
|
|
|
322
332
|
/* Overlay badge, anchors a small count/dot/icon badge to a corner of any element
|
|
323
333
|
* (icon, button, text). Wrap the content in .fdy-badge-wrap; add .fdy-badge-ov as a
|
|
@@ -408,7 +418,7 @@ a { color: var(--color-primary); }
|
|
|
408
418
|
.fdy-breadcrumb__item{display:inline-flex;align-items:center;gap:var(--space-2);color:var(--color-text-muted);}
|
|
409
419
|
.fdy-breadcrumb__link{color:var(--color-text-muted);text-decoration:none;border-radius:var(--radius-sm);}
|
|
410
420
|
.fdy-breadcrumb__link:hover{color:var(--color-primary-strong);text-decoration:underline;}
|
|
411
|
-
.fdy-breadcrumb__link:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
421
|
+
.fdy-breadcrumb__link:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
412
422
|
.fdy-breadcrumb__item[aria-current="page"]{color:var(--color-text);font-weight:var(--weight-medium);}
|
|
413
423
|
.fdy-breadcrumb__sep{color:var(--color-text-subtle);user-select:none;}
|
|
414
424
|
|
|
@@ -478,16 +488,24 @@ a { color: var(--color-primary); }
|
|
|
478
488
|
}
|
|
479
489
|
|
|
480
490
|
/* Freeday. Button */
|
|
491
|
+
/* The fill is a FLAT colour with a black veil laid over it, not a gradient between two shades.
|
|
492
|
+
* It used to be `linear-gradient(primary, color-mix(in srgb, #000 10%, primary))`, and that is the
|
|
493
|
+
* same colour at every stop — veiling a solid base with black 0 -> .1 darkens it by exactly 10% —
|
|
494
|
+
* but the mix form carries var(), so on Safari <= 16.1 the whole declaration failed at
|
|
495
|
+
* computed-value time and the button lost its fill rather than falling back. Measured identical to
|
|
496
|
+
* the mix it replaces (within the 1/255 the gradient's own 8-bit rounding costs); see
|
|
497
|
+
* test/color-mix.test.mjs for the rule and tokens/build.mjs for why none of these may use
|
|
498
|
+
* color-mix(). Pressed states veil from the TOP, which is the same trick read upside down. */
|
|
481
499
|
.fdy-btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-2);
|
|
482
500
|
height:var(--control-h);padding:0 var(--space-4);
|
|
483
501
|
font-family:var(--font-body);font-size:var(--text-sm);font-weight:var(--weight-semibold);
|
|
484
502
|
line-height:1;white-space:nowrap;cursor:pointer;text-decoration:none;color:var(--color-on-primary);
|
|
485
|
-
background:
|
|
503
|
+
background:var(--color-primary) linear-gradient(180deg,rgba(0,0,0,0),rgba(0,0,0,.1));
|
|
486
504
|
border:var(--bw) solid transparent;border-radius:var(--radius-md);
|
|
487
|
-
box-shadow:0 2px 9px -1px
|
|
505
|
+
box-shadow:0 2px 9px -1px rgba(var(--color-primary-rgb),.5),inset 0 1px 0 rgba(255,255,255,.26);
|
|
488
506
|
transition:background var(--dur-fast) var(--ease-standard),box-shadow var(--dur-fast) var(--ease-standard),transform var(--dur-fast) var(--ease-standard);}
|
|
489
|
-
.fdy-btn:hover{transform:translateY(-1px);box-shadow:0 6px 18px -2px
|
|
490
|
-
.fdy-btn:active{transform:translateY(1px);box-shadow:0 1px 4px -1px
|
|
507
|
+
.fdy-btn:hover{transform:translateY(-1px);box-shadow:0 6px 18px -2px rgba(var(--color-primary-rgb),.6),inset 0 1px 0 rgba(255,255,255,.26);}
|
|
508
|
+
.fdy-btn:active{transform:translateY(1px);box-shadow:0 1px 4px -1px rgba(var(--color-primary-rgb),.46);}
|
|
491
509
|
.fdy-btn:disabled{opacity:.5;cursor:not-allowed;transform:none;box-shadow:none;}
|
|
492
510
|
/* Pressed / toggle. `aria-pressed` is already the right attribute for a toggle button, so this adds
|
|
493
511
|
no class and no new markup contract, and it is what makes .fdy-btn-group a complete segmented
|
|
@@ -495,8 +513,8 @@ a { color: var(--color-primary); }
|
|
|
495
513
|
defines its OWN pressed look below; a single shared rule cannot work, because a gradient is a
|
|
496
514
|
background-IMAGE and would blank the ghost variant's background-color. Solid: invert the gradient
|
|
497
515
|
and sink the shadow inward, so a held button reads as depressed, not merely primary-coloured. */
|
|
498
|
-
.fdy-btn[aria-pressed="true"]{background:linear-gradient(180deg,
|
|
499
|
-
.fdy-btn[aria-pressed="true"]:hover{transform:none;box-shadow:inset 0 2px 6px
|
|
516
|
+
.fdy-btn[aria-pressed="true"]{background:var(--color-primary) linear-gradient(180deg,rgba(0,0,0,.12),rgba(0,0,0,0));box-shadow:inset 0 2px 6px rgba(0,0,0,.22);}
|
|
517
|
+
.fdy-btn[aria-pressed="true"]:hover{transform:none;box-shadow:inset 0 2px 6px rgba(0,0,0,.22);}
|
|
500
518
|
|
|
501
519
|
.fdy-btn--ghost{background:var(--color-surface);color:var(--color-primary-strong);border-color:var(--color-border-strong);box-shadow:var(--shadow-1);}
|
|
502
520
|
.fdy-btn--ghost:hover{transform:none;background:var(--color-primary-soft);border-color:var(--color-primary-border);box-shadow:var(--shadow-1);}
|
|
@@ -508,15 +526,15 @@ a { color: var(--color-primary); }
|
|
|
508
526
|
screen. `.fdy-menu__item--danger` has always modelled the quiet form (red text, not a red block);
|
|
509
527
|
the pairing rules below bring it to the button. They are more specific than this one and come
|
|
510
528
|
after it, so this rule needs no :not() guard of its own, one mechanism, not two. */
|
|
511
|
-
.fdy-btn--danger{background:
|
|
512
|
-
.fdy-btn--danger:hover{transform:translateY(-1px);box-shadow:0 6px 18px -2px
|
|
529
|
+
.fdy-btn--danger{background:var(--color-danger-btn) linear-gradient(180deg,rgba(0,0,0,0),rgba(0,0,0,.12));color:var(--color-on-danger);box-shadow:0 2px 9px -1px rgba(var(--color-danger-btn-rgb),.46),inset 0 1px 0 rgba(255,255,255,.22);}
|
|
530
|
+
.fdy-btn--danger:hover{transform:translateY(-1px);box-shadow:0 6px 18px -2px rgba(var(--color-danger-btn-rgb),.54),inset 0 1px 0 rgba(255,255,255,.22);}
|
|
513
531
|
.fdy-btn--danger:active{transform:translateY(1px);}
|
|
514
532
|
/* Quiet destructive: the variant keeps its own ground and only the ink turns. */
|
|
515
|
-
.fdy-btn--ghost.fdy-btn--danger{background:transparent;color:var(--color-danger-strong);border-color:
|
|
533
|
+
.fdy-btn--ghost.fdy-btn--danger{background:transparent;color:var(--color-danger-strong);border-color:rgba(var(--color-danger-rgb),.4);box-shadow:none;}
|
|
516
534
|
.fdy-btn--ghost.fdy-btn--danger:hover{background:var(--color-danger-soft);border-color:var(--color-danger);color:var(--color-danger-strong);}
|
|
517
535
|
.fdy-btn--text.fdy-btn--danger{background:none;color:var(--color-danger-strong);border-color:transparent;box-shadow:none;}
|
|
518
536
|
.fdy-btn--text.fdy-btn--danger:hover{background:var(--color-danger-soft);color:var(--color-danger-strong);}
|
|
519
|
-
.fdy-btn--danger[aria-pressed="true"]{background:
|
|
537
|
+
.fdy-btn--danger[aria-pressed="true"]{background:var(--color-danger-btn) linear-gradient(180deg,rgba(0,0,0,.14),rgba(0,0,0,0));box-shadow:inset 0 2px 6px rgba(0,0,0,.24);}
|
|
520
538
|
|
|
521
539
|
.fdy-btn--sm{height:calc(var(--control-h) - var(--space-2));padding:0 var(--space-3);font-size:var(--text-xs);border-radius:var(--radius-sm);}
|
|
522
540
|
.fdy-btn--lg{height:calc(var(--control-h) + var(--space-2));padding:0 var(--space-6);font-size:var(--text-base);border-radius:var(--radius-lg);}
|
|
@@ -565,7 +583,7 @@ a { color: var(--color-primary); }
|
|
|
565
583
|
.fdy-btn-group .fdy-btn:last-child{border-top-right-radius:var(--radius-md);border-bottom-right-radius:var(--radius-md);}
|
|
566
584
|
|
|
567
585
|
/* FAB, circular elevated action button (icon), optional extended pill with label */
|
|
568
|
-
.fdy-fab{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-2);width:3.5rem;height:3.5rem;padding:0;border:var(--bw) solid transparent;border-radius:var(--radius-full);cursor:pointer;color:var(--color-on-primary);background:
|
|
586
|
+
.fdy-fab{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-2);width:3.5rem;height:3.5rem;padding:0;border:var(--bw) solid transparent;border-radius:var(--radius-full);cursor:pointer;color:var(--color-on-primary);background:var(--color-primary) linear-gradient(180deg,rgba(0,0,0,0),rgba(0,0,0,.1));box-shadow:var(--shadow-3);transition:transform var(--dur-fast) var(--ease-standard),box-shadow var(--dur-fast) var(--ease-standard);}
|
|
569
587
|
.fdy-fab:hover{transform:translateY(-1px);box-shadow:var(--shadow-4);}
|
|
570
588
|
.fdy-fab:active{transform:translateY(1px);}
|
|
571
589
|
.fdy-fab:focus-visible{border-radius:var(--radius-full);}
|
|
@@ -574,8 +592,8 @@ a { color: var(--color-primary); }
|
|
|
574
592
|
.fdy-fab--sm{width:2.5rem;height:2.5rem;}
|
|
575
593
|
.fdy-fab--sm svg{width:1.25rem;height:1.25rem;}
|
|
576
594
|
.fdy-fab--extended{width:auto;padding:0 var(--space-5);font-family:var(--font-body);font-size:var(--text-sm);font-weight:var(--weight-semibold);}
|
|
577
|
-
.fdy-fab--danger{background:
|
|
578
|
-
.fdy-fab--accent{background:
|
|
595
|
+
.fdy-fab--danger{background:var(--color-danger-btn) linear-gradient(180deg,rgba(0,0,0,0),rgba(0,0,0,.12));color:var(--color-on-danger);}
|
|
596
|
+
.fdy-fab--accent{background:var(--color-accent) linear-gradient(180deg,rgba(0,0,0,0),rgba(0,0,0,.1));color:var(--color-on-accent);}
|
|
579
597
|
|
|
580
598
|
/* Freeday. Card */
|
|
581
599
|
/* position:relative, containing block for out-of-flow card content (see base.css); it also gives
|
|
@@ -630,9 +648,9 @@ a { color: var(--color-primary); }
|
|
|
630
648
|
.fdy-carousel__viewport{position:relative;display:flex;overflow-x:auto;scroll-snap-type:x mandatory;scroll-behavior:smooth;border-radius:var(--radius-lg);scrollbar-width:none;-ms-overflow-style:none;}
|
|
631
649
|
.fdy-carousel__viewport::-webkit-scrollbar{display:none;}
|
|
632
650
|
.fdy-carousel__slide{flex:0 0 100%;min-width:0;scroll-snap-align:center;}
|
|
633
|
-
.fdy-carousel__arrow{position:absolute;top:50%;transform:translateY(-50%);z-index:2;display:inline-flex;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;border:0;border-radius:var(--radius-full);background:
|
|
651
|
+
.fdy-carousel__arrow{position:absolute;top:50%;transform:translateY(-50%);z-index:2;display:inline-flex;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;border:0;border-radius:var(--radius-full);background:rgba(var(--color-surface-rgb),.86);color:var(--color-text);box-shadow:var(--shadow-2);cursor:pointer;transition:background var(--dur-fast) var(--ease-standard);}
|
|
634
652
|
.fdy-carousel__arrow:hover{background:var(--color-surface);}
|
|
635
|
-
.fdy-carousel__arrow:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
653
|
+
.fdy-carousel__arrow:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.4);}
|
|
636
654
|
.fdy-carousel__arrow:disabled{opacity:.4;cursor:not-allowed;}
|
|
637
655
|
.fdy-carousel__arrow--prev{left:var(--space-3);}
|
|
638
656
|
.fdy-carousel__arrow--next{right:var(--space-3);}
|
|
@@ -640,7 +658,7 @@ a { color: var(--color-primary); }
|
|
|
640
658
|
.fdy-carousel__dots{display:flex;justify-content:center;gap:var(--space-2);margin-top:var(--space-3);}
|
|
641
659
|
.fdy-carousel__dot{width:.5rem;height:.5rem;padding:0;border:0;border-radius:var(--radius-full);background:var(--color-border-strong);cursor:pointer;transition:background var(--dur-fast) var(--ease-standard),width var(--dur-fast) var(--ease-standard);}
|
|
642
660
|
.fdy-carousel__dot[aria-current="true"]{background:var(--color-primary);width:1.25rem;}
|
|
643
|
-
.fdy-carousel__dot:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
661
|
+
.fdy-carousel__dot:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.4);}
|
|
644
662
|
@media (prefers-reduced-motion:reduce){.fdy-carousel__viewport{scroll-behavior:auto;}}
|
|
645
663
|
|
|
646
664
|
/* Freeday. Cascade select (hierarchical drill-down picker).
|
|
@@ -652,14 +670,14 @@ a { color: var(--color-primary); }
|
|
|
652
670
|
.fdy-cascade{position:relative;display:inline-block;width:100%;max-width:22rem;}
|
|
653
671
|
.fdy-cascade__trigger{display:inline-flex;align-items:center;justify-content:space-between;gap:var(--space-2);width:100%;height:var(--control-h);padding:0 var(--space-3);text-align:left;cursor:pointer;font-family:var(--font-body);font-size:var(--text-sm);color:var(--color-text);background:var(--color-surface);border:1.5px solid var(--color-control-border);border-radius:var(--radius-md);box-shadow:inset 0 1px 2px rgba(16,14,30,.06);transition:border-color var(--dur-fast) var(--ease-standard),box-shadow var(--dur-fast) var(--ease-standard);}
|
|
654
672
|
.fdy-cascade__trigger:hover{border-color:var(--color-text-muted);}
|
|
655
|
-
.fdy-cascade__trigger:focus-visible{outline:none;border-color:var(--color-primary);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px
|
|
656
|
-
.fdy-cascade__trigger.is-open{border-color:var(--color-primary);box-shadow:0 0 0 3px
|
|
673
|
+
.fdy-cascade__trigger:focus-visible{outline:none;border-color:var(--color-primary);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
674
|
+
.fdy-cascade__trigger.is-open{border-color:var(--color-primary);box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
657
675
|
.fdy-cascade__trigger:disabled,.fdy-cascade__trigger[aria-disabled="true"]{opacity:.5;cursor:not-allowed;}
|
|
658
676
|
.fdy-cascade__trigger[aria-readonly="true"]{background:var(--color-surface-2);border-color:var(--color-border);cursor:default;}
|
|
659
677
|
.fdy-cascade__trigger[aria-readonly="true"]:hover{border-color:var(--color-border);}
|
|
660
678
|
.fdy-cascade__trigger[aria-readonly="true"]:focus-visible{border-color:var(--color-border-strong);box-shadow:none;}
|
|
661
679
|
.fdy-cascade--error .fdy-cascade__trigger,.fdy-cascade__trigger[aria-invalid="true"]{border-color:var(--color-danger);}
|
|
662
|
-
.fdy-cascade--error .fdy-cascade__trigger:focus-visible,.fdy-cascade--error .fdy-cascade__trigger.is-open,.fdy-cascade__trigger[aria-invalid="true"]:focus-visible{border-color:var(--color-danger);box-shadow:0 0 0 3px
|
|
680
|
+
.fdy-cascade--error .fdy-cascade__trigger:focus-visible,.fdy-cascade--error .fdy-cascade__trigger.is-open,.fdy-cascade__trigger[aria-invalid="true"]:focus-visible{border-color:var(--color-danger);box-shadow:0 0 0 3px rgba(var(--color-danger-rgb),.26);}
|
|
663
681
|
.fdy-cascade__value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
|
664
682
|
.fdy-cascade__value--placeholder{color:var(--color-text-subtle);}
|
|
665
683
|
.fdy-cascade__trigger::after{content:"";flex:none;width:.5rem;height:.5rem;margin-top:-.15rem;border-right:2px solid var(--color-text-subtle);border-bottom:2px solid var(--color-text-subtle);transform:rotate(45deg);transition:transform var(--dur-fast) var(--ease-standard);}
|
|
@@ -671,7 +689,7 @@ a { color: var(--color-primary); }
|
|
|
671
689
|
.fdy-cascade__head{display:flex;align-items:center;gap:var(--space-2);padding:var(--space-1) var(--space-1) var(--space-2);margin-bottom:var(--space-1);border-bottom:var(--bw) solid var(--color-border);}
|
|
672
690
|
.fdy-cascade__back{display:inline-flex;align-items:center;justify-content:center;flex:none;width:1.5rem;height:1.5rem;padding:0;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--color-text-muted);cursor:pointer;}
|
|
673
691
|
.fdy-cascade__back:hover{background:var(--color-surface-3);color:var(--color-text);}
|
|
674
|
-
.fdy-cascade__back:focus-visible{outline:none;box-shadow:0 0 0 2px
|
|
692
|
+
.fdy-cascade__back:focus-visible{outline:none;box-shadow:0 0 0 2px rgba(var(--color-primary-rgb),.45);}
|
|
675
693
|
.fdy-cascade__back[hidden]{display:none;}
|
|
676
694
|
.fdy-cascade__back svg{display:block;width:1rem;height:1rem;}
|
|
677
695
|
.fdy-cascade__crumb{min-width:0;flex:1;font-size:var(--text-xs);font-weight:var(--weight-semibold);color:var(--color-text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
|
@@ -834,30 +852,48 @@ a { color: var(--color-primary); }
|
|
|
834
852
|
|
|
835
853
|
/* Freeday. Chip (tag / removable filter) */
|
|
836
854
|
.fdy-chip{display:inline-flex;align-items:center;gap:var(--space-2);height:1.75rem;padding:0 var(--space-3);border-radius:var(--radius-full);font-size:var(--text-xs);font-weight:var(--weight-medium);color:var(--color-text);background:var(--color-surface-3);border:var(--bw) solid var(--color-border);}
|
|
837
|
-
.fdy-chip--primary{color:var(--color-primary-strong);background:var(--color-primary-soft);border-color:
|
|
855
|
+
.fdy-chip--primary{color:var(--color-primary-strong);background:var(--color-primary-soft);border-color:rgba(var(--color-primary-rgb),.22);}
|
|
838
856
|
/* Categorical tone chips, non-semantic category tags / legend swatches, from the general
|
|
839
857
|
* --tone-1..8 palette. Same validated AA formula as .fdy-avatar--tone-* (text >=4.5:1 both themes,
|
|
840
858
|
* gated by test/contrast.test.mjs). */
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
.
|
|
844
|
-
.
|
|
845
|
-
.fdy-chip--tone-
|
|
846
|
-
.fdy-chip--tone-
|
|
847
|
-
.fdy-chip--tone-
|
|
848
|
-
.fdy-chip--tone-
|
|
849
|
-
.fdy-chip--tone-
|
|
850
|
-
.fdy-
|
|
851
|
-
.fdy-
|
|
852
|
-
.fdy-
|
|
859
|
+
/* Precomputed tone tokens, the same --tone-N-bg / --tone-N-ink the avatar and the badge read.
|
|
860
|
+
* --tone-N-border is the chip's edge: 30% of the tone over --color-border, opaque, which is a
|
|
861
|
+
* different edge from the badge's translucent one and so a different token. See avatar.css for
|
|
862
|
+
* why the mix left the component, and tokens/build.mjs for where it went. */
|
|
863
|
+
.fdy-chip--tone-1{background:var(--tone-1-bg);color:var(--tone-1-ink);border-color:var(--tone-1-border);}
|
|
864
|
+
.fdy-chip--tone-2{background:var(--tone-2-bg);color:var(--tone-2-ink);border-color:var(--tone-2-border);}
|
|
865
|
+
.fdy-chip--tone-3{background:var(--tone-3-bg);color:var(--tone-3-ink);border-color:var(--tone-3-border);}
|
|
866
|
+
.fdy-chip--tone-4{background:var(--tone-4-bg);color:var(--tone-4-ink);border-color:var(--tone-4-border);}
|
|
867
|
+
.fdy-chip--tone-5{background:var(--tone-5-bg);color:var(--tone-5-ink);border-color:var(--tone-5-border);}
|
|
868
|
+
.fdy-chip--tone-6{background:var(--tone-6-bg);color:var(--tone-6-ink);border-color:var(--tone-6-border);}
|
|
869
|
+
.fdy-chip--tone-7{background:var(--tone-7-bg);color:var(--tone-7-ink);border-color:var(--tone-7-border);}
|
|
870
|
+
.fdy-chip--tone-8{background:var(--tone-8-bg);color:var(--tone-8-ink);border-color:var(--tone-8-border);}
|
|
871
|
+
.fdy-chip__remove{position:relative;display:inline-flex;align-items:center;justify-content:center;width:1.25rem;height:1.25rem;margin-right:calc(var(--space-1)*-1);border:0;padding:0;border-radius:var(--radius-full);background:transparent;color:currentColor;opacity:.6;cursor:pointer;font-size:var(--text-sm);line-height:1;}
|
|
872
|
+
/* The hover wash is 16% of the chip's OWN ink, and the chip's ink is whatever the variant set:
|
|
873
|
+
* --color-text, --color-primary-strong, --tone-N-ink. So no token can stand in for it, which is why
|
|
874
|
+
* this was the last color-mix() in the kit — and the only one whose two-line fallback actually
|
|
875
|
+
* worked, the mix carrying no var() and therefore being rejected at parse time.
|
|
876
|
+
*
|
|
877
|
+
* It is a VEIL now, the same trick the button gradients use (button.css): currentColor at .16 over
|
|
878
|
+
* the chip, which is algebraically the colour the mix produced — `F·.16 + (1-.16)·ground` either
|
|
879
|
+
* way, including at the glyph's antialiased edges, where the veil's colour equals the glyph's and so
|
|
880
|
+
* composites back to itself. No @supports, no fallback line, and nothing newer than Safari 4.
|
|
881
|
+
*
|
|
882
|
+
* Absolutely positioned, so it paints above the × as well as the background; `border-radius:inherit`
|
|
883
|
+
* keeps it inside the pill. No transition: the mix had none, and a veil that fades is a different
|
|
884
|
+
* component. */
|
|
885
|
+
.fdy-chip__remove::before{content:"";position:absolute;inset:0;border-radius:inherit;background:currentColor;opacity:0;}
|
|
886
|
+
.fdy-chip__remove:hover{opacity:1;}
|
|
887
|
+
.fdy-chip__remove:hover::before{opacity:.16;}
|
|
888
|
+
.fdy-chip__remove:focus-visible{outline:none;opacity:1;box-shadow:0 0 0 2px rgba(var(--color-primary-rgb),.45);}
|
|
853
889
|
/* Group wrapper for a row of chips (choice / filter). */
|
|
854
890
|
.fdy-chips{display:flex;flex-wrap:wrap;gap:var(--space-2);}
|
|
855
891
|
/* Interactive chips: choice (toggle) + filter (toggle with a check when on).
|
|
856
892
|
* Rendered as <button aria-pressed> and enhanced by freeday-chip.js. */
|
|
857
893
|
.fdy-chip--choice,.fdy-chip--filter{cursor:pointer;font-family:inherit;background:var(--color-surface);border-color:var(--color-border);transition:background var(--dur-fast) var(--ease-standard),border-color var(--dur-fast) var(--ease-standard),color var(--dur-fast) var(--ease-standard);}
|
|
858
894
|
.fdy-chip--choice:hover,.fdy-chip--filter:hover{background:var(--color-surface-3);border-color:var(--color-text-subtle);}
|
|
859
|
-
.fdy-chip--choice:focus-visible,.fdy-chip--filter:focus-visible{outline:none;box-shadow:0 0 0 2px
|
|
860
|
-
.fdy-chip--choice[aria-pressed="true"],.fdy-chip--filter[aria-pressed="true"]{color:var(--color-primary-strong);background:var(--color-primary-soft);border-color:
|
|
895
|
+
.fdy-chip--choice:focus-visible,.fdy-chip--filter:focus-visible{outline:none;box-shadow:0 0 0 2px rgba(var(--color-primary-rgb),.45);}
|
|
896
|
+
.fdy-chip--choice[aria-pressed="true"],.fdy-chip--filter[aria-pressed="true"]{color:var(--color-primary-strong);background:var(--color-primary-soft);border-color:rgba(var(--color-primary-rgb),.4);}
|
|
861
897
|
.fdy-chip--choice:disabled,.fdy-chip--filter:disabled,.fdy-chip--choice[aria-disabled="true"],.fdy-chip--filter[aria-disabled="true"]{opacity:.5;cursor:not-allowed;}
|
|
862
898
|
.fdy-chip__check{display:none;flex:none;width:.85rem;height:.85rem;margin-left:calc(var(--space-1)*-1);}
|
|
863
899
|
.fdy-chip__check svg{display:block;width:100%;height:100%;}
|
|
@@ -867,8 +903,8 @@ a { color: var(--color-primary); }
|
|
|
867
903
|
.fdy-combo{position:relative;display:block;max-width:22rem;}
|
|
868
904
|
.fdy-combo__button{display:inline-flex;align-items:center;justify-content:space-between;gap:var(--space-2);width:100%;height:var(--control-h);padding:0 var(--space-3);text-align:left;cursor:pointer;font-family:var(--font-body);font-size:var(--text-sm);color:var(--color-text);background:var(--color-surface);border:1.5px solid var(--color-control-border);border-radius:var(--radius-md);box-shadow:inset 0 1px 2px rgba(16,14,30,.06);transition:border-color var(--dur-fast) var(--ease-standard),box-shadow var(--dur-fast) var(--ease-standard);}
|
|
869
905
|
.fdy-combo__button:hover{border-color:var(--color-text-muted);}
|
|
870
|
-
.fdy-combo__button:focus-visible{outline:none;border-color:var(--color-primary);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px
|
|
871
|
-
.fdy-combo__button.is-open{border-color:var(--color-primary);box-shadow:0 0 0 3px
|
|
906
|
+
.fdy-combo__button:focus-visible{outline:none;border-color:var(--color-primary);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
907
|
+
.fdy-combo__button.is-open{border-color:var(--color-primary);box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
872
908
|
.fdy-combo__button:disabled,.fdy-combo__button[aria-disabled="true"]{opacity:.5;cursor:not-allowed;}
|
|
873
909
|
/* Read-only: stays focusable & shows its value at full contrast but can't open, muted surface,
|
|
874
910
|
softened border, default cursor, no focus-ring escalation (matches input[readonly], #39). */
|
|
@@ -876,7 +912,7 @@ a { color: var(--color-primary); }
|
|
|
876
912
|
.fdy-combo__button[aria-readonly="true"]:hover{border-color:var(--color-border);}
|
|
877
913
|
.fdy-combo__button[aria-readonly="true"]:focus-visible{border-color:var(--color-border-strong);box-shadow:none;}
|
|
878
914
|
.fdy-combo--error .fdy-combo__button,.fdy-combo__button[aria-invalid="true"]{border-color:var(--color-danger);}
|
|
879
|
-
.fdy-combo--error .fdy-combo__button:focus-visible,.fdy-combo--error .fdy-combo__button.is-open,.fdy-combo__button[aria-invalid="true"]:focus-visible{border-color:var(--color-danger);box-shadow:0 0 0 3px
|
|
915
|
+
.fdy-combo--error .fdy-combo__button:focus-visible,.fdy-combo--error .fdy-combo__button.is-open,.fdy-combo__button[aria-invalid="true"]:focus-visible{border-color:var(--color-danger);box-shadow:0 0 0 3px rgba(var(--color-danger-rgb),.26);}
|
|
880
916
|
.fdy-combo__value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
|
881
917
|
.fdy-combo__value--placeholder{color:var(--color-text-subtle);}
|
|
882
918
|
.fdy-combo__button::after{content:"";flex:none;width:.5rem;height:.5rem;margin-top:-.15rem;border-right:2px solid var(--color-text-subtle);border-bottom:2px solid var(--color-text-subtle);transform:rotate(45deg);transition:transform var(--dur-fast) var(--ease-standard);}
|
|
@@ -891,14 +927,14 @@ a { color: var(--color-primary); }
|
|
|
891
927
|
.fdy-combo__option{display:flex;align-items:center;gap:var(--space-2);padding:var(--space-2) var(--space-3);border-radius:var(--radius-sm);font-size:var(--text-sm);color:var(--color-text);cursor:pointer;white-space:nowrap;}
|
|
892
928
|
.fdy-combo__option.is-highlighted{background:var(--color-surface-3);}
|
|
893
929
|
.fdy-combo__option[aria-selected="true"]{background:var(--color-primary-soft);color:var(--color-primary-strong);font-weight:var(--weight-semibold);}
|
|
894
|
-
.fdy-combo__option.is-highlighted[aria-selected="true"]{box-shadow:inset 0 0 0 2px
|
|
930
|
+
.fdy-combo__option.is-highlighted[aria-selected="true"]{box-shadow:inset 0 0 0 2px rgba(var(--color-primary-rgb),.55);}
|
|
895
931
|
/* The tick is CSS, not content (#004 §2). Inside role="option" it joined the option's ACCESSIBLE
|
|
896
932
|
NAME, so the selected option announced "✓August" while every other announced "August": the state
|
|
897
933
|
was read twice, once as aria-selected, once as decoration, and a test asking for an option by
|
|
898
934
|
its own label stopped matching the one that was selected. The `/ ""` is alt text: the glyph is
|
|
899
935
|
painted, the accessibility tree gets nothing. Same reasoning as .fdy-label--required (1.29.0).
|
|
900
936
|
The empty box still reserves its width, so labels stay aligned whether selected or not. */
|
|
901
|
-
.fdy-combo__check{display:inline-flex;justify-content:center;width:var(--space-4);flex:none;font-weight:var(--weight-bold);color:var(--color-primary);}
|
|
937
|
+
.fdy-combo__check{display:inline-flex;justify-content:center;width:var(--space-4);flex:none;font-weight:var(--weight-bold);color:var(--color-primary-strong);}
|
|
902
938
|
.fdy-combo__option[aria-selected="true"] .fdy-combo__check::after{content:"✓" / "";}
|
|
903
939
|
@media (prefers-reduced-motion:no-preference){.fdy-combo__listbox:not([hidden]){animation:fdy-combo-in var(--dur-fast) var(--ease-standard);}}
|
|
904
940
|
@keyframes fdy-combo-in{from{opacity:0;transform:translateY(-4px);}to{opacity:1;transform:none;}}
|
|
@@ -1048,10 +1084,10 @@ a { color: var(--color-primary); }
|
|
|
1048
1084
|
.fdy-field>.fdy-datepicker,.fdy-field>.fdy-timepicker,.fdy-field>.fdy-daterange{max-width:none;}
|
|
1049
1085
|
.fdy-datepicker__trigger{display:inline-flex;align-items:center;gap:var(--space-2);width:100%;height:var(--control-h);padding:0 var(--space-3);text-align:left;cursor:pointer;font-family:var(--font-body);font-size:var(--text-sm);color:var(--color-text);background:var(--color-surface);border:1.5px solid var(--color-control-border);border-radius:var(--radius-md);box-shadow:inset 0 1px 2px rgba(16,14,30,.06);transition:border-color var(--dur-fast) var(--ease-standard),box-shadow var(--dur-fast) var(--ease-standard);}
|
|
1050
1086
|
.fdy-datepicker__trigger:hover{border-color:var(--color-text-muted);}
|
|
1051
|
-
.fdy-datepicker__trigger:focus-visible{outline:none;border-color:var(--color-primary);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px
|
|
1052
|
-
.fdy-datepicker__trigger.is-open{border-color:var(--color-primary);box-shadow:0 0 0 3px
|
|
1087
|
+
.fdy-datepicker__trigger:focus-visible{outline:none;border-color:var(--color-primary);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1088
|
+
.fdy-datepicker__trigger.is-open{border-color:var(--color-primary);box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1053
1089
|
.fdy-datepicker--error .fdy-datepicker__trigger,.fdy-datepicker__trigger[aria-invalid="true"]{border-color:var(--color-danger);}
|
|
1054
|
-
.fdy-datepicker--error .fdy-datepicker__trigger:focus-visible,.fdy-datepicker--error .fdy-datepicker__trigger.is-open,.fdy-datepicker__trigger[aria-invalid="true"]:focus-visible{border-color:var(--color-danger);box-shadow:0 0 0 3px
|
|
1090
|
+
.fdy-datepicker--error .fdy-datepicker__trigger:focus-visible,.fdy-datepicker--error .fdy-datepicker__trigger.is-open,.fdy-datepicker__trigger[aria-invalid="true"]:focus-visible{border-color:var(--color-danger);box-shadow:0 0 0 3px rgba(var(--color-danger-rgb),.26);}
|
|
1055
1091
|
.fdy-datepicker__trigger:disabled,.fdy-datepicker__trigger[aria-disabled="true"]{opacity:.5;cursor:not-allowed;}
|
|
1056
1092
|
.fdy-datepicker__trigger[aria-readonly="true"]{background:var(--color-surface-2);border-color:var(--color-border);cursor:default;}
|
|
1057
1093
|
.fdy-datepicker__trigger[aria-readonly="true"]:hover{border-color:var(--color-border);}
|
|
@@ -1066,7 +1102,7 @@ a { color: var(--color-primary); }
|
|
|
1066
1102
|
.fdy-datepicker__icon.is-hidden{visibility:hidden;}
|
|
1067
1103
|
.fdy-datepicker__clear{position:absolute;top:50%;right:var(--space-3);transform:translateY(-50%);display:inline-flex;align-items:center;justify-content:center;width:1.15rem;height:1.15rem;padding:0;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--color-text-subtle);cursor:pointer;transition:color var(--dur-fast) var(--ease-standard),background var(--dur-fast) var(--ease-standard);}
|
|
1068
1104
|
.fdy-datepicker__clear:hover{color:var(--color-text);background:var(--color-surface-2);}
|
|
1069
|
-
.fdy-datepicker__clear:focus-visible{outline:none;color:var(--color-text);box-shadow:0 0 0 3px
|
|
1105
|
+
.fdy-datepicker__clear:focus-visible{outline:none;color:var(--color-text);box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1070
1106
|
.fdy-datepicker__clear svg{display:block;width:.9rem;height:.9rem;}
|
|
1071
1107
|
|
|
1072
1108
|
.fdy-datepicker__panel{position:absolute;top:calc(100% + var(--space-1));left:0;z-index:130;padding:var(--space-3);background:var(--color-surface);color:var(--color-text);border:var(--bw) solid var(--color-border-strong);border-radius:var(--radius-md);box-shadow:var(--shadow-3);}
|
|
@@ -1078,16 +1114,16 @@ a { color: var(--color-primary); }
|
|
|
1078
1114
|
reset and the same hover/focus treatment as the arrows beside it. */
|
|
1079
1115
|
.fdy-cal__title{flex:1;appearance:none;border:0;background:transparent;margin:0;padding:var(--space-1) var(--space-2);border-radius:var(--radius-sm);text-align:center;font-family:inherit;font-weight:var(--weight-semibold);font-size:var(--text-sm);color:var(--color-text);text-transform:capitalize;cursor:pointer;}
|
|
1080
1116
|
.fdy-cal__title:hover{background:var(--color-surface-2);}
|
|
1081
|
-
.fdy-cal__title:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
1117
|
+
.fdy-cal__title:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1082
1118
|
.fdy-cal__month,.fdy-cal__year{display:inline-flex;align-items:center;justify-content:center;height:2.25rem;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--color-text);font-family:inherit;font-size:var(--text-sm);text-transform:capitalize;cursor:pointer;}
|
|
1083
1119
|
.fdy-cal__month:hover,.fdy-cal__year:hover{background:var(--color-surface-2);}
|
|
1084
|
-
.fdy-cal__month:focus-visible,.fdy-cal__year:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
1120
|
+
.fdy-cal__month:focus-visible,.fdy-cal__year:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1085
1121
|
.fdy-cal__month:disabled,.fdy-cal__year:disabled{opacity:.4;cursor:not-allowed;background:transparent;}
|
|
1086
1122
|
.fdy-cal__month.is-today,.fdy-cal__year.is-today{font-weight:var(--weight-bold);box-shadow:inset 0 0 0 1.5px var(--color-border-strong);}
|
|
1087
1123
|
.fdy-cal__month.is-selected,.fdy-cal__year.is-selected{background:var(--color-primary);color:var(--color-on-primary);font-weight:var(--weight-semibold);}
|
|
1088
1124
|
.fdy-cal__nav{display:inline-flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;flex:none;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--color-text-muted);font-size:var(--text-lg);line-height:1;cursor:pointer;}
|
|
1089
1125
|
.fdy-cal__nav:hover{background:var(--color-surface-2);color:var(--color-text);}
|
|
1090
|
-
.fdy-cal__nav:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
1126
|
+
.fdy-cal__nav:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1091
1127
|
.fdy-cal__grid{display:grid;grid-template-columns:repeat(7,2rem);gap:2px;}
|
|
1092
1128
|
/* Month grid. 3×4 over the same track width as the 7-column day grid, so the panel does not resize
|
|
1093
1129
|
when you drill and the pointer does not have to travel.
|
|
@@ -1099,7 +1135,7 @@ a { color: var(--color-primary); }
|
|
|
1099
1135
|
.fdy-cal__dow{display:flex;align-items:center;justify-content:center;height:1.75rem;font-size:var(--text-xs);font-weight:var(--weight-semibold);color:var(--color-text-muted);text-transform:capitalize;}
|
|
1100
1136
|
.fdy-cal__day{display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--color-text);font-size:var(--text-sm);font-variant-numeric:tabular-nums;cursor:pointer;}
|
|
1101
1137
|
.fdy-cal__day:hover{background:var(--color-surface-2);}
|
|
1102
|
-
.fdy-cal__day:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
1138
|
+
.fdy-cal__day:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1103
1139
|
.fdy-cal__day.is-outside{color:var(--color-text-subtle);opacity:.55;}
|
|
1104
1140
|
.fdy-cal__day.is-today{font-weight:var(--weight-bold);box-shadow:inset 0 0 0 1.5px var(--color-border-strong);}
|
|
1105
1141
|
.fdy-cal__day.in-range{background:var(--color-primary-soft);color:var(--color-primary-strong);border-radius:0;}
|
|
@@ -1180,11 +1216,11 @@ a { color: var(--color-primary); }
|
|
|
1180
1216
|
* Enhanced by freeday-upload.js; states: idle · drag-over · uploading · done · error. */
|
|
1181
1217
|
.fdy-dropzone{display:flex;flex-direction:column;align-items:center;gap:var(--space-2);padding:var(--space-6);text-align:center;border:2px dashed var(--color-control-border);border-radius:var(--radius-lg);background:var(--color-surface-2);color:var(--color-text-muted);cursor:pointer;transition:border-color var(--dur-fast) var(--ease-standard),background var(--dur-fast) var(--ease-standard),color var(--dur-fast) var(--ease-standard);}
|
|
1182
1218
|
.fdy-dropzone:hover{border-color:var(--color-text-muted);}
|
|
1183
|
-
.fdy-dropzone:focus-visible{outline:none;border-color:var(--color-primary);box-shadow:0 0 0 3px
|
|
1219
|
+
.fdy-dropzone:focus-visible{outline:none;border-color:var(--color-primary);box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1184
1220
|
.fdy-dropzone.is-dragover{border-color:var(--color-primary);background:var(--color-primary-soft);color:var(--color-primary-strong);}
|
|
1185
1221
|
.fdy-dropzone[aria-disabled="true"],.fdy-dropzone.is-disabled{opacity:.55;cursor:not-allowed;pointer-events:none;}
|
|
1186
1222
|
.fdy-dropzone__icon{color:var(--color-text-subtle);}
|
|
1187
|
-
.fdy-dropzone.is-dragover .fdy-dropzone__icon{color:var(--color-primary);}
|
|
1223
|
+
.fdy-dropzone.is-dragover .fdy-dropzone__icon{color:var(--color-primary-strong);}
|
|
1188
1224
|
.fdy-dropzone__icon svg{display:block;width:2rem;height:2rem;}
|
|
1189
1225
|
.fdy-dropzone__title{font-size:inherit;font-weight:var(--weight-medium);color:var(--color-text);margin:0;}
|
|
1190
1226
|
.fdy-dropzone__hint{font-size:var(--text-xs);}
|
|
@@ -1211,9 +1247,14 @@ a { color: var(--color-primary); }
|
|
|
1211
1247
|
.fdy-file__progress{margin-top:var(--space-2);}
|
|
1212
1248
|
.fdy-file__remove{flex:none;display:inline-flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--color-text-muted);font-size:var(--text-lg);line-height:1;cursor:pointer;}
|
|
1213
1249
|
.fdy-file__remove:hover{background:var(--color-surface-2);color:var(--color-text);}
|
|
1214
|
-
.fdy-file__remove:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
1250
|
+
.fdy-file__remove:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1215
1251
|
.fdy-file--success .fdy-file__icon{color:var(--color-success);}
|
|
1216
|
-
|
|
1252
|
+
/* 40% of --color-danger over --color-border, as a token rather than as a mix written here: it blends
|
|
1253
|
+
* two ROLES, so no channel triple can state it, and mixing it in the component carried var() into
|
|
1254
|
+
* color-mix() — the shape that goes invalid at computed-value time and drops border-color to its
|
|
1255
|
+
* initial currentColor, which is the black box an iPhone 7 drew around a failed upload. The blend is
|
|
1256
|
+
* now computed per theme by tokens/build.mjs. */
|
|
1257
|
+
.fdy-file--error{border-color:var(--color-danger-border);}
|
|
1217
1258
|
.fdy-file--error .fdy-file__icon{color:var(--color-danger);}
|
|
1218
1259
|
.fdy-file--error .fdy-file__sub{color:var(--color-danger-strong);}
|
|
1219
1260
|
|
|
@@ -1285,7 +1326,7 @@ a { color: var(--color-primary); }
|
|
|
1285
1326
|
/* Freeday. Input group (prefix/suffix addons, e.g. Rp / % / icon) */
|
|
1286
1327
|
.fdy-input-group{display:flex;align-items:stretch;height:var(--control-h);max-width:22rem;background:var(--color-surface);border:1.5px solid var(--color-control-border);border-radius:var(--radius-md);box-shadow:inset 0 1px 2px rgba(16,14,30,.06);overflow:hidden;transition:border-color var(--dur-fast) var(--ease-standard),box-shadow var(--dur-fast) var(--ease-standard);}
|
|
1287
1328
|
.fdy-input-group:hover{border-color:var(--color-text-muted);}
|
|
1288
|
-
.fdy-input-group:focus-within{border-color:var(--color-primary);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px
|
|
1329
|
+
.fdy-input-group:focus-within{border-color:var(--color-primary);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1289
1330
|
/* The group owns the height; the input fills whatever the border leaves. It used to subtract 3px
|
|
1290
1331
|
for two 1.5px borders, which is arithmetic the engine is free to round: at dpr 1 each border
|
|
1291
1332
|
resolves to 1px, so the group rendered 1px short of every control beside it (#018). Stretching
|
|
@@ -1314,7 +1355,7 @@ a { color: var(--color-primary); }
|
|
|
1314
1355
|
.fdy-input-group__btn:disabled:hover{background:var(--color-surface-2);color:var(--color-text-muted);}
|
|
1315
1356
|
/* Error state must win over the neutralizing rules above, promote to the wrapper. */
|
|
1316
1357
|
.fdy-input-group:has(.fdy-input--error),.fdy-input-group:has(.fdy-combo--error),.fdy-input-group:has([aria-invalid="true"]){border-color:var(--color-danger);}
|
|
1317
|
-
.fdy-input-group:has(.fdy-input--error):focus-within,.fdy-input-group:has(.fdy-combo--error):focus-within,.fdy-input-group:has([aria-invalid="true"]):focus-within{border-color:var(--color-danger);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px
|
|
1358
|
+
.fdy-input-group:has(.fdy-input--error):focus-within,.fdy-input-group:has(.fdy-combo--error):focus-within,.fdy-input-group:has([aria-invalid="true"]):focus-within{border-color:var(--color-danger);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px rgba(var(--color-danger-rgb),.26);}
|
|
1318
1359
|
|
|
1319
1360
|
/* Freeday. Field & Input */
|
|
1320
1361
|
.fdy-field{display:flex;flex-direction:column;gap:var(--space-2);max-width:22rem;}
|
|
@@ -1350,7 +1391,7 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1350
1391
|
.fdy-input::placeholder,.fdy-textarea::placeholder{color:var(--color-text-subtle);}
|
|
1351
1392
|
.fdy-textarea{height:auto;min-height:5.5rem;padding:var(--space-3);line-height:var(--leading-normal);resize:vertical;}
|
|
1352
1393
|
.fdy-input:hover,.fdy-textarea:hover{border-color:var(--color-text-muted);}
|
|
1353
|
-
.fdy-input:focus,.fdy-textarea:focus{outline:none;border-color:var(--color-primary);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px
|
|
1394
|
+
.fdy-input:focus,.fdy-textarea:focus{outline:none;border-color:var(--color-primary);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1354
1395
|
.fdy-input:disabled,.fdy-textarea:disabled,.fdy-input[aria-disabled="true"],.fdy-textarea[aria-disabled="true"]{opacity:.5;cursor:not-allowed;}
|
|
1355
1396
|
/* Read-only (#39): the value is real and may be read/copied, only not edited. Full contrast (unlike
|
|
1356
1397
|
:disabled which dims to placeholder-grey), muted surface + softened border so it still reads as
|
|
@@ -1367,7 +1408,7 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1367
1408
|
.fdy-input[type="number"]{appearance:textfield;-webkit-appearance:textfield;}
|
|
1368
1409
|
.fdy-input[type="number"]::-webkit-outer-spin-button,.fdy-input[type="number"]::-webkit-inner-spin-button{appearance:none;-webkit-appearance:none;margin:0;}
|
|
1369
1410
|
.fdy-input--error,.fdy-input[aria-invalid="true"],.fdy-textarea[aria-invalid="true"]{border-color:var(--color-danger);}
|
|
1370
|
-
.fdy-input--error:focus,.fdy-input[aria-invalid="true"]:focus,.fdy-textarea[aria-invalid="true"]:focus{border-color:var(--color-danger);box-shadow:0 0 0 3px
|
|
1411
|
+
.fdy-input--error:focus,.fdy-input[aria-invalid="true"]:focus,.fdy-textarea[aria-invalid="true"]:focus{border-color:var(--color-danger);box-shadow:0 0 0 3px rgba(var(--color-danger-rgb),.26);}
|
|
1371
1412
|
/* Required marker. The control already carries `required`, so the asterisk is decoration: the
|
|
1372
1413
|
`/ ""` is CSS alt text, the glyph is painted but exposes NOTHING to the accessibility tree, so a
|
|
1373
1414
|
screen reader does not read "star" after every label. That is stricter than a <span> an app has to
|
|
@@ -1433,7 +1474,7 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1433
1474
|
/* Focus is not hover. The enhancer moves real DOM focus (freeday-menu.js `.focus()`), so this is
|
|
1434
1475
|
the only thing a keyboard user has to go on, with the hover fill alone, arrowing through the
|
|
1435
1476
|
menu is invisible. Same ring as .fdy-nav__item, which got this right. Reported twice. */
|
|
1436
|
-
.fdy-menu__item:focus-visible{outline:none;background:var(--color-surface-3);box-shadow:0 0 0 2px
|
|
1477
|
+
.fdy-menu__item:focus-visible{outline:none;background:var(--color-surface-3);box-shadow:0 0 0 2px rgba(var(--color-primary-rgb),.45);}
|
|
1437
1478
|
.fdy-menu__item:disabled{opacity:.5;cursor:not-allowed;background:transparent;}
|
|
1438
1479
|
.fdy-menu__item--danger{color:var(--color-danger-strong);}
|
|
1439
1480
|
.fdy-menu__item svg{display:block;width:1rem;height:1rem;flex:none;}
|
|
@@ -1450,8 +1491,8 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1450
1491
|
.fdy-btn-split__toggle{padding:0 var(--space-2);margin-left:calc(var(--bw) * -1);border-top-left-radius:0;border-bottom-left-radius:0;}
|
|
1451
1492
|
/* Hairline divider between the halves (outranks the segment rule above). */
|
|
1452
1493
|
.fdy-btn-split > .fdy-btn-split__toggle{box-shadow:inset 0 1px 0 rgba(255,255,255,.26),inset 1px 0 0 rgba(0,0,0,.16);}
|
|
1453
|
-
.fdy-btn-split:hover{transform:translateY(-1px);box-shadow:0 6px 18px -2px
|
|
1454
|
-
.fdy-btn-split:active{transform:translateY(1px);box-shadow:0 1px 4px -1px
|
|
1494
|
+
.fdy-btn-split:hover{transform:translateY(-1px);box-shadow:0 6px 18px -2px rgba(var(--color-primary-rgb),.55);}
|
|
1495
|
+
.fdy-btn-split:active{transform:translateY(1px);box-shadow:0 1px 4px -1px rgba(var(--color-primary-rgb),.46);}
|
|
1455
1496
|
.fdy-btn-split__toggle:hover,.fdy-btn-split__toggle:focus-visible{z-index:1;}
|
|
1456
1497
|
.fdy-btn-split__toggle svg{display:block;width:1rem;height:1rem;}
|
|
1457
1498
|
|
|
@@ -1482,7 +1523,7 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1482
1523
|
.fdy-pagination__list{display:flex;align-items:center;gap:var(--space-1);list-style:none;margin:0;padding:0;}
|
|
1483
1524
|
.fdy-pagination__link{display:inline-flex;align-items:center;justify-content:center;min-width:2.25rem;height:2.25rem;padding:0 var(--space-2);border-radius:var(--radius-md);font-size:var(--text-sm);font-weight:var(--weight-medium);color:var(--color-text);background:transparent;border:var(--bw) solid transparent;text-decoration:none;cursor:pointer;transition:background var(--dur-fast) var(--ease-standard),border-color var(--dur-fast) var(--ease-standard);}
|
|
1484
1525
|
.fdy-pagination__link:hover{background:var(--color-surface-2);border-color:var(--color-border);}
|
|
1485
|
-
.fdy-pagination__link:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
1526
|
+
.fdy-pagination__link:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1486
1527
|
.fdy-pagination__link[aria-current="page"]{background:var(--color-primary);color:var(--color-on-primary);}
|
|
1487
1528
|
.fdy-pagination__link[aria-disabled="true"],.fdy-pagination__link:disabled{opacity:.5;cursor:not-allowed;pointer-events:none;}
|
|
1488
1529
|
.fdy-pagination__ellipsis{display:inline-flex;align-items:center;justify-content:center;min-width:2.25rem;height:2.25rem;color:var(--color-text-subtle);}
|
|
@@ -1528,7 +1569,7 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1528
1569
|
.fdy-radio input::before{content:"";width:.55rem;height:.55rem;border-radius:50%;transform:scale(0);transition:transform var(--dur-fast) var(--ease-spring);box-shadow:inset 1rem 1rem var(--color-on-primary);}
|
|
1529
1570
|
.fdy-check input:checked,.fdy-radio input:checked{background:var(--color-primary);border-color:var(--color-primary);}
|
|
1530
1571
|
.fdy-check input:checked::before,.fdy-radio input:checked::before{transform:scale(1);}
|
|
1531
|
-
.fdy-check input:focus-visible,.fdy-radio input:focus-visible,.fdy-switch input:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
1572
|
+
.fdy-check input:focus-visible,.fdy-radio input:focus-visible,.fdy-switch input:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1532
1573
|
.fdy-check input:disabled,.fdy-radio input:disabled,.fdy-switch input:disabled{opacity:.5;cursor:not-allowed;}
|
|
1533
1574
|
.fdy-check:has(input:disabled),.fdy-radio:has(input:disabled),.fdy-switch:has(input:disabled){cursor:not-allowed;}
|
|
1534
1575
|
.fdy-switch input{appearance:none;-webkit-appearance:none;flex:none;position:relative;width:var(--control-switch-w);height:var(--control-switch-h);margin:0;border-radius:var(--radius-full);background:var(--color-control-border);cursor:pointer;transition:background var(--dur-base) var(--ease-standard);}
|
|
@@ -1548,11 +1589,11 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1548
1589
|
.fdy-checkbox:checked,.fdy-checkbox:indeterminate{background:var(--color-primary);border-color:var(--color-primary);}
|
|
1549
1590
|
.fdy-checkbox:checked::before{transform:scale(1);}
|
|
1550
1591
|
.fdy-checkbox:indeterminate::before{width:.6rem;height:2px;transform:scale(1);clip-path:none;box-shadow:none;background:var(--color-on-primary);}
|
|
1551
|
-
.fdy-checkbox:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
1592
|
+
.fdy-checkbox:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1552
1593
|
.fdy-checkbox:disabled{opacity:.5;cursor:not-allowed;}
|
|
1553
1594
|
|
|
1554
1595
|
/* Freeday. Skeleton */
|
|
1555
|
-
.fdy-skeleton{display:block;border-radius:var(--radius-sm);background:var(--color-surface-3);background-image:linear-gradient(90deg,transparent,
|
|
1596
|
+
.fdy-skeleton{display:block;border-radius:var(--radius-sm);background:var(--color-surface-3);background-image:linear-gradient(90deg,transparent,rgba(var(--color-surface-rgb),.6),transparent);background-size:200% 100%;background-repeat:no-repeat;animation:fdy-skeleton 1.4s ease-in-out infinite;}
|
|
1556
1597
|
.fdy-skeleton--text{height:.8rem;margin:.3rem 0;}
|
|
1557
1598
|
.fdy-skeleton--title{height:1.2rem;width:40%;}
|
|
1558
1599
|
.fdy-skeleton--circle{border-radius:var(--radius-full);}
|
|
@@ -1633,7 +1674,7 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1633
1674
|
.fdy-stepper[aria-busy="true"]{opacity:.72;}
|
|
1634
1675
|
.fdy-step.is-active .fdy-step__label{color:var(--color-text);font-weight:var(--weight-semibold);}
|
|
1635
1676
|
.fdy-step__btn:focus-visible{outline:none;}
|
|
1636
|
-
.fdy-step__btn:focus-visible .fdy-step__marker{box-shadow:0 0 0 3px
|
|
1677
|
+
.fdy-step__btn:focus-visible .fdy-step__marker{box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.3);}
|
|
1637
1678
|
|
|
1638
1679
|
.fdy-step-panels{margin-top:var(--space-5);}
|
|
1639
1680
|
.fdy-step-nav{display:flex;justify-content:space-between;gap:var(--space-2);margin-top:var(--space-5);}
|
|
@@ -1654,10 +1695,15 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1654
1695
|
invisible on every second row. The tint is HALF a surface step rather than --color-surface-2
|
|
1655
1696
|
itself, for the same reason: hover paints the full step, so the two must not be the same colour.
|
|
1656
1697
|
Exposed as a Tier-3 token through the var() FALLBACK, never as a declaration — a custom property
|
|
1657
|
-
set here would outrank a host's own :root override.
|
|
1698
|
+
set here would outrank a host's own :root override.
|
|
1699
|
+
The tint arrives as --color-surface-stripe, already flattened, rather than as a color-mix() of
|
|
1700
|
+
two surfaces. A custom property cannot carry color-mix(): the `background` that finally reads it
|
|
1701
|
+
contains var(), so on Safari <= 16.1 it failed at computed-value time and the stripe vanished,
|
|
1702
|
+
and a preceding declaration is never consulted in that path. The token is also OPAQUE on
|
|
1703
|
+
purpose, which the frozen column below depends on. */
|
|
1658
1704
|
/* The resting colour is also published as --_fdy-row-rest, so a row that must not answer the
|
|
1659
1705
|
pointer can hover back to exactly what it was (see --hover-actionable). */
|
|
1660
|
-
.fdy-table--striped tbody tr:nth-child(even){--_fdy-row-rest:var(--fdy-table-stripe,
|
|
1706
|
+
.fdy-table--striped tbody tr:nth-child(even){--_fdy-row-rest:var(--fdy-table-stripe,var(--color-surface-stripe));background:var(--_fdy-row-rest);}
|
|
1661
1707
|
.fdy-table tbody tr:hover{background:var(--_fdy-row-hover,var(--color-surface-2));}
|
|
1662
1708
|
/* Opt-in (#064): only a row that DOES something answers the pointer. A tint on a row with no click
|
|
1663
1709
|
handler promises a target that is not there: people click the row, nothing happens, and the
|
|
@@ -1681,13 +1727,13 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1681
1727
|
/* Expandable detail row (FdyTable row-detail slot): a muted panel under its row, no hover tint. */
|
|
1682
1728
|
.fdy-table__detailrow>td,.fdy-table__detailrow:hover>td{background:var(--color-surface-2);}
|
|
1683
1729
|
.fdy-table th[aria-sort]{cursor:pointer;}
|
|
1684
|
-
.fdy-table th[aria-sort="ascending"]::after{content:" ↑";color:var(--color-primary);}
|
|
1685
|
-
.fdy-table th[aria-sort="descending"]::after{content:" ↓";color:var(--color-primary);}
|
|
1730
|
+
.fdy-table th[aria-sort="ascending"]::after{content:" ↑";color:var(--color-primary-strong);}
|
|
1731
|
+
.fdy-table th[aria-sort="descending"]::after{content:" ↓";color:var(--color-primary-strong);}
|
|
1686
1732
|
|
|
1687
1733
|
/* Sortable header button (accessible click target inside th) */
|
|
1688
1734
|
.fdy-table__sortbtn{appearance:none;border:0;background:transparent;font:inherit;color:inherit;text-transform:inherit;letter-spacing:inherit;font-weight:inherit;cursor:pointer;padding:0;}
|
|
1689
1735
|
.fdy-table__sortbtn:hover{color:var(--color-text);}
|
|
1690
|
-
.fdy-table__sortbtn:focus-visible{outline:none;border-radius:var(--radius-sm);box-shadow:0 0 0 3px
|
|
1736
|
+
.fdy-table__sortbtn:focus-visible{outline:none;border-radius:var(--radius-sm);box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1691
1737
|
|
|
1692
1738
|
/* Selection column + selected row */
|
|
1693
1739
|
.fdy-table__selcol{width:1px;white-space:nowrap;}
|
|
@@ -1734,7 +1780,7 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1734
1780
|
stripe — and deliberately WITHOUT `.fdy-table--sticky` in the selector, which would push this to
|
|
1735
1781
|
(0,4,3) and beat the hover rule below. At (0,3,3) it ties, and the later rule wins, so a hovered
|
|
1736
1782
|
row still bands unbroken across the freeze line. */
|
|
1737
|
-
.fdy-table--striped tbody tr:nth-child(even) td.fdy-table__freeze{background:var(--fdy-table-stripe,
|
|
1783
|
+
.fdy-table--striped tbody tr:nth-child(even) td.fdy-table__freeze{background:var(--fdy-table-stripe,var(--color-surface-stripe));}
|
|
1738
1784
|
.fdy-table--sticky tbody tr:hover td.fdy-table__freeze{background:var(--_fdy-row-hover,var(--color-surface-2));}
|
|
1739
1785
|
/* A frozen header cell is stuck on both axes wherever the head is frozen too, so
|
|
1740
1786
|
it has to outrank both. */
|
|
@@ -1771,7 +1817,7 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1771
1817
|
.fdy-table__filterwrap{display:inline-flex;align-items:center;vertical-align:middle;}
|
|
1772
1818
|
.fdy-table__filterbtn{appearance:none;display:inline-flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;margin-left:var(--space-1);padding:0;vertical-align:middle;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--color-text-subtle);cursor:pointer;}
|
|
1773
1819
|
.fdy-table__filterbtn:hover{background:var(--color-surface-3);color:var(--color-text);}
|
|
1774
|
-
.fdy-table__filterbtn:focus-visible{outline:none;box-shadow:0 0 0 3px
|
|
1820
|
+
.fdy-table__filterbtn:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1775
1821
|
.fdy-table__filterbtn.is-active{color:var(--color-primary-strong);}
|
|
1776
1822
|
.fdy-table__filterbtn svg{width:.85rem;height:.85rem;}
|
|
1777
1823
|
|
|
@@ -1827,12 +1873,43 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1827
1873
|
a panel per tab) for in-page tabs; use these classes on plain links for routed ones, and
|
|
1828
1874
|
`.fdy-nav--horizontal` for an application's PRIMARY navigation. */
|
|
1829
1875
|
.fdy-tabs__tab[aria-selected="true"],.fdy-tabs__tab[aria-current="page"]{color:var(--color-primary-strong);border-bottom-color:var(--color-primary);}
|
|
1830
|
-
.fdy-tabs__tab:focus-visible{outline:none;border-radius:var(--radius-sm);box-shadow:0 0 0 3px
|
|
1876
|
+
.fdy-tabs__tab:focus-visible{outline:none;border-radius:var(--radius-sm);box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1831
1877
|
.fdy-tabs__panel{padding:var(--space-5) 0;}
|
|
1832
1878
|
.fdy-tabs__panel[hidden]{display:none;}
|
|
1833
1879
|
/* Reveal the newly-shown panel on tab switch (fade + rise), reduced-motion gated. */
|
|
1834
1880
|
@media (prefers-reduced-motion:no-preference){.fdy-tabs__panel:not([hidden]){animation:fdy-combo-in var(--dur-base) var(--ease-standard);}}
|
|
1835
1881
|
|
|
1882
|
+
/* VERTICAL VARIANT: the same tabs turned down the page, list on the leading side, panel beside it.
|
|
1883
|
+
*
|
|
1884
|
+
* Two markers, one each, and they are not interchangeable. The CLASS decides the look, because a
|
|
1885
|
+
* stylesheet cannot reach a parent from a child and the two-column box belongs to `.fdy-tabs`
|
|
1886
|
+
* itself. The ATTRIBUTE `aria-orientation="vertical"` on the tablist decides the keyboard, because
|
|
1887
|
+
* that is the thing an assistive technology announces and APG requires it on a vertical tablist
|
|
1888
|
+
* anyway. `freeday-tabs.js` writes the attribute when only the class is present, so an app states
|
|
1889
|
+
* the axis once and the two can never disagree.
|
|
1890
|
+
*
|
|
1891
|
+
* Selection is a SOFT FILL here, not a leading edge bar. Sideways, the marker is an underline under
|
|
1892
|
+
* the tab it belongs to; turned 90 degrees that line lands between two tabs and points at the wrong
|
|
1893
|
+
* one. The kit already has an answer for "one item in a vertical list is where you are" and spends
|
|
1894
|
+
* it in four places (`.fdy-nav__item[aria-current]`, the combo, cascade and autocomplete options):
|
|
1895
|
+
* `--color-primary-soft` behind `--color-primary-strong`. Both are precomputed tone tokens, so this
|
|
1896
|
+
* needs no color-mix() and no alpha of its own.
|
|
1897
|
+
*
|
|
1898
|
+
* What it deliberately does NOT do: pick a column width (set `--fdy-tabs-list-w`, default `auto`),
|
|
1899
|
+
* and collapse to one column on a narrow screen. Whether these tabs are a whole page, a card or a
|
|
1900
|
+
* drawer is the page's knowledge, not the component's, so the breakpoint is the page's to write. */
|
|
1901
|
+
.fdy-tabs--vertical{display:flex;align-items:flex-start;gap:var(--space-5);}
|
|
1902
|
+
/* `overflow:visible` on both axes, because the base strip scrolls sideways: a scroll container
|
|
1903
|
+
clips to its padding box, and a column has no sideways overflow to scroll, only a focus ring to
|
|
1904
|
+
lose. `box-shadow:none` drops the strip's own bottom line with it. */
|
|
1905
|
+
.fdy-tabs--vertical .fdy-tabs__list{flex:none;flex-direction:column;width:var(--fdy-tabs-list-w,auto);overflow:visible;box-shadow:none;}
|
|
1906
|
+
/* `white-space:normal` and `text-align:start` are corrections, not taste: a tab in a column of
|
|
1907
|
+
fixed width that may not wrap will overflow it, and a button centres its label by default. */
|
|
1908
|
+
.fdy-tabs--vertical .fdy-tabs__tab{border-bottom:0;border-radius:var(--radius-md);text-align:start;white-space:normal;}
|
|
1909
|
+
.fdy-tabs--vertical .fdy-tabs__tab:focus-visible{border-radius:var(--radius-md);}
|
|
1910
|
+
.fdy-tabs--vertical .fdy-tabs__tab[aria-selected="true"],.fdy-tabs--vertical .fdy-tabs__tab[aria-current="page"]{background:var(--color-primary-soft);color:var(--color-primary-strong);font-weight:var(--weight-semibold);}
|
|
1911
|
+
.fdy-tabs--vertical .fdy-tabs__panel{flex:1;min-width:0;padding:0;}
|
|
1912
|
+
|
|
1836
1913
|
/* Freeday. Timeline (vertical event feed: dot markers on a connector line). Pure CSS. */
|
|
1837
1914
|
.fdy-timeline{list-style:none;margin:0;padding:0;}
|
|
1838
1915
|
.fdy-timeline__item{position:relative;padding:0 0 var(--space-5) var(--space-6);border-left:2px solid var(--color-border);}
|
|
@@ -1852,10 +1929,10 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1852
1929
|
.fdy-timepicker{position:relative;display:inline-block;width:100%;max-width:11rem;}
|
|
1853
1930
|
.fdy-timepicker__trigger{display:inline-flex;align-items:center;gap:var(--space-2);width:100%;height:var(--control-h);padding:0 var(--space-3);text-align:left;cursor:pointer;font-family:var(--font-body);font-size:var(--text-sm);color:var(--color-text);background:var(--color-surface);border:1.5px solid var(--color-control-border);border-radius:var(--radius-md);box-shadow:inset 0 1px 2px rgba(16,14,30,.06);transition:border-color var(--dur-fast) var(--ease-standard),box-shadow var(--dur-fast) var(--ease-standard);}
|
|
1854
1931
|
.fdy-timepicker__trigger:hover{border-color:var(--color-text-muted);}
|
|
1855
|
-
.fdy-timepicker__trigger:focus-visible{outline:none;border-color:var(--color-primary);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px
|
|
1856
|
-
.fdy-timepicker__trigger.is-open{border-color:var(--color-primary);box-shadow:0 0 0 3px
|
|
1932
|
+
.fdy-timepicker__trigger:focus-visible{outline:none;border-color:var(--color-primary);box-shadow:inset 0 1px 2px rgba(16,14,30,.04),0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1933
|
+
.fdy-timepicker__trigger.is-open{border-color:var(--color-primary);box-shadow:0 0 0 3px rgba(var(--color-primary-rgb),.26);}
|
|
1857
1934
|
.fdy-timepicker--error .fdy-timepicker__trigger,.fdy-timepicker__trigger[aria-invalid="true"]{border-color:var(--color-danger);}
|
|
1858
|
-
.fdy-timepicker--error .fdy-timepicker__trigger:focus-visible,.fdy-timepicker--error .fdy-timepicker__trigger.is-open,.fdy-timepicker__trigger[aria-invalid="true"]:focus-visible{border-color:var(--color-danger);box-shadow:0 0 0 3px
|
|
1935
|
+
.fdy-timepicker--error .fdy-timepicker__trigger:focus-visible,.fdy-timepicker--error .fdy-timepicker__trigger.is-open,.fdy-timepicker__trigger[aria-invalid="true"]:focus-visible{border-color:var(--color-danger);box-shadow:0 0 0 3px rgba(var(--color-danger-rgb),.26);}
|
|
1859
1936
|
.fdy-timepicker__trigger:disabled,.fdy-timepicker__trigger[aria-disabled="true"]{opacity:.5;cursor:not-allowed;}
|
|
1860
1937
|
.fdy-timepicker__value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-variant-numeric:tabular-nums;}
|
|
1861
1938
|
.fdy-timepicker__value--placeholder{color:var(--color-text-subtle);}
|
|
@@ -1895,7 +1972,7 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1895
1972
|
.fdy-toast__text{opacity:.88;line-height:var(--leading-normal);}
|
|
1896
1973
|
.fdy-toast__close{flex:none;border:0;background:transparent;color:var(--color-inverse-text);opacity:.7;cursor:pointer;font-size:var(--text-lg);line-height:1;padding:0 var(--space-1);border-radius:var(--radius-sm);}
|
|
1897
1974
|
.fdy-toast__close:hover{opacity:1;}
|
|
1898
|
-
.fdy-toast__close:focus-visible{outline:none;opacity:1;box-shadow:0 0 0 3px
|
|
1975
|
+
.fdy-toast__close:focus-visible{outline:none;opacity:1;box-shadow:0 0 0 3px rgba(var(--color-inverse-text-rgb),.4);}
|
|
1899
1976
|
.fdy-toast.is-leaving{opacity:0;transform:translateX(16px);transition:opacity var(--dur-base) var(--ease-standard),transform var(--dur-base) var(--ease-standard);}
|
|
1900
1977
|
@media (prefers-reduced-motion:no-preference){.fdy-toast{animation:fdy-toast-in var(--dur-base) var(--ease-spring);}}
|
|
1901
1978
|
@keyframes fdy-toast-in{from{opacity:0;transform:translateY(14px);}to{opacity:1;transform:none;}}
|
|
@@ -1915,7 +1992,7 @@ fieldset.fdy-field>legend{padding:0;float:none;margin-bottom:var(--space-2);}
|
|
|
1915
1992
|
.fdy-tree__branch > summary{list-style:none;cursor:pointer;}
|
|
1916
1993
|
.fdy-tree__branch > summary::-webkit-details-marker{display:none;}
|
|
1917
1994
|
.fdy-tree__branch > summary:hover,.fdy-tree__leaf:hover{background:var(--color-surface-2);}
|
|
1918
|
-
.fdy-tree__branch > summary:focus-visible{outline:none;box-shadow:inset 0 0 0 2px
|
|
1995
|
+
.fdy-tree__branch > summary:focus-visible{outline:none;box-shadow:inset 0 0 0 2px rgba(var(--color-primary-rgb),.45);}
|
|
1919
1996
|
.fdy-tree__chevron{flex:none;width:.9rem;height:.9rem;color:var(--color-text-subtle);transition:transform var(--dur-fast) var(--ease-standard);}
|
|
1920
1997
|
.fdy-tree__branch[open] > summary .fdy-tree__chevron{transform:rotate(90deg);}
|
|
1921
1998
|
.fdy-tree__icon{flex:none;width:1rem;height:1rem;color:var(--color-text-muted);}
|