@codenhub/styles 0.4.0 → 0.5.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 +1 -1
- 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 +1 -1
- package/dist/aesthetics/neobrutalism.css +1 -1
- package/dist/aesthetics/pixel.css +1 -1
- package/dist/aesthetics/sketch.css +1 -0
- package/dist/components.css +1 -1
- package/dist/index.css +1 -1
- package/dist/native.css +1 -1
- package/dist/palette.css +1 -1
- package/dist/theme.css +1 -1
- package/dist/tw/aesthetics/chunky-tile.css +142 -126
- package/dist/tw/aesthetics/cyber.css +132 -95
- package/dist/tw/aesthetics/glass.css +97 -56
- package/dist/tw/aesthetics/index.css +1 -0
- package/dist/tw/aesthetics/neobrutalism.css +99 -52
- package/dist/tw/aesthetics/pixel.css +127 -87
- package/dist/tw/aesthetics/sketch.css +326 -0
- package/dist/tw/box.css +100 -35
- package/dist/tw/components/button.css +40 -22
- package/dist/tw/components/feedback.css +29 -14
- package/dist/tw/components/form.css +151 -155
- package/dist/tw/components/index.css +15 -3
- package/dist/tw/components/loader.css +34 -25
- package/dist/tw/components/surface.css +28 -71
- package/dist/tw/components/tooltip.css +20 -10
- package/dist/tw/corner.css +26 -0
- package/dist/tw/elevation.css +8 -9
- package/dist/tw/intent.css +17 -9
- package/dist/tw/native.css +45 -39
- package/dist/tw/palette.css +452 -446
- package/dist/tw/presentation.css +9 -4
- package/dist/tw/surface.css +62 -0
- package/dist/tw/theme.css +106 -75
- package/dist/tw/utilities/content.css +25 -16
- package/dist/tw/utilities/layout.css +2 -2
- package/docs/accessibility.md +16 -16
- package/docs/changelog/0.5.0.md +38 -0
- package/docs/changelog/index.md +1 -0
- package/docs/index.md +3 -3
- package/docs/setup.md +23 -3
- package/docs/usage/aesthetics.md +56 -13
- package/docs/usage/buttons.md +13 -13
- package/docs/usage/composing.md +11 -11
- package/docs/usage/content-and-layout.md +13 -13
- package/docs/usage/customizing.md +90 -52
- package/docs/usage/feedback.md +1 -1
- package/docs/usage/forms.md +11 -11
- package/docs/usage/theming.md +1 -1
- package/llms-full.txt +274 -136
- package/package.json +12 -2
package/docs/setup.md
CHANGED
|
@@ -89,8 +89,8 @@ Compiled entrypoints are ready-to-import CSS and require only tooling that can r
|
|
|
89
89
|
| `@codenhub/styles/palette` | Generated, self-contained `--palette-*` custom properties: every intent/presentation cell's fill, text, and edge color, plus the flat `border`/`surface`/`text` neutral tokens, pre-composed to a flat value. For a consumer that cannot take this package as a build-time dependency (an optional peer, for example) but wants to look consistent with it. Not a replacement for the components themselves when Tailwind is available -- see [Customizing → Generated palette](./usage/customizing.md#generated-palette). |
|
|
90
90
|
| `@codenhub/styles/components` | Compiled theme tokens, typography utilities, and every component class. Includes static reduced-motion loader masks; no reset, layout/content utilities, or native mappings. |
|
|
91
91
|
| `@codenhub/styles/native` | Compiled complete surface plus classless mappings for headings, text, content elements, form controls, and buttons. Applies the reset and broad element selectors. |
|
|
92
|
-
| `@codenhub/styles/aesthetics` | Compiled `.neobrutalism`, `.glass`, `.pixel`, `.chunky-tile`, and `.
|
|
93
|
-
| `@codenhub/styles/aesthetics/*` | One compiled aesthetic and its solo class: `/neobrutalism`, `/glass`, `/pixel`, `/chunky-tile`, or `/
|
|
92
|
+
| `@codenhub/styles/aesthetics` | Compiled `.neobrutalism`, `.glass`, `.pixel`, `.chunky-tile`, `.cyber`, and `.sketch` classes, and each one's `-solo` class. Adds no tokens or components of its own; import after the base stylesheet. |
|
|
93
|
+
| `@codenhub/styles/aesthetics/*` | One compiled aesthetic and its solo class: `/neobrutalism`, `/glass`, `/pixel`, `/chunky-tile`, `/cyber`, or `/sketch`. Same rules and ordering as the combined file. |
|
|
94
94
|
| `@codenhub/styles/tw` | Source equivalent of the complete stylesheet. Imports Tailwind itself, theme, typography, utilities, components, and reset; applies the same global rules. |
|
|
95
95
|
| `@codenhub/styles/tw/theme` | Source theme, tokens, and presentation classes. Imports Tailwind's theme layer; emits root/system/explicit theme selectors and defines the package's custom `dark:` variant. |
|
|
96
96
|
| `@codenhub/styles/tw/components` | Published Tailwind source for theme, typography, buttons, feedback, forms, loaders, surfaces, and tooltips, including static reduced-motion loader masks. No reset, layout/content utilities, or native mappings. |
|
|
@@ -104,13 +104,33 @@ Compiled entrypoints are ready-to-import CSS and require only tooling that can r
|
|
|
104
104
|
| `@codenhub/styles/tw/native` | Source complete surface plus reset and classless native-element mappings; broadest global effects. |
|
|
105
105
|
| `@codenhub/styles/tw/typography` | Source theme plus typography utilities; sets theme selectors but no reset or classless mappings. |
|
|
106
106
|
| `@codenhub/styles/tw/utilities` | Source theme and typography composition plus layout and content utilities; safelists the package utility names. |
|
|
107
|
-
| `@codenhub/styles/tw/aesthetics` | Source aesthetics, combined. `/tw/aesthetics/neobrutalism`, `/glass`, `/pixel`, `/chunky-tile`, and `/
|
|
107
|
+
| `@codenhub/styles/tw/aesthetics` | Source aesthetics, combined. `/tw/aesthetics/neobrutalism`, `/glass`, `/pixel`, `/chunky-tile`, `/cyber`, and `/sketch` publish one apiece. Plain CSS with no theme or reset side effects. |
|
|
108
108
|
|
|
109
109
|
Avoid importing overlapping entrypoints in the same build unless duplicate generated CSS is acceptable; pick the narrowest entrypoint that covers what a page needs.
|
|
110
110
|
|
|
111
|
+
## Cascade layers
|
|
112
|
+
|
|
113
|
+
Every entrypoint maps its CSS into Tailwind's four cascade layers (with documented unlayered exceptions), in Tailwind's order, and declares that order before using a layer, so the result does not depend on which file loads first:
|
|
114
|
+
|
|
115
|
+
| Layer | Holds |
|
|
116
|
+
| ------------ | ---------------------------------------------------------------------------------------------- |
|
|
117
|
+
| `theme` | Tailwind's theme, the foundation tokens, the theme selectors, and `/palette`. |
|
|
118
|
+
| `base` | The reset and the classless element styles. |
|
|
119
|
+
| `components` | The intent, presentation, elevation, and aesthetic classes. |
|
|
120
|
+
| `utilities` | Every component (`.btn`, `.card`, `.ipt`, ...), next to your own Tailwind utilities. |
|
|
121
|
+
| _unlayered_ | The `forced-colors` and reduced-motion overrides, the `<dialog>` fix, and the `-solo` classes. |
|
|
122
|
+
|
|
123
|
+
What that means in practice:
|
|
124
|
+
|
|
125
|
+
- **Your utility or unlayered CSS beats an intent, presentation, elevation, or aesthetic class** on the same element for normal declarations. `[--ui-fill:50%]` on a `.solid` button, `font-serif` on a `.pixel` region, or `.my-card { --ui-radius: 0 }` in your own stylesheet all apply.
|
|
126
|
+
- **A component and your utility share the `utilities` layer.** Which wins is decided by specificity and then source order, as between any two utilities. Your unlayered normal CSS always beats a component.
|
|
127
|
+
- **State beats your intent.** An `aria-invalid` field stays destructive even with an intent utility on it.
|
|
128
|
+
- **The `-solo` classes are unlayered on purpose**, so they beat a foreign component's own styles; tune them through their knobs rather than with utilities.
|
|
129
|
+
|
|
111
130
|
## Requirements
|
|
112
131
|
|
|
113
132
|
- Consumer tooling must resolve package CSS imports.
|
|
133
|
+
- Every shipped stylesheet can be pasted into an HTML `<style>` element, for critical-CSS inlining or a server-rendered head: none contains the `</style` sequence that would end the element early.
|
|
114
134
|
- Chrome 123, Safari 17.5, or Firefox 121 and newer. Color tokens are declared with `light-dark()` and selected by `color-scheme` (Firefox 120), and `.input-group` propagates a nested control's invalid and disabled state with `:has()` (Firefox 121).
|
|
115
135
|
- Tailwind CSS 4 or newer is required only for `/tw` source entrypoints.
|
|
116
136
|
- The package has no JavaScript runtime. Apps must provide semantic HTML, ARIA, keyboard behavior, focus management, validation, and announcements; see [Accessibility](./accessibility.md).
|
package/docs/usage/aesthetics.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Aesthetics
|
|
3
|
-
description: The
|
|
3
|
+
description: The six shipped aesthetics in depth, their solo classes, and their documented exceptions.
|
|
4
4
|
order: 4
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -31,6 +31,7 @@ Like presentation, an aesthetic class cascades to any subtree:
|
|
|
31
31
|
| `.pixel` | Corners cut by one grid unit, a chunky outline drawn as an inset ring, and the consumer-supplied `--font-pixel` over monospace. |
|
|
32
32
|
| `.chunky-tile` | Rounded slabs seated on a darker shade of themselves, with a press that moves the element down into its own bar. |
|
|
33
33
|
| `.cyber` | Bevelled corners, a thin bright edge, and a glow in the component's own colour. |
|
|
34
|
+
| `.sketch` | Varying elliptical corners, a solid ink line with dashed accents, a small offset shadow, and an optional handwriting face. |
|
|
34
35
|
|
|
35
36
|
Aesthetics compose with every supported fill and edge pair. `.ghost.edgeless` intentionally removes the visible material traits from components whose aesthetic is expressed only through their fill, edge, or elevation.
|
|
36
37
|
|
|
@@ -38,6 +39,8 @@ An explicit presentation on the element still wins over the aesthetic's defaults
|
|
|
38
39
|
|
|
39
40
|
An aesthetic directly on a component likewise wins over an inherited aesthetic. This includes tooltip bubbles: `.tooltip-bubble.glass` gets the complete glass bubble under a pixel ancestor, and `.tooltip-bubble.pixel` gets the complete stepped bubble under a glass ancestor.
|
|
40
41
|
|
|
42
|
+
Your own CSS wins over an aesthetic. The aesthetic classes sit in the `components` cascade layer, so a Tailwind utility on the same element -- `font-mono` on a `.pixel` region, `[--ui-radius:0]` on a `.cyber` one -- or a rule in your own unlayered stylesheet beats them. See [Setup → Cascade layers](../setup.md#cascade-layers).
|
|
43
|
+
|
|
41
44
|
Each aesthetic that scales from one number publishes it as a knob — see [Customizing → Aesthetic tokens](./customizing.md#aesthetic-tokens) for how knobs resolve and where they can be set. This page covers what each aesthetic looks like and where it makes documented exceptions.
|
|
42
45
|
|
|
43
46
|
## Neobrutalism
|
|
@@ -72,8 +75,10 @@ The shadow is cast in the component's own intent, so a success button throws a g
|
|
|
72
75
|
|
|
73
76
|
**Exceptions:**
|
|
74
77
|
|
|
78
|
+
- Every surface in a glass region is glass, a neutral `.card.soft`, `.panel`, and `.alert` included.
|
|
75
79
|
- The blur applies to `.card`, `.panel`, `.alert`, and the tooltip bubble only. Controls stay solid and sit on the glass: a blur under every control of a dense cluster costs a composited layer apiece and reads as noise. Controls still take the aesthetic's radius, border, and shadow.
|
|
76
80
|
- Under `prefers-reduced-transparency: reduce`, glass surfaces drop the blur and become opaque.
|
|
81
|
+
- Controls draw their line in the page's ink at 55% rather than the white hairline, which would erase an unchecked checkbox on a light page. It is `--ui-control-ink`; set it on the region to choose another.
|
|
77
82
|
|
|
78
83
|
## Pixel
|
|
79
84
|
|
|
@@ -116,10 +121,11 @@ The bar is a darker shade of the element's own colour rather than a shadow under
|
|
|
116
121
|
```
|
|
117
122
|
|
|
118
123
|
- `--font-rounded` is yours to supply. A heavy rounded grotesque is most of this look and the package ships no font binary, so with nothing supplied the page's own stack is used.
|
|
119
|
-
-
|
|
124
|
+
- Labels are drawn heavier and slightly tracked, through `--ui-label-weight` and `--ui-label-tracking`, so your own `font-*` or `tracking-*` utility still wins. It reaches `.btn` and `.badge`, and a bare `<button>` only where `/native` styles it. Casing is left alone: how a label is worded is the application's decision, so if you want uppercase buttons, write that rule in your own stylesheet.
|
|
120
125
|
- `.card.interactive` presses like a `.btn`, so a chunky answer tile drops onto its bar on click; `.card.pressable` gets the same press on its own. A plain `.card` stays put.
|
|
121
126
|
- The shipped `.primary` is a near-black-or-near-white monochrome depending on theme, and the bar mixes toward a fixed black regardless of theme. In light theme this leaves a primary button's bar almost invisible against its own near-black plate (measured `1.04:1`, 10 units of sRGB distance); in dark theme the near-white plate against the same black-anchored bar reads fine (`2.48:1`, 154 units). Give `.primary` a hue of its own if it is the call to action and needs the depth cue in both themes.
|
|
122
127
|
- Depth in this aesthetic is the bar, never a blurred drop shadow. Anything the registry rests flat sits flush on the page.
|
|
128
|
+
- Controls draw a heavier grey than the tiles around them -- `neutral-600` in light, `neutral-400` in dark -- through `--ui-control-ink`, so a field reads as a field inside a tile.
|
|
123
129
|
|
|
124
130
|
## Cyber
|
|
125
131
|
|
|
@@ -127,7 +133,7 @@ Bevelled corners, a 1px edge, and a glow in the component's own colour: a succes
|
|
|
127
133
|
|
|
128
134
|
Controls and surfaces take the cut on opposite diagonals, so a button and the card around it read as the same material and as different things: buttons and fields cut top-left and bottom-right, cards, panels, and alerts top-right and bottom-left. Anything fully round cuts to points -- a radio, a switch knob, and the tooltip icon become diamonds, a pill button or a badge a pointed hexagon -- and chips square, so the checkbox reads as a plain square beside the diamond radio.
|
|
129
135
|
|
|
130
|
-
`--cyber-cut` is the
|
|
136
|
+
`--cyber-cut` is the cut at the default size, `0.625rem`. Controls scale it with their size step, so a `.p-xs` icon button takes half of it and keeps its corners, and it stays a true 45 degrees. `--cyber-shape` and `--cyber-shape-surface` replace the default placement with any `border-radius` value, used as written. `--cyber-glow` is the glow's blur, `8px`. `--cyber-ink` is the neutral line and glow colour, which follows the theme by default -- near-black on light, near-white on dark -- and is where a neon neutral goes if you want one.
|
|
131
137
|
|
|
132
138
|
```html
|
|
133
139
|
<section class="cyber" style="--cyber-ink: rgb(0 229 255); --cyber-cut: 0.75rem">
|
|
@@ -135,7 +141,7 @@ Controls and surfaces take the cut on opposite diagonals, so a button and the ca
|
|
|
135
141
|
</section>
|
|
136
142
|
```
|
|
137
143
|
|
|
138
|
-
Other shapes are a value away. Set them on the `.cyber` element or any ancestor
|
|
144
|
+
Other shapes are a value away. Set them on the `.cyber` element or any ancestor. `--ui-radius` set on an element reaches that element and every component inside it that does not set its own. A shape you set is used as written and does not scale, so for a scaled one on a single control use `.cut-diagonal-reverse` instead.
|
|
139
145
|
|
|
140
146
|
| Shape | Value |
|
|
141
147
|
| ---------------------- | --------------------- |
|
|
@@ -156,23 +162,60 @@ A parallelogram slants its sides into the content, so give a surface that takes
|
|
|
156
162
|
**Exceptions:**
|
|
157
163
|
|
|
158
164
|
- The bevel is Chromium-only today. Firefox and Safari do not draw `corner-shape` yet, and there the aesthetic squares its cut corners instead of rounding them, and what is fully round stays round, so the look degrades to square, lined, and glowing. It picks up the bevel with no change once an engine ships it.
|
|
159
|
-
- The glow is depth, so it
|
|
165
|
+
- The glow is a halo, not depth, so every component takes it -- fields, badges, and alerts included -- and `.flat` does not take it off. `.raised` and `.floating` add no shadow under this aesthetic.
|
|
160
166
|
- In the light theme the glow of a neutral or `.primary` component is its near-black ink, which reads as a soft shadow rather than as light. The look is at its strongest on a dark page, or with a hued `--cyber-ink`.
|
|
161
167
|
- A plain `.btn.icon` is a square control, so it takes the control diagonal; a `.btn.icon.pill` is round, so it becomes a diamond.
|
|
162
168
|
- `--font-cyber` is yours to supply. The package ships no font binary, so the aesthetic falls back to the monospace stack.
|
|
163
169
|
- Casing is left alone, for the reason [Chunky tile](#chunky-tile) gives.
|
|
164
170
|
|
|
171
|
+
## Sketch
|
|
172
|
+
|
|
173
|
+
Hand-drawn outlines: controls take long, uneven elliptical corners, and cards, panels, and alerts take sharper ones that stay clear of their padding. Siblings rotate through four outlines by position, and a field's control takes its field's position, so a row of buttons or a stacked form does not repeat one shape. The rotation is stable for a given DOM order, not random on each render. Every outline is a complete `border-radius`, used as written rather than scaled by the size step or placed by `.cut-diagonal`.
|
|
174
|
+
|
|
175
|
+
The 1px ink line is solid; checkboxes, dividers, and table rules are dashed. `--ui-line-style: dashed` dashes any other component, and `--ui-rule-style: solid` puts a divider or table back to solid. The 2px hard shadow is a small neutral depth cue.
|
|
176
|
+
|
|
177
|
+
`--sketch-radius`, `--sketch-radius-surface`, and `--sketch-radius-pill` replace the control, surface, and pill-button outlines. Set one and every position takes that one outline. To shape a single component instead, set `--ui-radius` (`--ui-radius-surface` on a surface) on it.
|
|
178
|
+
|
|
179
|
+
```html
|
|
180
|
+
<section class="sketch" style='--font-sketch: "Comic Sans MS", cursive'>
|
|
181
|
+
<button class="btn primary">Send note</button>
|
|
182
|
+
<button class="btn ghost edged" style="--ui-line-style: dashed">Draft note</button>
|
|
183
|
+
</section>
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
The dashed button is `ghost edged` because a filled button has no separate line to dash.
|
|
187
|
+
|
|
188
|
+
`.sketch-rounded` trades the long corners for short, rounded ones, bounded so a wide element keeps straight top and bottom edges. Put it beside `.sketch` on the region, or on one component inside it. `--sketch-radius-rounded` and `--sketch-radius-surface-rounded` are its knobs.
|
|
189
|
+
|
|
190
|
+
```html
|
|
191
|
+
<section class="sketch sketch-rounded">
|
|
192
|
+
<div class="card">
|
|
193
|
+
<button class="btn primary">Rounded action</button>
|
|
194
|
+
</div>
|
|
195
|
+
</section>
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
**Exceptions:**
|
|
199
|
+
|
|
200
|
+
- Sketch names components to rotate their outlines, so its outlines reach only this package's components; a region of another aesthetic nested inside a sketch region keeps that aesthetic's corners.
|
|
201
|
+
- Chips -- checkboxes, key caps, code, badges, switches, and progress bars -- rotate through small uneven outlines through `--ui-radius-tight`. Set that token on a chip to choose its shape.
|
|
202
|
+
- A `.btn.pill` takes a rounded pill bounded to its own height, so a wide one does not become an oval. Badges, progress bars, and switches take their chip outline. Radios and the tooltip icon stay circles, slightly uneven, so a radio is never mistaken for a checkbox. An explicit `--ui-radius-pill` on an element still wins.
|
|
203
|
+
- `--font-sketch` is yours to supply. The package ships no handwriting font and falls back to the platform `cursive` family.
|
|
204
|
+
- Buttons press with the plain `scale(0.97)`; reduced motion turns it off.
|
|
205
|
+
- Forced-colours mode draws the dashed accents solid, like every other material line.
|
|
206
|
+
|
|
165
207
|
## Solo classes
|
|
166
208
|
|
|
167
209
|
An aesthetic class sets material tokens and nothing paints until a component reads them, so `.glass` on an element this package does not style -- a toast from another library, a dialog, a plain `<div>` on a page without the base stylesheet -- changes nothing. Each aesthetic also ships a solo class that paints its look directly onto the one element carrying it:
|
|
168
210
|
|
|
169
|
-
| Aesthetic | Solo class | Paints
|
|
170
|
-
| --------------- | -------------------- |
|
|
171
|
-
| `.glass` | `.glass-solo` | Translucent ground, hairline edge, blur, the tucked two-layer shadow, the surface corner.
|
|
172
|
-
| `.neobrutalism` | `.neobrutalism-solo` | 2px ink edge, square corners, the hard offset slab.
|
|
173
|
-
| `.pixel` | `.pixel-solo` | The stepped silhouette, the inset ring in place of a border, the pixel font.
|
|
174
|
-
| `.chunky-tile` | `.chunky-tile-solo` | The tile corner, 2px edge, the bar under it, the rounded font.
|
|
175
|
-
| `.cyber` | `.cyber-solo` | The surface diagonal (the control one on an action), 1px edge, the glow, the font.
|
|
211
|
+
| Aesthetic | Solo class | Paints |
|
|
212
|
+
| --------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
213
|
+
| `.glass` | `.glass-solo` | Translucent ground, hairline edge, blur, the tucked two-layer shadow, the surface corner. |
|
|
214
|
+
| `.neobrutalism` | `.neobrutalism-solo` | 2px ink edge, square corners, the hard offset slab. |
|
|
215
|
+
| `.pixel` | `.pixel-solo` | The stepped silhouette, the inset ring in place of a border, the pixel font. |
|
|
216
|
+
| `.chunky-tile` | `.chunky-tile-solo` | The tile corner, 2px edge, the bar under it, the rounded font. |
|
|
217
|
+
| `.cyber` | `.cyber-solo` | The surface diagonal (the control one on an action), 1px edge, the glow, the font. |
|
|
218
|
+
| `.sketch` | `.sketch-solo` | Uneven elliptical corners (sharp surface outline on a pane, expressive control outline on an action; subtle rounded contours when paired with `.sketch-rounded`), a 1px solid ink line, the 2px offset shadow, the handwriting face. |
|
|
176
219
|
|
|
177
220
|
```css
|
|
178
221
|
/* The only stylesheet from this package on the page. */
|
|
@@ -186,7 +229,7 @@ An aesthetic class sets material tokens and nothing paints until a component rea
|
|
|
186
229
|
A solo class ships in the same entrypoint as its aesthetic, and needs nothing else loaded:
|
|
187
230
|
|
|
188
231
|
- **It paints material, not colour.** Edge, corner, depth, silhouette, backdrop, font, and press. No intent, no fill amount, no hover tint -- the element has no presentation to compose. Glass's translucent ground is the one fill, because it is glass's material.
|
|
189
|
-
- **It reads its aesthetic's knobs and the theme's tokens, with the shipped values as fallbacks.** `--glass-radius-surface`, `--neo-offset`, `--pixel-unit`, `--tile-lift`, `--tile-radius`, `--cyber-cut`, `--cyber-shape`, `--cyber-shape-surface`, `--cyber-glow`, `--cyber-ink`, and the font knobs all work, set on the element or any ancestor. With the theme loaded it follows it; without it, it renders the shipped look.
|
|
232
|
+
- **It reads its aesthetic's knobs and the theme's tokens, with the shipped values as fallbacks.** `--glass-radius-surface`, `--neo-offset`, `--pixel-unit`, `--tile-lift`, `--tile-radius`, `--cyber-cut`, `--cyber-shape`, `--cyber-shape-surface`, `--cyber-glow`, `--cyber-ink`, `--sketch-radius`, `--sketch-radius-surface`, `--sketch-radius-rounded`, `--sketch-radius-surface-rounded`, and the font knobs (including `--font-sketch`) all work, set on the element or any ancestor. With the theme loaded it follows it; without it, it renders the shipped look.
|
|
190
233
|
- **It ignores the aesthetic around it.** It reads no `--ui-*` or `--elevation-color`, so a `.glass-solo` inside a `.pixel` region keeps its corners. The elevation modifiers do not reach it either.
|
|
191
234
|
- **It beats a foreign component's own styles.** The rules are unlayered and one class deep, so they win over a component's zero-specificity or layered rules wherever the two load. The flip side is that a Tailwind utility on the same element (`rounded-none`) loses to it: tune a solo class through its knobs.
|
|
192
235
|
- **It presses only an action.** Neobrutalism, chunky tile, and cyber press a `button`, `a[href]`, `[role="button"]`, `summary`, or button-type `input` that is not disabled; a container stays put, so a toast does not sink when clicked. Reduced motion drops the movement. Chunky tile's heavier label follows the same rule.
|
package/docs/usage/buttons.md
CHANGED
|
@@ -12,15 +12,15 @@ Intent classes map color tokens into button tone slots. [Presentation](./composi
|
|
|
12
12
|
|
|
13
13
|
Intent classes:
|
|
14
14
|
|
|
15
|
-
| Class
|
|
16
|
-
|
|
|
17
|
-
| `.neutral` _(default)_
|
|
18
|
-
| `.primary`
|
|
19
|
-
| `.secondary`
|
|
20
|
-
| `.success`
|
|
21
|
-
| `.warning`
|
|
22
|
-
| `.destructive
|
|
23
|
-
| `.info`
|
|
15
|
+
| Class | Meaning |
|
|
16
|
+
| ---------------------- | ------------------------------ |
|
|
17
|
+
| `.neutral` _(default)_ | No specific intent. |
|
|
18
|
+
| `.primary` | Primary action. |
|
|
19
|
+
| `.secondary` | Secondary/accent action. |
|
|
20
|
+
| `.success` | Successful or positive action. |
|
|
21
|
+
| `.warning` | Warning/caution action. |
|
|
22
|
+
| `.destructive` | Destructive or error action. |
|
|
23
|
+
| `.info` | Informational action. |
|
|
24
24
|
|
|
25
25
|
Every component that supports intent accepts the same list and reads the same [intent tokens](./theming.md#intent-tokens), so a custom intent class works everywhere without touching a component.
|
|
26
26
|
|
|
@@ -30,12 +30,12 @@ Size and shape classes:
|
|
|
30
30
|
|
|
31
31
|
| Class | Purpose |
|
|
32
32
|
| ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
33
|
-
| `.pill` | Fully rounded button corners
|
|
33
|
+
| `.pill` | Fully rounded button corners by default; under sketch it takes organic hand-drawn pill contours avoiding egg-shaped distortion. |
|
|
34
34
|
| `.sm` | Smaller button. |
|
|
35
35
|
| `.lg` | Larger button. |
|
|
36
|
-
| `.p-xs
|
|
37
|
-
| `.p-sm
|
|
38
|
-
| `.p-lg
|
|
36
|
+
| `.p-xs` | Tightest padding modifier (`px-2 py-0.5`; icon `p-0.5`). Also drops the `--control-height` minimum so a chip-sized button fits a table cell or a dense toolbar; every other size and padding class keeps that floor for a labeled button. |
|
|
37
|
+
| `.p-sm` | Compact padding modifier (`px-2.5 py-1`; icon `p-1`). |
|
|
38
|
+
| `.p-lg` | Spacious padding modifier (`px-6 py-3`; icon `p-3`). |
|
|
39
39
|
| `.icon` | Square icon button, sized to its own padding rather than to `--control-height`. Use an accessible name in HTML. |
|
|
40
40
|
| `.disabled`, `[disabled]`, `[aria-disabled="true"]`, `[data-disabled]` | Disabled styling. |
|
|
41
41
|
|
package/docs/usage/composing.md
CHANGED
|
@@ -57,7 +57,7 @@ The combinations mean exactly what they spell:
|
|
|
57
57
|
<!-- A field sunk into the page -->
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
-
A fill class never decides an edge and an edge class never decides a fill. Use `.solid.edgeless` for a filled box with no line
|
|
60
|
+
A fill class never decides an edge and an edge class never decides a fill. Use `.solid.edgeless` for a filled box with no line; `.solid.edged` renders the same box, because the line fades out as the fill fills in.
|
|
61
61
|
|
|
62
62
|
The edge is the silhouette and nothing else. Rules _inside_ a component that has an inside are a separate switch — see [Content and layout → Table rules](./content-and-layout.md#table-rules) — because tying them to this axis made them arrive by implication rather than by request.
|
|
63
63
|
|
|
@@ -125,26 +125,26 @@ Presentation is two independent axes, so they get a column each. A `Yes` means t
|
|
|
125
125
|
|
|
126
126
|
Every other text control floors a _cascaded_ `.edgeless` and honours its own: a `.edgeless` toolbar will not erase the line of a field nobody classed, while `.ipt.edgeless` is a consumer describing what they want and gets it.
|
|
127
127
|
|
|
128
|
-
|
|
128
|
+
State and modifier classes such as `.interactive`, `.hoverable`, `.pressable`, `.invalid`, `.p-sm`, and `.vertical` sit above this map and are documented with their component.
|
|
129
129
|
|
|
130
130
|
## Elevation
|
|
131
131
|
|
|
132
132
|
Depth is a modifier, not an axis. Nothing is raised until an [aesthetic](./aesthetics.md) draws depth or one of these classes asks for it.
|
|
133
133
|
|
|
134
|
-
| Class
|
|
135
|
-
|
|
|
136
|
-
| `.
|
|
137
|
-
| `.
|
|
138
|
-
| `.
|
|
134
|
+
| Class | Depth |
|
|
135
|
+
| ----------- | ------------------------------------------------------------------------ |
|
|
136
|
+
| `.flat` | Removes part-based elevation; glass surfaces keep their complete shadow. |
|
|
137
|
+
| `.raised` | One unit of the depth in scope. Cards, tiles, popovers that sit close. |
|
|
138
|
+
| `.floating` | Twice it, for menus and popovers. |
|
|
139
139
|
|
|
140
|
-
|
|
140
|
+
These are a different thing from the raw `--elevation-*` shadow tokens in [Theming](./theming.md#foundation-tokens), which are fixed shadows for elements you style yourself.
|
|
141
141
|
|
|
142
142
|
Each is one unitless multiplier over whatever shadow geometry is in scope, so the same class reads as a soft blur on a plain page and as a hard offset slab under `.neobrutalism` — the aesthetic decides what depth looks like, the class decides how much of it this element takes.
|
|
143
143
|
|
|
144
144
|
```html
|
|
145
|
-
<article class="card
|
|
146
|
-
<div class="
|
|
147
|
-
<article class="card
|
|
145
|
+
<article class="card raised">Lifted</article>
|
|
146
|
+
<div class="floating panel">A menu surface</div>
|
|
147
|
+
<article class="card flat">Flat, whatever the page or container says</article>
|
|
148
148
|
```
|
|
149
149
|
|
|
150
150
|
The multiplier does not inherit: an elevation class lifts or flattens the element it is written on only, and an unclassed element inside it takes no depth of its own. Give each element that needs depth its own elevation class. Spread is deliberately left out of the multiplication, because an aesthetic that draws its edge as an inset ring spends spread on it and scaling that would erase the edge.
|
|
@@ -133,19 +133,19 @@ Use `.table-wrap` around `.data-table` when table width may exceed its container
|
|
|
133
133
|
|
|
134
134
|
## Surfaces
|
|
135
135
|
|
|
136
|
-
| Class
|
|
137
|
-
|
|
|
138
|
-
| `.card`
|
|
139
|
-
| `.panel`
|
|
140
|
-
| `.interactive`
|
|
141
|
-
| `.hoverable`
|
|
142
|
-
| `.pressable`
|
|
143
|
-
| `.p-xs
|
|
144
|
-
| `.p-sm
|
|
145
|
-
| `.p-lg
|
|
146
|
-
| `.flush`
|
|
147
|
-
|
|
148
|
-
Both read intent, [presentation](./composing.md#presentation), and [material tokens](./customizing.md#material-tokens). A plain `.card` is a neutral bordered container; only an explicit presentation tints it. Resting at elevation `1` is not a visible shadow by itself — nothing draws depth until an [aesthetic](./aesthetics.md) supplies shadow geometry or `.
|
|
136
|
+
| Class | Purpose |
|
|
137
|
+
| -------------- | ------------------------------------------------------------------------------------- |
|
|
138
|
+
| `.card` | Bordered container, surface radius, padded. Rests at elevation `1`. |
|
|
139
|
+
| `.panel` | Flush container for sidebars, toolbars, and wells. No elevation. |
|
|
140
|
+
| `.interactive` | On `.card`. Adds pointer cursor, hover and press response, and a focus ring. |
|
|
141
|
+
| `.hoverable` | On `.card`. The hover half of `.interactive`: hover response only, no pointer cursor. |
|
|
142
|
+
| `.pressable` | On `.card`. The press half of `.interactive`: press response and pointer cursor. |
|
|
143
|
+
| `.p-xs` | On `.card` or `.panel`. Reduces padding further than `.p-sm`. |
|
|
144
|
+
| `.p-sm` | On `.card` or `.panel`. Reduces padding. |
|
|
145
|
+
| `.p-lg` | On `.card` or `.panel`. Increases padding. |
|
|
146
|
+
| `.flush` | On `.card` or `.panel`. Removes padding, for edge-to-edge content. |
|
|
147
|
+
|
|
148
|
+
Both read intent, [presentation](./composing.md#presentation), and [material tokens](./customizing.md#material-tokens). A plain `.card` is a neutral bordered container; only an explicit presentation tints it. Resting at elevation `1` is not a visible shadow by itself — nothing draws depth until an [aesthetic](./aesthetics.md) supplies shadow geometry or `.raised`/`.floating` asks for it; see [Composing → Elevation](./composing.md#elevation).
|
|
149
149
|
|
|
150
150
|
`.card.soft` with no named intent is untinted at rest — a plain `--color-foreground` plate, no ink mixed in, marking a different container without drawing attention to it. The intent tint and a `--color-surface` ground only appear together, on `:hover`, and only on `.card.interactive`/`.card.hoverable`: a plain `.card.soft` with neither has no hover state to reveal into and stays at the quiet rest. A named intent (`.card.soft.success`, `.card.soft.destructive`, and so on) keeps its ordinary tint at rest instead, and deepens further on hover the same way any other filled surface does — only the no-intent case is untinted, since removing an intent's own color would silence it rather than quiet it. `.solid` and `.ghost` are unaffected either way.
|
|
151
151
|
|
|
@@ -20,7 +20,7 @@ Presentation tokens describe _how much_ of an intent a component shows, never _w
|
|
|
20
20
|
|
|
21
21
|
A component resolves them with `color-mix` from its published default. Hover is derived by adding `--hover-step` to the resting fill and using `--intent-hover`; there are no per-presentation hover tokens.
|
|
22
22
|
|
|
23
|
-
No fill class writes `--ui-border` and no edge class writes `--ui-fill`. A filled box with no line is `.solid.edgeless`,
|
|
23
|
+
No fill class writes `--ui-border` and no edge class writes `--ui-fill`. A filled box with no line is `.solid.edgeless`, and `.solid.edged` renders the same box: the line fades out as the fill fills in, so even a neutral fill, capped and translucent, shows through its own border as one coat.
|
|
24
24
|
|
|
25
25
|
```css
|
|
26
26
|
background: color-mix(in oklab, var(--color-primary) var(--ui-fill, 100%), transparent);
|
|
@@ -38,41 +38,55 @@ Material tokens describe what a component is _made of_ rather than which intent
|
|
|
38
38
|
|
|
39
39
|
Components read each with a fallback, so leaving them unset produces the default look. Setting them on a container restyles the whole subtree. Only shadow geometry is split into colorless parts that inherit safely; color-capable inputs such as `--ui-ink` and `--ui-surface-shadow` may include their own colors.
|
|
40
40
|
|
|
41
|
-
| Token
|
|
42
|
-
|
|
|
43
|
-
| `--ui-
|
|
44
|
-
| `--ui-
|
|
45
|
-
| `--ui-corner-
|
|
46
|
-
| `--ui-radius
|
|
47
|
-
| `--ui-radius-
|
|
48
|
-
| `--ui-
|
|
49
|
-
| `--ui-
|
|
50
|
-
| `--ui-
|
|
51
|
-
| `--ui-
|
|
52
|
-
| `--ui-
|
|
53
|
-
| `--ui-
|
|
54
|
-
| `--ui-
|
|
55
|
-
| `--ui-
|
|
56
|
-
| `--ui-
|
|
57
|
-
| `--ui-
|
|
58
|
-
| `--ui-
|
|
59
|
-
| `--ui-
|
|
60
|
-
| `--ui-
|
|
61
|
-
| `--ui-
|
|
62
|
-
| `--ui-shadow-
|
|
63
|
-
| `--ui-shadow-
|
|
64
|
-
| `--ui-
|
|
65
|
-
| `--ui-
|
|
66
|
-
| `--ui-
|
|
67
|
-
| `--ui-
|
|
68
|
-
| `--ui-
|
|
69
|
-
| `--ui-
|
|
70
|
-
| `--ui-
|
|
71
|
-
| `--ui-
|
|
72
|
-
| `--ui-
|
|
41
|
+
| Token | Purpose | Fallback |
|
|
42
|
+
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------- |
|
|
43
|
+
| `--ui-corner` | Control corner at the default size; scaled by the size step. | `--radius-control` |
|
|
44
|
+
| `--ui-corner-surface` | Surface corner at the default padding; scaled by the size step. | `--radius-surface` |
|
|
45
|
+
| `--ui-corner-tl` | `0` or `1`: whether the top-left takes the corner. `-tr`, `-br`, and `-bl` for the others. | `1` |
|
|
46
|
+
| `--ui-radius` | A complete control radius, used as written: overrides the corner, the step, and the pattern. | Computed from the corner |
|
|
47
|
+
| `--ui-radius-surface` | A complete surface radius, used as written. | Computed from the corner |
|
|
48
|
+
| `--ui-scale` | Overrides the size step the size and padding classes set. | The step |
|
|
49
|
+
| `--ui-corner-shape` | What every corner draws: `round`, or `bevel` for a straight cut. Chromium only today. | `round` |
|
|
50
|
+
| `--ui-radius-pill` | Corner for what is fully round by default: badges, switches, progress, the tooltip icon; `.btn.pill` and `.radio` read it with no fallback but full. | `--ui-radius`, `--ui-corner`, then full |
|
|
51
|
+
| `--ui-radius-tight` | Complete radius for chips -- checkbox, `.kbd`, `.code` -- when set; otherwise a small computed default. | `min(--ui-radius or --ui-corner, small)` |
|
|
52
|
+
| `--ui-line-style` | Style of every line a component draws: `solid`, `dashed`, `dotted`, or `double` (3px wide or more). | `solid` |
|
|
53
|
+
| `--ui-border-width` | Edge thickness. | `--border-width` |
|
|
54
|
+
| `--ui-border-max` | Ceiling on computed edge width. | `100px` |
|
|
55
|
+
| `--ui-ink` | Neutral line color when no intent is set. | `--color-border` |
|
|
56
|
+
| `--ui-control-ink` | Neutral line color of fields, selects, checkboxes, radios, and switches when no intent is set. | `--ui-ink`, then `--color-control-border` |
|
|
57
|
+
| `--ui-rule` | Lines inside a table. Unset draws the head and foot boundaries only; `0%` draws none; `100%` rules every row. | unset |
|
|
58
|
+
| `--ui-shadow-x` | Shadow horizontal offset. | `0px` |
|
|
59
|
+
| `--ui-shadow-y` | Shadow vertical offset. | `0px` |
|
|
60
|
+
| `--ui-shadow-blur` | Shadow blur radius. | `0px` |
|
|
61
|
+
| `--ui-shadow-spread` | Shadow spread radius. | `0px` |
|
|
62
|
+
| `--ui-shadow-inset` | The `inset` keyword for an inner ring. | Empty |
|
|
63
|
+
| `--ui-hover-shadow-x` | Shadow horizontal offset while hovered. | `--ui-shadow-x` |
|
|
64
|
+
| `--ui-hover-shadow-y` | Shadow vertical offset while hovered. | `--ui-shadow-y` |
|
|
65
|
+
| `--ui-active-shadow-x` | Shadow horizontal offset while pressed. | `--ui-shadow-x` |
|
|
66
|
+
| `--ui-active-shadow-y` | Shadow vertical offset while pressed. | `--ui-shadow-y` |
|
|
67
|
+
| `--ui-active-transform` | Transform while pressed. `none` under `prefers-reduced-motion`. | `scale(0.97)` |
|
|
68
|
+
| `--ui-active-translate-x` | Distance a press travels into the element's depth; `-y` beside it. Scaled like the shadow. | `0px` |
|
|
69
|
+
| `--ui-shadow-ink` | Percentage of shadow color taken from intent ink. | `0%` |
|
|
70
|
+
| `--ui-halo-blur` | Blur of a halo around the element; `--ui-halo-spread` beside it. Elevation does not scale it. | `0px` |
|
|
71
|
+
| `--ui-halo-ink` | The halo's share of the intent colour, over nothing. Unset, there is no halo. | Unset |
|
|
72
|
+
| `--ui-shadow-edge` | Declared, even empty, when the shadow is the element's edge rather than its depth. Read for presence. | Unset |
|
|
73
|
+
| `--ui-elevation` | Unitless multiplier over shadow geometry. | `1` |
|
|
74
|
+
| `--ui-surface-shadow` | Complete multi-layer shadow accepted by surfaces only. | Unset |
|
|
75
|
+
| `--ui-surface-ground` | Ground a surface sits on. | `--color-background` |
|
|
76
|
+
| `--ui-bg-alpha` | Multiplier over fill for translucent materials. | `1` |
|
|
77
|
+
| `--ui-backdrop` | Backdrop filter accepted by surfaces only. | `none` |
|
|
78
|
+
| `--ui-surface-image` | A painted layer over a surface's plate: any `background-image` value. Surfaces only. | `none` |
|
|
79
|
+
| `--ui-hover-transform` | Transform while an interactive element is hovered. | `none` |
|
|
80
|
+
| `--ui-clip` | Structural component silhouette. | `none` |
|
|
81
|
+
| `--ui-clip-tight` | Compact component silhouette. | `--ui-clip` |
|
|
82
|
+
| `--ui-focus-inset` | Inset focus layer width. | Unset |
|
|
83
|
+
| `--ui-label-weight` | Label weight of `.btn` (and, with `/native`, a bare `<button>`) and `.badge`. | Semibold on a button, bold on a badge |
|
|
84
|
+
| `--ui-label-tracking` | Label letter spacing. Unset, the label inherits it. | Unset |
|
|
85
|
+
| `--ui-label-case` | Label `text-transform`. | `none` on a button; inherited on a badge |
|
|
86
|
+
| `--ui-label-shadow` | Label `text-shadow`, written without a colour so it takes the label's own. | `none` on a button; inherited on a badge |
|
|
73
87
|
|
|
74
88
|
```html
|
|
75
|
-
<section style="--ui-
|
|
89
|
+
<section style="--ui-corner: 0; --ui-border-width: 3px">
|
|
76
90
|
<button class="btn primary">Square and heavy</button>
|
|
77
91
|
<input class="ipt" placeholder="Matches" />
|
|
78
92
|
</section>
|
|
@@ -80,13 +94,31 @@ Components read each with a fallback, so leaving them unset produces the default
|
|
|
80
94
|
|
|
81
95
|
> **Material token contract**: components read these; aesthetic classes and consumer overrides set them.
|
|
82
96
|
|
|
97
|
+
### Corner size and pattern
|
|
98
|
+
|
|
99
|
+
The corner scales with the element. `.p-xs` sets a size step of `0.5`, `.sm` and `.p-sm` `0.75`, and `.lg` and `.p-lg` `1.25`. When a size class and a padding class sit on one element, the smaller step wins, so `.lg.p-xs` is small. `box` multiplies `--ui-corner` by the step, so a small button takes a small corner and a bevel stays a true 45 degrees. Depth follows the step down but not up: a `.p-xs` button sits on half its aesthetic's shadow, and a `.lg` one on the whole of it. A press that travels into that depth, given as `--ui-active-translate-x` and `-y`, travels the same scaled distance, so it always lands flat.
|
|
100
|
+
|
|
101
|
+
Which corners take the corner is its own choice. `.cut-diagonal` keeps the top-left and bottom-right and squares the other two; `.cut-diagonal-reverse` keeps the other pair. Both set `--ui-corner-tl`, `-tr`, `-br`, and `-bl`, which you can also set yourself: a two-corner leaf on the default look, two cuts on a control under `.cyber`. A surface under `.cyber` keeps the aesthetic's own surface shape, which the pattern does not reach, and an explicit `--ui-radius` or `--ui-radius-surface` ignores the step and the pattern.
|
|
102
|
+
|
|
103
|
+
### Lines, layers, and labels
|
|
104
|
+
|
|
105
|
+
`--ui-line-style` reaches every line a component draws: the box's edge, the progress track, and dividers and table rules. `--ui-rule-style` optionally overrides just dividers and table rules, without changing the box edge; sketch uses it for dashed accents. A dashed or dotted line keeps its colour, so it keeps its contrast; `double` needs a width of 3px or more to draw two lines.
|
|
106
|
+
|
|
107
|
+
`--ui-halo-*` is light rather than depth -- a glow in the element's own intent colour -- so elevation does not scale it and `.flat` leaves it on. It appears only when its ink is set.
|
|
108
|
+
|
|
109
|
+
`--ui-surface-image` lays any `background-image` over a surface's plate: cards, panels, alerts, and tooltips, not controls. Whoever sets it owns the contrast of the text over it, and your own `background-image` on a surface still wins.
|
|
110
|
+
|
|
111
|
+
`--ui-label-*` treats the label of a button or a badge: weight, tracking, case, and a text shadow. Write the shadow without a colour -- `0 0 6px` -- so it takes the label's own colour and cannot lower its contrast. Your own `font-*`, `tracking-*`, and case utilities still win.
|
|
112
|
+
|
|
113
|
+
Under forced colours each of these draws its plain version: a solid line, no halo, no painted layer, and no label shadow.
|
|
114
|
+
|
|
83
115
|
### Shape and ring composition
|
|
84
116
|
|
|
85
117
|
Clipping removes borders, outlines, and outer shadows. An aesthetic that uses a clip can replace the border with an inset shadow by setting `--ui-shadow-inset` and the four shadow geometry parts. Set `--ui-border-max: 0px` when that ring replaces the component border. Focusable components restore the clipped focus outline through `--ui-focus-inset`.
|
|
86
118
|
|
|
87
119
|
A clip is not the only way to cut a corner. `--ui-corner-shape: bevel` draws the corner the radius sets as a straight cut instead of an arc, and the border, outer shadow, focus outline, and backdrop all follow it -- so a bevelled element keeps its glow and its line, where a clipped one loses both. `.cyber` uses it. Engines without `corner-shape` ignore it and draw the radius round, so an aesthetic that bevels should square its radius under `@supports not (corner-shape: bevel)`. A bevel on a full radius cuts to points: a radio, a `.btn.pill`, and anything reading `--ui-radius-pill` become diamonds or pointed hexagons.
|
|
88
120
|
|
|
89
|
-
|
|
121
|
+
`--ui-radius` accepts any `border-radius` value and is used as written, so it can place the corner per side: `10px 0` cuts only top-left and bottom-right. The pill and chip corners are separate tokens. An unset chip corner computes a small default from `--ui-radius`, then `--ui-corner`, capped at `--radius-small`; an explicit `--ui-radius-tight` is used as written, even for a per-corner or elliptical value. Aesthetic and consumer overrides can therefore give a chip a larger or more irregular shape. `.btn.pill` takes `--ui-radius-pill` ahead of the other radii; under sketch it takes organic hand-drawn pill contours avoiding egg distortion, while an explicit `--ui-radius-pill` on that button still wins.
|
|
90
122
|
|
|
91
123
|
Declare `--ui-shadow-edge` when that ring _is_ the border. The ring then takes the element's edge color, which carries the edge axis as its alpha, so `.edged` draws it and `.edgeless` does not — the same answer a real border gives. Without it the ring paints on every component the aesthetic reaches and the edge classes have no effect. Use `--ui-shadow-ink` instead when the shadow is depth cast in the intent's own ink, such as a hard offset slab, which an `.edgeless` element still gets.
|
|
92
124
|
|
|
@@ -113,22 +145,28 @@ Variables prefixed `--_` are internal composition outputs — `--_bg`, `--_fg`,
|
|
|
113
145
|
|
|
114
146
|
The shipped [aesthetic classes](./aesthetics.md) set material tokens for you. Only aesthetics with a token listed below expose an aesthetic-specific token. Tune all other behavior through the shared material tokens above. Listed tokens are available only where that aesthetic's stylesheet is imported.
|
|
115
147
|
|
|
116
|
-
| Token
|
|
117
|
-
|
|
|
118
|
-
| `--neo-offset`
|
|
119
|
-
| `--glass-radius`
|
|
120
|
-
| `--glass-radius-surface`
|
|
121
|
-
| `--pixel-unit`
|
|
122
|
-
| `--font-pixel`
|
|
123
|
-
| `--tile-radius`
|
|
124
|
-
| `--tile-lift`
|
|
125
|
-
| `--font-rounded`
|
|
126
|
-
| `--cyber-cut`
|
|
127
|
-
| `--cyber-shape`
|
|
128
|
-
| `--cyber-shape-surface`
|
|
129
|
-
| `--cyber-glow`
|
|
130
|
-
| `--cyber-ink`
|
|
131
|
-
| `--font-cyber`
|
|
148
|
+
| Token | Aesthetic | Purpose | Default |
|
|
149
|
+
| --------------------------------- | ---------------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
|
|
150
|
+
| `--neo-offset` | `.neobrutalism` | Hard shadow offset and distance the press travels. | `4px` |
|
|
151
|
+
| `--glass-radius` | `.glass` | Control corner radius. | `0.75rem` |
|
|
152
|
+
| `--glass-radius-surface` | `.glass` | Surface corner radius. | `1rem` |
|
|
153
|
+
| `--pixel-unit` | `.pixel` | One pixel of the grid. The corner cut and the ring are one. | `4px` |
|
|
154
|
+
| `--font-pixel` | `.pixel` | Consumer-supplied pixel font stack. | Falls back to the monospace stack |
|
|
155
|
+
| `--tile-radius` | `.chunky-tile` | Corner radius, on controls and surfaces alike. | `0.75rem` |
|
|
156
|
+
| `--tile-lift` | `.chunky-tile` | Depth of the seated bar, and how far a press travels. | `4px` |
|
|
157
|
+
| `--font-rounded` | `.chunky-tile` | Consumer-supplied rounded font stack. | Falls back to the page stack |
|
|
158
|
+
| `--cyber-cut` | `.cyber` | The cut at the default size, on controls and surfaces alike; controls scale it with the step. | `0.625rem` |
|
|
159
|
+
| `--cyber-shape` | `.cyber` | Where controls take the cut: any `border-radius` value. | `<cut> 0` (top-left, bottom-right) |
|
|
160
|
+
| `--cyber-shape-surface` | `.cyber` | Where surfaces take the cut: any `border-radius` value. | `0 <cut>` (top-right, bottom-left) |
|
|
161
|
+
| `--cyber-glow` | `.cyber` | Blur of the glow. | `8px` |
|
|
162
|
+
| `--cyber-ink` | `.cyber` | Neutral line and glow colour, where no intent sets one. | Theme ink (near-black, near-white) |
|
|
163
|
+
| `--font-cyber` | `.cyber` | Consumer-supplied technical font stack. | Falls back to the monospace stack |
|
|
164
|
+
| `--sketch-radius` | `.sketch` | Control outline radius: any `border-radius` value. | Irregular box outline with sibling variation |
|
|
165
|
+
| `--sketch-radius-surface` | `.sketch` | Surface container outline radius: any `border-radius` value. | Sharp irregular square outline with sibling variation |
|
|
166
|
+
| `--sketch-radius-rounded` | `.sketch`, `.sketch-rounded` | Rounded control outline radius: expressive elliptical contour with sibling variation. | `26px 10px 24px 11px / 12px 23px 11px 20px` with sibling variation |
|
|
167
|
+
| `--sketch-radius-surface-rounded` | `.sketch`, `.sketch-rounded` | Rounded surface container outline radius: expressive elliptical contour with sibling variation. | `38px 16px 36px 17px / 16px 34px 17px 32px` with sibling variation |
|
|
168
|
+
| `--sketch-radius-pill` | `.sketch` | Pill button outline radius: organic hand-drawn pill contour avoiding egg-shaped distortion. | `24px 16px 23px 17px / 17px 21px 16px 20px` with sibling variation |
|
|
169
|
+
| `--font-sketch` | `.sketch` | Consumer-supplied handwriting font stack. | Falls back to `cursive` |
|
|
132
170
|
|
|
133
171
|
Every aesthetic's knobs reach the same way: each knob is _read_ with its default as a `var()` fallback rather than declared, so it resolves once into a private on the aesthetic's own class (`--_pixel-unit`, `--_neo-offset`, `--_tile-radius`, `--_tile-lift`, and so on). Set a knob on the element carrying the aesthetic class, or on any ancestor including `:root`:
|
|
134
172
|
|
|
@@ -148,7 +186,7 @@ Every aesthetic's knobs reach the same way: each knob is _read_ with its default
|
|
|
148
186
|
|
|
149
187
|
Knobs and material tokens reach in opposite directions, and telling them apart matters. A knob resolves once at the aesthetic's own class and inherits down already-resolved, so it reaches the aesthetic **from above**: setting it on the element or any ancestor works, but setting it on a _descendant_ of the aesthetic class changes nothing — the value has already been read. `--ui-radius` and the other material tokens above are read fresh by each component as it draws, so they reach **at or below** the element carrying them, which is how you round one card differently from its neighbours without touching the knob at all.
|
|
150
188
|
|
|
151
|
-
Shipped aesthetics set the shared material tokens above.
|
|
189
|
+
Shipped aesthetics set the shared material tokens above. Every shipped aesthetic sets `--ui-ink` for its neutral line. `.glass` and `.chunky-tile` also set `--ui-control-ink`, so their controls keep a heavier line than their surfaces; the others clear it and their controls take `--ui-ink`. Intent classes still override the intent slots on each component.
|
|
152
190
|
|
|
153
191
|
The same knobs tune each aesthetic's [solo class](./aesthetics.md#solo-classes), which reads them on its own element.
|
|
154
192
|
|