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.
Files changed (164) hide show
  1. package/README.md +200 -17
  2. package/dist/index.d.ts +4 -4
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +2 -2
  5. package/dist/index.js.map +1 -1
  6. package/dist/plugin.d.ts +77 -7
  7. package/dist/plugin.d.ts.map +1 -1
  8. package/dist/plugin.js +104 -15
  9. package/dist/plugin.js.map +1 -1
  10. package/dist/registry.d.ts +1 -1
  11. package/dist/registry.d.ts.map +1 -1
  12. package/dist/registry.js +6 -1
  13. package/dist/registry.js.map +1 -1
  14. package/dist/styles/atlas.css +99 -0
  15. package/dist/styles/atlas.min.css +1 -0
  16. package/dist/styles/atlasDark.css +99 -0
  17. package/dist/styles/atlasDark.min.css +1 -0
  18. package/dist/styles/atlasSepia.css +99 -0
  19. package/dist/styles/atlasSepia.min.css +1 -0
  20. package/dist/styles/aurora.css +97 -4
  21. package/dist/styles/aurora.min.css +1 -1
  22. package/dist/styles/brutalist.css +5 -0
  23. package/dist/styles/brutalist.min.css +1 -1
  24. package/dist/styles/calm.css +0 -4
  25. package/dist/styles/calm.min.css +1 -1
  26. package/dist/styles/candy.css +71 -0
  27. package/dist/styles/candy.min.css +1 -0
  28. package/dist/styles/clay.css +13 -0
  29. package/dist/styles/clay.min.css +1 -1
  30. package/dist/styles/core.css +239 -36
  31. package/dist/styles/core.min.css +1 -1
  32. package/dist/styles/graphite.css +29 -0
  33. package/dist/styles/graphite.min.css +1 -0
  34. package/dist/styles/morph.css +12 -0
  35. package/dist/styles/morph.min.css +1 -1
  36. package/dist/styles/neon.css +8 -0
  37. package/dist/styles/neon.min.css +1 -1
  38. package/dist/styles/sketchy.css +4 -0
  39. package/dist/styles/sketchy.min.css +1 -1
  40. package/dist/styles/soft.css +1 -12
  41. package/dist/styles/soft.min.css +1 -1
  42. package/dist/styles.css +577 -52
  43. package/dist/styles.min.css +1 -1
  44. package/dist/themes/atlas.d.ts +38 -0
  45. package/dist/themes/atlas.d.ts.map +1 -0
  46. package/dist/themes/atlas.js +203 -0
  47. package/dist/themes/atlas.js.map +1 -0
  48. package/dist/themes/atlasDark.d.ts +8 -0
  49. package/dist/themes/atlasDark.d.ts.map +1 -0
  50. package/dist/themes/atlasDark.js +64 -0
  51. package/dist/themes/atlasDark.js.map +1 -0
  52. package/dist/themes/atlasSepia.d.ts +11 -0
  53. package/dist/themes/atlasSepia.d.ts.map +1 -0
  54. package/dist/themes/atlasSepia.js +60 -0
  55. package/dist/themes/atlasSepia.js.map +1 -0
  56. package/dist/themes/aurora.d.ts.map +1 -1
  57. package/dist/themes/aurora.js +27 -2
  58. package/dist/themes/aurora.js.map +1 -1
  59. package/dist/themes/brutalist.d.ts.map +1 -1
  60. package/dist/themes/brutalist.js +26 -0
  61. package/dist/themes/brutalist.js.map +1 -1
  62. package/dist/themes/calm.d.ts.map +1 -1
  63. package/dist/themes/calm.js +22 -2
  64. package/dist/themes/calm.js.map +1 -1
  65. package/dist/themes/candy.d.ts +20 -0
  66. package/dist/themes/candy.d.ts.map +1 -0
  67. package/dist/themes/candy.js +142 -0
  68. package/dist/themes/candy.js.map +1 -0
  69. package/dist/themes/classic.d.ts.map +1 -1
  70. package/dist/themes/classic.js +2 -0
  71. package/dist/themes/classic.js.map +1 -1
  72. package/dist/themes/clay.d.ts.map +1 -1
  73. package/dist/themes/clay.js +22 -0
  74. package/dist/themes/clay.js.map +1 -1
  75. package/dist/themes/darkGlass.d.ts.map +1 -1
  76. package/dist/themes/darkGlass.js +21 -0
  77. package/dist/themes/darkGlass.js.map +1 -1
  78. package/dist/themes/graphite.d.ts +13 -0
  79. package/dist/themes/graphite.d.ts.map +1 -0
  80. package/dist/themes/graphite.js +147 -0
  81. package/dist/themes/graphite.js.map +1 -0
  82. package/dist/themes/index.d.ts +5 -0
  83. package/dist/themes/index.d.ts.map +1 -1
  84. package/dist/themes/index.js +5 -0
  85. package/dist/themes/index.js.map +1 -1
  86. package/dist/themes/liquidGlass.d.ts.map +1 -1
  87. package/dist/themes/liquidGlass.js +27 -3
  88. package/dist/themes/liquidGlass.js.map +1 -1
  89. package/dist/themes/lux.d.ts.map +1 -1
  90. package/dist/themes/lux.js +21 -2
  91. package/dist/themes/lux.js.map +1 -1
  92. package/dist/themes/morph.d.ts.map +1 -1
  93. package/dist/themes/morph.js +23 -3
  94. package/dist/themes/morph.js.map +1 -1
  95. package/dist/themes/neon.d.ts.map +1 -1
  96. package/dist/themes/neon.js +22 -0
  97. package/dist/themes/neon.js.map +1 -1
  98. package/dist/themes/paper.d.ts.map +1 -1
  99. package/dist/themes/paper.js +16 -0
  100. package/dist/themes/paper.js.map +1 -1
  101. package/dist/themes/sketchy.d.ts.map +1 -1
  102. package/dist/themes/sketchy.js +17 -0
  103. package/dist/themes/sketchy.js.map +1 -1
  104. package/dist/themes/slate.d.ts.map +1 -1
  105. package/dist/themes/slate.js +22 -1
  106. package/dist/themes/slate.js.map +1 -1
  107. package/dist/themes/soft.d.ts.map +1 -1
  108. package/dist/themes/soft.js +21 -2
  109. package/dist/themes/soft.js.map +1 -1
  110. package/dist/types.d.ts +40 -0
  111. package/dist/types.d.ts.map +1 -1
  112. package/dist/util/defaults.d.ts.map +1 -1
  113. package/dist/util/defaults.js +11 -1
  114. package/dist/util/defaults.js.map +1 -1
  115. package/dist/util/defineTheme.d.ts.map +1 -1
  116. package/dist/util/defineTheme.js +11 -5
  117. package/dist/util/defineTheme.js.map +1 -1
  118. package/package.json +2 -2
  119. package/src/index.ts +8 -2
  120. package/src/plugin.ts +214 -21
  121. package/src/registry.ts +10 -0
  122. package/src/styles/core.css +563 -35
  123. package/src/styles/index.css +4 -0
  124. package/src/styles/themes/_atlas.css +194 -0
  125. package/src/styles/themes/atlas.css +2 -0
  126. package/src/styles/themes/atlasDark.css +2 -0
  127. package/src/styles/themes/atlasSepia.css +2 -0
  128. package/src/styles/themes/aurora.css +151 -7
  129. package/src/styles/themes/brutalist.css +5 -3
  130. package/src/styles/themes/calm.css +0 -7
  131. package/src/styles/themes/candy.css +113 -0
  132. package/src/styles/themes/clay.css +24 -0
  133. package/src/styles/themes/graphite.css +63 -0
  134. package/src/styles/themes/liquidGlass.css +0 -2
  135. package/src/styles/themes/lux.css +0 -4
  136. package/src/styles/themes/morph.css +22 -0
  137. package/src/styles/themes/neon.css +8 -3
  138. package/src/styles/themes/paper.css +0 -2
  139. package/src/styles/themes/sketchy.css +9 -0
  140. package/src/styles/themes/slate.css +0 -4
  141. package/src/styles/themes/soft.css +1 -12
  142. package/src/themes/atlas.ts +211 -0
  143. package/src/themes/atlasDark.ts +64 -0
  144. package/src/themes/atlasSepia.ts +60 -0
  145. package/src/themes/aurora.ts +30 -2
  146. package/src/themes/brutalist.ts +29 -0
  147. package/src/themes/calm.ts +25 -2
  148. package/src/themes/candy.ts +144 -0
  149. package/src/themes/classic.ts +3 -0
  150. package/src/themes/clay.ts +24 -0
  151. package/src/themes/darkGlass.ts +24 -0
  152. package/src/themes/graphite.ts +150 -0
  153. package/src/themes/index.ts +5 -0
  154. package/src/themes/liquidGlass.ts +30 -3
  155. package/src/themes/lux.ts +24 -2
  156. package/src/themes/morph.ts +25 -3
  157. package/src/themes/neon.ts +25 -0
  158. package/src/themes/paper.ts +19 -0
  159. package/src/themes/sketchy.ts +20 -0
  160. package/src/themes/slate.ts +25 -1
  161. package/src/themes/soft.ts +24 -2
  162. package/src/types.ts +41 -0
  163. package/src/util/defaults.ts +12 -1
  164. package/src/util/defineTheme.ts +11 -5
