tyrell-components 1.0.0-TC40 → 1.0.0-TC42

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.
Files changed (53) hide show
  1. package/css/tyrell-theme.css +130 -77
  2. package/css/tyrell.css +68 -10
  3. package/dist/tyrell-theme.css +130 -77
  4. package/dist/tyrell.css +68 -10
  5. package/dist/tyrell.js +1 -1
  6. package/lib/styles/button.d.ts +35 -5
  7. package/lib/styles/button.d.ts.map +1 -1
  8. package/lib/styles/button.js +171 -39
  9. package/lib/styles/button.js.map +1 -1
  10. package/lib/styles/calendar-month.js +1 -1
  11. package/lib/styles/calendar-navigation.d.ts +1 -1
  12. package/lib/styles/calendar-navigation.d.ts.map +1 -1
  13. package/lib/styles/calendar-navigation.js +1 -1
  14. package/lib/styles/checkbox.js +2 -2
  15. package/lib/styles/copy.js +2 -2
  16. package/lib/styles/custom-scrollbar.d.ts +1 -1
  17. package/lib/styles/custom-scrollbar.d.ts.map +1 -1
  18. package/lib/styles/custom-scrollbar.js +2 -2
  19. package/lib/styles/date-picker.js +1 -1
  20. package/lib/styles/file-upload.d.ts +1 -1
  21. package/lib/styles/file-upload.d.ts.map +1 -1
  22. package/lib/styles/file-upload.js +3 -3
  23. package/lib/styles/input.js +3 -3
  24. package/lib/styles/radio.js +1 -1
  25. package/lib/styles/scroll-container.d.ts +1 -1
  26. package/lib/styles/scroll-container.d.ts.map +1 -1
  27. package/lib/styles/select-base.d.ts.map +1 -1
  28. package/lib/styles/select-base.js +18 -4
  29. package/lib/styles/select-base.js.map +1 -1
  30. package/lib/styles/select.d.ts +1 -1
  31. package/lib/styles/select.d.ts.map +1 -1
  32. package/lib/styles/select.js +1 -0
  33. package/lib/styles/select.js.map +1 -1
  34. package/lib/styles/step.d.ts +1 -1
  35. package/lib/styles/step.d.ts.map +1 -1
  36. package/lib/styles/switch.js +2 -2
  37. package/lib/styles/tab.d.ts +1 -1
  38. package/lib/styles/tab.d.ts.map +1 -1
  39. package/lib/styles/tabs.d.ts +1 -1
  40. package/lib/styles/tabs.d.ts.map +1 -1
  41. package/lib/styles/tabs.js +1 -1
  42. package/lib/styles/tag.d.ts.map +1 -1
  43. package/lib/styles/tag.js +4 -1
  44. package/lib/styles/tag.js.map +1 -1
  45. package/lib/styles/textarea.d.ts +1 -1
  46. package/lib/styles/textarea.d.ts.map +1 -1
  47. package/lib/styles/textarea.js +5 -5
  48. package/lib/styles/wizard.d.ts +1 -1
  49. package/lib/styles/wizard.d.ts.map +1 -1
  50. package/lib/styles/wizard.js +3 -3
  51. package/lib/version.d.ts +1 -1
  52. package/lib/version.js +1 -1
  53. package/package.json +1 -1
@@ -1,17 +1,47 @@
1
1
  /**
2
2
  * Button Component Styles
3
3
  *
4
- * Three appearance variants × six semantic flavors × three tones (+/base/-).
4
+ * Three appearance variants × five semantic flavors × three tones (+/base/-).
5
5
  * Each variant uses ONE token system:
6
+ *
6
7
  * - solid → flat per-segment tokens --ty-solid-{flavor}{,-hover,-active,
7
8
  * -strong,-soft,-fg}. Derived in tyrell-theme.css via OKLCH on
8
9
  * 3 axes (color / hover-active / theme chroma-hue); literal in
9
- * tyrell.css. The component does no color math.
10
- * - outlined → --ty-color-{flavor}-{strong|base|soft} (text === border)
11
- * - ghost → --ty-color-{flavor}-{strong|base|soft} (text), --ty-bg-{flavor}-soft (hover)
10
+ * tyrell.css. The component does no color math for the fill.
11
+ * Depth chrome (border + drop shadow) IS computed here, from
12
+ * the fill, via relative color — see "Depth chrome" below.
13
+ * - outlined → --ty-color-{flavor}-{strong|base|soft} (text === border at
14
+ * rest); hover/active/focus always resolve to -strong,
15
+ * whatever the resting tone was — see "Hover escalation".
16
+ * - ghost → same as outlined, text only (no border), --ty-bg-{flavor}-soft
17
+ * background on hover.
18
+ *
19
+ * Neutral is the exception in both outlined and ghost: its `+` tone reads
20
+ * --ty-solid-neutral-strong (the ink dial solid buttons use — the only
21
+ * value that actually inverts light↔dark for full contrast) instead of the
22
+ * generic --ty-color-neutral-strong text-emphasis token. Base/soft neutral
23
+ * stay on the generic token like every other flavor.
24
+ *
25
+ * Depth chrome (solid only): a 1px border + soft drop shadow, both derived
26
+ * from the fill via oklch(from …), scaled by --ty-button-depth (0–1). The
27
+ * border reads the TONE'S RESTING fill (not the current/hover one) so it
28
+ * stays stationary while the fill rises toward it on interaction. Offset
29
+ * direction/magnitude is --ty-button-border-l (mode-flipped: no border at
30
+ * all for colored solids in dark, a lit edge in light) with its own
31
+ * stronger dial for neutral, --ty-button-border-l-neutral (ink has no hue
32
+ * to separate it from the canvas). Escape hatches --ty-solid-border-color
33
+ * / --ty-solid-border-width outrank the derivation entirely.
34
+ *
35
+ * Hover escalation (outlined/ghost): :hover/:active/:focus-visible always
36
+ * resolve to the -strong tier regardless of starting tone — soft and base
37
+ * both rise to the same peak on interaction. Composes with `muted` rather
38
+ * than fighting it (see the escalation rules themselves for the exact
39
+ * split) — a pressed muted button lands on the same color as a pressed
40
+ * plain one of the same flavor.
12
41
  *
13
42
  * Per-instance overrides via host CSS variables:
14
- * --ty-button-bg, --ty-button-bg-hover, --ty-button-color, --ty-button-border
43
+ * --ty-button-bg, --ty-button-bg-hover, --ty-button-color, --ty-button-border,
44
+ * --ty-solid-border-color, --ty-solid-border-width
15
45
  */
16
46
  /** Rules for one custom (non-built-in) flavor across all three appearances. */
17
47
  export declare const buttonCustomFlavorCss: (base: string) => string;
