@ropav/styles 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +79 -0
- package/dist/components/accordion.css +1 -9
- package/dist/components/alert-dialog.css +0 -12
- package/dist/components/autocomplete.css +25 -35
- package/dist/components/breadcrumbs.css +9 -2
- package/dist/components/button-group.css +0 -4
- package/dist/components/button.css +3 -7
- package/dist/components/calendar-year-picker.css +19 -7
- package/dist/components/calendar.css +46 -21
- package/dist/components/checkbox.css +54 -56
- package/dist/components/chip.css +3 -1
- package/dist/components/close-button.css +7 -6
- package/dist/components/color-area.css +6 -6
- package/dist/components/color-input-group.css +10 -27
- package/dist/components/color-picker.css +1 -5
- package/dist/components/color-slider.css +14 -12
- package/dist/components/color-swatch-picker.css +2 -85
- package/dist/components/color-swatch.css +1 -1
- package/dist/components/combo-box.css +13 -3
- package/dist/components/date-input-group.css +34 -32
- package/dist/components/date-picker.css +1 -5
- package/dist/components/date-range-picker.css +1 -5
- package/dist/components/disclosure.css +0 -4
- package/dist/components/drawer.css +4 -8
- package/dist/components/drop-zone/drop-zone.styles.d.ts +34 -0
- package/dist/components/drop-zone/drop-zone.styles.d.ts.map +1 -0
- package/dist/components/drop-zone/drop-zone.styles.js +8 -0
- package/dist/components/drop-zone/index.d.ts +2 -0
- package/dist/components/drop-zone/index.d.ts.map +1 -0
- package/dist/components/drop-zone/index.js +2 -0
- package/dist/components/drop-zone.css +78 -0
- package/dist/components/dropdown.css +0 -4
- package/dist/components/error-message.css +0 -4
- package/dist/components/field-error.css +0 -4
- package/dist/components/index.css +1 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/input-group.css +12 -37
- package/dist/components/input-otp.css +14 -26
- package/dist/components/input.css +11 -32
- package/dist/components/kbd.css +3 -1
- package/dist/components/label.css +7 -2
- package/dist/components/link.css +13 -11
- package/dist/components/list-box-item.css +4 -10
- package/dist/components/menu-item.css +4 -10
- package/dist/components/meter.css +8 -16
- package/dist/components/modal.css +0 -12
- package/dist/components/number-field.css +23 -35
- package/dist/components/pagination.css +0 -4
- package/dist/components/popover.css +0 -4
- package/dist/components/progress-bar/progress-bar.styles.d.ts +36 -0
- package/dist/components/progress-bar/progress-bar.styles.d.ts.map +1 -1
- package/dist/components/progress-bar/progress-bar.styles.js +10 -0
- package/dist/components/progress-bar.css +82 -16
- package/dist/components/progress-circle.css +0 -4
- package/dist/components/radio.css +7 -9
- package/dist/components/range-calendar.css +73 -31
- package/dist/components/search-field.css +11 -28
- package/dist/components/segmented-control.css +9 -14
- package/dist/components/select.css +18 -32
- package/dist/components/sidebar/sidebar.styles.d.ts +36 -0
- package/dist/components/sidebar/sidebar.styles.d.ts.map +1 -1
- package/dist/components/sidebar/sidebar.styles.js +14 -1
- package/dist/components/sidebar.css +132 -38
- package/dist/components/slider.css +10 -11
- package/dist/components/splitter.css +44 -36
- package/dist/components/switch.css +16 -15
- package/dist/components/table.css +69 -27
- package/dist/components/tabs.css +8 -19
- package/dist/components/tag.css +32 -24
- package/dist/components/textarea.css +11 -32
- package/dist/components/toast.css +3 -1
- package/dist/components/toggle-button-group.css +0 -4
- package/dist/components/toggle-button.css +2 -6
- package/dist/components/tooltip.css +0 -4
- package/dist/components/typography.css +12 -4
- package/dist/components/virtualizer.css +11 -3
- package/dist/index.js +2 -1
- package/dist/ropav.min.css +1 -1
- package/dist/themes/airbnb.css +6 -4
- package/dist/themes/coinbase.css +6 -4
- package/dist/themes/default.css +24 -4
- package/dist/themes/discord.css +6 -4
- package/dist/themes/hero.css +24 -4
- package/dist/themes/lavender.css +6 -4
- package/dist/themes/mint.css +6 -4
- package/dist/themes/netflix.css +6 -4
- package/dist/themes/rabbit.css +6 -4
- package/dist/themes/shared/theme.css +1 -0
- package/dist/themes/sky.css +6 -4
- package/dist/themes/spotify.css +6 -4
- package/dist/themes/uber.css +6 -4
- package/package.json +1 -1
- package/src/components/drop-zone/drop-zone.styles.ts +12 -0
- package/src/components/drop-zone/index.ts +1 -0
- package/src/components/index.ts +1 -0
- package/src/components/progress-bar/progress-bar.styles.ts +14 -0
- package/src/components/sidebar/sidebar.styles.ts +23 -0
package/README.md
CHANGED
|
@@ -112,6 +112,11 @@ component that publishes it as an attribute.
|
|
|
112
112
|
|
|
113
113
|
`components/button.css` is the densest example of both — read it before writing a new component file.
|
|
114
114
|
|
|
115
|
+
**Every `ropav` component takes a `class` prop**, merged through its `tv()` recipe rather than
|
|
116
|
+
concatenated, so a utility that conflicts with one the recipe already carries replaces it. That is
|
|
117
|
+
the first thing to reach for. It cannot reach a part drawn in `::before`/`::after`, and it flattens
|
|
118
|
+
every state of whatever property it sets — see [State colors](#state-colors) for the way round both.
|
|
119
|
+
|
|
115
120
|
## Theming
|
|
116
121
|
|
|
117
122
|
Two independent axes. `data-theme` picks the palette, a `light`/`dark` class picks the appearance:
|
|
@@ -203,6 +208,80 @@ scrollbar set, and shadows.
|
|
|
203
208
|
stale the moment a token moves. `themes/shared/theme.css` holds what is derived from those tokens: the
|
|
204
209
|
`--radius-xs` … `--radius-4xl` scale and the easing curves.
|
|
205
210
|
|
|
211
|
+
### State colors
|
|
212
|
+
|
|
213
|
+
A component's own properties are the third tier, declared on its block and private to its file —
|
|
214
|
+
`--button-bg`, `--switch-control-bg-checked-hover`, `--sidebar-rail-line`. The convention:
|
|
215
|
+
|
|
216
|
+
> **A color a state rule paints goes through a custom property — where more than one state paints
|
|
217
|
+
> that property.**
|
|
218
|
+
|
|
219
|
+
That is what makes one state retunable on its own. A color written straight into the rule is not:
|
|
220
|
+
the resting and the lit value are the same property on the same element, so the one declaration a
|
|
221
|
+
caller writes to change either beats every state rule at once — and a utility beats them all
|
|
222
|
+
whatever their specificity, `utilities` being a later layer than `components`. The only way left is
|
|
223
|
+
to restate the whole state set behind `:not()`, which drifts silently the day a state is added.
|
|
224
|
+
|
|
225
|
+
So a caller sets the property instead, and the states that read the others are left standing:
|
|
226
|
+
|
|
227
|
+
```html
|
|
228
|
+
<!-- No line at rest; it still flares on hover and while dragging. -->
|
|
229
|
+
<SidebarRoot class="[--sidebar-rail-line:transparent]">
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
The qualifier is what keeps this from becoming surface for its own sake. Where exactly one state
|
|
233
|
+
paints a property, a caller can name that state from the call site — `hover:bg-*`, `focus-visible:outline-*` —
|
|
234
|
+
and there is no other state for it to flatten, so no property is minted. It is the second state
|
|
235
|
+
painting the same thing that makes the call site unable to tell them apart.
|
|
236
|
+
|
|
237
|
+
Defaults chain, so retuning one carries the states below it unless they are set too —
|
|
238
|
+
`--sidebar-rail-line-dragging` follows `--sidebar-rail-line-hover`, the way `--button-bg-pressed`
|
|
239
|
+
follows `--button-bg-hover`. Read `components/button.css` for the shape and
|
|
240
|
+
`components/sidebar.css` for a part painted on a pseudo-element, which a class cannot reach at all.
|
|
241
|
+
|
|
242
|
+
Two limits. The properties are per component and resolve to the tokens above, so a palette change
|
|
243
|
+
belongs in a theme rather than here. And Forced Colors Mode is not covered: those blocks paint the
|
|
244
|
+
system keywords, which are the only colors exempt from the override and not a component's to
|
|
245
|
+
retune — `[--sidebar-rail-line:transparent]` leaves the line drawn under High Contrast, on purpose.
|
|
246
|
+
|
|
247
|
+
`state-colors.test.ts` in the `ropav` package reads every component file and fails on a state color
|
|
248
|
+
that does not go through a property. Its ledger of exceptions is currently empty, so an entry
|
|
249
|
+
appearing there is debt to pay down rather than a licence to add more.
|
|
250
|
+
|
|
251
|
+
### Translucent surfaces
|
|
252
|
+
|
|
253
|
+
A `surface--transparent` paints nothing of its own, and so does a surface a caller has thinned to
|
|
254
|
+
let something through — a blurred header, a panel over an image, a window whose material the OS
|
|
255
|
+
draws. What sits on one of those has no way to know what is behind it, and that splits the palette
|
|
256
|
+
in two.
|
|
257
|
+
|
|
258
|
+
**Safe on anything: the tokens that are an alpha.** `--state-layer` is what a state paints, and
|
|
259
|
+
`--separator` and `--border` are the lines — each an alpha of `--surface-foreground` rather than a
|
|
260
|
+
neutral of its own. An alpha darkens or lightens whatever it lands on, so it holds its contrast
|
|
261
|
+
against a fill it was never tuned for: another surface, the far half of the theme, or a photograph.
|
|
262
|
+
The `-soft` family and `--scrollbar-thumb` are alphas too, which is why a selection is
|
|
263
|
+
`--accent-soft` wherever the library marks one.
|
|
264
|
+
|
|
265
|
+
**Not safe: the fills.** `--default`, `--accent`, the status colors, `--surface` and its secondary
|
|
266
|
+
and tertiary steps are opaque, and they are meant to be — a badge you can read the page through is a
|
|
267
|
+
broken badge. They assume a background because they *are* one. Use them to fill a box, never to mark
|
|
268
|
+
a state on a box that is already transparent.
|
|
269
|
+
|
|
270
|
+
`--surface-hover` sits on the fill side of that line despite the name: it is a surface that has been
|
|
271
|
+
tinted and stays opaque, for a component opaque at rest whose hover must stay that way.
|
|
272
|
+
`--state-layer` is the one for a component transparent at rest. Reaching for the wrong one fails
|
|
273
|
+
quietly — a translucent hover on an opaque tag shows the page through it, and a flat neutral on a
|
|
274
|
+
transparent row vanishes the moment the fill behind it matches.
|
|
275
|
+
|
|
276
|
+
The line between the two is what a color is for, not what it looks like. `--default` is a fine grey
|
|
277
|
+
until it is asked to be a state layer: then it is a fixed lightness laid on an unknown one, and the
|
|
278
|
+
day those two match it is gone with nothing to fail but the eye.
|
|
279
|
+
|
|
280
|
+
**Contrast on a translucent surface is the app's to guarantee.** `contrast.browser.test.ts` holds
|
|
281
|
+
the floor for text on the fills, where both sides are known. Once the background is whatever happens
|
|
282
|
+
to be behind the window, ropav cannot see it and does not claim to — an app that thins a surface
|
|
283
|
+
owns the legibility of what it puts there.
|
|
284
|
+
|
|
206
285
|
### Reduced motion
|
|
207
286
|
|
|
208
287
|
`data-reduce-motion="true"` on any ancestor forces animations off, `"false"` forces them on regardless
|
|
@@ -59,10 +59,6 @@
|
|
|
59
59
|
/* Base Styles */
|
|
60
60
|
@apply flex flex-1 items-center justify-between px-4 py-4 text-start text-sm font-medium no-highlight;
|
|
61
61
|
|
|
62
|
-
/**
|
|
63
|
-
* Transitions
|
|
64
|
-
* CRITICAL: motion-reduce must be AFTER transition for correct override specificity
|
|
65
|
-
*/
|
|
66
62
|
transition:
|
|
67
63
|
opacity 150ms var(--ease-out),
|
|
68
64
|
box-shadow 150ms var(--ease-out);
|
|
@@ -98,10 +94,6 @@
|
|
|
98
94
|
height: var(--disclosure-panel-height);
|
|
99
95
|
overflow: clip;
|
|
100
96
|
|
|
101
|
-
/**
|
|
102
|
-
* Transitions
|
|
103
|
-
* CRITICAL: motion-reduce must be AFTER transition for correct override specificity
|
|
104
|
-
*/
|
|
105
97
|
transition:
|
|
106
98
|
height 200ms var(--ease-out-quad),
|
|
107
99
|
opacity 200ms var(--ease-out);
|
|
@@ -129,7 +121,7 @@
|
|
|
129
121
|
@media (hover: hover) {
|
|
130
122
|
&:hover:not([aria-expanded="true"]),
|
|
131
123
|
&[data-hovered="true"]:not([aria-expanded="true"]) {
|
|
132
|
-
@apply bg-
|
|
124
|
+
@apply bg-state-layer;
|
|
133
125
|
}
|
|
134
126
|
}
|
|
135
127
|
}
|
|
@@ -10,10 +10,6 @@
|
|
|
10
10
|
@apply inline-block;
|
|
11
11
|
@apply cursor-(--cursor-interactive);
|
|
12
12
|
|
|
13
|
-
/**
|
|
14
|
-
* Transitions
|
|
15
|
-
* CRITICAL: motion-reduce must be AFTER transition for correct override specificity
|
|
16
|
-
*/
|
|
17
13
|
transition:
|
|
18
14
|
transform 250ms var(--ease-out-quart),
|
|
19
15
|
background-color 150ms var(--ease-smooth),
|
|
@@ -57,10 +53,6 @@
|
|
|
57
53
|
@apply animate-out duration-100 ease-out fade-out-0;
|
|
58
54
|
}
|
|
59
55
|
|
|
60
|
-
/**
|
|
61
|
-
* Reduce Animation
|
|
62
|
-
* CRITICAL: motion-reduce must be AFTER animate for correct override specificity
|
|
63
|
-
*/
|
|
64
56
|
&[data-exiting="true"],
|
|
65
57
|
&[data-entering="true"] {
|
|
66
58
|
@apply will-change-[opacity];
|
|
@@ -126,10 +118,6 @@
|
|
|
126
118
|
@apply animate-out duration-100 ease-out-quad fade-out-0 zoom-out-95;
|
|
127
119
|
}
|
|
128
120
|
|
|
129
|
-
/**
|
|
130
|
-
* Reduce Animation
|
|
131
|
-
* CRITICAL: motion-reduce must be AFTER animate for correct override specificity
|
|
132
|
-
*/
|
|
133
121
|
&[data-exiting="true"],
|
|
134
122
|
&[data-entering="true"] {
|
|
135
123
|
@apply will-change-[opacity,transform];
|
|
@@ -4,7 +4,14 @@
|
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
.autocomplete__trigger {
|
|
7
|
-
@apply relative isolate inline-flex min-h-9 rounded-field border
|
|
7
|
+
@apply relative isolate inline-flex min-h-9 rounded-field border px-3 field-line-md text-field-foreground shadow-field outline-none select-none no-highlight;
|
|
8
|
+
|
|
9
|
+
/* The fill, per state. The `--secondary` variant re-points these and declares nothing else. */
|
|
10
|
+
--autocomplete-trigger-bg: var(--field-background, var(--default));
|
|
11
|
+
--autocomplete-trigger-bg-hover: var(--field-hover);
|
|
12
|
+
--autocomplete-trigger-bg-focus: var(--field-focus);
|
|
13
|
+
|
|
14
|
+
background-color: var(--autocomplete-trigger-bg);
|
|
8
15
|
|
|
9
16
|
/* Forced Colors Mode flattens the fill onto the page and strips the shadow, leaving a control
|
|
10
17
|
* with nothing to say it is one. `ButtonBorder` is the keyword the platform uses for a
|
|
@@ -14,10 +21,6 @@
|
|
|
14
21
|
outline-offset: -1px;
|
|
15
22
|
}
|
|
16
23
|
|
|
17
|
-
/**
|
|
18
|
-
* Transitions
|
|
19
|
-
* CRITICAL: motion-reduce must be AFTER transition for correct override specificity
|
|
20
|
-
*/
|
|
21
24
|
transition:
|
|
22
25
|
background-color 150ms var(--ease-smooth),
|
|
23
26
|
border-color 150ms var(--ease-smooth),
|
|
@@ -39,7 +42,7 @@
|
|
|
39
42
|
@media (hover: hover) {
|
|
40
43
|
&:hover:not(:has(.autocomplete__clear-button:hover)),
|
|
41
44
|
&[data-hovered="true"]:not(:has(.autocomplete__clear-button:hover)) {
|
|
42
|
-
|
|
45
|
+
background-color: var(--autocomplete-trigger-bg-hover);
|
|
43
46
|
border-color: var(--field-border-hover);
|
|
44
47
|
}
|
|
45
48
|
}
|
|
@@ -49,7 +52,7 @@
|
|
|
49
52
|
&[data-focus-visible="true"] {
|
|
50
53
|
@apply status-focused;
|
|
51
54
|
border-color: var(--field-border-focus);
|
|
52
|
-
background-color: var(--
|
|
55
|
+
background-color: var(--autocomplete-trigger-bg-focus);
|
|
53
56
|
}
|
|
54
57
|
|
|
55
58
|
/* Focus state */
|
|
@@ -61,7 +64,7 @@
|
|
|
61
64
|
.autocomplete[data-invalid="true"] &,
|
|
62
65
|
.autocomplete[aria-invalid="true"] & {
|
|
63
66
|
@apply status-invalid-field;
|
|
64
|
-
background-color: var(--
|
|
67
|
+
background-color: var(--autocomplete-trigger-bg-focus);
|
|
65
68
|
}
|
|
66
69
|
|
|
67
70
|
/* Disabled state */
|
|
@@ -79,40 +82,22 @@
|
|
|
79
82
|
|
|
80
83
|
.autocomplete--secondary .autocomplete__trigger {
|
|
81
84
|
@apply shadow-none;
|
|
82
|
-
background-color: var(--autocomplete-trigger-bg);
|
|
83
85
|
|
|
84
86
|
--autocomplete-trigger-bg: var(--default);
|
|
85
87
|
--autocomplete-trigger-bg-hover: var(--default-hover);
|
|
86
88
|
--autocomplete-trigger-bg-focus: var(--default);
|
|
87
|
-
|
|
88
|
-
/* Exclude when clear button is hovered to prevent double hover effect */
|
|
89
|
-
@media (hover: hover) {
|
|
90
|
-
&:hover:not(:has(.autocomplete__clear-button:hover)),
|
|
91
|
-
&[data-hovered="true"]:not(:has(.autocomplete__clear-button:hover)) {
|
|
92
|
-
background-color: var(--autocomplete-trigger-bg-hover);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
&:focus-visible:not(:focus),
|
|
97
|
-
&[data-focus-visible="true"] {
|
|
98
|
-
background-color: var(--autocomplete-trigger-bg-focus);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
&:focus,
|
|
102
|
-
&[data-focus="true"] {
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
.autocomplete[data-invalid="true"] &,
|
|
106
|
-
.autocomplete[aria-invalid="true"] & {
|
|
107
|
-
background-color: var(--autocomplete-trigger-bg-focus);
|
|
108
|
-
}
|
|
109
89
|
}
|
|
110
90
|
|
|
111
91
|
.autocomplete__value {
|
|
112
|
-
@apply flex-1 text-start wrap-break-word
|
|
92
|
+
@apply flex-1 text-start wrap-break-word;
|
|
93
|
+
|
|
94
|
+
--autocomplete-value-fg: currentcolor;
|
|
95
|
+
--autocomplete-value-fg-placeholder: var(--field-placeholder, var(--muted));
|
|
96
|
+
|
|
97
|
+
color: var(--autocomplete-value-fg);
|
|
113
98
|
|
|
114
99
|
&[data-placeholder="true"] {
|
|
115
|
-
|
|
100
|
+
color: var(--autocomplete-value-fg-placeholder);
|
|
116
101
|
}
|
|
117
102
|
|
|
118
103
|
/* Removes the list-box-item indicator element from the autocomplete value*/
|
|
@@ -252,7 +237,12 @@
|
|
|
252
237
|
/* Clear Button styles */
|
|
253
238
|
.autocomplete__clear-button {
|
|
254
239
|
@apply relative isolate inline-flex h-6 w-6 shrink-0 origin-center items-center justify-center rounded-xl p-1 text-muted select-none no-highlight;
|
|
255
|
-
@apply me-0 size-5 shrink-0 self-center
|
|
240
|
+
@apply me-0 size-5 shrink-0 self-center;
|
|
241
|
+
|
|
242
|
+
--autocomplete-clear-button-bg: transparent;
|
|
243
|
+
--autocomplete-clear-button-bg-hover: var(--default-hover);
|
|
244
|
+
|
|
245
|
+
background-color: var(--autocomplete-clear-button-bg);
|
|
256
246
|
|
|
257
247
|
/* Cursor */
|
|
258
248
|
cursor: var(--cursor-interactive);
|
|
@@ -280,7 +270,7 @@
|
|
|
280
270
|
@media (hover: hover) {
|
|
281
271
|
&:hover,
|
|
282
272
|
&[data-hovered="true"] {
|
|
283
|
-
|
|
273
|
+
background-color: var(--autocomplete-clear-button-bg-hover);
|
|
284
274
|
}
|
|
285
275
|
}
|
|
286
276
|
|
|
@@ -4,7 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
/* Breadcrumb link */
|
|
6
6
|
.breadcrumbs__link {
|
|
7
|
-
@apply relative px-0.5 text-sm leading-5 font-medium
|
|
7
|
+
@apply relative px-0.5 text-sm leading-5 font-medium no-underline opacity-100;
|
|
8
|
+
|
|
9
|
+
--breadcrumbs-link-fg: var(--muted);
|
|
10
|
+
--breadcrumbs-link-fg-current: var(--link);
|
|
11
|
+
|
|
12
|
+
color: var(--breadcrumbs-link-fg);
|
|
8
13
|
|
|
9
14
|
&:hover,
|
|
10
15
|
&[data-hovered="true"] {
|
|
@@ -12,7 +17,9 @@
|
|
|
12
17
|
}
|
|
13
18
|
|
|
14
19
|
&[data-current="true"] {
|
|
15
|
-
@apply
|
|
20
|
+
@apply opacity-100;
|
|
21
|
+
|
|
22
|
+
color: var(--breadcrumbs-link-fg-current);
|
|
16
23
|
}
|
|
17
24
|
}
|
|
18
25
|
|
|
@@ -75,10 +75,6 @@
|
|
|
75
75
|
position: absolute;
|
|
76
76
|
pointer-events: none;
|
|
77
77
|
|
|
78
|
-
/**
|
|
79
|
-
* Transitions
|
|
80
|
-
* CRITICAL: motion-reduce must be AFTER transition for correct override specificity
|
|
81
|
-
*/
|
|
82
78
|
transition: opacity 150ms var(--ease-smooth);
|
|
83
79
|
@apply motion-reduce:transition-none;
|
|
84
80
|
|
|
@@ -4,10 +4,6 @@
|
|
|
4
4
|
.button {
|
|
5
5
|
@apply relative isolate inline-flex h-9 w-fit origin-center items-center justify-center gap-2 rounded-component px-4 text-sm font-medium whitespace-nowrap outline-none select-none no-highlight;
|
|
6
6
|
|
|
7
|
-
/**
|
|
8
|
-
* Transitions
|
|
9
|
-
* CRITICAL: motion-reduce must be AFTER transition for correct override specificity
|
|
10
|
-
*/
|
|
11
7
|
transition:
|
|
12
8
|
transform 250ms var(--ease-smooth),
|
|
13
9
|
background-color 100ms var(--ease-out),
|
|
@@ -130,14 +126,14 @@
|
|
|
130
126
|
.button--ghost,
|
|
131
127
|
.button--outline {
|
|
132
128
|
--button-bg: transparent;
|
|
133
|
-
--button-bg-hover: var(--
|
|
134
|
-
--button-bg-pressed: var(--
|
|
129
|
+
--button-bg-hover: var(--state-layer);
|
|
130
|
+
--button-bg-pressed: var(--state-layer);
|
|
135
131
|
--button-fg: var(--default-foreground);
|
|
136
132
|
}
|
|
137
133
|
|
|
138
134
|
.button--outline {
|
|
139
135
|
@apply border border-border;
|
|
140
|
-
--button-bg-hover: color-mix(in
|
|
136
|
+
--button-bg-hover: color-mix(in oklab, var(--state-layer) 60%, transparent);
|
|
141
137
|
}
|
|
142
138
|
|
|
143
139
|
.button--danger {
|
|
@@ -119,10 +119,19 @@
|
|
|
119
119
|
@apply relative inline-flex h-8 items-center justify-center rounded-component px-2.5 text-sm font-medium outline-none select-none no-highlight;
|
|
120
120
|
touch-action: manipulation;
|
|
121
121
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
122
|
+
/* The fill and label, per state — selected and hovered land together on the current year. */
|
|
123
|
+
--calendar-year-picker-year-cell-bg: transparent;
|
|
124
|
+
--calendar-year-picker-year-cell-bg-hover: var(--state-layer);
|
|
125
|
+
--calendar-year-picker-year-cell-bg-selected: var(--accent);
|
|
126
|
+
--calendar-year-picker-year-cell-bg-selected-hover: var(--accent-hover);
|
|
127
|
+
--calendar-year-picker-year-cell-fg: currentcolor;
|
|
128
|
+
--calendar-year-picker-year-cell-fg-hover: var(--default-foreground);
|
|
129
|
+
--calendar-year-picker-year-cell-fg-selected: var(--accent-foreground);
|
|
130
|
+
|
|
131
|
+
background-color: var(--calendar-year-picker-year-cell-bg);
|
|
132
|
+
color: var(--calendar-year-picker-year-cell-fg);
|
|
133
|
+
|
|
134
|
+
/* Same as `.tag`. */
|
|
126
135
|
transition:
|
|
127
136
|
color 100ms var(--ease-smooth),
|
|
128
137
|
scale 100ms var(--ease-smooth),
|
|
@@ -136,19 +145,22 @@
|
|
|
136
145
|
/* Hover state (when not selected) – only on devices that support hover */
|
|
137
146
|
@media (hover: hover) and (pointer: fine) {
|
|
138
147
|
&:is(:hover, [data-hovered="true"]):not([data-selected="true"]) {
|
|
139
|
-
|
|
148
|
+
background-color: var(--calendar-year-picker-year-cell-bg-hover);
|
|
149
|
+
color: var(--calendar-year-picker-year-cell-fg-hover);
|
|
140
150
|
}
|
|
141
151
|
}
|
|
142
152
|
|
|
143
153
|
/* Selected state (current year) – same as .tag[data-selected] */
|
|
144
154
|
&[data-selected="true"],
|
|
145
155
|
&[aria-selected="true"] {
|
|
146
|
-
|
|
156
|
+
background-color: var(--calendar-year-picker-year-cell-bg-selected);
|
|
157
|
+
color: var(--calendar-year-picker-year-cell-fg-selected);
|
|
158
|
+
|
|
147
159
|
@apply forced-selected;
|
|
148
160
|
|
|
149
161
|
@media (hover: hover) and (pointer: fine) {
|
|
150
162
|
&:is(:hover, [data-hovered="true"]) {
|
|
151
|
-
|
|
163
|
+
background-color: var(--calendar-year-picker-year-cell-bg-selected-hover);
|
|
152
164
|
}
|
|
153
165
|
}
|
|
154
166
|
}
|
|
@@ -80,14 +80,12 @@
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
.calendar__nav-button {
|
|
83
|
-
@apply flex size-6 items-center justify-center
|
|
83
|
+
@apply flex size-6 items-center justify-center text-accent-soft-foreground;
|
|
84
|
+
|
|
85
|
+
border-radius: min(32px, var(--component-radius));
|
|
84
86
|
|
|
85
87
|
will-change: scale;
|
|
86
88
|
|
|
87
|
-
/**
|
|
88
|
-
* Transitions
|
|
89
|
-
* CRITICAL: motion-reduce must be AFTER transition for correct override specificity
|
|
90
|
-
*/
|
|
91
89
|
transition:
|
|
92
90
|
transform 250ms var(--ease-out),
|
|
93
91
|
background-color 100ms var(--ease-out),
|
|
@@ -101,7 +99,7 @@
|
|
|
101
99
|
@media (hover: hover) {
|
|
102
100
|
&:hover,
|
|
103
101
|
&[data-hovered="true"] {
|
|
104
|
-
@apply bg-
|
|
102
|
+
@apply bg-state-layer;
|
|
105
103
|
}
|
|
106
104
|
}
|
|
107
105
|
|
|
@@ -183,13 +181,30 @@
|
|
|
183
181
|
* -------------------------------------------------------------------------- */
|
|
184
182
|
.calendar__cell {
|
|
185
183
|
/* Cell (td) wrapper styles - margins now work with grid layout */
|
|
186
|
-
@apply relative flex aspect-square size-full items-center justify-center
|
|
184
|
+
@apply relative flex aspect-square size-full items-center justify-center text-center text-sm font-medium outline-none no-highlight;
|
|
185
|
+
|
|
186
|
+
border-radius: min(32px, var(--component-radius));
|
|
187
|
+
|
|
188
|
+
/* Eight states repaint a day, several of them in pairs — today and hovered, selected and
|
|
189
|
+
* pressed, selected and outside the month. One declaration cannot tell them apart, so each
|
|
190
|
+
* reads its own. */
|
|
191
|
+
--calendar-cell-bg: transparent;
|
|
192
|
+
--calendar-cell-bg-hover: var(--state-layer);
|
|
193
|
+
--calendar-cell-bg-pressed: var(--calendar-cell-bg-hover);
|
|
194
|
+
--calendar-cell-bg-today: var(--accent-soft);
|
|
195
|
+
--calendar-cell-bg-today-hover: var(--accent-soft-hover);
|
|
196
|
+
--calendar-cell-bg-selected: var(--accent);
|
|
197
|
+
--calendar-cell-bg-selected-pressed: var(--accent-hover);
|
|
198
|
+
--calendar-cell-bg-selected-outside-month: var(--state-layer);
|
|
199
|
+
--calendar-cell-fg: currentcolor;
|
|
200
|
+
--calendar-cell-fg-today: var(--accent-soft-foreground);
|
|
201
|
+
--calendar-cell-fg-selected: var(--accent-foreground);
|
|
202
|
+
--calendar-cell-fg-outside-month: var(--muted);
|
|
203
|
+
|
|
204
|
+
background-color: var(--calendar-cell-bg);
|
|
205
|
+
color: var(--calendar-cell-fg);
|
|
187
206
|
|
|
188
207
|
will-change: scale;
|
|
189
|
-
/**
|
|
190
|
-
* Transitions
|
|
191
|
-
* CRITICAL: motion-reduce must be AFTER transition for correct override specificity
|
|
192
|
-
*/
|
|
193
208
|
transition:
|
|
194
209
|
transform 250ms var(--ease-out),
|
|
195
210
|
box-shadow 100ms var(--ease-out);
|
|
@@ -205,7 +220,8 @@
|
|
|
205
220
|
|
|
206
221
|
/* Today indicator */
|
|
207
222
|
&[data-today="true"] {
|
|
208
|
-
|
|
223
|
+
background-color: var(--calendar-cell-bg-today);
|
|
224
|
+
color: var(--calendar-cell-fg-today);
|
|
209
225
|
|
|
210
226
|
/* A tinted background is all that marks today, and forced colors flattens it onto the page.
|
|
211
227
|
* An edge rather than a fill, so today still reads as itself once it is also selected. */
|
|
@@ -217,25 +233,27 @@
|
|
|
217
233
|
@media (hover: hover) {
|
|
218
234
|
&:hover:not([data-selected="true"]),
|
|
219
235
|
&[data-hovered="true"]:not([data-selected="true"]) {
|
|
220
|
-
|
|
236
|
+
background-color: var(--calendar-cell-bg-today-hover);
|
|
221
237
|
}
|
|
222
238
|
}
|
|
223
239
|
}
|
|
224
240
|
|
|
225
241
|
/* Selected state */
|
|
226
242
|
&[data-selected="true"] {
|
|
227
|
-
|
|
243
|
+
background-color: var(--calendar-cell-bg-selected);
|
|
244
|
+
color: var(--calendar-cell-fg-selected);
|
|
245
|
+
|
|
228
246
|
@apply forced-selected;
|
|
229
247
|
}
|
|
230
248
|
|
|
231
249
|
/* Pressed state */
|
|
232
250
|
&:active,
|
|
233
251
|
&[data-pressed="true"] {
|
|
234
|
-
|
|
252
|
+
background-color: var(--calendar-cell-bg-pressed);
|
|
235
253
|
transform: scale(0.95);
|
|
236
254
|
|
|
237
255
|
&[data-selected="true"] {
|
|
238
|
-
|
|
256
|
+
background-color: var(--calendar-cell-bg-selected-pressed);
|
|
239
257
|
}
|
|
240
258
|
}
|
|
241
259
|
|
|
@@ -243,17 +261,19 @@
|
|
|
243
261
|
@media (hover: hover) {
|
|
244
262
|
&:hover:not([data-selected="true"]),
|
|
245
263
|
&[data-hovered="true"]:not([data-selected="true"]) {
|
|
246
|
-
|
|
264
|
+
background-color: var(--calendar-cell-bg-hover);
|
|
247
265
|
}
|
|
248
266
|
}
|
|
249
267
|
|
|
250
268
|
/* Outside month (previous/next month days) */
|
|
251
269
|
&[data-outside-month="true"] {
|
|
252
|
-
@apply
|
|
270
|
+
@apply opacity-50;
|
|
271
|
+
|
|
272
|
+
color: var(--calendar-cell-fg-outside-month);
|
|
253
273
|
}
|
|
254
274
|
|
|
255
275
|
&[data-selected="true"][data-outside-month="true"] {
|
|
256
|
-
|
|
276
|
+
background-color: var(--calendar-cell-bg-selected-outside-month);
|
|
257
277
|
}
|
|
258
278
|
|
|
259
279
|
/* Unavailable dates */
|
|
@@ -272,10 +292,15 @@
|
|
|
272
292
|
|
|
273
293
|
/* Cell indicator - small dot at bottom center of cell */
|
|
274
294
|
.calendar__cell-indicator {
|
|
275
|
-
@apply absolute bottom-1 left-1/2 size-[3px] -translate-x-1/2 rounded-xs
|
|
295
|
+
@apply absolute bottom-1 left-1/2 size-[3px] -translate-x-1/2 rounded-xs;
|
|
296
|
+
|
|
297
|
+
--calendar-cell-indicator-bg: var(--muted);
|
|
298
|
+
--calendar-cell-indicator-bg-selected: var(--accent-foreground);
|
|
299
|
+
|
|
300
|
+
background-color: var(--calendar-cell-indicator-bg);
|
|
276
301
|
|
|
277
302
|
/* Indicator color changes when cell is selected */
|
|
278
303
|
[data-selected="true"] > & {
|
|
279
|
-
|
|
304
|
+
background-color: var(--calendar-cell-indicator-bg-selected);
|
|
280
305
|
}
|
|
281
306
|
}
|