@@ -13,9 +13,13 @@
13
13
  /* Everyday */
14
14
  @import './themes/paper.css';
15
15
  @import './themes/slate.css';
16
+ @import './themes/graphite.css';
17
+ /* One stylesheet for the three Atlas variants. */
18
+ @import './themes/_atlas.css';
16
19
  @import './themes/calm.css';
17
20
  @import './themes/lux.css';
18
21
  @import './themes/soft.css';
22
+ @import './themes/candy.css';
19
23
 
20
24
  /* Tactile */
21
25
  @import './themes/clay.css';
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Atlas — shared by the three variants, because they are one design with
3
+ * three grounds rather than three themes that resemble each other.
4
+ *
5
+ * The theme says most of what it has to say through variables; what is left
6
+ * are the two structures a panel needs and a `ThemeDefinition` cannot
7
+ * express: a header that separates from its rows, and a card whose title
8
+ * separates from its content. Both are hairlines. Nothing here casts a
9
+ * shadow — on a screen this quiet a shadow is the loudest thing on it.
10
+ */
11
+ .v-theme--atlas,
12
+ .v-theme--atlasDark,
13
+ .v-theme--atlasSepia {
14
+ /**
15
+ * The frame reads as a frame: the navigation takes the muted band, the
16
+ * content keeps the white. It is the oldest console layout there is, and
17
+ * the reason a panel on a white page still looks like an application.
18
+ */
19
+ & .v-navigation-drawer {
20
+ background-color: rgb(var(--v-theme-surface-light));
21
+ }
22
+
23
+ /**
24
+ * A table header that keeps its own ground, so a sticky one does not have
25
+ * rows sliding through it, and a rule under it that reads as structure
26
+ * rather than as a border round the table.
27
+ */
28
+ & :is(.v-table thead th, .v-data-table__th) {
29
+ /* A shade off the rows rather than the same white: the header of a
30
+ console table is a band, and a band you cannot see is a caption. */
31
+ background-color: rgb(var(--v-theme-surface-light));
32
+ border-bottom: 1px solid rgba(var(--v-border-color), calc(var(--v-border-opacity) * 1.6));
33
+ }
34
+
35
+ /* The title block of a panel, ruled off from what it introduces. */
36
+ & .v-card--variant-outlined > .v-card-item:not(:last-child) {
37
+ border-block-end: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
38
+ padding-block-end: 12px;
39
+ }
40
+
41
+ /**
42
+ * Vuetify zeroes the top padding of a `v-card-text` that follows a
43
+ * `v-card-item`, which is right when nothing separates them and wrong the
44
+ * moment the rule above is drawn: the content ends up sitting on the line.
45
+ */
46
+ & .v-card--variant-outlined > .v-card-item + :is(.v-card-text, .v-card-actions) {
47
+ padding-top: 12px;
48
+ }
49
+
50
+ /**
51
+ * Data runs a size smaller than prose.
52
+ *
53
+ * Vuetify sets one body size for the whole application, which is right
54
+ * for a page someone reads and wrong for a grid someone scans: at 16px a
55
+ * table of twelve columns stops fitting, and every admin tool worth
56
+ * copying runs its rows at 13 or 14. The reduction is scoped to the
57
+ * places that hold records — tables and lists — so forms and prose keep
58
+ * the size they were designed at.
59
+ */
60
+ & :is(.v-table, .v-data-table) {
61
+ font-size: 0.875rem;
62
+ }
63
+
64
+ & :is(.v-list-item-title, .v-list-item-subtitle) {
65
+ font-size: 0.875rem;
66
+ }
67
+
68
+ /**
69
+ * A panel title is a label for what is under it, not a headline. Vuetify's
70
+ * 1.25rem belongs on a marketing card; a screen with nine panels on it
71
+ * needs them to sit down.
72
+ */
73
+ & .v-card-title {
74
+ font-size: 1rem;
75
+ font-weight: 600;
76
+ letter-spacing: 0;
77
+ }
78
+
79
+ /**
80
+ * The pickers, at a size that fits a form.
81
+ *
82
+ * Vuetify sizes them for a touch dialog: 328px wide with 44px day cells,
83
+ * which next to a compact field looks like a component from another
84
+ * application. 36px cells still clear the 24px minimum for a pointer
85
+ * target and take a third off the height.
86
+ */
87
+ & :is(.v-date-picker, .v-picker) {
88
+ /* 306, not 296: the month and year controls need that much, and a
89
+ picker narrower than its own header is a picker that wraps. */
90
+ width: 306px;
91
+ }
92
+
93
+ /* The time picker sets its own floor, and it is the same 328. */
94
+ & .v-time-picker {
95
+ min-width: 296px;
96
+ }
97
+
98
+ & .v-date-picker-month__day {
99
+ height: 32px;
100
+ }
101
+
102
+ /* The date grid is a table of numbers, so it takes the table's size. */
103
+ & :is(.v-date-picker-month, .v-date-picker-years, .v-date-picker-months) {
104
+ font-size: 0.8125rem;
105
+ }
106
+
107
+ /* The clock face is sized for a thumb on a phone: 256px next to a
108
+ compact field is a component from another application. */
109
+ & .v-time-picker-clock {
110
+ max-width: 208px;
111
+ }
112
+
113
+ & .v-date-picker-controls {
114
+ padding-block: 4px;
115
+ }
116
+
117
+ /**
118
+ * Two nested paddings around five boxes on a control that is one line —
119
+ * and boxes sized for a thumb on a phone. A code entered with a keyboard
120
+ * beside compact fields should match them.
121
+ */
122
+ & .v-otp-input {
123
+ padding-block: 0;
124
+ }
125
+
126
+ & .v-otp-input__content {
127
+ max-width: 240px;
128
+ padding: 0;
129
+ }
130
+
131
+ & .v-otp-input .v-field {
132
+ height: 40px;
133
+ }
134
+
135
+ /**
136
+ * A panel header is a row, and rows here are 40 to 44. Vuetify's 48
137
+ * growing to 64 on open makes the list jump as much as it discloses.
138
+ */
139
+ & .v-expansion-panel-title {
140
+ min-height: 44px;
141
+ /* The height comes from the padding, not the minimum: 16px above and
142
+ below a 24px line is 56 whatever the minimum says. */
143
+ padding-block: 10px;
144
+ }
145
+
146
+ & .v-expansion-panel-title--active {
147
+ min-height: 52px;
148
+ }
149
+
150
+ /**
151
+ * Vuetify's empty state fills its container, which is right for a
152
+ * full-page one and wrong for the panel-sized ones an admin screen is
153
+ * full of.
154
+ */
155
+ & .v-empty-state {
156
+ min-height: 0;
157
+ padding-block: 24px;
158
+ }
159
+
160
+ /**
161
+ * Vuetify sets an alert title at 24px with a 28px glyph beside it, which
162
+ * on a console page is a headline announcing a footnote. Ant Design runs
163
+ * its alerts at 16 and 14, and that is the register a notice belongs in
164
+ * when the screen behind it is full of data.
165
+ */
166
+ & .v-alert-title {
167
+ font-size: 1rem;
168
+ line-height: 1.5;
169
+ }
170
+
171
+ & .v-alert .v-alert__content {
172
+ font-size: 0.875rem;
173
+ }
174
+
175
+ & .v-alert .v-alert__prepend .v-icon {
176
+ font-size: 20px;
177
+ }
178
+
179
+ /**
180
+ * A breadcrumb trail is orientation, not content: it sits above the page
181
+ * title saying where you are, and Vuetify runs it at body size, which
182
+ * puts it in the same voice as the text it introduces. Every console this
183
+ * theme is measured against sets it a step down.
184
+ */
185
+ & .v-breadcrumbs {
186
+ font-size: 0.875rem;
187
+ }
188
+
189
+ /* Dense screens read better when the rules between rows are lighter than
190
+ the ones around the panels that hold them. */
191
+ & :is(.v-table tbody td, .v-data-table__td) {
192
+ border-color: rgba(var(--v-border-color), calc(var(--v-border-opacity) * 0.7));
193
+ }
194
+ }
@@ -0,0 +1,2 @@
1
+ /* The family shares one stylesheet — see _atlas.css. */
2
+ @import './_atlas.css';
@@ -0,0 +1,2 @@
1
+ /* The family shares one stylesheet — see _atlas.css. */
2
+ @import './_atlas.css';
@@ -0,0 +1,2 @@
1
+ /* The family shares one stylesheet — see _atlas.css. */
2
+ @import './_atlas.css';
@@ -12,14 +12,38 @@
12
12
  * restyles the entire theme.