@@ -1 +1 @@
1
- {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../src/styles/button.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AA4EH,+EAA+E;AAC/E,eAAO,MAAM,qBAAqB,GAAI,MAAM,MAAM,WAC6C,CAAA;AAE/F,eAAO,MAAM,YAAY,QAkUsB,CAAC"}
1
+ {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../src/styles/button.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AA6IH,+EAA+E;AAC/E,eAAO,MAAM,qBAAqB,GAAI,MAAM,MAAM,WAC6C,CAAA;AAE/F,eAAO,MAAM,YAAY,QA0WsB,CAAC"}
@@ -1,17 +1,47 @@
1
1
  /**
2
2
  * Button Component Styles
3
3
  *
4
- * Three appearance variants × six semantic flavors × three tones (+/base/-).
4
+ * Three appearance variants × five semantic flavors × three tones (+/base/-).
5
5
  * Each variant uses ONE token system:
6
+ *
6
7
  * - solid → flat per-segment tokens --ty-solid-{flavor}{,-hover,-active,
7
8
  * -strong,-soft,-fg}. Derived in tyrell-theme.css via OKLCH on
8
9
  * 3 axes (color / hover-active / theme chroma-hue); literal in
9
- * tyrell.css. The component does no color math.
10
- * - outlined → --ty-color-{flavor}-{strong|base|soft} (text === border)
11
- * - ghost → --ty-color-{flavor}-{strong|base|soft} (text), --ty-bg-{flavor}-soft (hover)
10
+ * tyrell.css. The component does no color math for the fill.
11
+ * Depth chrome (border + drop shadow) IS computed here, from
12
+ * the fill, via relative color — see "Depth chrome" below.
13
+ * - outlined → --ty-color-{flavor}-{strong|base|soft} (text === border at
14
+ * rest); hover/active/focus always resolve to -strong,
15
+ * whatever the resting tone was — see "Hover escalation".
16
+ * - ghost → same as outlined, text only (no border), --ty-bg-{flavor}-soft
17
+ * background on hover.
18
+ *
19
+ * Neutral is the exception in both outlined and ghost: its `+` tone reads
20
+ * --ty-solid-neutral-strong (the ink dial solid buttons use — the only
21
+ * value that actually inverts light↔dark for full contrast) instead of the
22
+ * generic --ty-color-neutral-strong text-emphasis token. Base/soft neutral
23
+ * stay on the generic token like every other flavor.
24
+ *
25
+ * Depth chrome (solid only): a 1px border + soft drop shadow, both derived
26
+ * from the fill via oklch(from …), scaled by --ty-button-depth (0–1). The
27
+ * border reads the TONE'S RESTING fill (not the current/hover one) so it
28
+ * stays stationary while the fill rises toward it on interaction. Offset
29
+ * direction/magnitude is --ty-button-border-l (mode-flipped: no border at
30
+ * all for colored solids in dark, a lit edge in light) with its own
31
+ * stronger dial for neutral, --ty-button-border-l-neutral (ink has no hue
32
+ * to separate it from the canvas). Escape hatches --ty-solid-border-color
33
+ * / --ty-solid-border-width outrank the derivation entirely.
34
+ *
35
+ * Hover escalation (outlined/ghost): :hover/:active/:focus-visible always
36
+ * resolve to the -strong tier regardless of starting tone — soft and base
37
+ * both rise to the same peak on interaction. Composes with `muted` rather
38
+ * than fighting it (see the escalation rules themselves for the exact
39
+ * split) — a pressed muted button lands on the same color as a pressed
40
+ * plain one of the same flavor.
12
41
  *
13
42
  * Per-instance overrides via host CSS variables:
14
- * --ty-button-bg, --ty-button-bg-hover, --ty-button-color, --ty-button-border
43
+ * --ty-button-bg, --ty-button-bg-hover, --ty-button-color, --ty-button-border,
44
+ * --ty-solid-border-color, --ty-solid-border-width
15
45
  */
16
46
  import { FLAVORS } from '../types/common.js';
17
47
  /* One block per flavor, per appearance. Selectors and tokens are formulaic —
@@ -33,49 +63,111 @@ const tokenRef = (prefix, f, suffix, fb) => fb
33
63
  0.08 L nudges keep AA for any rest-passing fill, and re-deriving would
34
64
  flicker black↔white whenever a nudge crosses the fg threshold. */
35
65
  const nudged = (fillExpr, offsetDial) => `oklch(from ${fillExpr} calc(l + var(--ty-${offsetDial})) c h)`;
66
+ /* Fill-relative nudge: moves TOWARD mid-lightness by the dial's magnitude,
67
+ whatever the fill. Needed for neutral+ — full-contrast ink sits at an L
68
+ extreme in both modes (near-black light / near-white dark), where the
69
+ MODE-directional dials clip into the L ceiling/floor and vanish. */
70
+ const nudgedMid = (fillExpr, offsetDial) => `oklch(from ${fillExpr} calc(l + sign(0.5 - l) * abs(var(--ty-${offsetDial}))) c h)`;
71
+ /* Solid rules assign --_solid-bg (the CURRENT fill — swapped by hover/
72
+ active) and --_solid-rest (the tone's RESTING fill — set only by rest/
73
+ tone rules, never by state rules). The base button.solid rule holds the
74
+ single set of formulas that consume them: background follows --_solid-bg;
75
+ the depth border derives from --_solid-rest so it stays STATIONARY while
76
+ the fill steps up on hover — the fill rises toward the lit edge instead
77
+ of dragging the edge along with it. */
36
78
  const solidFlavor = (f, fb) => {
37
79
  const solid = (suffix) => tokenRef('--ty-solid', f, suffix, fb);
80
+ // Neutral reads its own, stronger border offset (no hue separates ink
81
+ // from the canvas — see --ty-button-border-l-neutral in tyrell.css).
82
+ // Colored flavors must RESET to the plain dial: the bare button.solid
83
+ // rule (which matches every solid button) sets the neutral chain.
84
+ const borderL = f === 'neutral'
85
+ ? ' --_border-l: var(--ty-button-border-l-neutral, var(--ty-button-border-l, -0.15));'
86
+ : ' --_border-l: var(--ty-button-border-l, -0.15);';
87
+ // Neutral+ is full-contrast ink at an L extreme — its hover/active must
88
+ // move toward mid (fill-relative), not in the mode's direction.
89
+ const plusNudge = f === 'neutral' ? nudgedMid : nudged;
38
90
  return `
39
- button.solid.${f} { --_ring: ${tokenRef('--ty-color', f, '', fb)}; background: var(--ty-button-bg, var(--_muted-solid-bg, ${solid('')})); color: var(--ty-button-color, var(--_muted-solid-fg, ${solid('-fg')})); }
40
- button.solid.${f}.tone-plus { background: var(--ty-button-bg, var(--_muted-solid-bg, ${solid('-strong')})); color: var(--ty-button-color, var(--_muted-solid-fg, ${solid('-strong-fg')})); }
41
- button.solid.${f}.tone-minus { background: var(--ty-button-bg, var(--_muted-solid-bg, ${solid('-soft')})); color: var(--ty-button-color, var(--_muted-solid-fg, ${solid('-soft-fg')})); }
42
- button.solid.${f}:hover:not(:disabled) { background: var(--ty-button-bg-hover, ${solid('-hover')}); }
43
- button.solid.${f}:active:not(:disabled) { background: ${solid('-active')}; }
44
- button.solid.${f}.tone-plus:hover:not(:disabled) { background: var(--ty-button-bg-hover, ${nudged(solid('-strong'), 'solid-hover-l')}); }
45
- button.solid.${f}.tone-plus:active:not(:disabled) { background: ${nudged(solid('-strong'), 'solid-active-l')}; }
46
- button.solid.${f}.tone-minus:hover:not(:disabled) { background: var(--ty-button-bg-hover, ${nudged(solid('-soft'), 'solid-hover-l')}); }
47
- button.solid.${f}.tone-minus:active:not(:disabled) { background: ${nudged(solid('-soft'), 'solid-active-l')}; }
91
+ button.solid.${f} { --_ring: ${tokenRef('--ty-color', f, '', fb)}; --_solid-bg: var(--ty-button-bg, var(--_muted-solid-bg, ${solid('')})); --_solid-rest: var(--ty-button-bg, var(--_muted-solid-bg, ${solid('')}));${borderL} color: var(--ty-button-color, var(--_muted-solid-fg, ${solid('-fg')})); }
92
+ button.solid.${f}.tone-plus { --_solid-bg: var(--ty-button-bg, var(--_muted-solid-bg, ${solid('-strong')})); --_solid-rest: var(--ty-button-bg, var(--_muted-solid-bg, ${solid('-strong')})); color: var(--ty-button-color, var(--_muted-solid-fg, ${solid('-strong-fg')})); }
93
+ button.solid.${f}.tone-minus { --_solid-bg: var(--ty-button-bg, var(--_muted-solid-bg, ${solid('-soft')})); --_solid-rest: var(--ty-button-bg, var(--_muted-solid-bg, ${solid('-soft')})); color: var(--ty-button-color, var(--_muted-solid-fg, ${solid('-soft-fg')})); }
94
+ button.solid.${f}:hover:not(:disabled) { --_solid-bg: var(--ty-button-bg-hover, ${solid('-hover')}); }
95
+ button.solid.${f}:active:not(:disabled) { --_solid-bg: ${solid('-active')}; }
96
+ button.solid.${f}.tone-plus:hover:not(:disabled) { --_solid-bg: var(--ty-button-bg-hover, ${plusNudge(solid('-strong'), 'solid-hover-l')}); }
97
+ button.solid.${f}.tone-plus:active:not(:disabled) { --_solid-bg: ${plusNudge(solid('-strong'), 'solid-active-l')}; }
98
+ button.solid.${f}.tone-minus:hover:not(:disabled) { --_solid-bg: var(--ty-button-bg-hover, ${nudged(solid('-soft'), 'solid-hover-l')}); }
99
+ button.solid.${f}.tone-minus:active:not(:disabled) { --_solid-bg: ${nudged(solid('-soft'), 'solid-active-l')}; }
48
100
  `;
49
101
  };
50
102
  const outlinedFlavor = (f, fb) => {
51
103
  const color = (suffix) => tokenRef('--ty-color', f, suffix, fb);
104
+ // Neutral+ only: bare text/border need page contrast, which the
105
+ // per-flavor ladder is FOR (it deliberately inverts per mode) — pointing
106
+ // base/soft at the solid ink ramp was a real bug (dark-mode contrast
107
+ // against the canvas measured 1.01/1.20 — invisible; WCAG minimum is
108
+ // 4.5). Strong stays on ink: at 0.93 dark / 0.15 light it's still 16.5:1,
109
+ // and matches solid's "+" for the loud-CTA identity that was the ask.
110
+ const textInk = (suffix) => (f === 'neutral' && suffix === '-strong' ? `var(--ty-solid-neutral${suffix})` : color(suffix));
52
111
  return `
53
112
  button.outlined.${f} {
54
- color: var(--ty-button-color, var(--_muted-outlined-line, ${color('')}));
55
- border-color: var(--ty-button-border, var(--_muted-outlined-line, ${color('')}));
113
+ color: var(--ty-button-color, var(--_muted-outlined-line, ${textInk('')}));
114
+ border-color: var(--ty-button-border, var(--_muted-outlined-line, ${textInk('')}));
56
115
  }
57
116
  button.outlined.${f}.tone-plus {
58
- color: var(--ty-button-color, var(--_muted-outlined-line, ${color('-strong')}));
59
- border-color: var(--ty-button-border, var(--_muted-outlined-line, ${color('-strong')}));
117
+ color: var(--ty-button-color, var(--_muted-outlined-line, ${textInk('-strong')}));
118
+ border-color: var(--ty-button-border, var(--_muted-outlined-line, ${textInk('-strong')}));
60
119
  }
61
120
  button.outlined.${f}.tone-minus {
62
- color: var(--ty-button-color, var(--_muted-outlined-line, ${color('-soft')}));
63
- border-color: var(--ty-button-border, var(--_muted-outlined-line, ${color('-soft')}));
121
+ color: var(--ty-button-color, var(--_muted-outlined-line, ${textInk('-soft')}));
122
+ border-color: var(--ty-button-border, var(--_muted-outlined-line, ${textInk('-soft')}));
64
123
  }
65
124
  button.outlined.${f}:hover:not(:disabled) {
66
125
  background: var(--ty-button-bg-hover, ${tokenRef('--ty-bg', f, '-soft', fb)});
67
126
  }
127
+ /* Rest is whatever tone you picked; hover/active/focus always escalates to
128
+ the SAME peak — most-emphasized ("+") color, regardless of starting
129
+ tone. tone-plus is already there at rest, so this is a no-op for it.
130
+ :hover only, :not(.muted) — muted's hover-reveal is a DIFFERENT contract
131
+ (reveal the plain button's RESTING color, tested directly against it);
132
+ this rule would outrank that fallback and show strong instead.
133
+ :active/:focus-visible apply to muted too (no exclusion) — muted's own
134
+ reveal-on-press mechanism has much lower specificity than this rule, so
135
+ it simply wins outright, landing muted and plain on the same escalated
136
+ color when both are pressed — which is what muted's OWN test expects. */
137
+ button.outlined.${f}:not(.muted):hover:not(:disabled),
138
+ button.outlined.${f}:active:not(:disabled),
139
+ button.outlined.${f}:focus-visible {
140
+ color: var(--ty-button-color, ${textInk('-strong')});
141
+ border-color: var(--ty-button-border, ${textInk('-strong')});
142
+ }
68
143
  `;
69
144
  };
70
145
  const ghostFlavor = (f, fb) => {
71
146
  const color = (suffix) => tokenRef('--ty-color', f, suffix, fb);
147
+ // Neutral+ only: bare text needs page contrast, which is what the
148
+ // per-flavor text ladder is FOR (it deliberately inverts per mode) — the
149
+ // solid ink ramp doesn't need to invert for readability, a fill reads as
150
+ // a shape regardless of its own lightness. Pointing base/soft neutral
151
+ // text at ink was a real bug: dark-mode contrast against the canvas
152
+ // measured 1.01/1.20 (WCAG minimum is 4.5), i.e. invisible. Strong stays
153
+ // on ink — at 0.93 dark / 0.15 light it's still far above threshold
154
+ // (16.5:1), and matches solid's "+" for the loud-CTA identity that was
155
+ // the actual ask.
156
+ const ink = (suffix) => (f === 'neutral' && suffix === '-strong' ? `var(--ty-solid-neutral${suffix})` : color(suffix));
72
157
  return `
73
- button.ghost.${f} { color: var(--ty-button-color, var(--_muted-ghost-fg, ${color('')})); }
74
- button.ghost.${f}.tone-plus { color: var(--ty-button-color, var(--_muted-ghost-fg, ${color('-strong')})); }
75
- button.ghost.${f}.tone-minus { color: var(--ty-button-color, var(--_muted-ghost-fg, ${color('-soft')})); }
158
+ button.ghost.${f} { color: var(--ty-button-color, var(--_muted-ghost-fg, ${ink('')})); }
159
+ button.ghost.${f}.tone-plus { color: var(--ty-button-color, var(--_muted-ghost-fg, ${ink('-strong')})); }
160
+ button.ghost.${f}.tone-minus { color: var(--ty-button-color, var(--_muted-ghost-fg, ${ink('-soft')})); }
76
161
  button.ghost.${f}:hover:not(:disabled) {
77
162
  background: var(--ty-button-bg-hover, ${tokenRef('--ty-bg', f, '-soft', fb)});
78
163
  }
164
+ /* See outlinedFlavor above — same escalation-to-peak, same :hover-only
165
+ :not(.muted) split, text only. */
166
+ button.ghost.${f}:not(.muted):hover:not(:disabled),
167
+ button.ghost.${f}:active:not(:disabled),
168
+ button.ghost.${f}:focus-visible {
169
+ color: var(--ty-button-color, ${ink('-strong')});
170
+ }
79
171
  `;
80
172
  };
81
173
  /** Rules for one custom (non-built-in) flavor across all three appearances. */
@@ -100,11 +192,14 @@ button {
100
192
  font-size: var(--ty-font-xs);
101
193
  line-height: var(--ty-leading-xs);
102
194
  letter-spacing: var(--ty-tracking-xs);
103
- font-weight: var(--ty-font-semibold);
195
+ /* Mode-flipped weight dial (tyrell.css): medium in light, normal in dark —
196
+ light-on-dark text blooms, a fixed semibold read heavy there. Override
197
+ with --ty-weight-action at any scope. */
198
+ font-weight: var(--ty-weight-action, var(--ty-font-medium));
104
199
  white-space: nowrap;
105
200
  cursor: pointer;
106
201
  user-select: none;
107
- transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
202
+ transition: var(--ty-local-transition, background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease);
108
203
  background: transparent;
109
204
  color: var(--ty-color-neutral);
110
205
  border: 1px solid transparent;
@@ -275,6 +370,13 @@ button.action.xl ::slotted(ty-icon) { height: 1.25rem; width: 1.25rem; }
275
370
  Hover reveal is gated to real pointers (touch has no hover); :active /
276
371
  :focus-visible cover the tap case so touch still gets the color on press. */
277
372
 
373
+ /* --_muted-solid-* reads the SOLID neutral ink tokens — a fill's L doesn't
374
+ need page contrast. --_muted-outlined-line / --_muted-ghost-fg are bare
375
+ text/border and DO — they stay on the regular text ladder (it already
376
+ inverts correctly per mode), except tone-plus, which is legible AND
377
+ loud on the ink dial (16.5:1 dark, matches solid's "+" identity). Base/
378
+ soft on ink measured 1.01/1.20 dark contrast against the canvas —
379
+ invisible; WCAG minimum is 4.5. */
278
380
  button.muted {
279
381
  --_muted-solid-bg: var(--ty-solid-neutral);
280
382
  --_muted-solid-fg: var(--ty-solid-neutral-fg);
@@ -283,11 +385,16 @@ button.muted {
283
385
  }
284
386
  button.muted.tone-plus {
285
387
  --_muted-solid-bg: var(--ty-solid-neutral-strong);
286
- --_muted-outlined-line: var(--ty-color-neutral-strong);
287
- --_muted-ghost-fg: var(--ty-color-neutral-strong);
388
+ /* fg must track the tone's fill: neutral+ is inverted ink in dark mode
389
+ (white fill), so inheriting base neutral's white fg would be
390
+ white-on-white. */
391
+ --_muted-solid-fg: var(--ty-solid-neutral-strong-fg);
392
+ --_muted-outlined-line: var(--ty-solid-neutral-strong);
393
+ --_muted-ghost-fg: var(--ty-solid-neutral-strong);
288
394
  }
289
395
  button.muted.tone-minus {
290
396
  --_muted-solid-bg: var(--ty-solid-neutral-soft);
397
+ --_muted-solid-fg: var(--ty-solid-neutral-soft-fg);
291
398
  --_muted-outlined-line: var(--ty-color-neutral-soft);
292
399
  --_muted-ghost-fg: var(--ty-color-neutral-soft);
293
400
  }
@@ -343,26 +450,51 @@ button.pill.xl:has(ty-icon:only-child) { min-width: 2.5rem; min-height: 2.5rem;
343
450
  ============================================================ */
344
451
 
345
452
  button.solid {
346
- border: none;
347
453
  --_ring: var(--ty-color-neutral);
348
- background: var(--ty-button-bg, var(--ty-solid-neutral));
349
- color: var(--ty-button-color, var(--ty-solid-neutral-fg));
350
- }
351
- button.solid.tone-plus { background: var(--ty-button-bg, var(--ty-solid-neutral-strong)); color: var(--ty-button-color, var(--ty-solid-neutral-strong-fg)); }
352
- button.solid.tone-minus { background: var(--ty-button-bg, var(--ty-solid-neutral-soft)); color: var(--ty-button-color, var(--ty-solid-neutral-soft-fg)); }
353
- button.solid:hover:not(:disabled) { background: var(--ty-button-bg-hover, var(--ty-solid-neutral-hover)); }
354
- button.solid:active:not(:disabled) { background: var(--ty-solid-neutral-active); }
454
+ --_solid-bg: var(--ty-button-bg, var(--ty-solid-neutral));
455
+ --_solid-rest: var(--ty-button-bg, var(--ty-solid-neutral));
456
+ /* Bare .solid is the flavorless default = neutral ink, so it takes the
457
+ neutral border offset; colored flavor rules reset this to the plain
458
+ dial. */
459
+ --_border-l: var(--ty-button-border-l-neutral, var(--ty-button-border-l, -0.15));
460
+ background: var(--_solid-bg);
461
+ color: var(--ty-button-color, var(--ty-solid-neutral-fg));
462
+ /* Depth chrome — border + drop shadow, both scaled by --ty-button-depth.
463
+ (A top-edge sheen — inset 0 1px 0 <lightened fill> — used to live here
464
+ too; dropped, it read as a dizzying bright line rather than a subtle
465
+ highlight.) depth 0 = border matches fill exactly and the shadow goes
466
+ transparent — pixel-flat, but the 1px border stays in the layout so
467
+ toggling depth never shifts geometry (and solid now shares the same
468
+ box as outlined/ghost, which always had a 1px border).
469
+ --ty-button-border-l flips sign with the mode (tyrell.css): dark mode
470
+ runs a LIGHTER-than-fill hairline (fills read washed-out against dark
471
+ surfaces without a lit edge), light mode a slightly darker one.
472
+ Direct escape hatches outrank the derivation: --ty-solid-border-color
473
+ pins the border to ANY color (the L-offset dials stop mattering), and
474
+ --ty-solid-border-width changes thickness (widths ≠ 1px do shift
475
+ geometry — that's inherent).
476
+ Browsers without relative color drop these declarations: border falls
477
+ back to the base button's 1px transparent, shadows to none. */
478
+ border: var(--ty-solid-border-width, 1px) solid
479
+ var(--ty-solid-border-color,
480
+ oklch(from var(--_solid-rest, var(--_solid-bg)) calc(l + var(--_border-l, -0.15) * var(--ty-button-depth, 0.35)) c h));
481
+ box-shadow: 0 1px 2px oklch(0 0 0 / calc(0.4 * var(--ty-button-depth, 0.35)));
482
+ }
483
+ button.solid.tone-plus { --_solid-bg: var(--ty-button-bg, var(--ty-solid-neutral-strong)); --_solid-rest: var(--ty-button-bg, var(--ty-solid-neutral-strong)); color: var(--ty-button-color, var(--ty-solid-neutral-strong-fg)); }
484
+ button.solid.tone-minus { --_solid-bg: var(--ty-button-bg, var(--ty-solid-neutral-soft)); --_solid-rest: var(--ty-button-bg, var(--ty-solid-neutral-soft)); color: var(--ty-button-color, var(--ty-solid-neutral-soft-fg)); }
485
+ button.solid:hover:not(:disabled) { --_solid-bg: var(--ty-button-bg-hover, var(--ty-solid-neutral-hover)); }
486
+ button.solid:active:not(:disabled) { --_solid-bg: var(--ty-solid-neutral-active); }
355
487
  button.solid.tone-plus:hover:not(:disabled) {
356
- background: var(--ty-button-bg-hover, oklch(from var(--ty-solid-neutral-strong) calc(l + var(--ty-solid-hover-l)) c h));
488
+ --_solid-bg: var(--ty-button-bg-hover, oklch(from var(--ty-solid-neutral-strong) calc(l + sign(0.5 - l) * abs(var(--ty-solid-hover-l))) c h));
357
489
  }
358
490
  button.solid.tone-plus:active:not(:disabled) {
359
- background: oklch(from var(--ty-solid-neutral-strong) calc(l + var(--ty-solid-active-l)) c h);
491
+ --_solid-bg: oklch(from var(--ty-solid-neutral-strong) calc(l + sign(0.5 - l) * abs(var(--ty-solid-active-l))) c h);
360
492
  }
361
493
  button.solid.tone-minus:hover:not(:disabled) {
362
- background: var(--ty-button-bg-hover, oklch(from var(--ty-solid-neutral-soft) calc(l + var(--ty-solid-hover-l)) c h));
494
+ --_solid-bg: var(--ty-button-bg-hover, oklch(from var(--ty-solid-neutral-soft) calc(l + var(--ty-solid-hover-l)) c h));
363
495
  }
364
496
  button.solid.tone-minus:active:not(:disabled) {
365
- background: oklch(from var(--ty-solid-neutral-soft) calc(l + var(--ty-solid-active-l)) c h);
497
+ --_solid-bg: oklch(from var(--ty-solid-neutral-soft) calc(l + var(--ty-solid-active-l)) c h);
366
498
  }
367
499
 
368
500
  ${FLAVORS.map((f) => solidFlavor(f)).join('')}
@@ -1 +1 @@
1
- {"version":3,"file":"button.js","sourceRoot":"","sources":["../../src/styles/button.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"button.js","sourceRoot":"","sources":["../../src/styles/button.ts"],"names":[],"mappings":"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"}
@@ -140,7 +140,7 @@ export const calendarMonthStyles = `
140
140
  background-color: var(--ty-calendar-day-bg, transparent);
141
141
  color: var(--ty-calendar-day-color, var(--ty-calendar-muted, var(--ty-text)));
142
142
  cursor: pointer;
143
- transition: background-color 0.15s ease, color 0.15s ease;
143
+ transition: var(--ty-local-transition, background-color 0.15s ease, color 0.15s ease);
144
144
 
145
145
  /* Typography */
146
146
  font-weight: 400;
@@ -2,5 +2,5 @@
2
2
  * Calendar Navigation Styles
3
3
  * Clean, modern design with proper visual hierarchy and size variants
4
4
  */
5
- export declare const calendarNavigationStyles = "\n/* ============================================================================\n Size Variants (CSS Custom Properties)\n ============================================================================ */\n\n/* Theming tokens applied as var(--ty-calendar-nav-*, <default>) at point of\n use (NOT on :host) so consumers can override them from outside \u2014 this\n component is nested inside ty-calendar's shadow, so a :host default would\n block inherited overrides. --ty-calendar-accent still cascades in. */\n\n:host([data-size=\"md\"]) {\n --nav-btn-size: 2rem;\n --nav-btn-icon-size: 1.25rem;\n --nav-font-size: 1rem;\n --nav-padding: 0.5rem 0.75rem;\n --nav-default-width: 280px;\n}\n\n:host([data-size=\"sm\"]) {\n --nav-btn-size: 1.5rem;\n --nav-btn-icon-size: 1rem;\n --nav-font-size: 0.875rem;\n --nav-padding: 0.375rem 0.5rem;\n --nav-default-width: 240px;\n}\n\n:host([data-size=\"lg\"]) {\n --nav-btn-size: 2.5rem;\n --nav-btn-icon-size: 1.5rem;\n --nav-font-size: 1.125rem;\n --nav-padding: 0.625rem 1rem;\n --nav-default-width: 360px;\n}\n\n/* ============================================================================\n Main Navigation Header\n ============================================================================ */\n\n.calendar-navigation-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--nav-padding);\n font-family: system-ui, sans-serif;\n user-select: none;\n width: var(--nav-width, var(--nav-default-width));\n box-sizing: border-box;\n}\n\n/* ============================================================================\n Navigation Groups (Left, Center, Right)\n ============================================================================ */\n\n.nav-group {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.nav-group-left,\n.nav-group-right {\n flex: 0 0 auto;\n}\n\n.nav-group-center {\n flex: 1;\n justify-content: center;\n}\n\n/* ============================================================================\n Navigation Buttons\n ============================================================================ */\n\n.nav-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--nav-btn-size);\n height: var(--nav-btn-size);\n padding: 0;\n border: none;\n border-radius: var(--ty-radius-base);\n background-color: transparent;\n color: var(--ty-calendar-nav-color, var(--ty-color-neutral));\n cursor: pointer;\n transition: all 0.15s ease;\n outline: none;\n}\n\n.nav-btn:hover {\n background-color: var(--ty-calendar-nav-hover-bg, var(--ty-bg-neutral-soft));\n color: var(--ty-calendar-nav-hover-color, var(--ty-color-neutral-strong));\n}\n\n.nav-btn:active {\n background-color: var(--ty-calendar-nav-active-bg, var(--ty-bg-neutral));\n transform: scale(0.95);\n}\n\n.nav-btn:disabled {\n opacity: 0.35;\n cursor: default;\n pointer-events: none;\n}\n\n.nav-btn:focus-visible {\n outline: 2px solid var(--ty-calendar-nav-focus-outline, var(--ty-calendar-accent, var(--ty-color-primary)));\n outline-offset: 2px;\n}\n\n/* SVG sizing */\n.nav-btn svg {\n width: var(--nav-btn-icon-size);\n height: var(--nav-btn-icon-size);\n display: block;\n}\n\n/* ============================================================================\n Month/Year Display (Center)\n ============================================================================ */\n\n.month-year-display {\n font-size: var(--nav-font-size);\n font-weight: 600;\n color: var(--ty-calendar-nav-title-color, var(--ty-color-neutral-strong));\n text-align: center;\n white-space: nowrap;\n letter-spacing: -0.01em;\n}\n";
5
+ export declare const calendarNavigationStyles = "\n/* ============================================================================\n Size Variants (CSS Custom Properties)\n ============================================================================ */\n\n/* Theming tokens applied as var(--ty-calendar-nav-*, <default>) at point of\n use (NOT on :host) so consumers can override them from outside \u2014 this\n component is nested inside ty-calendar's shadow, so a :host default would\n block inherited overrides. --ty-calendar-accent still cascades in. */\n\n:host([data-size=\"md\"]) {\n --nav-btn-size: 2rem;\n --nav-btn-icon-size: 1.25rem;\n --nav-font-size: 1rem;\n --nav-padding: 0.5rem 0.75rem;\n --nav-default-width: 280px;\n}\n\n:host([data-size=\"sm\"]) {\n --nav-btn-size: 1.5rem;\n --nav-btn-icon-size: 1rem;\n --nav-font-size: 0.875rem;\n --nav-padding: 0.375rem 0.5rem;\n --nav-default-width: 240px;\n}\n\n:host([data-size=\"lg\"]) {\n --nav-btn-size: 2.5rem;\n --nav-btn-icon-size: 1.5rem;\n --nav-font-size: 1.125rem;\n --nav-padding: 0.625rem 1rem;\n --nav-default-width: 360px;\n}\n\n/* ============================================================================\n Main Navigation Header\n ============================================================================ */\n\n.calendar-navigation-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--nav-padding);\n font-family: system-ui, sans-serif;\n user-select: none;\n width: var(--nav-width, var(--nav-default-width));\n box-sizing: border-box;\n}\n\n/* ============================================================================\n Navigation Groups (Left, Center, Right)\n ============================================================================ */\n\n.nav-group {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.nav-group-left,\n.nav-group-right {\n flex: 0 0 auto;\n}\n\n.nav-group-center {\n flex: 1;\n justify-content: center;\n}\n\n/* ============================================================================\n Navigation Buttons\n ============================================================================ */\n\n.nav-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--nav-btn-size);\n height: var(--nav-btn-size);\n padding: 0;\n border: none;\n border-radius: var(--ty-radius-base);\n background-color: transparent;\n color: var(--ty-calendar-nav-color, var(--ty-color-neutral));\n cursor: pointer;\n transition: var(--ty-local-transition, all 0.15s ease);\n outline: none;\n}\n\n.nav-btn:hover {\n background-color: var(--ty-calendar-nav-hover-bg, var(--ty-bg-neutral-soft));\n color: var(--ty-calendar-nav-hover-color, var(--ty-color-neutral-strong));\n}\n\n.nav-btn:active {\n background-color: var(--ty-calendar-nav-active-bg, var(--ty-bg-neutral));\n transform: scale(0.95);\n}\n\n.nav-btn:disabled {\n opacity: 0.35;\n cursor: default;\n pointer-events: none;\n}\n\n.nav-btn:focus-visible {\n outline: 2px solid var(--ty-calendar-nav-focus-outline, var(--ty-calendar-accent, var(--ty-color-primary)));\n outline-offset: 2px;\n}\n\n/* SVG sizing */\n.nav-btn svg {\n width: var(--nav-btn-icon-size);\n height: var(--nav-btn-icon-size);\n display: block;\n}\n\n/* ============================================================================\n Month/Year Display (Center)\n ============================================================================ */\n\n.month-year-display {\n font-size: var(--nav-font-size);\n font-weight: 600;\n color: var(--ty-calendar-nav-title-color, var(--ty-color-neutral-strong));\n text-align: center;\n white-space: nowrap;\n letter-spacing: -0.01em;\n}\n";
6
6
  //# sourceMappingURL=calendar-navigation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"calendar-navigation.d.ts","sourceRoot":"","sources":["../../src/styles/calendar-navigation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,wBAAwB,snHAiIpC,CAAC"}
1
+ {"version":3,"file":"calendar-navigation.d.ts","sourceRoot":"","sources":["../../src/styles/calendar-navigation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,wBAAwB,kpHAiIpC,CAAC"}
@@ -87,7 +87,7 @@ export const calendarNavigationStyles = `
87
87
  background-color: transparent;
88
88
  color: var(--ty-calendar-nav-color, var(--ty-color-neutral));
89
89
  cursor: pointer;
90
- transition: all 0.15s ease;
90
+ transition: var(--ty-local-transition, all 0.15s ease);
91
91
  outline: none;
92
92
  }
93
93
 
@@ -37,7 +37,7 @@ export const checkboxStyles = `
37
37
  display: inline-flex;
38
38
  align-items: center;
39
39
  outline: none;
40
- transition: all 0.15s ease-in-out;
40
+ transition: var(--ty-local-transition, all 0.15s ease-in-out);
41
41
  user-select: none;
42
42
  cursor: pointer;
43
43
  border-radius: 6px;
@@ -64,7 +64,7 @@ export const checkboxStyles = `
64
64
  align-items: center;
65
65
  justify-content: center;
66
66
  color: inherit;
67
- transition: color 0.15s ease-in-out;
67
+ transition: var(--ty-local-transition, color 0.15s ease-in-out);
68
68
  pointer-events: none;
69
69
  /* Let the container handle the click */
70
70
  }
@@ -89,7 +89,7 @@ export const copyStyles = `
89
89
  /* Hover state — flavor-soft background (primary by default) */
90
90
  .input-wrapper:not(.disabled):hover {
91
91
  background: var(--copy-bg-hover, var(--ty-bg-primary-soft));
92
- transition: background 0.2s ease;
92
+ transition: var(--ty-local-transition, background 0.2s ease);
93
93
  }
94
94
 
95
95
  /* Copy button */
@@ -104,7 +104,7 @@ export const copyStyles = `
104
104
  border: none;
105
105
  background: transparent;
106
106
  color: var(--copy-color, var(--ty-text-soft));
107
- transition: color 0.2s ease, transform 0.2s ease;
107
+ transition: var(--ty-local-transition, color 0.2s ease, transform 0.2s ease);
108
108
  padding: 0;
109
109
  margin: 0;
110
110
  }
@@ -2,5 +2,5 @@
2
2
  * Shared CSS for CustomScrollbar utility
3
3
  * Include this in any component that uses CustomScrollbar
4
4
  */
5
- export declare const customScrollbarStyles = "\n/* ===================================== */\n/* Custom Scrollbar - Vertical Track */\n/* ===================================== */\n\n.ty-scrollbar-track-y {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: var(--ty-scrollbar-width, 8px);\n z-index: 3;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.25s ease-out;\n cursor: pointer;\n}\n\n.ty-scrollbar-track-y.has-overflow {\n pointer-events: auto;\n}\n\n.ty-scrollbar-track-y.has-overflow:hover,\n.ty-scrollbar-track-y.has-overflow.scrolling,\n.ty-scrollbar-track-y.dragging {\n opacity: 1;\n}\n\n.ty-scrollbar-track-y::before {\n content: '';\n position: absolute;\n inset: 0;\n background: var(--ty-scrollbar-track, transparent);\n border-radius: var(--ty-scrollbar-radius, 4px);\n opacity: 0;\n transition: opacity 0.15s ease-out;\n}\n\n.ty-scrollbar-track-y:hover::before,\n.ty-scrollbar-track-y.dragging::before {\n opacity: 1;\n background: var(--ty-scrollbar-track-hover, color-mix(in oklab, var(--ty-color-neutral-bold) 8%, transparent));\n}\n\n.ty-scrollbar-thumb-y {\n position: absolute;\n right: 0;\n width: 100%;\n min-height: var(--ty-scrollbar-thumb-min-height, 30px);\n background: var(--ty-scrollbar-thumb, color-mix(in oklab, var(--ty-color-neutral-bold) 40%, transparent));\n border-radius: var(--ty-scrollbar-radius, 4px);\n transition: background 0.15s ease-out;\n box-sizing: border-box;\n border: 1px solid transparent;\n}\n\n.ty-scrollbar-thumb-y:hover,\n.ty-scrollbar-track-y.dragging .ty-scrollbar-thumb-y {\n background: var(--ty-scrollbar-thumb-hover, color-mix(in oklab, var(--ty-color-neutral-bold) 55%, transparent));\n}\n\n.ty-scrollbar-thumb-y:active,\n.ty-scrollbar-track-y.dragging .ty-scrollbar-thumb-y {\n background: var(--ty-scrollbar-thumb-active, color-mix(in oklab, var(--ty-color-neutral-bold) 70%, transparent));\n}\n\n/* ===================================== */\n/* Custom Scrollbar - Horizontal Track */\n/* ===================================== */\n\n.ty-scrollbar-track-x {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: var(--ty-scrollbar-width, 8px);\n z-index: 3;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.25s ease-out;\n cursor: pointer;\n}\n\n.ty-scrollbar-track-x.has-overflow {\n pointer-events: auto;\n}\n\n.ty-scrollbar-track-x.has-overflow:hover,\n.ty-scrollbar-track-x.has-overflow.scrolling,\n.ty-scrollbar-track-x.dragging {\n opacity: 1;\n}\n\n.ty-scrollbar-track-x::before {\n content: '';\n position: absolute;\n inset: 0;\n background: var(--ty-scrollbar-track, transparent);\n border-radius: var(--ty-scrollbar-radius, 4px);\n opacity: 0;\n transition: opacity 0.15s ease-out;\n}\n\n.ty-scrollbar-track-x:hover::before,\n.ty-scrollbar-track-x.dragging::before {\n opacity: 1;\n background: var(--ty-scrollbar-track-hover, color-mix(in oklab, var(--ty-color-neutral-bold) 8%, transparent));\n}\n\n.ty-scrollbar-thumb-x {\n position: absolute;\n bottom: 0;\n height: 100%;\n min-width: var(--ty-scrollbar-thumb-min-height, 30px);\n background: var(--ty-scrollbar-thumb, color-mix(in oklab, var(--ty-color-neutral-bold) 40%, transparent));\n border-radius: var(--ty-scrollbar-radius, 4px);\n transition: background 0.15s ease-out;\n box-sizing: border-box;\n border: 1px solid transparent;\n}\n\n.ty-scrollbar-thumb-x:hover,\n.ty-scrollbar-track-x.dragging .ty-scrollbar-thumb-x {\n background: var(--ty-scrollbar-thumb-hover, color-mix(in oklab, var(--ty-color-neutral-bold) 55%, transparent));\n}\n\n.ty-scrollbar-thumb-x:active,\n.ty-scrollbar-track-x.dragging .ty-scrollbar-thumb-x {\n background: var(--ty-scrollbar-thumb-active, color-mix(in oklab, var(--ty-color-neutral-bold) 70%, transparent));\n}\n\n/* ===================================== */\n/* Touch devices - hide custom scrollbar */\n/* ===================================== */\n\n@media (pointer: coarse) and (hover: none) {\n .ty-scrollbar-track-y,\n .ty-scrollbar-track-x {\n display: none !important;\n }\n}\n\n/* Respect reduced motion */\n@media (prefers-reduced-motion: reduce) {\n .ty-scrollbar-track-y,\n .ty-scrollbar-track-x,\n .ty-scrollbar-thumb-y,\n .ty-scrollbar-thumb-x {\n transition-duration: 0ms !important;\n }\n}\n";
5
+ export declare const customScrollbarStyles = "\n/* ===================================== */\n/* Custom Scrollbar - Vertical Track */\n/* ===================================== */\n\n.ty-scrollbar-track-y {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: var(--ty-scrollbar-width, 8px);\n z-index: 3;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.25s ease-out;\n cursor: pointer;\n}\n\n.ty-scrollbar-track-y.has-overflow {\n pointer-events: auto;\n}\n\n.ty-scrollbar-track-y.has-overflow:hover,\n.ty-scrollbar-track-y.has-overflow.scrolling,\n.ty-scrollbar-track-y.dragging {\n opacity: 1;\n}\n\n.ty-scrollbar-track-y::before {\n content: '';\n position: absolute;\n inset: 0;\n background: var(--ty-scrollbar-track, transparent);\n border-radius: var(--ty-scrollbar-radius, 4px);\n opacity: 0;\n transition: opacity 0.15s ease-out;\n}\n\n.ty-scrollbar-track-y:hover::before,\n.ty-scrollbar-track-y.dragging::before {\n opacity: 1;\n background: var(--ty-scrollbar-track-hover, color-mix(in oklab, var(--ty-color-neutral-bold) 8%, transparent));\n}\n\n.ty-scrollbar-thumb-y {\n position: absolute;\n right: 0;\n width: 100%;\n min-height: var(--ty-scrollbar-thumb-min-height, 30px);\n background: var(--ty-scrollbar-thumb, color-mix(in oklab, var(--ty-color-neutral-bold) 40%, transparent));\n border-radius: var(--ty-scrollbar-radius, 4px);\n transition: var(--ty-local-transition, background 0.15s ease-out);\n box-sizing: border-box;\n border: 1px solid transparent;\n}\n\n.ty-scrollbar-thumb-y:hover,\n.ty-scrollbar-track-y.dragging .ty-scrollbar-thumb-y {\n background: var(--ty-scrollbar-thumb-hover, color-mix(in oklab, var(--ty-color-neutral-bold) 55%, transparent));\n}\n\n.ty-scrollbar-thumb-y:active,\n.ty-scrollbar-track-y.dragging .ty-scrollbar-thumb-y {\n background: var(--ty-scrollbar-thumb-active, color-mix(in oklab, var(--ty-color-neutral-bold) 70%, transparent));\n}\n\n/* ===================================== */\n/* Custom Scrollbar - Horizontal Track */\n/* ===================================== */\n\n.ty-scrollbar-track-x {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: var(--ty-scrollbar-width, 8px);\n z-index: 3;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.25s ease-out;\n cursor: pointer;\n}\n\n.ty-scrollbar-track-x.has-overflow {\n pointer-events: auto;\n}\n\n.ty-scrollbar-track-x.has-overflow:hover,\n.ty-scrollbar-track-x.has-overflow.scrolling,\n.ty-scrollbar-track-x.dragging {\n opacity: 1;\n}\n\n.ty-scrollbar-track-x::before {\n content: '';\n position: absolute;\n inset: 0;\n background: var(--ty-scrollbar-track, transparent);\n border-radius: var(--ty-scrollbar-radius, 4px);\n opacity: 0;\n transition: opacity 0.15s ease-out;\n}\n\n.ty-scrollbar-track-x:hover::before,\n.ty-scrollbar-track-x.dragging::before {\n opacity: 1;\n background: var(--ty-scrollbar-track-hover, color-mix(in oklab, var(--ty-color-neutral-bold) 8%, transparent));\n}\n\n.ty-scrollbar-thumb-x {\n position: absolute;\n bottom: 0;\n height: 100%;\n min-width: var(--ty-scrollbar-thumb-min-height, 30px);\n background: var(--ty-scrollbar-thumb, color-mix(in oklab, var(--ty-color-neutral-bold) 40%, transparent));\n border-radius: var(--ty-scrollbar-radius, 4px);\n transition: var(--ty-local-transition, background 0.15s ease-out);\n box-sizing: border-box;\n border: 1px solid transparent;\n}\n\n.ty-scrollbar-thumb-x:hover,\n.ty-scrollbar-track-x.dragging .ty-scrollbar-thumb-x {\n background: var(--ty-scrollbar-thumb-hover, color-mix(in oklab, var(--ty-color-neutral-bold) 55%, transparent));\n}\n\n.ty-scrollbar-thumb-x:active,\n.ty-scrollbar-track-x.dragging .ty-scrollbar-thumb-x {\n background: var(--ty-scrollbar-thumb-active, color-mix(in oklab, var(--ty-color-neutral-bold) 70%, transparent));\n}\n\n/* ===================================== */\n/* Touch devices - hide custom scrollbar */\n/* ===================================== */\n\n@media (pointer: coarse) and (hover: none) {\n .ty-scrollbar-track-y,\n .ty-scrollbar-track-x {\n display: none !important;\n }\n}\n\n/* Respect reduced motion */\n@media (prefers-reduced-motion: reduce) {\n .ty-scrollbar-track-y,\n .ty-scrollbar-track-x,\n .ty-scrollbar-thumb-y,\n .ty-scrollbar-thumb-x {\n transition-duration: 0ms !important;\n }\n}\n";
6
6
  //# sourceMappingURL=custom-scrollbar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"custom-scrollbar.d.ts","sourceRoot":"","sources":["../../src/styles/custom-scrollbar.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,qBAAqB,urIAuJjC,CAAC"}
1
+ {"version":3,"file":"custom-scrollbar.d.ts","sourceRoot":"","sources":["../../src/styles/custom-scrollbar.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,qBAAqB,+uIAuJjC,CAAC"}
@@ -53,7 +53,7 @@ export const customScrollbarStyles = `
53
53
  min-height: var(--ty-scrollbar-thumb-min-height, 30px);
54
54
  background: var(--ty-scrollbar-thumb, color-mix(in oklab, var(--ty-color-neutral-bold) 40%, transparent));
55
55
  border-radius: var(--ty-scrollbar-radius, 4px);
56
- transition: background 0.15s ease-out;
56
+ transition: var(--ty-local-transition, background 0.15s ease-out);
57
57
  box-sizing: border-box;
58
58
  border: 1px solid transparent;
59
59
  }
@@ -118,7 +118,7 @@ export const customScrollbarStyles = `
118
118
  min-width: var(--ty-scrollbar-thumb-min-height, 30px);
119
119
  background: var(--ty-scrollbar-thumb, color-mix(in oklab, var(--ty-color-neutral-bold) 40%, transparent));
120
120
  border-radius: var(--ty-scrollbar-radius, 4px);
121
- transition: background 0.15s ease-out;
121
+ transition: var(--ty-local-transition, background 0.15s ease-out);
122
122
  box-sizing: border-box;
123
123
  border: 1px solid transparent;
124
124
  }
@@ -231,7 +231,7 @@ ${FLAVORS.filter((f) => f !== "neutral").map((f) => datePickerFlavor(f)).join(""
231
231
  color: var(--ty-color-neutral-soft);
232
232
  cursor: pointer;
233
233
  border-radius: var(--ty-radius-sm);
234
- transition: all 0.15s ease;
234
+ transition: var(--ty-local-transition, all 0.15s ease);
235
235
  pointer-events: auto;
236
236
  }
237
237
 
@@ -1,2 +1,2 @@
1
- export declare const fileUploadStyles = "\n:host {\n display: block;\n font-family: var(--ty-font-sans);\n width: 100%;\n}\n\n.file-upload-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n box-sizing: border-box;\n}\n\n/* ===== LABEL ===== */\n\n.upload-label {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n font-weight: var(--ty-font-medium);\n color: var(--ty-label-color);\n margin-bottom: 6px;\n padding-left: 4px;\n display: flex;\n align-items: center;\n}\n\n.required-icon {\n color: var(--ty-color-danger);\n margin-left: 4px;\n font-size: 0.75rem;\n line-height: 1;\n}\n\n/* ===== DROP ZONE ===== */\n\n.drop-zone {\n border: 2px dashed var(--ty-border);\n border-radius: var(--ty-radius-base);\n padding: 2rem 1.5rem;\n text-align: center;\n cursor: pointer;\n transition: border-color 0.15s ease, background-color 0.15s ease, box-shadow 0.15s ease;\n outline: none;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n min-height: 140px;\n user-select: none;\n}\n\n.drop-zone:hover:not(.disabled) {\n border-color: var(--ty-input-border-hover);\n background: var(--ty-surface-content);\n}\n\n.drop-zone.focused {\n border-color: var(--ty-input-border-focus);\n box-shadow: 0 0 0 3px var(--ty-input-shadow-focus);\n}\n\n.drop-zone.drag-active {\n border-color: var(--ty-color-primary);\n border-style: solid;\n background: var(--ty-bg-primary-);\n}\n\n.drop-zone.drag-active .upload-icon {\n color: var(--ty-color-primary);\n transform: translateY(-2px);\n}\n\n.drop-zone.has-files {\n min-height: 80px;\n padding: 1.25rem 1.5rem;\n}\n\n.drop-zone.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n\n.drop-zone.error {\n border-color: var(--ty-color-danger);\n}\n\n.drop-zone.error:not(.disabled) {\n background: var(--ty-bg-danger-);\n}\n\n/* ===== UPLOAD ICON ===== */\n\n.upload-icon {\n color: var(--ty-text-faint);\n width: 2.5rem;\n height: 2.5rem;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: color 0.15s ease, transform 0.15s ease;\n pointer-events: none;\n}\n\n.upload-icon svg {\n width: 100%;\n height: 100%;\n}\n\n/* ===== HINT TEXT ===== */\n\n.upload-hint {\n color: var(--ty-text-soft);\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n pointer-events: none;\n}\n\n.browse-link {\n color: var(--ty-color-primary);\n font-weight: var(--ty-font-medium);\n}\n\n.upload-sub-hint {\n color: var(--ty-text-faint);\n font-size: var(--ty-font-xs);\n line-height: var(--ty-leading-xs);\n pointer-events: none;\n}\n\n/* ===== FILE LIST ===== */\n\n.file-list {\n display: flex;\n flex-direction: column;\n gap: 0.375rem;\n margin-top: 0.5rem;\n}\n\n.file-item {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 0.75rem;\n border-radius: var(--ty-radius-base);\n background: var(--ty-surface-content);\n border: 1px solid var(--ty-border-soft);\n}\n\n.file-icon {\n color: var(--ty-text-faint);\n flex-shrink: 0;\n width: 1rem;\n height: 1rem;\n display: flex;\n align-items: center;\n}\n\n.file-icon svg {\n width: 100%;\n height: 100%;\n}\n\n.file-name {\n flex: 1;\n font-size: var(--ty-font-sm);\n color: var(--ty-text);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n min-width: 0;\n}\n\n.file-size {\n font-size: var(--ty-font-xs);\n color: var(--ty-text-faint);\n flex-shrink: 0;\n font-variant-numeric: tabular-nums;\n}\n\n.file-remove {\n flex-shrink: 0;\n cursor: pointer;\n color: var(--ty-text-faint);\n width: 1.25rem;\n height: 1.25rem;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n transition: color 0.15s ease, background-color 0.15s ease;\n border: none;\n background: none;\n padding: 0;\n outline: none;\n}\n\n.file-remove:hover {\n color: var(--ty-color-danger);\n background: var(--ty-bg-danger-);\n}\n\n.file-remove:focus-visible {\n box-shadow: 0 0 0 2px var(--ty-color-danger);\n}\n\n.file-remove svg {\n width: 12px;\n height: 12px;\n}\n\n/* ===== ERROR MESSAGE ===== */\n\n.error-message {\n font-size: var(--ty-font-xs);\n line-height: var(--ty-leading-xs);\n color: var(--ty-color-danger);\n margin-top: 4px;\n padding-left: 4px;\n}\n\n/* ===== ACCESSIBILITY ===== */\n\n@media (prefers-reduced-motion: reduce) {\n .drop-zone,\n .upload-icon,\n .file-remove {\n transition: none;\n }\n}\n\n@media (prefers-contrast: high) {\n .drop-zone {\n border-width: 3px;\n }\n}\n";
1
+ export declare const fileUploadStyles = "\n:host {\n display: block;\n font-family: var(--ty-font-sans);\n width: 100%;\n}\n\n.file-upload-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n box-sizing: border-box;\n}\n\n/* ===== LABEL ===== */\n\n.upload-label {\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n letter-spacing: var(--ty-tracking-sm);\n font-weight: var(--ty-font-medium);\n color: var(--ty-label-color);\n margin-bottom: 6px;\n padding-left: 4px;\n display: flex;\n align-items: center;\n}\n\n.required-icon {\n color: var(--ty-color-danger);\n margin-left: 4px;\n font-size: 0.75rem;\n line-height: 1;\n}\n\n/* ===== DROP ZONE ===== */\n\n.drop-zone {\n border: 2px dashed var(--ty-border);\n border-radius: var(--ty-radius-base);\n padding: 2rem 1.5rem;\n text-align: center;\n cursor: pointer;\n transition: var(--ty-local-transition, border-color 0.15s ease, background-color 0.15s ease, box-shadow 0.15s ease);\n outline: none;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n min-height: 140px;\n user-select: none;\n}\n\n.drop-zone:hover:not(.disabled) {\n border-color: var(--ty-input-border-hover);\n background: var(--ty-surface-content);\n}\n\n.drop-zone.focused {\n border-color: var(--ty-input-border-focus);\n box-shadow: 0 0 0 3px var(--ty-input-shadow-focus);\n}\n\n.drop-zone.drag-active {\n border-color: var(--ty-color-primary);\n border-style: solid;\n background: var(--ty-bg-primary-);\n}\n\n.drop-zone.drag-active .upload-icon {\n color: var(--ty-color-primary);\n transform: translateY(-2px);\n}\n\n.drop-zone.has-files {\n min-height: 80px;\n padding: 1.25rem 1.5rem;\n}\n\n.drop-zone.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n\n.drop-zone.error {\n border-color: var(--ty-color-danger);\n}\n\n.drop-zone.error:not(.disabled) {\n background: var(--ty-bg-danger-);\n}\n\n/* ===== UPLOAD ICON ===== */\n\n.upload-icon {\n color: var(--ty-text-faint);\n width: 2.5rem;\n height: 2.5rem;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: var(--ty-local-transition, color 0.15s ease, transform 0.15s ease);\n pointer-events: none;\n}\n\n.upload-icon svg {\n width: 100%;\n height: 100%;\n}\n\n/* ===== HINT TEXT ===== */\n\n.upload-hint {\n color: var(--ty-text-soft);\n font-size: var(--ty-font-sm);\n line-height: var(--ty-leading-sm);\n pointer-events: none;\n}\n\n.browse-link {\n color: var(--ty-color-primary);\n font-weight: var(--ty-font-medium);\n}\n\n.upload-sub-hint {\n color: var(--ty-text-faint);\n font-size: var(--ty-font-xs);\n line-height: var(--ty-leading-xs);\n pointer-events: none;\n}\n\n/* ===== FILE LIST ===== */\n\n.file-list {\n display: flex;\n flex-direction: column;\n gap: 0.375rem;\n margin-top: 0.5rem;\n}\n\n.file-item {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 0.75rem;\n border-radius: var(--ty-radius-base);\n background: var(--ty-surface-content);\n border: 1px solid var(--ty-border-soft);\n}\n\n.file-icon {\n color: var(--ty-text-faint);\n flex-shrink: 0;\n width: 1rem;\n height: 1rem;\n display: flex;\n align-items: center;\n}\n\n.file-icon svg {\n width: 100%;\n height: 100%;\n}\n\n.file-name {\n flex: 1;\n font-size: var(--ty-font-sm);\n color: var(--ty-text);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n min-width: 0;\n}\n\n.file-size {\n font-size: var(--ty-font-xs);\n color: var(--ty-text-faint);\n flex-shrink: 0;\n font-variant-numeric: tabular-nums;\n}\n\n.file-remove {\n flex-shrink: 0;\n cursor: pointer;\n color: var(--ty-text-faint);\n width: 1.25rem;\n height: 1.25rem;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n transition: var(--ty-local-transition, color 0.15s ease, background-color 0.15s ease);\n border: none;\n background: none;\n padding: 0;\n outline: none;\n}\n\n.file-remove:hover {\n color: var(--ty-color-danger);\n background: var(--ty-bg-danger-);\n}\n\n.file-remove:focus-visible {\n box-shadow: 0 0 0 2px var(--ty-color-danger);\n}\n\n.file-remove svg {\n width: 12px;\n height: 12px;\n}\n\n/* ===== ERROR MESSAGE ===== */\n\n.error-message {\n font-size: var(--ty-font-xs);\n line-height: var(--ty-leading-xs);\n color: var(--ty-color-danger);\n margin-top: 4px;\n padding-left: 4px;\n}\n\n/* ===== ACCESSIBILITY ===== */\n\n@media (prefers-reduced-motion: reduce) {\n .drop-zone,\n .upload-icon,\n .file-remove {\n transition: none;\n }\n}\n\n@media (prefers-contrast: high) {\n .drop-zone {\n border-width: 3px;\n }\n}\n";
2
2
  //# sourceMappingURL=file-upload.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"file-upload.d.ts","sourceRoot":"","sources":["../../src/styles/file-upload.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,yhJA+O5B,CAAA"}
1
+ {"version":3,"file":"file-upload.d.ts","sourceRoot":"","sources":["../../src/styles/file-upload.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,6mJA+O5B,CAAA"}
@@ -41,7 +41,7 @@ export const fileUploadStyles = `
41
41
  padding: 2rem 1.5rem;
42
42
  text-align: center;
43
43
  cursor: pointer;
44
- transition: border-color 0.15s ease, background-color 0.15s ease, box-shadow 0.15s ease;
44
+ transition: var(--ty-local-transition, border-color 0.15s ease, background-color 0.15s ease, box-shadow 0.15s ease);
45
45
  outline: none;
46
46
  display: flex;
47
47
  flex-direction: column;
@@ -101,7 +101,7 @@ export const fileUploadStyles = `
101
101
  display: flex;
102
102
  align-items: center;
103
103
  justify-content: center;
104
- transition: color 0.15s ease, transform 0.15s ease;
104
+ transition: var(--ty-local-transition, color 0.15s ease, transform 0.15s ease);
105
105
  pointer-events: none;
106
106
  }
107
107
 
@@ -191,7 +191,7 @@ export const fileUploadStyles = `
191
191
  align-items: center;
192
192
  justify-content: center;
193
193
  border-radius: 50%;
194
- transition: color 0.15s ease, background-color 0.15s ease;
194
+ transition: var(--ty-local-transition, color 0.15s ease, background-color 0.15s ease);
195
195
  border: none;
196
196
  background: none;
197
197
  padding: 0;
@@ -110,8 +110,8 @@ export const inputStyles = `
110
110
  border: 1px solid var(--input-accent, var(--input-border, var(--ty-input-border)));
111
111
  border-radius: var(--ty-radius-base);
112
112
  background: var(--input-bg, var(--input-bg, var(--ty-input-bg)));
113
- transition: all 0.15s ease-in-out;
114
-
113
+ transition: var(--ty-local-transition, all 0.15s ease-in-out);
114
+
115
115
  /* Default size (md) */
116
116
  min-height: var(--ty-size-md);
117
117
  padding: 0 12px;
@@ -166,7 +166,7 @@ export const inputStyles = `
166
166
  background: none;
167
167
  cursor: pointer;
168
168
  color: var(--input-placeholder, var(--ty-input-placeholder));
169
- transition: color 0.15s ease-in-out;
169
+ transition: var(--ty-local-transition, color 0.15s ease-in-out);
170
170
  }
171
171
  .password-toggle:hover {
172
172
  color: var(--input-color, var(--ty-input-color));
@@ -118,7 +118,7 @@ ${inputStyles}
118
118
  border: 2px solid var(--ty-input-border);
119
119
  background: var(--ty-input-bg);
120
120
  box-sizing: border-box;
121
- transition: border-color 0.15s ease-in-out;
121
+ transition: var(--ty-local-transition, border-color 0.15s ease-in-out);
122
122
  }
123
123
 
124
124
  /* Default (no flavor attribute) is primary — defaults don't reflect to the