vuetiwatch 0.1.0 → 0.2.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 +200 -17
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/plugin.d.ts +77 -7
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +104 -15
- package/dist/plugin.js.map +1 -1
- package/dist/registry.d.ts +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +6 -1
- package/dist/registry.js.map +1 -1
- package/dist/styles/atlas.css +99 -0
- package/dist/styles/atlas.min.css +1 -0
- package/dist/styles/atlasDark.css +99 -0
- package/dist/styles/atlasDark.min.css +1 -0
- package/dist/styles/atlasSepia.css +99 -0
- package/dist/styles/atlasSepia.min.css +1 -0
- package/dist/styles/aurora.css +97 -4
- package/dist/styles/aurora.min.css +1 -1
- package/dist/styles/brutalist.css +5 -0
- package/dist/styles/brutalist.min.css +1 -1
- package/dist/styles/calm.css +0 -4
- package/dist/styles/calm.min.css +1 -1
- package/dist/styles/candy.css +71 -0
- package/dist/styles/candy.min.css +1 -0
- package/dist/styles/clay.css +13 -0
- package/dist/styles/clay.min.css +1 -1
- package/dist/styles/core.css +239 -36
- package/dist/styles/core.min.css +1 -1
- package/dist/styles/graphite.css +29 -0
- package/dist/styles/graphite.min.css +1 -0
- package/dist/styles/morph.css +12 -0
- package/dist/styles/morph.min.css +1 -1
- package/dist/styles/neon.css +8 -0
- package/dist/styles/neon.min.css +1 -1
- package/dist/styles/sketchy.css +4 -0
- package/dist/styles/sketchy.min.css +1 -1
- package/dist/styles/soft.css +1 -12
- package/dist/styles/soft.min.css +1 -1
- package/dist/styles.css +577 -52
- package/dist/styles.min.css +1 -1
- package/dist/themes/atlas.d.ts +38 -0
- package/dist/themes/atlas.d.ts.map +1 -0
- package/dist/themes/atlas.js +203 -0
- package/dist/themes/atlas.js.map +1 -0
- package/dist/themes/atlasDark.d.ts +8 -0
- package/dist/themes/atlasDark.d.ts.map +1 -0
- package/dist/themes/atlasDark.js +64 -0
- package/dist/themes/atlasDark.js.map +1 -0
- package/dist/themes/atlasSepia.d.ts +11 -0
- package/dist/themes/atlasSepia.d.ts.map +1 -0
- package/dist/themes/atlasSepia.js +60 -0
- package/dist/themes/atlasSepia.js.map +1 -0
- package/dist/themes/aurora.d.ts.map +1 -1
- package/dist/themes/aurora.js +27 -2
- package/dist/themes/aurora.js.map +1 -1
- package/dist/themes/brutalist.d.ts.map +1 -1
- package/dist/themes/brutalist.js +26 -0
- package/dist/themes/brutalist.js.map +1 -1
- package/dist/themes/calm.d.ts.map +1 -1
- package/dist/themes/calm.js +22 -2
- package/dist/themes/calm.js.map +1 -1
- package/dist/themes/candy.d.ts +20 -0
- package/dist/themes/candy.d.ts.map +1 -0
- package/dist/themes/candy.js +142 -0
- package/dist/themes/candy.js.map +1 -0
- package/dist/themes/classic.d.ts.map +1 -1
- package/dist/themes/classic.js +2 -0
- package/dist/themes/classic.js.map +1 -1
- package/dist/themes/clay.d.ts.map +1 -1
- package/dist/themes/clay.js +22 -0
- package/dist/themes/clay.js.map +1 -1
- package/dist/themes/darkGlass.d.ts.map +1 -1
- package/dist/themes/darkGlass.js +21 -0
- package/dist/themes/darkGlass.js.map +1 -1
- package/dist/themes/graphite.d.ts +13 -0
- package/dist/themes/graphite.d.ts.map +1 -0
- package/dist/themes/graphite.js +147 -0
- package/dist/themes/graphite.js.map +1 -0
- package/dist/themes/index.d.ts +5 -0
- package/dist/themes/index.d.ts.map +1 -1
- package/dist/themes/index.js +5 -0
- package/dist/themes/index.js.map +1 -1
- package/dist/themes/liquidGlass.d.ts.map +1 -1
- package/dist/themes/liquidGlass.js +27 -3
- package/dist/themes/liquidGlass.js.map +1 -1
- package/dist/themes/lux.d.ts.map +1 -1
- package/dist/themes/lux.js +21 -2
- package/dist/themes/lux.js.map +1 -1
- package/dist/themes/morph.d.ts.map +1 -1
- package/dist/themes/morph.js +23 -3
- package/dist/themes/morph.js.map +1 -1
- package/dist/themes/neon.d.ts.map +1 -1
- package/dist/themes/neon.js +22 -0
- package/dist/themes/neon.js.map +1 -1
- package/dist/themes/paper.d.ts.map +1 -1
- package/dist/themes/paper.js +16 -0
- package/dist/themes/paper.js.map +1 -1
- package/dist/themes/sketchy.d.ts.map +1 -1
- package/dist/themes/sketchy.js +17 -0
- package/dist/themes/sketchy.js.map +1 -1
- package/dist/themes/slate.d.ts.map +1 -1
- package/dist/themes/slate.js +22 -1
- package/dist/themes/slate.js.map +1 -1
- package/dist/themes/soft.d.ts.map +1 -1
- package/dist/themes/soft.js +21 -2
- package/dist/themes/soft.js.map +1 -1
- package/dist/types.d.ts +40 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/util/defaults.d.ts.map +1 -1
- package/dist/util/defaults.js +11 -1
- package/dist/util/defaults.js.map +1 -1
- package/dist/util/defineTheme.d.ts.map +1 -1
- package/dist/util/defineTheme.js +11 -5
- package/dist/util/defineTheme.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +8 -2
- package/src/plugin.ts +214 -21
- package/src/registry.ts +10 -0
- package/src/styles/core.css +563 -35
- package/src/styles/index.css +4 -0
- package/src/styles/themes/_atlas.css +194 -0
- package/src/styles/themes/atlas.css +2 -0
- package/src/styles/themes/atlasDark.css +2 -0
- package/src/styles/themes/atlasSepia.css +2 -0
- package/src/styles/themes/aurora.css +151 -7
- package/src/styles/themes/brutalist.css +5 -3
- package/src/styles/themes/calm.css +0 -7
- package/src/styles/themes/candy.css +113 -0
- package/src/styles/themes/clay.css +24 -0
- package/src/styles/themes/graphite.css +63 -0
- package/src/styles/themes/liquidGlass.css +0 -2
- package/src/styles/themes/lux.css +0 -4
- package/src/styles/themes/morph.css +22 -0
- package/src/styles/themes/neon.css +8 -3
- package/src/styles/themes/paper.css +0 -2
- package/src/styles/themes/sketchy.css +9 -0
- package/src/styles/themes/slate.css +0 -4
- package/src/styles/themes/soft.css +1 -12
- package/src/themes/atlas.ts +211 -0
- package/src/themes/atlasDark.ts +64 -0
- package/src/themes/atlasSepia.ts +60 -0
- package/src/themes/aurora.ts +30 -2
- package/src/themes/brutalist.ts +29 -0
- package/src/themes/calm.ts +25 -2
- package/src/themes/candy.ts +144 -0
- package/src/themes/classic.ts +3 -0
- package/src/themes/clay.ts +24 -0
- package/src/themes/darkGlass.ts +24 -0
- package/src/themes/graphite.ts +150 -0
- package/src/themes/index.ts +5 -0
- package/src/themes/liquidGlass.ts +30 -3
- package/src/themes/lux.ts +24 -2
- package/src/themes/morph.ts +25 -3
- package/src/themes/neon.ts +25 -0
- package/src/themes/paper.ts +19 -0
- package/src/themes/sketchy.ts +20 -0
- package/src/themes/slate.ts +25 -1
- package/src/themes/soft.ts +24 -2
- package/src/types.ts +41 -0
- package/src/util/defaults.ts +12 -1
- package/src/util/defineTheme.ts +11 -5
package/src/styles/core.css
CHANGED
|
@@ -10,19 +10,31 @@
|
|
|
10
10
|
* The scope is either a Vuetiwatch theme class or the `data-vuetiwatch`
|
|
11
11
|
* attribute `createVuetiwatch()` sets on `<html>` — the latter is what
|
|
12
12
|
* extends this layer to themes you build yourself with `defineTheme()`.
|
|
13
|
-
* `VUETIWATCH_THEMES`
|
|
14
|
-
*
|
|
13
|
+
* `VUETIWATCH_THEMES` and `VUETIWATCH_STOCK` are placeholders: the build
|
|
14
|
+
* expands the first into one class per registered theme and the second into
|
|
15
|
+
* the attribute value of every theme that declared `meta.stock`, so neither
|
|
16
|
+
* list can drift from the registry. A stock theme is excluded twice over —
|
|
17
|
+
* by class and by attribute — which is what makes `classic` a control
|
|
18
|
+
* rather than another theme.
|
|
15
19
|
* Importing this file therefore cannot affect an app that is not running a
|
|
16
20
|
* Vuetiwatch theme, and every value falls back to the stock Vuetify one, so
|
|
17
21
|
* a theme only pays for what it overrides.
|
|
18
22
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
23
|
+
* Weight is deliberate, and it runs one way: every rule here has to beat
|
|
24
|
+
* Vuetify and lose to everything else. It beats Vuetify for free — all but
|
|
25
|
+
* six of its rules ship inside `@layer vuetify-*`, and an unlayered author
|
|
26
|
+
* rule outranks a layered one whatever its specificity — so the scope below
|
|
27
|
+
* sits in `:where()` and costs nothing. What is left is the component
|
|
28
|
+
* selector alone, which a theme file (a theme class plus the same selector)
|
|
29
|
+
* and an app's own stylesheet both clear without a fight. Vuetify's utility
|
|
30
|
+
* classes are the exception in the other direction: they carry `!important`,
|
|
31
|
+
* which no specificity reaches, so the rules here step around them with
|
|
32
|
+
* `:not([class*='bg-'])` and its siblings instead.
|
|
21
33
|
*
|
|
22
34
|
* Authored with CSS nesting; the published file is flattened at build time.
|
|
23
35
|
*/
|
|
24
36
|
|
|
25
|
-
:
|
|
37
|
+
:where([data-vuetiwatch]:not(VUETIWATCH_STOCK), .v-theme--VUETIWATCH_THEMES) {
|
|
26
38
|
/* -------------------------------------------------------------- radius */
|
|
27
39
|
|
|
28
40
|
/**
|
|
@@ -35,7 +47,11 @@
|
|
|
35
47
|
* those children individually turns a joined group into separate pills
|
|
36
48
|
* and a full-height toolbar button into a rounded slab.
|
|
37
49
|
*/
|
|
38
|
-
& .v-btn.v-btn
|
|
50
|
+
& .v-btn--icon:not([class*='rounded-'], .v-btn-group *, .v-pagination *) {
|
|
51
|
+
border-radius: var(--v-vw-radius-icon-btn, 50%);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
& .v-btn:not(
|
|
39
55
|
.v-btn--icon,
|
|
40
56
|
.v-btn--rounded,
|
|
41
57
|
[class*='rounded-'],
|
|
@@ -46,6 +62,104 @@
|
|
|
46
62
|
border-radius: var(--v-vw-radius-btn, var(--v-vw-radius, 4px));
|
|
47
63
|
}
|
|
48
64
|
|
|
65
|
+
/**
|
|
66
|
+
* A list standing on its own is a panel and takes the panel corner. One
|
|
67
|
+
* inside a card, a drawer, a menu or another list is not: that surface
|
|
68
|
+
* owns the corner already, and rounding the inner box would clip its own
|
|
69
|
+
* rows for nothing. Vuetify ships `.v-list` at radius 0 with no edge at
|
|
70
|
+
* all, which is why a bare list was the one surface that stayed stock
|
|
71
|
+
* whatever theme was running.
|
|
72
|
+
*/
|
|
73
|
+
& :is(.v-list, .v-sheet, .v-banner, .v-table, .v-skeleton-loader):not(:is(.v-card, .v-overlay__content, .v-navigation-drawer, .v-expansion-panels, .v-list) *) {
|
|
74
|
+
border-radius: var(--v-vw-radius-lg, var(--v-vw-radius, 4px));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* And what that panel is drawn with. Fifteen themes had written this
|
|
79
|
+
* selector out in full — the same four components, the same five
|
|
80
|
+
* containers that own their children's edges — and each carried its own
|
|
81
|
+
* copy of a list that has had to grow twice. The selector belongs in one
|
|
82
|
+
* place; the treatment is a value, so it travels as one.
|
|
83
|
+
*
|
|
84
|
+
* Every fallback is `revert-layer`, which hands the property back to
|
|
85
|
+
* Vuetify's own layer, so a theme that says nothing here changes nothing.
|
|
86
|
+
* The radius is above rather than in this block because it comes from the
|
|
87
|
+
* shape scale every other surface uses, and a skeleton loader takes the
|
|
88
|
+
* corner without taking the edge.
|
|
89
|
+
*/
|
|
90
|
+
& :is(.v-list, .v-sheet, .v-banner, .v-table):not(:is(.v-card, .v-overlay__content, .v-navigation-drawer, .v-expansion-panels, .v-list) *) {
|
|
91
|
+
border: var(--v-vw-panel-border, revert-layer);
|
|
92
|
+
box-shadow: var(--v-vw-panel-shadow, revert-layer);
|
|
93
|
+
background-color: var(--v-vw-panel-fill, revert-layer);
|
|
94
|
+
background-image: var(--v-vw-panel-image, revert-layer);
|
|
95
|
+
backdrop-filter: var(--v-vw-panel-filter, none);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* `border` on a list or a sheet is the author asking for an edge, and the
|
|
100
|
+
* shorthand above would answer with Vuetify's hairline. The width stays
|
|
101
|
+
* the theme's — which is how a theme that draws no borders at all keeps
|
|
102
|
+
* its zero, and how `brutalist` keeps its three pixels.
|
|
103
|
+
*/
|
|
104
|
+
& :is(.v-list--border, .v-sheet--border):not(:is(.v-card, .v-overlay__content, .v-navigation-drawer, .v-expansion-panels, .v-list) *) {
|
|
105
|
+
border-width: var(--v-vw-border-width, thin);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* `.v-sheet` is Vuetify's surface primitive, so this one selector reaches
|
|
110
|
+
* the stepper and the pickers as well — components with enough layout of
|
|
111
|
+
* their own that no theme had thought to name them.
|
|
112
|
+
*/
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* A button group is one control, so the corner belongs to the group and
|
|
116
|
+
* not to the buttons inside it — which is why the rule above steps over
|
|
117
|
+
* `.v-btn-group *`. Without this the group kept Vuetify's 8px while every
|
|
118
|
+
* button in the theme was square.
|
|
119
|
+
*/
|
|
120
|
+
& :is(.v-btn-group, .v-btn-toggle):not([class*='rounded-']) {
|
|
121
|
+
border-radius: var(--v-vw-radius-btn, var(--v-vw-radius, 4px));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Vuetify's outlined card is transparent, so it shows the page through
|
|
126
|
+
* itself and so does everything nested in it — a list, a table, a tree.
|
|
127
|
+
* On the stock theme that is invisible, because its background and its
|
|
128
|
+
* surface are both white; on a theme with a tinted ground it means half
|
|
129
|
+
* the panels on a screen are panels and half are holes.
|
|
130
|
+
*
|
|
131
|
+
* Material 3 gives an outlined card the surface colour, and so does this:
|
|
132
|
+
* a card is a container, and a container that is not there cannot hold
|
|
133
|
+
* anything. The relief and glass themes, whose whole idea is that a
|
|
134
|
+
* surface is the ground, set the knob back to `transparent`.
|
|
135
|
+
*/
|
|
136
|
+
& .v-card--variant-outlined:not([class*='bg-']) {
|
|
137
|
+
background-color: var(--v-vw-outlined-fill, rgb(var(--v-theme-surface)));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/* A badge is a very small chip and rounds like one. */
|
|
141
|
+
& .v-badge__badge {
|
|
142
|
+
border-radius: var(--v-vw-radius-chip, 9999px);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Avatars and timeline dots are circles in Material and stay circles by
|
|
147
|
+
* default. They get their own knobs because a theme with no curve
|
|
148
|
+
* anywhere — `brutalist`, `neon` — was still drawing two of them.
|
|
149
|
+
*/
|
|
150
|
+
& .v-avatar:not([class*='rounded-']) {
|
|
151
|
+
border-radius: var(--v-vw-radius-avatar, 50%);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
& :is(.v-timeline-divider__dot, .v-timeline-divider__inner-dot) {
|
|
155
|
+
border-radius: var(--v-vw-radius-dot, 50%);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* The `rounded` prop is the pill; everything else follows the theme. */
|
|
159
|
+
& .v-progress-linear:not(.v-progress-linear--rounded, [class*='rounded-']) {
|
|
160
|
+
border-radius: var(--v-vw-radius, 0);
|
|
161
|
+
}
|
|
162
|
+
|
|
49
163
|
/**
|
|
50
164
|
* Vuetify's square-inset switch hardcodes 6px and 4px, so a theme with no
|
|
51
165
|
* corners at all still got a rounded toggle. Only this variant follows the
|
|
@@ -98,33 +212,24 @@
|
|
|
98
212
|
}
|
|
99
213
|
|
|
100
214
|
/* The group keeps the corners its children gave up. */
|
|
101
|
-
& .v-btn-group
|
|
215
|
+
& .v-btn-group:not([class*='rounded-']) {
|
|
102
216
|
border-radius: var(--v-vw-radius, 4px);
|
|
103
217
|
}
|
|
104
218
|
|
|
105
219
|
/**
|
|
106
|
-
* Pagination items are `icon` buttons
|
|
107
|
-
*
|
|
108
|
-
*
|
|
220
|
+
* Pagination items are `icon` buttons, but they read as a row of tiles
|
|
221
|
+
* rather than icons, so they follow the button radius. The rule above
|
|
222
|
+
* excludes them by name for that reason: two rules of equal weight
|
|
223
|
+
* claiming the same element would leave the outcome to source order,
|
|
224
|
+
* which is not something a stylesheet should have an opinion about.
|
|
109
225
|
*/
|
|
110
|
-
& .v-pagination .v-btn
|
|
226
|
+
& .v-pagination .v-btn {
|
|
111
227
|
border-radius: var(--v-vw-radius-btn, var(--v-vw-radius, 4px));
|
|
112
228
|
}
|
|
113
229
|
|
|
114
|
-
/**
|
|
115
|
-
* The same containers join their buttons into one shape, so a per-button
|
|
116
|
-
* shadow draws a seam down every join. Decoration belongs on the
|
|
117
|
-
* container — this out-specifies the theme layers that give `.v-btn` a
|
|
118
|
-
* relief, and a theme that wants a decorated group styles
|
|
119
|
-
* `.v-btn-group` itself.
|
|
120
|
-
*/
|
|
121
|
-
& :is(.v-btn-group, .v-toolbar-items) .v-btn.v-btn {
|
|
122
|
-
box-shadow: none;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
230
|
& :is(
|
|
126
|
-
.v-card
|
|
127
|
-
.v-table
|
|
231
|
+
.v-card:not([class*='rounded-']),
|
|
232
|
+
.v-table
|
|
128
233
|
) {
|
|
129
234
|
border-radius: var(--v-vw-radius-lg, var(--v-vw-radius, 4px));
|
|
130
235
|
}
|
|
@@ -135,14 +240,14 @@
|
|
|
135
240
|
* to unlayered ones at any specificity, so styling `.v-expansion-panel`
|
|
136
241
|
* here would flatten that logic and round every panel in the stack.
|
|
137
242
|
*/
|
|
138
|
-
& .v-expansion-panels
|
|
243
|
+
& .v-expansion-panels {
|
|
139
244
|
border-radius: var(--v-vw-radius-lg, var(--v-vw-radius, 4px));
|
|
140
245
|
}
|
|
141
246
|
|
|
142
247
|
& :is(
|
|
143
|
-
.v-alert
|
|
144
|
-
.v-field
|
|
145
|
-
.v-list-item
|
|
248
|
+
.v-alert:not([class*='rounded-']),
|
|
249
|
+
.v-field:not([class*='rounded-']),
|
|
250
|
+
.v-list-item:not([class*='rounded-']),
|
|
146
251
|
.v-snackbar__wrapper,
|
|
147
252
|
.v-menu > .v-overlay__content,
|
|
148
253
|
.v-tooltip > .v-overlay__content,
|
|
@@ -152,11 +257,11 @@
|
|
|
152
257
|
}
|
|
153
258
|
|
|
154
259
|
/* Filled and underlined fields only round their top corners. */
|
|
155
|
-
& .v-field
|
|
260
|
+
& .v-field:is(.v-field--variant-filled, .v-field--variant-underlined):not([class*='rounded-']) {
|
|
156
261
|
border-radius: var(--v-vw-radius, 4px) var(--v-vw-radius, 4px) 0 0;
|
|
157
262
|
}
|
|
158
263
|
|
|
159
|
-
& .v-chip
|
|
264
|
+
& .v-chip:not([class*='rounded-']) {
|
|
160
265
|
border-radius: var(--v-vw-radius-chip, 9999px);
|
|
161
266
|
}
|
|
162
267
|
|
|
@@ -166,7 +271,7 @@
|
|
|
166
271
|
* most themes even when nothing else is — only the square-cornered ones
|
|
167
272
|
* set it.
|
|
168
273
|
*/
|
|
169
|
-
& .v-slider-track
|
|
274
|
+
& .v-slider-track {
|
|
170
275
|
border-radius: var(--v-vw-radius, 4px);
|
|
171
276
|
}
|
|
172
277
|
|
|
@@ -211,17 +316,54 @@
|
|
|
211
316
|
background-color: rgb(var(--v-theme-surface));
|
|
212
317
|
}
|
|
213
318
|
|
|
319
|
+
/* --------------------------------------------------- nested surfaces */
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* A card is the surface; what it wraps is content. Vuetify paints a list
|
|
323
|
+
* or a table with `theme-surface` of its own, which matches only while the
|
|
324
|
+
* card is painted the same colour — so under a theme that defaults cards
|
|
325
|
+
* to outlined or tonal, or gives them a treatment of their own, the inner
|
|
326
|
+
* block reads as a pale slab that stops where its content does instead of
|
|
327
|
+
* filling the card.
|
|
328
|
+
*
|
|
329
|
+
* Direct children only, so a list inside `v-card-text` or a nested card
|
|
330
|
+
* keeps whatever it was given, and an explicit `bg-` still wins.
|
|
331
|
+
*/
|
|
332
|
+
& .v-card > :is(.v-list, .v-table):not([class*='bg-']) {
|
|
333
|
+
background: transparent;
|
|
334
|
+
}
|
|
335
|
+
|
|
214
336
|
/* -------------------------------------------------------- border width */
|
|
215
337
|
|
|
216
338
|
& :is(
|
|
217
339
|
.v-btn--variant-outlined,
|
|
218
340
|
.v-card--variant-outlined,
|
|
219
341
|
.v-alert--variant-outlined,
|
|
220
|
-
.v-chip--variant-outlined
|
|
342
|
+
.v-chip--variant-outlined,
|
|
343
|
+
.v-list--border,
|
|
344
|
+
.v-sheet--border
|
|
221
345
|
) {
|
|
222
346
|
border-width: var(--v-vw-border-width, thin);
|
|
223
347
|
}
|
|
224
348
|
|
|
349
|
+
/**
|
|
350
|
+
* Vuetify draws an outlined card with `border: thin solid currentColor`,
|
|
351
|
+
* so the line around a panel is the ink of the text inside it — near
|
|
352
|
+
* black at high emphasis, measured. Every system this package is held
|
|
353
|
+
* against draws that line far lighter: Ant Design separates containers
|
|
354
|
+
* with #f0f0f0 and saves #d9d9d9 for controls.
|
|
355
|
+
*
|
|
356
|
+
* The line becomes the theme's own border colour instead. A theme that
|
|
357
|
+
* means its outline to be heavy — `brutalist` and its 3px rule — says so
|
|
358
|
+
* through the token rather than inheriting it by accident.
|
|
359
|
+
*/
|
|
360
|
+
& .v-card--variant-outlined:not([class*='border-']) {
|
|
361
|
+
border-color: rgba(
|
|
362
|
+
var(--v-border-color),
|
|
363
|
+
var(--v-vw-outline-opacity, var(--v-border-opacity))
|
|
364
|
+
);
|
|
365
|
+
}
|
|
366
|
+
|
|
225
367
|
/**
|
|
226
368
|
* Vuetify already funnels every outline segment through one property, so
|
|
227
369
|
* the field only needs that one set. Specificity matters here: this must
|
|
@@ -230,14 +372,29 @@
|
|
|
230
372
|
*/
|
|
231
373
|
& .v-field__outline {
|
|
232
374
|
--v-field-border-width: var(--v-vw-border-width, 1px);
|
|
375
|
+
/**
|
|
376
|
+
* Vuetify draws a resting field outline at 0.38 of the ink, which on a
|
|
377
|
+
* white ground reads around 2.3:1 — under the 3:1 WCAG asks for the
|
|
378
|
+
* boundary of a control you are meant to find and click. The value is
|
|
379
|
+
* declared on this element rather than inherited, so a theme cannot
|
|
380
|
+
* reach it through `variables` alone; the knob is here instead, and it
|
|
381
|
+
* defaults to Vuetify's own number so nothing moves unasked.
|
|
382
|
+
*/
|
|
383
|
+
--v-field-border-opacity: var(--v-vw-field-border-opacity, 0.38);
|
|
233
384
|
}
|
|
234
385
|
|
|
235
386
|
/* ---------------------------------------------------- button typography */
|
|
236
387
|
|
|
237
|
-
|
|
388
|
+
/**
|
|
389
|
+
* The fallbacks are Vuetify 4's own values, not Material's older ones: v4
|
|
390
|
+
* dropped the uppercase button and the wide tracking that came with it,
|
|
391
|
+
* and a fallback that reintroduced them would be this file changing a
|
|
392
|
+
* theme that never asked it to.
|
|
393
|
+
*/
|
|
394
|
+
& .v-btn {
|
|
238
395
|
font-weight: var(--v-vw-btn-weight, 500);
|
|
239
|
-
letter-spacing: var(--v-vw-btn-tracking, 0.
|
|
240
|
-
text-transform: var(--v-vw-btn-transform,
|
|
396
|
+
letter-spacing: var(--v-vw-btn-tracking, 0.0071428571em);
|
|
397
|
+
text-transform: var(--v-vw-btn-transform, none);
|
|
241
398
|
}
|
|
242
399
|
|
|
243
400
|
/* ------------------------------------------------- shared theme surfaces */
|
|
@@ -255,10 +412,231 @@
|
|
|
255
412
|
box-shadow: var(--v-vw-overlay-shadow, revert-layer);
|
|
256
413
|
}
|
|
257
414
|
|
|
415
|
+
/**
|
|
416
|
+
* A relief theme paints outside the shape it lifts, and a chip group is a
|
|
417
|
+
* scroller: it clips to its content box, so the glow around the chips
|
|
418
|
+
* comes out sheared along a straight edge with a corner where the row
|
|
419
|
+
* ends. The room has to be inside the clip to do any good, so the themes
|
|
420
|
+
* that lift their controls say how much the relief needs and the scroller
|
|
421
|
+
* carries it as padding.
|
|
422
|
+
*/
|
|
423
|
+
& .v-chip-group .v-slide-group__content {
|
|
424
|
+
padding: var(--v-vw-relief-inset, 0);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* The timeline's connecting line is structure, not decoration — it is the
|
|
429
|
+
* only thing saying the items are one sequence, so it cannot be left to
|
|
430
|
+
* `--v-border-opacity` alone. The two relief themes hold that variable at
|
|
431
|
+
* 0.001 so no stray rule can draw an outline anywhere, and the line went
|
|
432
|
+
* with it; they raise this one instead and get the line back without a
|
|
433
|
+
* single border returning.
|
|
434
|
+
*/
|
|
435
|
+
/**
|
|
436
|
+
* Vuetify paints a skeleton's bones with `--v-border-opacity`, which ties
|
|
437
|
+
* "how visible is a loading placeholder" to "how heavy are this theme's
|
|
438
|
+
* borders". A theme that draws no borders at all — `clay` and `morph` hold
|
|
439
|
+
* the value at 0.001 so no stray outline can appear — loses its loading
|
|
440
|
+
* state entirely — while a theme whose borders are solid black paints the
|
|
441
|
+
* bones solid black, which is a filled box rather than a placeholder.
|
|
442
|
+
* Clamping both ends keeps the loading state legible in either direction
|
|
443
|
+
* without touching a single border, and a theme can still overrule it.
|
|
444
|
+
*
|
|
445
|
+
* The list is Vuetify's own: `__bone` is the layout class every piece
|
|
446
|
+
* carries, containers included, so painting that one fills the whole
|
|
447
|
+
* block instead of drawing bars on it.
|
|
448
|
+
*/
|
|
449
|
+
& :is(
|
|
450
|
+
.v-skeleton-loader__avatar,
|
|
451
|
+
.v-skeleton-loader__button,
|
|
452
|
+
.v-skeleton-loader__chip,
|
|
453
|
+
.v-skeleton-loader__divider,
|
|
454
|
+
.v-skeleton-loader__heading,
|
|
455
|
+
.v-skeleton-loader__image,
|
|
456
|
+
.v-skeleton-loader__ossein,
|
|
457
|
+
.v-skeleton-loader__text
|
|
458
|
+
) {
|
|
459
|
+
background: rgba(
|
|
460
|
+
var(--v-theme-on-surface),
|
|
461
|
+
var(--v-vw-skeleton-opacity, clamp(0.08, var(--v-border-opacity), 0.2))
|
|
462
|
+
);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* The pieces carry hardcoded pill corners — 12px on a heading, 16 on a
|
|
467
|
+
* chip, 6 on a line of text — so a theme with square corners loads
|
|
468
|
+
* rounded bars and a theme with generous ones loads tight bars. A
|
|
469
|
+
* placeholder should be the shape of the thing it stands in for.
|
|
470
|
+
*/
|
|
471
|
+
& :is(
|
|
472
|
+
.v-skeleton-loader__button,
|
|
473
|
+
.v-skeleton-loader__chip,
|
|
474
|
+
.v-skeleton-loader__heading,
|
|
475
|
+
.v-skeleton-loader__image,
|
|
476
|
+
.v-skeleton-loader__ossein,
|
|
477
|
+
.v-skeleton-loader__text
|
|
478
|
+
) {
|
|
479
|
+
border-radius: var(--v-vw-radius, 4px);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
& .v-skeleton-loader__avatar {
|
|
483
|
+
border-radius: var(--v-vw-radius-avatar, 50%);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* The month and year controls are a fixed-width row inside a fixed-width
|
|
488
|
+
* card, so a theme that widens its buttons — wide tracking, a larger
|
|
489
|
+
* size — or narrows the picker pushes them past the edge. Wrapping is the
|
|
490
|
+
* one outcome that neither clips them nor forces a scrollbar.
|
|
491
|
+
*/
|
|
492
|
+
/**
|
|
493
|
+
* The month and year buttons are navigation chrome inside a fixed-width
|
|
494
|
+
* card, not the theme's own buttons: a theme that sets wide tracking or
|
|
495
|
+
* capitals for its buttons — `lux` runs 0.16em — pushes them onto a
|
|
496
|
+
* second row, and a picker with two rows of navigation reads as broken.
|
|
497
|
+
* The type here follows the picker, not the theme's button voice.
|
|
498
|
+
*/
|
|
499
|
+
& .v-date-picker-controls .v-btn {
|
|
500
|
+
letter-spacing: normal;
|
|
501
|
+
text-transform: none;
|
|
502
|
+
/* And not the theme's button size either: `candy` ships `size="large"`,
|
|
503
|
+
whose padding and minimum width push the pair past the card just as
|
|
504
|
+
tracking does. The row is chrome, so it keeps the picker's own size. */
|
|
505
|
+
font-size: 0.875rem;
|
|
506
|
+
min-width: 0;
|
|
507
|
+
padding-inline: 8px;
|
|
508
|
+
--v-btn-height: 32px;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
& .v-date-picker-controls {
|
|
512
|
+
flex-wrap: wrap;
|
|
513
|
+
row-gap: 4px;
|
|
514
|
+
/* Vuetify pins the row at 56px, so a wrapped second line lands on the
|
|
515
|
+
weekday letters underneath. The height has to follow the content the
|
|
516
|
+
moment wrapping is allowed at all. */
|
|
517
|
+
height: auto;
|
|
518
|
+
min-height: var(--v-date-picker-controls-height, 56px);
|
|
519
|
+
padding-inline: 8px;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
& :is(.v-timeline-divider__before, .v-timeline-divider__after) {
|
|
523
|
+
background: var(
|
|
524
|
+
--v-vw-timeline-line,
|
|
525
|
+
rgba(var(--v-border-color), var(--v-vw-timeline-line-opacity, var(--v-border-opacity)))
|
|
526
|
+
);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* The whole background is a knob, not just its opacity, because a line is
|
|
531
|
+
* the one place a theme can say something with almost nothing: a
|
|
532
|
+
* repeating gradient makes it dashed, `--v-vw-gradient` makes it
|
|
533
|
+
* iridescent, a flat colour makes it a rule.
|
|
534
|
+
*
|
|
535
|
+
* The thickness is set on the segment rather than through Vuetify's
|
|
536
|
+
* `--v-timeline-line-thickness`, which the component writes inline from
|
|
537
|
+
* its own prop and would win.
|
|
538
|
+
*/
|
|
539
|
+
&.v-application .v-timeline--vertical :is(.v-timeline-divider__before, .v-timeline-divider__after) {
|
|
540
|
+
width: var(--v-vw-timeline-line-width, var(--v-timeline-line-thickness));
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
&.v-application .v-timeline--horizontal :is(.v-timeline-divider__before, .v-timeline-divider__after) {
|
|
544
|
+
height: var(--v-vw-timeline-line-width, var(--v-timeline-line-thickness));
|
|
545
|
+
}
|
|
546
|
+
|
|
258
547
|
& .v-tab__slider {
|
|
259
548
|
height: var(--v-vw-tab-slider-height, 2px);
|
|
260
549
|
}
|
|
261
550
|
|
|
551
|
+
/**
|
|
552
|
+
* A tab is a label, not a button. Vuetify builds one out of the other, so
|
|
553
|
+
* a tab inherits whatever the button type is — which in this build is the
|
|
554
|
+
* body size, since the reset layer's `font-size: inherit` on `button`
|
|
555
|
+
* outranks the size class that meant to set 0.875rem. The label ends up a
|
|
556
|
+
* step larger than the text it introduces.
|
|
557
|
+
*
|
|
558
|
+
* Material's tab label is 0.875rem and so is the button size Vuetify
|
|
559
|
+
* intends, so the value is the same either way and the tab no longer
|
|
560
|
+
* depends on which order the two layers happened to load in.
|
|
561
|
+
*/
|
|
562
|
+
& .v-tab {
|
|
563
|
+
font-size: var(--v-vw-tab-size, 0.875rem);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/* -------------------------------------------------------- avatar type */
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Vuetify sizes the circle and leaves the letters inside it at whatever
|
|
570
|
+
* the surrounding text was: `RM` in a 28px avatar next to a button label
|
|
571
|
+
* comes out 16px, more than half the diameter. Material's own ratio is
|
|
572
|
+
* 0.4 — 16px inside the 40px default — so this changes nothing at the
|
|
573
|
+
* default size and only corrects the ones a size prop moved.
|
|
574
|
+
*
|
|
575
|
+
* Only the keyword sizes publish their height as a variable; a numeric
|
|
576
|
+
* `size` is an inline style no rule can read, and the guard on the class
|
|
577
|
+
* keeps the declaration from resolving against a missing variable there.
|
|
578
|
+
* Images and icons carry their own dimensions and are left alone.
|
|
579
|
+
*/
|
|
580
|
+
& .v-avatar[class*='--size-']:not(:has(img, .v-img, .v-icon)) {
|
|
581
|
+
font-size: calc(var(--v-avatar-height) * var(--v-vw-avatar-ratio, 0.4));
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/* ------------------------------------------------------------ stepper */
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* The stepper is a panel, and Vuetify raises it twice: an elevation on
|
|
588
|
+
* the sheet, and a second one under the header band. That is Material's
|
|
589
|
+
* way of separating a scrolling window from its chrome, and no theme here
|
|
590
|
+
* separates anything that way — the flat ones had already dropped the
|
|
591
|
+
* sheet's shadow through their `.v-sheet` rule and were left with a band
|
|
592
|
+
* floating inside a panel that casts nothing.
|
|
593
|
+
*
|
|
594
|
+
* So the panel takes the theme's own edge and the header separates with
|
|
595
|
+
* the theme's own hairline — through the panel tokens above, so a theme
|
|
596
|
+
* that decorates its panels decorates its stepper by saying nothing
|
|
597
|
+
* twice: brutalist's second shape and clay's relief arrive here on their
|
|
598
|
+
* own. What is left is the fallback for a theme with no opinion, which is
|
|
599
|
+
* a hairline and no shadow.
|
|
600
|
+
*/
|
|
601
|
+
& .v-stepper.v-sheet:not(.v-stepper--flat, [class*='elevation-']) {
|
|
602
|
+
box-shadow: var(--v-vw-panel-shadow, none);
|
|
603
|
+
border: var(--v-vw-panel-border, var(--v-vw-border-width, thin) solid
|
|
604
|
+
rgba(var(--v-border-color), var(--v-vw-outline-opacity, var(--v-border-opacity))));
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
& .v-stepper .v-stepper-header {
|
|
608
|
+
box-shadow: none;
|
|
609
|
+
border-block-end: var(--v-vw-border-width, thin) solid
|
|
610
|
+
rgba(var(--v-border-color), var(--v-vw-outline-opacity, var(--v-border-opacity)));
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
* And the steps themselves come down a size. Vuetify pads each one by
|
|
615
|
+
* 1.5rem on every side, which makes a three-word progress bar 72px tall —
|
|
616
|
+
* taller than the app bar above it — and margins the window by as much
|
|
617
|
+
* again. This is the one component where the stock metrics are set for a
|
|
618
|
+
* full-page wizard and every other use is a form inside a panel.
|
|
619
|
+
*/
|
|
620
|
+
& :where(.v-stepper-item) {
|
|
621
|
+
padding: 1rem 1.25rem;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
& :where(.v-stepper-window) {
|
|
625
|
+
margin: 1.25rem;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
& :where(.v-stepper .v-stepper-actions) {
|
|
629
|
+
padding: 0 1.25rem 1rem;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* Figures line up in a column only when every digit is the same width,
|
|
634
|
+
* which matters on any screen that is mostly numbers and nowhere else.
|
|
635
|
+
*/
|
|
636
|
+
& :is(.v-table, .v-data-table, .v-pagination) {
|
|
637
|
+
font-variant-numeric: var(--v-vw-numeric, normal);
|
|
638
|
+
}
|
|
639
|
+
|
|
262
640
|
& :is(.v-table thead th, .v-data-table__th) {
|
|
263
641
|
font-weight: var(--v-vw-th-weight, revert-layer);
|
|
264
642
|
letter-spacing: var(--v-vw-th-tracking, revert-layer);
|
|
@@ -274,6 +652,70 @@
|
|
|
274
652
|
border-inline-start: var(--v-vw-list-bar, 0) solid var(--v-vw-list-bar-color, currentColor);
|
|
275
653
|
}
|
|
276
654
|
|
|
655
|
+
/* -------------------------------------------------------------- motion */
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* Movement is the fourth axis a theme travels on, after colour, shape and
|
|
659
|
+
* type — `brutalist` snapping in two steps and `lux` easing over a
|
|
660
|
+
* quarter-second are as different as their palettes, and until now every
|
|
661
|
+
* theme moved like stock Vuetify unless it hand-rolled a rule.
|
|
662
|
+
*
|
|
663
|
+
* Themes state a character in four values and core spends them on the
|
|
664
|
+
* same interactions everywhere. Every selector here is wrapped in
|
|
665
|
+
* `:where()`, so its specificity is the theme class alone and any theme
|
|
666
|
+
* that wants its own move — brutalist sliding into its shadow, candy
|
|
667
|
+
* squashing — overrides this without a fight.
|
|
668
|
+
*
|
|
669
|
+
* Only `transform` is animated: it runs on the compositor, so none of
|
|
670
|
+
* this can cost a layout pass however deep the tree.
|
|
671
|
+
*/
|
|
672
|
+
& :where(.v-btn, .v-chip, .v-list-item, .v-card, .v-tab) {
|
|
673
|
+
transition: transform var(--v-vw-motion-duration, 160ms) var(--v-vw-motion-ease, cubic-bezier(0.2, 0, 0.2, 1));
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
& :where(.v-btn, .v-chip--link, .v-list-item--link):not(.v-btn--disabled):active {
|
|
677
|
+
transform:
|
|
678
|
+
translateY(var(--v-vw-press-shift, 0px))
|
|
679
|
+
scale(var(--v-vw-press-scale, 0.98));
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
& :where(.v-card--link):hover {
|
|
683
|
+
transform: translateY(calc(-1 * var(--v-vw-hover-lift, 0px)));
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
/**
|
|
687
|
+
* The pop: a control that has just been switched on overshoots its own
|
|
688
|
+
* size and settles back, which is the whole reason a like button feels
|
|
689
|
+
* like anything at all.
|
|
690
|
+
*
|
|
691
|
+
* It rides on the state classes Vuetify already toggles, so it costs no
|
|
692
|
+
* script and no markup. The tradeoff is that a control rendered already
|
|
693
|
+
* checked pops once on mount — a form arriving with its defaults ticking
|
|
694
|
+
* in, which reads as intent rather than as a glitch. A theme that would
|
|
695
|
+
* rather not can set `vw-pop-duration: 0ms`.
|
|
696
|
+
*/
|
|
697
|
+
& :where(
|
|
698
|
+
.v-selection-control--dirty .v-selection-control__input > .v-icon,
|
|
699
|
+
.v-btn--active > .v-btn__content > .v-icon,
|
|
700
|
+
.v-rating__item--full .v-icon
|
|
701
|
+
) {
|
|
702
|
+
animation: vw-pop var(--v-vw-pop-duration, 220ms) var(--v-vw-motion-ease, cubic-bezier(0.2, 0, 0.2, 1));
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
/* --------------------------------------------------------------- focus */
|
|
706
|
+
|
|
707
|
+
/**
|
|
708
|
+
* Vuetify marks focus with a wash of `primary` at low opacity, which
|
|
709
|
+
* disappears on a dark surface and on any element already carrying a
|
|
710
|
+
* colour. A ring does not: it is drawn outside the shape, so it survives
|
|
711
|
+
* every background, and it is the one piece of the interface that has to
|
|
712
|
+
* work for someone who never touches a mouse.
|
|
713
|
+
*/
|
|
714
|
+
& :where(.v-btn, .v-tab, .v-chip, .v-list-item, .v-selection-control__input):focus-visible {
|
|
715
|
+
outline: var(--v-vw-focus-ring, 2px solid rgb(var(--v-theme-primary)));
|
|
716
|
+
outline-offset: var(--v-vw-focus-offset, 2px);
|
|
717
|
+
}
|
|
718
|
+
|
|
277
719
|
/* ------------------------------------------------------------ headings */
|
|
278
720
|
|
|
279
721
|
/**
|
|
@@ -309,3 +751,89 @@
|
|
|
309
751
|
text-underline-offset: 0.15em;
|
|
310
752
|
}
|
|
311
753
|
}
|
|
754
|
+
|
|
755
|
+
@keyframes vw-pop {
|
|
756
|
+
0% {
|
|
757
|
+
transform: scale(1);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
45% {
|
|
761
|
+
transform: scale(var(--v-vw-pop-scale, 1.18));
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
100% {
|
|
765
|
+
transform: scale(1);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
/**
|
|
770
|
+
* Corrections, and the one place weight runs the other way.
|
|
771
|
+
*
|
|
772
|
+
* Everything above is a default a theme is free to overrule. The rules
|
|
773
|
+
* below are the opposite: they exist because a theme's own rule does damage
|
|
774
|
+
* in a context it never considered, so they keep the scope's weight and
|
|
775
|
+
* outrank it deliberately. Anything added here needs that justification —
|
|
776
|
+
* otherwise it belongs in the weightless block above.
|
|
777
|
+
*/
|
|
778
|
+
:is([data-vuetiwatch]:not(VUETIWATCH_STOCK), .v-theme--VUETIWATCH_THEMES) {
|
|
779
|
+
/**
|
|
780
|
+
* A button group and a toolbar join their buttons into one shape, so a
|
|
781
|
+
* per-button shadow draws a seam down every join — visible on any theme
|
|
782
|
+
* that gives `.v-btn` a relief or a glow. Decoration belongs on the
|
|
783
|
+
* container, and a theme that wants a decorated group styles
|
|
784
|
+
* `.v-btn-group` itself.
|
|
785
|
+
*/
|
|
786
|
+
& :is(.v-btn-group, .v-toolbar-items) .v-btn.v-btn {
|
|
787
|
+
box-shadow: none;
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
/**
|
|
792
|
+
* One switch for every theme at once: the tokens themselves go to zero, so
|
|
793
|
+
* anything driven by them stops moving — including a theme built with
|
|
794
|
+
* `defineTheme()` that never wrote a media query of its own.
|
|
795
|
+
*/
|
|
796
|
+
@media (prefers-reduced-motion: reduce) {
|
|
797
|
+
:where([data-vuetiwatch]:not(VUETIWATCH_STOCK), .v-theme--VUETIWATCH_THEMES) {
|
|
798
|
+
--v-vw-motion-duration: 1ms;
|
|
799
|
+
--v-vw-pop-duration: 1ms;
|
|
800
|
+
--v-vw-press-scale: 1;
|
|
801
|
+
--v-vw-press-shift: 0px;
|
|
802
|
+
--v-vw-hover-lift: 0px;
|
|
803
|
+
--v-vw-theme-transition: 0ms;
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
/**
|
|
808
|
+
* Theme switching, as a transition rather than a jump.
|
|
809
|
+
*
|
|
810
|
+
* `createVuetiwatch()` mirrors the active theme onto `<html>`, which is the
|
|
811
|
+
* same element the view-transition pseudo-elements hang off — so these
|
|
812
|
+
* rules reach exactly the documents running a Vuetiwatch theme and nothing
|
|
813
|
+
* else. The plugin writes the click coordinates into `--vw-origin-*` before
|
|
814
|
+
* it starts the transition, so the new theme opens from the switch the user
|
|
815
|
+
* actually pressed; with no event to read, it opens from the centre.
|
|
816
|
+
*
|
|
817
|
+
* The old snapshot is held still on purpose. Cross-fading both halves turns
|
|
818
|
+
* two legible screens into one muddy one, while wiping the new theme over a
|
|
819
|
+
* frozen old one keeps every edge crisp for the whole animation.
|
|
820
|
+
*/
|
|
821
|
+
@keyframes vw-theme-wipe {
|
|
822
|
+
from {
|
|
823
|
+
clip-path: circle(0% at var(--vw-origin-x, 50%) var(--vw-origin-y, 50%));
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
to {
|
|
827
|
+
clip-path: circle(150% at var(--vw-origin-x, 50%) var(--vw-origin-y, 50%));
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
html[data-vuetiwatch]::view-transition-old(root) {
|
|
832
|
+
animation: none;
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
html[data-vuetiwatch]::view-transition-new(root) {
|
|
836
|
+
animation: vw-theme-wipe
|
|
837
|
+
var(--v-vw-theme-transition, 420ms)
|
|
838
|
+
var(--v-vw-motion-ease, cubic-bezier(0.2, 0, 0.2, 1));
|
|
839
|
+
}
|