@codenhub/styles 0.5.0 → 0.7.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/NOTICE +18 -16
- package/README.es.md +61 -0
- package/README.md +27 -22
- package/README.pt-BR.md +61 -0
- package/dist/aesthetics/chunky-tile.css +1 -1
- package/dist/aesthetics/cyber.css +1 -1
- package/dist/aesthetics/glass.css +1 -1
- package/dist/aesthetics/index.css +2 -2
- package/dist/aesthetics/neobrutalism.css +1 -1
- package/dist/aesthetics/pixel.css +1 -1
- package/dist/aesthetics/sketch.css +1 -1
- package/dist/components.css +2 -2
- package/dist/index.css +2 -2
- package/dist/native.css +2 -2
- package/dist/palette.css +1 -1
- package/dist/theme.css +2 -2
- package/dist/tw/aesthetics/chunky-tile.css +120 -62
- package/dist/tw/aesthetics/cyber.css +102 -40
- package/dist/tw/aesthetics/glass.css +371 -19
- package/dist/tw/aesthetics/index.css +2 -1
- package/dist/tw/aesthetics/neobrutalism.css +121 -33
- package/dist/tw/aesthetics/pixel.css +111 -16
- package/dist/tw/aesthetics/sketch.css +100 -28
- package/dist/tw/box.css +69 -28
- package/dist/tw/components/button.css +35 -14
- package/dist/tw/components/feedback.css +61 -58
- package/dist/tw/components/form.css +255 -142
- package/dist/tw/components/index.css +4 -9
- package/dist/tw/components/surface.css +80 -68
- package/dist/tw/components/tooltip.css +75 -41
- package/dist/tw/elevation.css +14 -22
- package/dist/tw/index.css +15 -19
- package/dist/tw/intent.css +35 -27
- package/dist/tw/native.css +22 -12
- package/dist/tw/palette.css +14 -11
- package/dist/tw/presentation.css +16 -30
- package/dist/tw/reset.css +36 -43
- package/dist/tw/surface.css +11 -12
- package/dist/tw/theme.css +87 -103
- package/dist/tw/utilities/content.css +311 -200
- package/dist/tw/utilities/layout.css +41 -37
- package/docs/accessibility.md +104 -58
- package/docs/changelog/0.1.1.md +1 -0
- package/docs/changelog/0.2.0.md +1 -0
- package/docs/changelog/0.3.0.md +1 -0
- package/docs/changelog/0.4.0.md +1 -0
- package/docs/changelog/0.5.0.md +8 -3
- package/docs/changelog/0.6.0.md +53 -0
- package/docs/changelog/0.7.0.md +50 -0
- package/docs/changelog/index.md +2 -0
- package/docs/concepts.md +188 -46
- package/docs/es/accessibility.md +150 -0
- package/docs/es/concepts.md +212 -0
- package/docs/es/index.md +104 -0
- package/docs/es/integrating/astro.md +35 -0
- package/docs/es/integrating/index.md +47 -0
- package/docs/es/integrating/nextjs.md +67 -0
- package/docs/es/integrating/svelte.md +45 -0
- package/docs/es/integrating/tailwind.md +78 -0
- package/docs/es/integrating/vue.md +31 -0
- package/docs/es/integrating/without-a-bundler.md +115 -0
- package/docs/es/setup.md +180 -0
- package/docs/es/usage/aesthetics.md +276 -0
- package/docs/es/usage/buttons.md +131 -0
- package/docs/es/usage/composing.md +164 -0
- package/docs/es/usage/content-and-layout.md +215 -0
- package/docs/es/usage/customizing.md +298 -0
- package/docs/es/usage/feedback.md +153 -0
- package/docs/es/usage/forms.md +231 -0
- package/docs/es/usage/index.md +29 -0
- package/docs/es/usage/solo.md +84 -0
- package/docs/es/usage/theming.md +296 -0
- package/docs/es/usage/tooltips.md +127 -0
- package/docs/index.md +89 -21
- package/docs/integrating/astro.md +3 -4
- package/docs/integrating/index.md +18 -13
- package/docs/integrating/nextjs.md +4 -5
- package/docs/integrating/svelte.md +5 -4
- package/docs/integrating/tailwind.md +29 -8
- package/docs/integrating/vue.md +3 -4
- package/docs/integrating/without-a-bundler.md +114 -0
- package/docs/pt-BR/accessibility.md +150 -0
- package/docs/pt-BR/concepts.md +212 -0
- package/docs/pt-BR/index.md +104 -0
- package/docs/pt-BR/integrating/astro.md +35 -0
- package/docs/pt-BR/integrating/index.md +47 -0
- package/docs/pt-BR/integrating/nextjs.md +67 -0
- package/docs/pt-BR/integrating/svelte.md +45 -0
- package/docs/pt-BR/integrating/tailwind.md +78 -0
- package/docs/pt-BR/integrating/vue.md +31 -0
- package/docs/pt-BR/integrating/without-a-bundler.md +115 -0
- package/docs/pt-BR/setup.md +180 -0
- package/docs/pt-BR/usage/aesthetics.md +276 -0
- package/docs/pt-BR/usage/buttons.md +131 -0
- package/docs/pt-BR/usage/composing.md +164 -0
- package/docs/pt-BR/usage/content-and-layout.md +215 -0
- package/docs/pt-BR/usage/customizing.md +298 -0
- package/docs/pt-BR/usage/feedback.md +153 -0
- package/docs/pt-BR/usage/forms.md +231 -0
- package/docs/pt-BR/usage/index.md +29 -0
- package/docs/pt-BR/usage/solo.md +84 -0
- package/docs/pt-BR/usage/theming.md +296 -0
- package/docs/pt-BR/usage/tooltips.md +127 -0
- package/docs/setup.md +134 -91
- package/docs/usage/aesthetics.md +102 -65
- package/docs/usage/buttons.md +108 -40
- package/docs/usage/composing.md +105 -92
- package/docs/usage/content-and-layout.md +159 -127
- package/docs/usage/customizing.md +112 -43
- package/docs/usage/feedback.md +135 -70
- package/docs/usage/forms.md +184 -99
- package/docs/usage/index.md +18 -14
- package/docs/usage/solo.md +83 -0
- package/docs/usage/theming.md +260 -119
- package/docs/usage/tooltips.md +103 -42
- package/llms-full.txt +2465 -1272
- package/llms.txt +25 -17
- package/package.json +28 -35
- package/dist/tw/components/loader.css +0 -117
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/* Neobrutalism: thick ink outline, a hard unblurred offset shadow, and a press
|
|
2
2
|
that moves the element into its own shadow. Material tokens only, no component
|
|
3
3
|
named -- the ink reaches everything through the intent reset, the shadow is
|
|
4
|
-
colourless geometry each component colours against its own intent.
|
|
5
|
-
the base stylesheet; source order decides against the zero-specificity reset. */
|
|
4
|
+
colourless geometry each component colours against its own intent. */
|
|
6
5
|
|
|
7
6
|
/* The layer map, stated before anything uses a layer -- see `theme.css`. The
|
|
8
7
|
aesthetic's token class sits in `components`, below every utility, so a
|
|
@@ -37,6 +36,10 @@
|
|
|
37
36
|
is the whole look, so this aesthetic asks for the intent instead of the
|
|
38
37
|
neutral depth colour every other shadow uses. */
|
|
39
38
|
--ui-shadow-ink: 100%;
|
|
39
|
+
/* The ink replaces the depth colour whole, so this one is inert here; it is
|
|
40
|
+
restated so a region nested inside chunky tile or cyber does not inherit
|
|
41
|
+
their black or transparent depth. */
|
|
42
|
+
--elevation-color: light-dark(rgb(15 23 42 / 0.08), rgb(0 0 0 / 0.55));
|
|
40
43
|
--ui-shadow-x: var(--_neo-offset);
|
|
41
44
|
--ui-shadow-y: var(--_neo-offset);
|
|
42
45
|
--ui-shadow-blur: 0px;
|
|
@@ -47,19 +50,24 @@
|
|
|
47
50
|
--ui-halo-spread: initial;
|
|
48
51
|
--ui-halo-ink: initial;
|
|
49
52
|
|
|
50
|
-
/* The press: travel the offset, shrink the shadow to nothing, so the
|
|
51
|
-
lands flat where its slab was. A translation `box` scales with
|
|
52
|
-
the two stay the same length at every size and elevation.
|
|
53
|
-
`box-hover`'s derived fill
|
|
54
|
-
no `:hover` list, R3
|
|
53
|
+
/* The press: travel the offset, shrink the shadow to nothing, so the
|
|
54
|
+
element lands flat where its slab was. A translation `box` scales with
|
|
55
|
+
the slab, so the two stay the same length at every size and elevation.
|
|
56
|
+
Hover keeps the slab still under the pointer; `box-hover`'s derived fill
|
|
57
|
+
tint is the whole hover response. One token pair, no `:hover` list, R3
|
|
58
|
+
intact. */
|
|
55
59
|
--ui-active-shadow-x: 0px;
|
|
56
60
|
--ui-active-shadow-y: 0px;
|
|
57
61
|
--ui-active-transform: none;
|
|
58
62
|
--ui-active-translate-x: var(--_neo-offset);
|
|
59
63
|
--ui-active-translate-y: var(--_neo-offset);
|
|
64
|
+
--ui-hover-transform: none;
|
|
60
65
|
|
|
61
66
|
/* Nothing here clips or blurs, and an aesthetic nested inside another has to
|
|
62
|
-
say so rather than inherit it.
|
|
67
|
+
say so rather than inherit it. Nothing clips, so the global focus outline
|
|
68
|
+
shows and no inset focus layer is wanted: cleared so a region nested
|
|
69
|
+
inside pixel does not inherit pixel's. */
|
|
70
|
+
--ui-focus-inset: initial;
|
|
63
71
|
--ui-clip: none;
|
|
64
72
|
--ui-clip-tight: none;
|
|
65
73
|
/* Round corners, said explicitly, and the pill and chip corners cleared back
|
|
@@ -86,9 +94,13 @@
|
|
|
86
94
|
--ui-bg-alpha: 1;
|
|
87
95
|
--ui-surface-image: initial;
|
|
88
96
|
|
|
89
|
-
/*
|
|
90
|
-
|
|
91
|
-
|
|
97
|
+
/* A control's neutral line is the theme's control border, not this
|
|
98
|
+
aesthetic's ink: that ink is the primary colour in both themes, so every
|
|
99
|
+
unchecked toggle and resting field drew its boundary as loudly as a
|
|
100
|
+
primary one. Named rather than cleared, so a region nested inside glass
|
|
101
|
+
or chunky tile does not inherit theirs either. */
|
|
102
|
+
--ui-control-ink: var(--color-control-border);
|
|
103
|
+
--ui-rule-ink: initial;
|
|
92
104
|
|
|
93
105
|
/* Chunky tile's heavier label, cleared so a region nested inside it keeps
|
|
94
106
|
the button's and the badge's own label. */
|
|
@@ -108,48 +120,108 @@
|
|
|
108
120
|
|
|
109
121
|
In `utilities`, not with the token class: it has to beat `@utility alert`'s
|
|
110
122
|
own `--_d-elevation: 0`, which it does there at 0-2-0, and it writes only a
|
|
111
|
-
private nothing a consumer sets.
|
|
123
|
+
private nothing a consumer sets.
|
|
124
|
+
|
|
125
|
+
Bounded by the nearest aesthetic region: an alert inside another aesthetic
|
|
126
|
+
nested in a neobrutalist region rests as that aesthetic rests it, and one in
|
|
127
|
+
a neobrutalist region nested again inside that takes the slab back. A
|
|
128
|
+
`:not(.neobrutalism :is(...) *)` exclusion cannot tell those two apart, since
|
|
129
|
+
the re-entered alert also sits below the other aesthetic, so each region
|
|
130
|
+
writes a private flag instead and inheritance hands the alert the nearest
|
|
131
|
+
one's. The slab is the alert's own resting default when the flag is unset. */
|
|
112
132
|
@layer utilities {
|
|
133
|
+
.neobrutalism {
|
|
134
|
+
--_neo-alert-elevation: 1;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
:is(.glass, .pixel, .chunky-tile, .cyber, .sketch) {
|
|
138
|
+
--_neo-alert-elevation: initial;
|
|
139
|
+
}
|
|
140
|
+
|
|
113
141
|
.neobrutalism .alert {
|
|
114
|
-
--_d-elevation:
|
|
142
|
+
--_d-elevation: var(--_neo-alert-elevation, 0);
|
|
115
143
|
}
|
|
116
144
|
}
|
|
117
145
|
|
|
118
146
|
/* Solo: the same look painted onto the one element carrying the class, for an
|
|
119
147
|
element the package does not style. See docs/internal/model.md#solo-classes and
|
|
120
|
-
the note on `.glass-solo`:
|
|
121
|
-
|
|
122
|
-
|
|
148
|
+
the note on `.glass-solo`: it composes with the element's presentation,
|
|
149
|
+
intent, and elevation, and reads its material from its own knobs and
|
|
150
|
+
foundation tokens with literal fallbacks, never a shared material `--ui-*`
|
|
151
|
+
or `--elevation-color` token. Unlayered, and not for this package's own
|
|
152
|
+
components. */
|
|
123
153
|
.neobrutalism-solo {
|
|
124
154
|
--_neo-offset: var(--neo-offset, 4px);
|
|
125
|
-
|
|
155
|
+
/* The composition, the same in every solo class; `registry.test.ts` holds
|
|
156
|
+
the copies together. See the note on `.glass-solo`. */
|
|
157
|
+
--_solo-intent-color: initial;
|
|
158
|
+
--_solo-intent-contrast: initial;
|
|
159
|
+
--_solo-intent-strong: initial;
|
|
160
|
+
--_solo-intent-border: initial;
|
|
161
|
+
--_solo-intent-fill-max: initial;
|
|
162
|
+
--_solo-color: var(--_solo-intent-color, var(--color-text, light-dark(oklch(14.5% 0 0), oklch(98.5% 0 0))));
|
|
163
|
+
--_solo-contrast: var(
|
|
164
|
+
--_solo-intent-contrast,
|
|
165
|
+
var(--color-text-contrast, light-dark(oklch(98.5% 0 0), oklch(14.5% 0 0)))
|
|
166
|
+
);
|
|
167
|
+
--_solo-strong: var(--_solo-intent-strong, var(--color-text-strong, light-dark(oklch(20.5% 0 0), oklch(97% 0 0))));
|
|
168
|
+
--_solo-capped: min(var(--ui-fill, 0%), var(--_solo-intent-fill-max, 20%));
|
|
169
|
+
--_solo-fill: color-mix(in oklab, var(--_solo-color) var(--_solo-capped), transparent);
|
|
170
|
+
--_solo-on-fill: min(var(--ui-fg-on-fill, 0%), max(0%, calc(var(--_solo-capped) * 2 - 100%)));
|
|
171
|
+
--_solo-fg: color-mix(in oklab, var(--_solo-contrast) var(--_solo-on-fill), var(--_solo-strong));
|
|
172
|
+
/* The line with no intent on the element: this aesthetic's own ink. */
|
|
173
|
+
--_solo-ink: var(
|
|
174
|
+
--_solo-intent-border,
|
|
175
|
+
light-dark(var(--color-neutral-950, oklch(14.5% 0 0)), var(--color-neutral-50, oklch(98.5% 0 0)))
|
|
176
|
+
);
|
|
177
|
+
--_solo-edge: color-mix(in oklab, var(--_solo-ink) var(--ui-border, 100%), var(--_solo-fill));
|
|
178
|
+
/* The slab, scaled by the element's own elevation class: `.flat` takes it off
|
|
179
|
+
and `.floating` doubles it, and the press travels the same distance. */
|
|
180
|
+
--_solo-depth: calc(var(--_neo-offset) * var(--ui-elevation, 1));
|
|
126
181
|
|
|
127
|
-
border: 2px solid var(--
|
|
182
|
+
border: 2px solid var(--_solo-edge);
|
|
128
183
|
border-radius: 0;
|
|
129
|
-
box-shadow:
|
|
184
|
+
box-shadow:
|
|
185
|
+
var(--_solo-depth) var(--_solo-depth) 0 0 var(--_solo-ink),
|
|
186
|
+
inset 0 0 0 100vmax var(--_solo-fill);
|
|
130
187
|
transition:
|
|
131
188
|
box-shadow var(--motion-duration-normal, 200ms) var(--motion-ease, cubic-bezier(0.2, 0, 0, 1)),
|
|
132
189
|
transform var(--motion-duration-normal, 200ms) var(--motion-ease, cubic-bezier(0.2, 0, 0, 1));
|
|
133
190
|
}
|
|
134
191
|
|
|
192
|
+
/* An intent class on the element colours it, as on a component. Named rather
|
|
193
|
+
than read from `--intent-*` alone: those slots inherit, so a `.success`
|
|
194
|
+
container would colour a solo element where it leaves a component neutral. */
|
|
195
|
+
.neobrutalism-solo:is(.primary, .secondary, .success, .warning, .destructive, .info) {
|
|
196
|
+
--_solo-intent-color: var(--intent-color);
|
|
197
|
+
--_solo-intent-contrast: var(--intent-contrast);
|
|
198
|
+
--_solo-intent-strong: var(--intent-strong);
|
|
199
|
+
--_solo-intent-border: var(--intent-border);
|
|
200
|
+
--_solo-intent-fill-max: var(--intent-fill-max);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/* The text colour is written only where a fill or an intent is asked for, on
|
|
204
|
+
the element or by a container's fill class. Anywhere else the element keeps
|
|
205
|
+
its own: a dark toast keeps its light text. */
|
|
206
|
+
.neobrutalism-solo:is(
|
|
207
|
+
.solid,
|
|
208
|
+
.soft,
|
|
209
|
+
.ghost,
|
|
210
|
+
.primary,
|
|
211
|
+
.secondary,
|
|
212
|
+
.success,
|
|
213
|
+
.warning,
|
|
214
|
+
.destructive,
|
|
215
|
+
.info,
|
|
216
|
+
:is(.solid, .soft, .ghost) *
|
|
217
|
+
) {
|
|
218
|
+
color: var(--_solo-fg);
|
|
219
|
+
}
|
|
220
|
+
|
|
135
221
|
/* The press, only on something pressed: an action, not disabled. A solo
|
|
136
222
|
container -- a toast clicked to dismiss -- stays put, the way only `.btn` and
|
|
137
223
|
an opted-in card press under the aesthetic class. */
|
|
138
224
|
.neobrutalism-solo:is(
|
|
139
|
-
button,
|
|
140
|
-
a[href],
|
|
141
|
-
[role="button"],
|
|
142
|
-
summary,
|
|
143
|
-
input[type="button"],
|
|
144
|
-
input[type="submit"],
|
|
145
|
-
input[type="reset"]
|
|
146
|
-
):active:not(:disabled, [aria-disabled="true"]) {
|
|
147
|
-
box-shadow: 0 0 0 0 var(--_neo-ink);
|
|
148
|
-
transform: translate(var(--_neo-offset), var(--_neo-offset));
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
@media (prefers-reduced-motion: reduce) {
|
|
152
|
-
.neobrutalism-solo:is(
|
|
153
225
|
button,
|
|
154
226
|
a[href],
|
|
155
227
|
[role="button"],
|
|
@@ -158,6 +230,22 @@
|
|
|
158
230
|
input[type="submit"],
|
|
159
231
|
input[type="reset"]
|
|
160
232
|
):active:not(:disabled, [aria-disabled="true"]) {
|
|
233
|
+
box-shadow:
|
|
234
|
+
0 0 0 0 var(--_solo-ink),
|
|
235
|
+
inset 0 0 0 100vmax var(--_solo-fill);
|
|
236
|
+
transform: translate(var(--_solo-depth), var(--_solo-depth));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
@media (prefers-reduced-motion: reduce) {
|
|
240
|
+
.neobrutalism-solo:is(
|
|
241
|
+
button,
|
|
242
|
+
a[href],
|
|
243
|
+
[role="button"],
|
|
244
|
+
summary,
|
|
245
|
+
input[type="button"],
|
|
246
|
+
input[type="submit"],
|
|
247
|
+
input[type="reset"]
|
|
248
|
+
):active:not(:disabled, [aria-disabled="true"]) {
|
|
161
249
|
transform: none;
|
|
162
250
|
}
|
|
163
251
|
}
|
|
@@ -64,11 +64,10 @@
|
|
|
64
64
|
has to be wider than the edge to show at all. */
|
|
65
65
|
--ui-focus-inset: calc(var(--_pixel-unit) + var(--focus-ring-width));
|
|
66
66
|
|
|
67
|
-
/* One square unit off each corner, and nothing else.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
shape the look is actually made of.
|
|
67
|
+
/* One square unit off each corner, and nothing else. A staircase
|
|
68
|
+
approximates a curve, which is the one thing a low-resolution grid cannot
|
|
69
|
+
do: it reads as a bevel that has not quite committed. A single cut of the
|
|
70
|
+
grid's own unit is the shape the look is made of.
|
|
72
71
|
|
|
73
72
|
The polygon resolves the unit here, on `.pixel`, and inherits down
|
|
74
73
|
already-resolved -- so a component cannot rescale the corner by setting
|
|
@@ -108,6 +107,13 @@
|
|
|
108
107
|
--ui-corner-br: initial;
|
|
109
108
|
--ui-corner-bl: initial;
|
|
110
109
|
|
|
110
|
+
/* The ring is the edge and nothing here is depth, so the shadow ink, the
|
|
111
|
+
press's shadow, and the depth colour are cleared or restated rather than
|
|
112
|
+
inherited from an aesthetic around this one. */
|
|
113
|
+
--ui-shadow-ink: initial;
|
|
114
|
+
--ui-active-shadow-x: initial;
|
|
115
|
+
--ui-active-shadow-y: initial;
|
|
116
|
+
--elevation-color: light-dark(rgb(15 23 42 / 0.08), rgb(0 0 0 / 0.55));
|
|
111
117
|
--ui-hover-transform: none;
|
|
112
118
|
--ui-active-transform: none;
|
|
113
119
|
--ui-active-translate-x: initial;
|
|
@@ -122,9 +128,13 @@
|
|
|
122
128
|
font to fall back to but a monospace stack. */
|
|
123
129
|
font-family: var(--font-pixel, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
|
|
124
130
|
|
|
125
|
-
/*
|
|
126
|
-
|
|
127
|
-
|
|
131
|
+
/* A control's neutral line is the theme's control border, not this
|
|
132
|
+
aesthetic's ink: that ink is the primary colour in both themes, so every
|
|
133
|
+
unchecked toggle and resting field drew its boundary as loudly as a
|
|
134
|
+
primary one. Named rather than cleared, so a region nested inside glass
|
|
135
|
+
or chunky tile does not inherit theirs either. */
|
|
136
|
+
--ui-control-ink: var(--color-control-border);
|
|
137
|
+
--ui-rule-ink: initial;
|
|
128
138
|
|
|
129
139
|
/* Chunky tile's heavier label, cleared so a region nested inside it keeps
|
|
130
140
|
the button's and the badge's own label. */
|
|
@@ -137,18 +147,46 @@
|
|
|
137
147
|
|
|
138
148
|
/* Solo: the same look painted onto the one element carrying the class, for an
|
|
139
149
|
element the package does not style. See docs/internal/model.md#solo-classes and
|
|
140
|
-
the note on `.glass-solo`:
|
|
141
|
-
|
|
142
|
-
|
|
150
|
+
the note on `.glass-solo`: it composes with the element's presentation,
|
|
151
|
+
intent, and elevation, and reads its material from its own knobs and
|
|
152
|
+
foundation tokens with literal fallbacks, never a shared material `--ui-*`
|
|
153
|
+
or `--elevation-color` token. Unlayered, and not for this package's own
|
|
154
|
+
components. */
|
|
143
155
|
.pixel-solo {
|
|
144
156
|
--_pixel-unit: var(--pixel-unit, 4px);
|
|
145
|
-
|
|
157
|
+
/* The composition, the same in every solo class; `registry.test.ts` holds
|
|
158
|
+
the copies together. See the note on `.glass-solo`. */
|
|
159
|
+
--_solo-intent-color: initial;
|
|
160
|
+
--_solo-intent-contrast: initial;
|
|
161
|
+
--_solo-intent-strong: initial;
|
|
162
|
+
--_solo-intent-border: initial;
|
|
163
|
+
--_solo-intent-fill-max: initial;
|
|
164
|
+
--_solo-color: var(--_solo-intent-color, var(--color-text, light-dark(oklch(14.5% 0 0), oklch(98.5% 0 0))));
|
|
165
|
+
--_solo-contrast: var(
|
|
166
|
+
--_solo-intent-contrast,
|
|
167
|
+
var(--color-text-contrast, light-dark(oklch(98.5% 0 0), oklch(14.5% 0 0)))
|
|
168
|
+
);
|
|
169
|
+
--_solo-strong: var(--_solo-intent-strong, var(--color-text-strong, light-dark(oklch(20.5% 0 0), oklch(97% 0 0))));
|
|
170
|
+
--_solo-capped: min(var(--ui-fill, 0%), var(--_solo-intent-fill-max, 20%));
|
|
171
|
+
--_solo-fill: color-mix(in oklab, var(--_solo-color) var(--_solo-capped), transparent);
|
|
172
|
+
--_solo-on-fill: min(var(--ui-fg-on-fill, 0%), max(0%, calc(var(--_solo-capped) * 2 - 100%)));
|
|
173
|
+
--_solo-fg: color-mix(in oklab, var(--_solo-contrast) var(--_solo-on-fill), var(--_solo-strong));
|
|
174
|
+
/* The line with no intent on the element: this aesthetic's own ink. */
|
|
175
|
+
--_solo-ink: var(
|
|
176
|
+
--_solo-intent-border,
|
|
177
|
+
light-dark(var(--color-neutral-950, oklch(14.5% 0 0)), var(--color-neutral-50, oklch(98.5% 0 0)))
|
|
178
|
+
);
|
|
179
|
+
/* The ring is the edge, and the fill is a layer under it rather than a plate
|
|
180
|
+
beneath a border, so the line fades to nothing instead of to the fill. */
|
|
181
|
+
--_solo-edge: color-mix(in oklab, var(--_solo-ink) var(--ui-border, 100%), transparent);
|
|
146
182
|
|
|
147
183
|
/* The clip removes a border at the straight sides, so the ring draws the
|
|
148
184
|
edge and the element's own border goes. */
|
|
149
185
|
border: 0;
|
|
150
186
|
border-radius: 0;
|
|
151
|
-
box-shadow:
|
|
187
|
+
box-shadow:
|
|
188
|
+
inset 0 0 0 var(--_pixel-unit) var(--_solo-edge),
|
|
189
|
+
inset 0 0 0 100vmax var(--_solo-fill);
|
|
152
190
|
clip-path: polygon(
|
|
153
191
|
0 var(--_pixel-unit),
|
|
154
192
|
var(--_pixel-unit) var(--_pixel-unit),
|
|
@@ -166,11 +204,68 @@
|
|
|
166
204
|
font-family: var(--font-pixel, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
|
|
167
205
|
}
|
|
168
206
|
|
|
207
|
+
/* An intent class on the element colours it, as on a component. Named rather
|
|
208
|
+
than read from `--intent-*` alone: those slots inherit, so a `.success`
|
|
209
|
+
container would colour a solo element where it leaves a component neutral. */
|
|
210
|
+
.pixel-solo:is(.primary, .secondary, .success, .warning, .destructive, .info) {
|
|
211
|
+
--_solo-intent-color: var(--intent-color);
|
|
212
|
+
--_solo-intent-contrast: var(--intent-contrast);
|
|
213
|
+
--_solo-intent-strong: var(--intent-strong);
|
|
214
|
+
--_solo-intent-border: var(--intent-border);
|
|
215
|
+
--_solo-intent-fill-max: var(--intent-fill-max);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/* The text colour is written only where a fill or an intent is asked for, on
|
|
219
|
+
the element or by a container's fill class. Anywhere else the element keeps
|
|
220
|
+
its own: a dark toast keeps its light text. */
|
|
221
|
+
.pixel-solo:is(
|
|
222
|
+
.solid,
|
|
223
|
+
.soft,
|
|
224
|
+
.ghost,
|
|
225
|
+
.primary,
|
|
226
|
+
.secondary,
|
|
227
|
+
.success,
|
|
228
|
+
.warning,
|
|
229
|
+
.destructive,
|
|
230
|
+
.info,
|
|
231
|
+
:is(.solid, .soft, .ghost) *
|
|
232
|
+
) {
|
|
233
|
+
color: var(--_solo-fg);
|
|
234
|
+
}
|
|
235
|
+
|
|
169
236
|
/* The clip takes the focus outline too, so focus is a second inset layer under
|
|
170
|
-
the ring, wider than it so it shows -- shadows paint first-on-top.
|
|
237
|
+
the ring, wider than it so it shows -- shadows paint first-on-top. A line of
|
|
238
|
+
the page colour sits inside that one, as in `box`: the ring is the ink, and
|
|
239
|
+
on an element filled with the ink it would not show. */
|
|
171
240
|
.pixel-solo:focus-visible {
|
|
172
241
|
box-shadow:
|
|
173
|
-
inset 0 0 0 var(--_pixel-unit) var(--
|
|
242
|
+
inset 0 0 0 var(--_pixel-unit) var(--_solo-edge),
|
|
174
243
|
inset 0 0 0 calc(var(--_pixel-unit) + var(--focus-ring-width, 3px))
|
|
175
|
-
var(
|
|
244
|
+
var(
|
|
245
|
+
--focus-ring,
|
|
246
|
+
color-mix(
|
|
247
|
+
in srgb,
|
|
248
|
+
light-dark(var(--color-neutral-950, oklch(14.5% 0 0)), var(--color-neutral-50, oklch(98.5% 0 0))) 64%,
|
|
249
|
+
transparent
|
|
250
|
+
)
|
|
251
|
+
),
|
|
252
|
+
inset 0 0 0 calc(var(--_pixel-unit) + var(--focus-ring-width, 3px) + 2px)
|
|
253
|
+
var(--color-background, light-dark(oklch(98.5% 0 0), oklch(14.5% 0 0))),
|
|
254
|
+
inset 0 0 0 100vmax var(--_solo-fill);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/* Forced colours remove every box shadow, and the ring is one: the element
|
|
258
|
+
would have no edge at all. An outline stands in for it, drawn inward so
|
|
259
|
+
nothing moves, and the clip goes so the focus outline can show. This
|
|
260
|
+
entrypoint may be the only package stylesheet loaded, so it says so itself. */
|
|
261
|
+
@media (forced-colors: active) {
|
|
262
|
+
.pixel-solo {
|
|
263
|
+
outline: var(--_pixel-unit) solid CanvasText;
|
|
264
|
+
outline-offset: calc(-1 * var(--_pixel-unit));
|
|
265
|
+
clip-path: none;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.pixel-solo:focus-visible {
|
|
269
|
+
outline-color: Highlight;
|
|
270
|
+
}
|
|
176
271
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* Sketch: uneven elliptical corners, a solid ink edge, and a small hard shadow.
|
|
2
2
|
The handwriting face is consumer-supplied, so this file has no font asset or
|
|
3
|
-
network side effect.
|
|
3
|
+
network side effect. */
|
|
4
4
|
|
|
5
5
|
/* The layer map, stated before anything uses a layer -- see `theme.css`. The
|
|
6
6
|
aesthetic's token class sits in `components`, below every utility, so a
|
|
@@ -28,7 +28,10 @@
|
|
|
28
28
|
--ui-corner-shape: round;
|
|
29
29
|
|
|
30
30
|
--ui-ink: light-dark(var(--color-neutral-950), var(--color-neutral-50));
|
|
31
|
-
|
|
31
|
+
/* Controls take the theme's control border rather than the ink, which is the
|
|
32
|
+
primary colour in both themes; see `neobrutalism.css`. */
|
|
33
|
+
--ui-control-ink: var(--color-control-border);
|
|
34
|
+
--ui-rule-ink: initial;
|
|
32
35
|
--ui-border-width: 1px;
|
|
33
36
|
--ui-border-max: 100px;
|
|
34
37
|
--ui-line-style: solid;
|
|
@@ -78,8 +81,14 @@
|
|
|
78
81
|
|
|
79
82
|
/* Rounded variant: bounded elliptical corners, so the top and bottom edges of
|
|
80
83
|
a wide element stay straight instead of bulging into an egg. On the region
|
|
81
|
-
with `.sketch`, or on one component inside it. Knobs follow R8.
|
|
82
|
-
|
|
84
|
+
with `.sketch`, or on one component inside it. Knobs follow R8.
|
|
85
|
+
|
|
86
|
+
Never on a solo element, here or in the rotation below:
|
|
87
|
+
`.sketch-solo.sketch-rounded` paints its own outline, and a complete
|
|
88
|
+
radius declared on it would inherit into whatever it holds -- a `.btn`
|
|
89
|
+
inside a solo toast took a sketch outline on a page with no sketch in
|
|
90
|
+
scope. */
|
|
91
|
+
.sketch-rounded:not(.sketch-solo) {
|
|
83
92
|
--ui-radius: var(--sketch-radius-rounded, 26px 10px 24px 11px / 12px 23px 11px 20px);
|
|
84
93
|
--ui-radius-surface: var(--sketch-radius-surface-rounded, 38px 16px 36px 17px / 16px 34px 17px 32px);
|
|
85
94
|
--ui-radius-pill: var(--sketch-radius-pill, 24px 16px 23px 17px / 17px 21px 16px 20px);
|
|
@@ -98,16 +107,16 @@
|
|
|
98
107
|
given DOM order. A knob, when set, is one outline for every position. */
|
|
99
108
|
:is(
|
|
100
109
|
.sketch,
|
|
101
|
-
.sketch-rounded,
|
|
102
|
-
:is(.sketch, .sketch-rounded)
|
|
110
|
+
.sketch-rounded:not(.sketch-solo),
|
|
111
|
+
:is(.sketch, .sketch-rounded:not(.sketch-solo))
|
|
103
112
|
:not(
|
|
104
|
-
:is(.sketch, .sketch-rounded) :is(.neobrutalism, .glass, .pixel, .chunky-tile, .cyber),
|
|
105
|
-
:is(.sketch, .sketch-rounded) :is(.neobrutalism, .glass, .pixel, .chunky-tile, .cyber) *
|
|
113
|
+
:is(.sketch, .sketch-rounded:not(.sketch-solo)) :is(.neobrutalism, .glass, .pixel, .chunky-tile, .cyber),
|
|
114
|
+
:is(.sketch, .sketch-rounded:not(.sketch-solo)) :is(.neobrutalism, .glass, .pixel, .chunky-tile, .cyber) *
|
|
106
115
|
)
|
|
107
116
|
) {
|
|
108
117
|
/* The pointed outlines: controls, fields, surfaces, and chips. */
|
|
109
|
-
&:is(.sketch, .sketch *):not(.sketch-rounded, .sketch-rounded *) {
|
|
110
|
-
&:is(.btn, .ipt, .textarea, .select, .input-group, .pre, .tooltip-bubble
|
|
118
|
+
&:is(.sketch, .sketch *):not(.sketch-rounded:not(.sketch-solo), .sketch-rounded:not(.sketch-solo) *) {
|
|
119
|
+
&:is(.btn, .ipt, .textarea, .select, .input-group, .pre, .tooltip-bubble) {
|
|
111
120
|
&:nth-child(4n + 2) {
|
|
112
121
|
--ui-radius: var(--sketch-radius, 18px 240px 15px 255px / 240px 15px 255px 18px);
|
|
113
122
|
}
|
|
@@ -139,7 +148,7 @@
|
|
|
139
148
|
}
|
|
140
149
|
}
|
|
141
150
|
|
|
142
|
-
&:is(.card, .panel, .alert) {
|
|
151
|
+
&:is(.card, .panel, .alert, .data-table) {
|
|
143
152
|
&:nth-child(4n + 2) {
|
|
144
153
|
--ui-radius-surface: var(--sketch-radius-surface, 4px 75px 5px 80px / 75px 3px 80px 4px);
|
|
145
154
|
}
|
|
@@ -169,8 +178,8 @@
|
|
|
169
178
|
}
|
|
170
179
|
|
|
171
180
|
/* The rounded outlines, in the same four places. */
|
|
172
|
-
&:is(.sketch-rounded, .sketch-rounded *) {
|
|
173
|
-
&:is(.btn, .ipt, .textarea, .select, .input-group, .pre, .tooltip-bubble
|
|
181
|
+
&:is(.sketch-rounded:not(.sketch-solo), .sketch-rounded:not(.sketch-solo) *) {
|
|
182
|
+
&:is(.btn, .ipt, .textarea, .select, .input-group, .pre, .tooltip-bubble) {
|
|
174
183
|
&:nth-child(4n + 2) {
|
|
175
184
|
--ui-radius: var(--sketch-radius-rounded, 11px 25px 12px 24px / 23px 11px 22px 12px);
|
|
176
185
|
}
|
|
@@ -202,7 +211,7 @@
|
|
|
202
211
|
}
|
|
203
212
|
}
|
|
204
213
|
|
|
205
|
-
&:is(.card, .panel, .alert) {
|
|
214
|
+
&:is(.card, .panel, .alert, .data-table) {
|
|
206
215
|
&:nth-child(4n + 2) {
|
|
207
216
|
--ui-radius-surface: var(--sketch-radius-surface-rounded, 17px 36px 18px 34px / 33px 16px 32px 17px);
|
|
208
217
|
}
|
|
@@ -274,19 +283,82 @@
|
|
|
274
283
|
}
|
|
275
284
|
}
|
|
276
285
|
|
|
277
|
-
/* Solo: the look
|
|
278
|
-
|
|
286
|
+
/* Solo: the same look painted onto the one element carrying the class, for an
|
|
287
|
+
element the package does not style. See docs/internal/model.md#solo-classes and
|
|
288
|
+
the note on `.glass-solo`: it composes with the element's presentation,
|
|
289
|
+
intent, and elevation, and reads its material from its own knobs and
|
|
290
|
+
foundation tokens with literal fallbacks, never a shared material `--ui-*`
|
|
291
|
+
or `--elevation-color` token. Unlayered, and not for this package's own
|
|
292
|
+
components. */
|
|
279
293
|
.sketch-solo {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
294
|
+
/* The composition, the same in every solo class; `registry.test.ts` holds
|
|
295
|
+
the copies together. See the note on `.glass-solo`. */
|
|
296
|
+
--_solo-intent-color: initial;
|
|
297
|
+
--_solo-intent-contrast: initial;
|
|
298
|
+
--_solo-intent-strong: initial;
|
|
299
|
+
--_solo-intent-border: initial;
|
|
300
|
+
--_solo-intent-fill-max: initial;
|
|
301
|
+
--_solo-color: var(--_solo-intent-color, var(--color-text, light-dark(oklch(14.5% 0 0), oklch(98.5% 0 0))));
|
|
302
|
+
--_solo-contrast: var(
|
|
303
|
+
--_solo-intent-contrast,
|
|
304
|
+
var(--color-text-contrast, light-dark(oklch(98.5% 0 0), oklch(14.5% 0 0)))
|
|
305
|
+
);
|
|
306
|
+
--_solo-strong: var(--_solo-intent-strong, var(--color-text-strong, light-dark(oklch(20.5% 0 0), oklch(97% 0 0))));
|
|
307
|
+
--_solo-capped: min(var(--ui-fill, 0%), var(--_solo-intent-fill-max, 20%));
|
|
308
|
+
--_solo-fill: color-mix(in oklab, var(--_solo-color) var(--_solo-capped), transparent);
|
|
309
|
+
--_solo-on-fill: min(var(--ui-fg-on-fill, 0%), max(0%, calc(var(--_solo-capped) * 2 - 100%)));
|
|
310
|
+
--_solo-fg: color-mix(in oklab, var(--_solo-contrast) var(--_solo-on-fill), var(--_solo-strong));
|
|
311
|
+
/* The line with no intent on the element: this aesthetic's own ink. */
|
|
312
|
+
--_solo-ink: var(
|
|
313
|
+
--_solo-intent-border,
|
|
314
|
+
light-dark(var(--color-neutral-950, oklch(14.5% 0 0)), var(--color-neutral-50, oklch(98.5% 0 0)))
|
|
315
|
+
);
|
|
316
|
+
--_solo-edge: color-mix(in oklab, var(--_solo-ink) var(--ui-border, 100%), var(--_solo-fill));
|
|
317
|
+
--_solo-depth: calc(2px * var(--ui-elevation, 1));
|
|
318
|
+
|
|
319
|
+
border: 1px solid var(--_solo-edge);
|
|
283
320
|
/* The surface shape: the element this exists for is usually a pane. An action
|
|
284
321
|
takes the control shape below. */
|
|
285
322
|
border-radius: var(--sketch-radius-surface, 80px 4px 75px 5px / 3px 70px 4px 80px);
|
|
286
|
-
|
|
323
|
+
/* The aesthetic's neutral depth cue, not the ink: the class casts its 2px
|
|
324
|
+
offset in the depth colour, and casting a solo pane in full ink would read
|
|
325
|
+
as a heavier, neobrutalist slab. The depth colour is a literal, for the reason
|
|
326
|
+
`.glass-solo` gives. */
|
|
327
|
+
box-shadow:
|
|
328
|
+
var(--_solo-depth) var(--_solo-depth) 0 0 light-dark(rgb(15 23 42 / 0.08), rgb(0 0 0 / 0.55)),
|
|
329
|
+
inset 0 0 0 100vmax var(--_solo-fill);
|
|
287
330
|
font-family: var(--font-sketch, cursive);
|
|
288
331
|
}
|
|
289
332
|
|
|
333
|
+
/* An intent class on the element colours it, as on a component. Named rather
|
|
334
|
+
than read from `--intent-*` alone: those slots inherit, so a `.success`
|
|
335
|
+
container would colour a solo element where it leaves a component neutral. */
|
|
336
|
+
.sketch-solo:is(.primary, .secondary, .success, .warning, .destructive, .info) {
|
|
337
|
+
--_solo-intent-color: var(--intent-color);
|
|
338
|
+
--_solo-intent-contrast: var(--intent-contrast);
|
|
339
|
+
--_solo-intent-strong: var(--intent-strong);
|
|
340
|
+
--_solo-intent-border: var(--intent-border);
|
|
341
|
+
--_solo-intent-fill-max: var(--intent-fill-max);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/* The text colour is written only where a fill or an intent is asked for, on
|
|
345
|
+
the element or by a container's fill class. Anywhere else the element keeps
|
|
346
|
+
its own: a dark toast keeps its light text. */
|
|
347
|
+
.sketch-solo:is(
|
|
348
|
+
.solid,
|
|
349
|
+
.soft,
|
|
350
|
+
.ghost,
|
|
351
|
+
.primary,
|
|
352
|
+
.secondary,
|
|
353
|
+
.success,
|
|
354
|
+
.warning,
|
|
355
|
+
.destructive,
|
|
356
|
+
.info,
|
|
357
|
+
:is(.solid, .soft, .ghost) *
|
|
358
|
+
) {
|
|
359
|
+
color: var(--_solo-fg);
|
|
360
|
+
}
|
|
361
|
+
|
|
290
362
|
/* An action takes the expressive control shape. */
|
|
291
363
|
.sketch-solo:is(
|
|
292
364
|
button,
|
|
@@ -306,14 +378,14 @@
|
|
|
306
378
|
}
|
|
307
379
|
|
|
308
380
|
.sketch-solo.sketch-rounded:is(
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
) {
|
|
381
|
+
button,
|
|
382
|
+
a[href],
|
|
383
|
+
[role="button"],
|
|
384
|
+
summary,
|
|
385
|
+
input[type="button"],
|
|
386
|
+
input[type="submit"],
|
|
387
|
+
input[type="reset"]
|
|
388
|
+
) {
|
|
317
389
|
border-radius: var(--sketch-radius-rounded, 26px 10px 24px 11px / 12px 23px 11px 20px);
|
|
318
390
|
}
|
|
319
391
|
|