13
13
  */
14
14
  .v-theme--aurora {
15
- /* The lit ground the glows sit on. */
15
+ /* The lit ground the glows sit on, now closed at the bottom by the third
16
+ colour of the gradient so the page is lit from every corner. */
16
17
  &.v-application {
17
18
  background-image:
18
19
  radial-gradient(60rem 40rem at 15% -10%, rgba(124, 92, 255, 0.16), transparent 60%),
19
- radial-gradient(50rem 35rem at 95% 5%, rgba(0, 212, 255, 0.12), transparent 60%);
20
+ radial-gradient(50rem 35rem at 95% 5%, rgba(0, 212, 255, 0.12), transparent 60%),
21
+ radial-gradient(45rem 30rem at 50% 105%, rgba(255, 92, 170, 0.1), transparent 60%);
20
22
  background-attachment: fixed;
21
23
  }
22
24
 
25
+ /**
26
+ * The aurora itself: a second field of light that drifts behind the
27
+ * content for half a minute at a time.
28
+ *
29
+ * Only `transform` is animated, so the whole thing lives on the
30
+ * compositor — the page never repaints for it. It is `position: fixed`
31
+ * and behind the content, which on a theme this dark means it shows
32
+ * through every translucent surface rather than over any of them.
33
+ */
34
+ &.v-application::before {
35
+ content: '';
36
+ position: fixed;
37
+ inset: -20%;
38
+ z-index: 0;
39
+ pointer-events: none;
40
+ background-image:
41
+ radial-gradient(35rem 28rem at 25% 25%, rgba(124, 92, 255, 0.14), transparent 60%),
42
+ radial-gradient(30rem 24rem at 75% 40%, rgba(0, 212, 255, 0.1), transparent 60%),
43
+ radial-gradient(28rem 22rem at 55% 85%, rgba(255, 92, 170, 0.09), transparent 60%);
44
+ animation: vw-aurora-drift 34s ease-in-out infinite alternate;
45
+ }
46
+
23
47
  & .v-card.v-card--variant-elevated {
24
48
  background-image: radial-gradient(
25
49
  36rem 18rem at 0% 0%,
@@ -30,7 +54,7 @@
30
54
  }
31
55
 
32
56
  /* An iridescent rim, drawn in the border box only. */
33
- & :is(.v-card, .v-alert)::after {
57
+ & :is(.v-card, .v-alert, :is(.v-list, .v-sheet, .v-banner):not(:is(.v-card, .v-overlay__content, .v-navigation-drawer, .v-expansion-panels, .v-list) *))::after {
34
58
  content: '';
35
59
  position: absolute;
36
60
  inset: 0;
@@ -45,9 +69,10 @@
45
69
  pointer-events: none;
46
70
  }
47
71
 
48
- /* Filled buttons are the gradient itself. */
72
+ /* Filled buttons are the gradient itself — the deep one, since they
73
+ carry a label. */
49
74
  & .v-btn.v-btn--variant-flat.bg-primary {
50
- background-image: var(--v-vw-gradient);
75
+ background-image: var(--v-vw-gradient-btn, var(--v-vw-gradient));
51
76
  box-shadow: 0 6px 24px rgba(124, 92, 255, 0.45);
52
77
  }
53
78
 
@@ -77,10 +102,129 @@
77
102
  box-shadow: 0 0 0 1px rgba(155, 140, 255, 0.16), 0 24px 64px rgba(0, 0, 0, 0.7);
78
103
  }
79
104
 
80
- /* The display sizes carry the gradient; body text stays legible. */
81
- & [class*='-display-'] {
105
+ /* Progress is the one element that is literally a moving gradient. */
106
+ & :is(.v-progress-linear__determinate, .v-progress-linear__indeterminate) {
107
+ background-image: var(--v-vw-gradient);
108
+ }
109
+
110
+ /**
111
+ * Tonal surfaces are a flat wash of one colour in stock Vuetify, which on
112
+ * this theme reads as the one place the palette gave up. The underlay is
113
+ * a separate element precisely so it can be repainted.
114
+ */
115
+ & :is(.v-alert__underlay, .v-chip__underlay) {
116
+ background-image: var(--v-vw-gradient);
117
+ opacity: 0.2;
118
+ }
119
+
120
+ /* The chrome is lit from the leading edge, like the ground under it. */
121
+ & :is(.v-app-bar, .v-toolbar, .v-navigation-drawer) {
122
+ background-image: linear-gradient(
123
+ 100deg,
124
+ rgba(124, 92, 255, 0.16),
125
+ rgba(0, 212, 255, 0.06) 55%,
126
+ transparent
127
+ );
128
+ }
129
+
130
+ /**
131
+ * A rule that fades out at both ends rather than stopping dead.
132
+ *
133
+ * `border-image` rather than a background: `VDivider` is an `<hr>` pinned
134
+ * at `max-height: 0` and drawn entirely by its top border, so a
135
+ * background has no box to paint in. The image lands on the one edge
136
+ * that has a width, and a divider is straight, so the usual objection to
137
+ * `border-image` — that it cannot follow a rounded corner — does not
138
+ * apply here. The opacity is baked into the gradient because Vuetify
139
+ * fades the whole element by `--v-border-opacity`.
140
+ */
141
+ & .v-divider:not(.v-divider--vertical) {
142
+ opacity: 1;
143
+ border-image: linear-gradient(
144
+ 90deg,
145
+ transparent,
146
+ rgba(155, 140, 255, 0.45) 25%,
147
+ rgba(0, 212, 255, 0.35) 75%,
148
+ transparent
149
+ ) 1;
150
+ }
151
+
152
+ /* Only the bottom border carries a width, so the image paints there
153
+ alone — and a table header is square, so the corner problem above
154
+ never comes up. */
155
+ & :is(.v-table thead th, .v-data-table__th) {
156
+ border-bottom: 1px solid transparent;
157
+ border-image: var(--v-vw-gradient) 1;
158
+ }
159
+
160
+ /* The active row is lit from its leading edge instead of barred. */
161
+ & .v-list-item.v-list-item--active {
162
+ background-image: linear-gradient(
163
+ 90deg,
164
+ rgba(124, 92, 255, 0.22),
165
+ transparent 45%
166
+ );
167
+ }
168
+
169
+ /* A badge is a number on a gradient, so it takes the deep one too. */
170
+ & .v-badge__badge {
171
+ background-image: var(--v-vw-gradient-btn, var(--v-vw-gradient));
172
+ }
173
+
174
+ /* A focused field gets the same rim the cards wear. */
175
+ & .v-field.v-field--variant-solo-filled.v-field--focused::after {
176
+ content: '';
177
+ position: absolute;
178
+ inset: 0;
179
+ border-radius: inherit;
180
+ padding: var(--v-vw-border-width);
181
+ background: var(--v-vw-gradient);
182
+ opacity: 0.7;
183
+ mask:
184
+ linear-gradient(#000 0 0) content-box,
185
+ linear-gradient(#000 0 0);
186
+ mask-composite: exclude;
187
+ pointer-events: none;
188
+ }
189
+
190
+ /* The display and headline sizes carry the gradient; body text stays
191
+ legible, which is the whole reason the line is drawn here. */
192
+ & :is([class*='-display-'], [class*='-headline-large']) {
82
193
  background: var(--v-vw-gradient);
83
194
  background-clip: text;
84
195
  color: transparent;
85
196
  }
197
+
198
+ /* The dot is a bead of the same light the line carries. */
199
+ & .v-timeline-divider__dot {
200
+ background-image: var(--v-vw-gradient);
201
+ box-shadow: 0 0 16px rgba(124, 92, 255, 0.55);
202
+ }
203
+
204
+ /**
205
+ * The dot above is the gradient, so its inner disc has to be clear for
206
+ * that to show. Vuetify writes this one inline when `dot-color` is a
207
+ * plain colour, which is the single place in the package where nothing
208
+ * but `!important` reaches — and the `bg-` guard keeps it off a dot whose
209
+ * colour the author did name, since that one arrives as a class.
210
+ */
211
+ & .v-timeline-divider__inner-dot:not([class*='bg-']) {
212
+ background-color: transparent !important;
213
+ }
214
+ }
215
+
216
+ @keyframes vw-aurora-drift {
217
+ from {
218
+ transform: translate3d(-3%, -2%, 0) scale(1.06);
219
+ }
220
+
221
+ to {
222
+ transform: translate3d(3%, 2%, 0) scale(1.14);
223
+ }
224
+ }
225
+
226
+ @media (prefers-reduced-motion: reduce) {
227
+ .v-theme--aurora.v-application::before {
228
+ animation: none;
229
+ }
86
230
  }
@@ -38,14 +38,16 @@
38
38
  font-weight: 700;
39
39
  }
40
40
 
41
-
42
-
43
41
  /* Panels are cards here, so they wear the same rule as one. */
44
42
  & .v-expansion-panels {
45
43
  border: var(--v-vw-border-width) solid rgb(var(--v-shadow-color));
46
44
  }
47
45
 
48
-
46
+ /* The dot is a block on a beam. */
47
+ & .v-timeline-divider__dot {
48
+ border: var(--v-vw-border-width) solid rgb(var(--v-shadow-color));
49
+ box-shadow: var(--vw-brut-offset) var(--vw-brut-offset) 0 rgb(var(--v-shadow-color));
50
+ }
49
51
  }
50
52
 
51
53
  @media (prefers-reduced-motion: reduce) {
@@ -7,23 +7,16 @@
7
7
  box-shadow: none;
8
8
  }
9
9
 
10
- /* Surfaces separate by tone alone, at the smallest step that still reads. */
11
- & .v-card.v-card--variant-flat {
12
- background-color: rgb(var(--v-theme-surface));
13
- }
14
-
15
10
  & :is(.v-menu, .v-dialog) > .v-overlay__content {
16
11
  border: var(--v-vw-border-width) solid rgba(var(--v-border-color), 0.09);
17
12
  box-shadow: 0 16px 48px rgba(58, 58, 54, 0.06);
18
13
  }
19
14
 
20
-
21
15
  & :is(.v-table thead th, .v-data-table__th) {
22
16
  font-weight: 500;
23
17
  border-bottom: var(--v-vw-border-width) solid rgba(var(--v-border-color), 0.09);
24
18
  }
25
19
 
26
-
27
20
  /* Room to breathe is the theme's only real ornament. */
28
21
  & .v-card-text {
29
22
  line-height: 1.7;
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Candy — everything on screen is a stuffed cushion.
3
+ *
4
+ * Three layers separate cloth from plastic. A white highlight along the top
5
+ * inside edge, where light catches a padded surface. A shading along the
6
+ * bottom inside edge, where the padding rolls away from it. And a wide,
7
+ * low-contrast drop that spreads far more than it darkens, the way
8
+ * something soft resting on a table casts light rather than a hard edge.
9
+ *
10
+ * Pressing squashes: the shape sinks, gives up a little width, and its
11
+ * shadow shortens with it — plush deforms, it does not click.
12
+ *
13
+ * The padding is the ink colour at low alpha rather than a darker shade of
14
+ * each element: it has to sit under six theme colours at once, and the pink
15
+ * of `--v-shadow-color` reads as a halo under the teal and the green.
16
+ */
17
+ .v-theme--candy {
18
+ --vw-candy-pad:
19
+ inset 0 2px 0 rgba(255, 255, 255, 0.55),
20
+ inset 0 -3px 0 rgba(var(--v-theme-on-surface), 0.08);
21
+ --vw-candy-rest:
22
+ 0 3px 6px rgba(var(--v-shadow-color), 0.16),
23
+ 0 10px 22px rgba(var(--v-shadow-color), 0.13);
24
+ --vw-candy-squash:
25
+ 0 1px 3px rgba(var(--v-shadow-color), 0.2),
26
+ 0 3px 9px rgba(var(--v-shadow-color), 0.12);
27
+ /* The soft drop reaches past the chip it lifts — see core.css. */
28
+ --v-vw-relief-inset: 4px;
29
+
30
+ & .v-btn.v-btn:is(.v-btn--variant-flat, .v-btn--variant-elevated):not(.v-btn--disabled) {
31
+ box-shadow: var(--vw-candy-pad), var(--vw-candy-rest);
32
+ transition: box-shadow var(--v-vw-motion-duration) var(--v-vw-motion-ease);
33
+ }
34
+
35
+ /* The squash itself is `vw-press-scale` and `vw-press-shift` in core; all
36
+ this has to do is take the shadow down with it. */
37
+ & .v-btn.v-btn:is(.v-btn--variant-flat, .v-btn--variant-elevated):not(.v-btn--disabled):active {
38
+ box-shadow: var(--vw-candy-pad), var(--vw-candy-squash);
39
+ }
40
+
41
+ /* Pills are small enough that the full pad closes up on them, so they
42
+ take the highlight and a short drop only. */
43
+ & .v-chip.v-chip:not(.v-chip--variant-text, .v-chip--variant-plain) {
44
+ box-shadow:
45
+ inset 0 1px 0 rgba(255, 255, 255, 0.5),
46
+ 0 2px 5px rgba(var(--v-shadow-color), 0.14);
47
+ }
48
+
49
+ & :is(.v-card.v-card--variant-elevated, .v-alert.v-alert--variant-tonal) {
50
+ box-shadow:
51
+ inset 0 2px 0 rgba(255, 255, 255, 0.6),
52
+ 0 6px 16px rgba(var(--v-shadow-color), 0.12),
53
+ 0 20px 44px rgba(var(--v-shadow-color), 0.1);
54
+ }
55
+
56
+ & .v-card.v-card--variant-elevated {
57
+ transition: box-shadow var(--v-vw-motion-duration) var(--v-vw-motion-ease);
58
+ }
59
+
60
+ /* The lift is `vw-hover-lift`, on the theme's own overshooting easing —
61
+ something soft that is picked up bounces past where it settles. */
62
+ & .v-card.v-card--variant-elevated.v-card--link:hover {
63
+ box-shadow:
64
+ inset 0 2px 0 rgba(255, 255, 255, 0.6),
65
+ 0 10px 22px rgba(var(--v-shadow-color), 0.14),
66
+ 0 28px 60px rgba(var(--v-shadow-color), 0.12);
67
+ }
68
+
69
+ /**
70
+ * Inputs are the one place the padding goes the other way: a dent pressed
71
+ * into the cushion, shaded at the top where the surface falls in. Without
72
+ * it `solo-filled` is the same white as the card it sits on.
73
+ */
74
+ & .v-field.v-field--variant-solo-filled {
75
+ box-shadow: inset 0 2px 5px rgba(var(--v-shadow-color), 0.16);
76
+ }
77
+
78
+ & .v-field.v-field--variant-solo-filled .v-field__overlay {
79
+ background-color: rgb(var(--v-theme-surface-light));
80
+ }
81
+
82
+ & :is(.v-switch__track, .v-slider-track__background) {
83
+ box-shadow: inset 0 2px 4px rgba(var(--v-shadow-color), 0.22);
84
+ }
85
+
86
+ /* The thumbs are the plushest things on screen: a lit top, a soft body,
87
+ and a halo standing in for the fibres a real one would have. */
88
+ & :is(.v-switch__thumb, .v-slider-thumb__surface) {
89
+ box-shadow:
90
+ inset 0 2px 0 rgba(255, 255, 255, 0.65),
91
+ 0 2px 5px rgba(var(--v-shadow-color), 0.32),
92
+ 0 0 0 5px rgba(var(--v-theme-primary), 0.14);
93
+ }
94
+
95
+ /* `VTabs` runs inset here, so the pill behind the active tab is the
96
+ indicator, and it is padded like everything else. */
97
+ & .v-tabs--inset .v-tab__slider {
98
+ box-shadow:
99
+ inset 0 1px 0 rgba(255, 255, 255, 0.5),
100
+ 0 4px 12px rgba(var(--v-theme-primary), 0.24);
101
+ }
102
+
103
+ /* The timeline is a ribbon, so it gets ends rather than corners. */
104
+ & :is(.v-timeline-divider__before, .v-timeline-divider__after) {
105
+ border-radius: 999px;
106
+ }
107
+
108
+ & .v-timeline-divider__dot {
109
+ box-shadow:
110
+ inset 0 2px 0 rgba(255, 255, 255, 0.6),
111
+ 0 3px 8px rgba(var(--v-shadow-color), 0.22);
112
+ }
113
+ }
@@ -26,6 +26,19 @@
26
26
  -2px -2px 5px rgba(255, 255, 255, 0.6);
27
27
  }
28
28
 
29
+ /**
30
+ * The lift is composed against this theme's own ground: a white
31
+ * highlight top-left, a dark shadow bottom-right. Inside a surface that
32
+ * paints its own colour — `color=` on a card, a coloured bar, a filled
33
+ * alert — the highlight has nothing to blend into and reads as a halo
34
+ * around the control, so the relief is dropped there and the control
35
+ * keeps its flat fill. Vuetify only emits `bg-*` when an author asked
36
+ * for a colour, so untouched surfaces are unaffected.
37
+ */
38
+ & [class*='bg-'] :is(.v-btn.v-btn, .v-chip.v-chip) {
39
+ box-shadow: none;
40
+ }
41
+
29
42
  & .v-btn:active:not(.v-btn--disabled) {
30
43
  box-shadow:
31
44
  4px 4px 10px rgba(var(--v-shadow-color), 0.16),
@@ -57,4 +70,15 @@
57
70
  & .v-tab__slider {
58
71
  border-radius: 5px;
59
72
  }
73
+
74
+ /* The line is a channel pressed into the ground, not drawn on it. */
75
+ & :is(.v-timeline-divider__before, .v-timeline-divider__after) {
76
+ box-shadow:
77
+ inset 2px 2px 5px rgba(var(--v-shadow-color), 0.18),
78
+ inset -2px -2px 5px rgba(255, 255, 255, 0.8);
79
+ }
80
+
81
+ & .v-timeline-divider__dot {
82
+ box-shadow: var(--vw-clay-lift);
83
+ }
60
84
  }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Graphite — the theme is one subtraction and one rule.
3
+ *
4
+ * The subtraction: nothing casts a shadow. On a near-black ground a drop
5
+ * shadow has nothing to fall on, so every elevation Vuetify draws reads as
6
+ * a grey smudge. Take them all away and depth has to come from the two
7
+ * things that survive at this contrast — a surface a few percent lighter,
8
+ * and a one-pixel line. Floating overlays are the exception and keep a
9
+ * shadow through `--v-vw-overlay-shadow`, because they have to separate
10
+ * from the page rather than sit on it.
11
+ *
12
+ * The second rule: anything the interface says about itself — a column
13
+ * name, a status, a path — is set in mono at a small size, and anything the
14
+ * user wrote is not. It is the oldest convention in developer tooling and it
15
+ * costs nothing but a font, while carrying the whole "built by engineers"
16
+ * reading that a colour cannot.
17
+ */
18
+ .v-theme--graphite {
19
+ --vw-graphite-label: 'JetBrains Mono', ui-monospace, 'SF Mono', 'Menlo', monospace;
20
+
21
+ & :is(
22
+ .v-card.v-card,
23
+ .v-btn.v-btn,
24
+ .v-chip.v-chip,
25
+ .v-alert.v-alert,
26
+ .v-table.v-table,
27
+ .v-expansion-panels.v-expansion-panels,
28
+ .v-list.v-list,
29
+ .v-sheet.v-sheet
30
+ ) {
31
+ box-shadow: none;
32
+ }
33
+
34
+ /**
35
+ * An elevated card lost the only edge it had, so it draws the line the
36
+ * outlined variant would have. `border` rather than a ring shadow: the
37
+ * card owns its box here, and a hairline that rounds with the corner is
38
+ * the whole visual language of the theme.
39
+ */
40
+ & .v-card.v-card--variant-elevated {
41
+ border: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
42
+ }
43
+
44
+ /* Column names are labels the table gives itself: mono, small, spaced. */
45
+ & :is(.v-table thead th, .v-data-table__th) {
46
+ font-family: var(--vw-graphite-label);
47
+ font-size: 0.6875rem;
48
+ color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity));
49
+ border-bottom: 1px solid rgba(var(--v-border-color), 0.2);
50
+ }
51
+
52
+ /* A status is a label too, and a breadcrumb trail is a path. */
53
+ & :is(.v-chip.v-chip--size-x-small, .v-chip.v-chip--size-small, .v-breadcrumbs-item) {
54
+ font-family: var(--vw-graphite-label);
55
+ font-size: 0.6875rem;
56
+ letter-spacing: 0.02em;
57
+ }
58
+
59
+ & .v-breadcrumbs-divider {
60
+ font-family: var(--vw-graphite-label);
61
+ opacity: 0.5;
62
+ }
63
+ }
@@ -115,7 +115,6 @@
115
115
  0 2px 8px rgba(var(--v-shadow-color), 0.28);
116
116
  }
117
117
 
118
-
119
118
  & [class*='-title-'] {
120
119
  letter-spacing: -0.01em;
121
120
  }
@@ -146,7 +145,6 @@
146
145
  color: rgba(var(--v-theme-on-surface), 0.5);
147
146
  border-bottom: 1px solid rgba(var(--v-border-color), 0.14);
148
147
  }
149
-
150
148
  }
151
149
 
152
150
  @media (prefers-reduced-transparency: reduce) {