@codenhub/styles 0.3.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 -0
- 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 +198 -111
- package/dist/tw/aesthetics/cyber.css +227 -0
- package/dist/tw/aesthetics/glass.css +134 -47
- package/dist/tw/aesthetics/index.css +2 -0
- package/dist/tw/aesthetics/neobrutalism.css +149 -49
- package/dist/tw/aesthetics/pixel.css +151 -63
- package/dist/tw/aesthetics/sketch.css +326 -0
- package/dist/tw/box.css +107 -35
- package/dist/tw/components/button.css +40 -19
- package/dist/tw/components/feedback.css +38 -15
- package/dist/tw/components/form.css +161 -154
- 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.4.0.md +12 -0
- package/docs/changelog/0.5.0.md +38 -0
- package/docs/changelog/index.md +2 -0
- package/docs/concepts.md +5 -5
- package/docs/index.md +3 -3
- package/docs/setup.md +23 -3
- package/docs/usage/aesthetics.md +119 -2
- 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 +97 -44
- 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 +359 -122
- package/package.json +22 -2
package/llms-full.txt
CHANGED
|
@@ -49,7 +49,7 @@ For the Tailwind CSS v4 entrypoint, theme selection, the intent/presentation axe
|
|
|
49
49
|
|
|
50
50
|
## Notes
|
|
51
51
|
|
|
52
|
-
This package has no JavaScript behavior; no version provides compatibility aliases for a removed class or token. `0.2.0` removes `.btn.loading` (compose a disabled `.btn` with a `.loader` child instead) and `.alert.icon`'s built-in glyph (drop a consumer-supplied icon into `.alert-icon` instead), and `.tooltip` now requires a `.tooltip-bubble` child element rather than a `data-tooltip` attribute. See the [changelog](./docs/changelog/index.md) for the complete history.
|
|
52
|
+
This package has no JavaScript behavior; no version provides compatibility aliases for a removed class or token. `0.2.0` removes `.btn.loading` (compose a disabled `.btn` with a `.loader` child instead) and `.alert.icon`'s built-in glyph (drop a consumer-supplied icon into `.alert-icon` instead), and `.tooltip` now requires a `.tooltip-bubble` child element rather than a `data-tooltip` attribute. `0.5.0` removes the second names: `.dense`, `.compact`, and `.spacious` (use `.p-xs`, `.p-sm`, and `.p-lg`), `.danger` and `.error` (use `.destructive`, and `.hint.destructive` for `.hint.error`), and `.elevation-none`, `.elevation-sm`, and `.elevation-md` (use `.flat`, `.raised`, and `.floating`). It also renames two material tokens: an aesthetic sets its corner as `--ui-corner` and `--ui-corner-surface` rather than `--ui-radius` and `--ui-radius-surface`, which now take a complete radius as written, and `--ui-button-weight` and `--ui-button-tracking` are `--ui-label-weight` and `--ui-label-tracking`. See the [changelog](./docs/changelog/index.md) for the complete history.
|
|
53
53
|
|
|
54
54
|
## License
|
|
55
55
|
|
|
@@ -59,7 +59,7 @@ Licensed under Apache-2.0. Embedded SVG icons derived from [Lucide](https://luci
|
|
|
59
59
|
|
|
60
60
|
# @codenhub/styles
|
|
61
61
|
|
|
62
|
-
`@codenhub/styles` is a CSS-only design system: tokens, a reset, typography and layout utilities, and composable classes for buttons, forms, feedback, surfaces, and tooltips. Every component separates three independent choices — which color, how much of it, and what it's made of — so changing one never requires a component-specific variant.
|
|
62
|
+
`@codenhub/styles` is a CSS-only design system: tokens, a reset, typography and layout utilities, and composable classes for buttons, forms, feedback, surfaces, and tooltips. Every component separates three independent choices — which color, how much of it, and what it's made of — so changing one never requires a component-specific variant. Six optional aesthetics (`.neobrutalism`, `.glass`, `.pixel`, `.chunky-tile`, `.cyber`, `.sketch`) restyle that same component set without touching markup.
|
|
63
63
|
|
|
64
64
|
The package ships as ready-to-import compiled CSS, or as Tailwind CSS v4 source entrypoints for a project that already runs Tailwind. Both cover the same classes; the difference is which build processes them.
|
|
65
65
|
|
|
@@ -68,7 +68,7 @@ The package ships as ready-to-import compiled CSS, or as Tailwind CSS v4 source
|
|
|
68
68
|
- Publishes color, foundation, intent, presentation, and material design tokens as CSS custom properties, themed with `light-dark()`.
|
|
69
69
|
- Provides a reset, focus-visible handling, and responsive layout/content utilities.
|
|
70
70
|
- Provides composable classes for buttons, form controls and toggles, alerts, badges, loaders, progress, cards/panels, tables, quotes, code, and tooltips.
|
|
71
|
-
- Provides
|
|
71
|
+
- Provides six opt-in aesthetics that restyle the same components by setting material tokens, not by adding component variants, each with a solo class that paints the look onto an element the package does not style.
|
|
72
72
|
- Provides classless mappings so plain HTML elements pick up base styling without added classes, from a dedicated entrypoint.
|
|
73
73
|
- Publishes Tailwind CSS v4 source entrypoints alongside the compiled output.
|
|
74
74
|
|
|
@@ -77,7 +77,7 @@ The package ships as ready-to-import compiled CSS, or as Tailwind CSS v4 source
|
|
|
77
77
|
- No JavaScript. There is no runtime, no framework bindings, and no build-time code generation beyond the CSS itself.
|
|
78
78
|
- No semantic HTML, ARIA, keyboard behavior, focus management, validation, or announcement timing. See [Accessibility](docs/accessibility.md) for the exact line between what the CSS provides and what an application must still add.
|
|
79
79
|
- No theme-toggling logic. Theme selection is a class or attribute a consumer applies; wiring a toggle to system preference, storage, or a user setting is outside this package. The `@codenhub/theme` package covers that need for consumers who want it.
|
|
80
|
-
- No shipped font binaries. `.pixel
|
|
80
|
+
- No shipped font binaries. `.pixel`, `.chunky-tile`, `.cyber`, and `.sketch` accept a consumer-supplied font and fall back to a system stack when none is given.
|
|
81
81
|
- No compatibility layer for removed tokens or classes. Breaking changes are documented, not silently aliased.
|
|
82
82
|
|
|
83
83
|
## Next steps
|
|
@@ -175,8 +175,8 @@ Compiled entrypoints are ready-to-import CSS and require only tooling that can r
|
|
|
175
175
|
| `@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](docs/usage/customizing.md#generated-palette). |
|
|
176
176
|
| `@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. |
|
|
177
177
|
| `@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. |
|
|
178
|
-
| `@codenhub/styles/aesthetics` | Compiled `.neobrutalism`, `.glass`, `.pixel`,
|
|
179
|
-
| `@codenhub/styles/aesthetics/*` | One compiled aesthetic: `/neobrutalism`, `/glass`, `/pixel`,
|
|
178
|
+
| `@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. |
|
|
179
|
+
| `@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. |
|
|
180
180
|
| `@codenhub/styles/tw` | Source equivalent of the complete stylesheet. Imports Tailwind itself, theme, typography, utilities, components, and reset; applies the same global rules. |
|
|
181
181
|
| `@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. |
|
|
182
182
|
| `@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. |
|
|
@@ -190,13 +190,33 @@ Compiled entrypoints are ready-to-import CSS and require only tooling that can r
|
|
|
190
190
|
| `@codenhub/styles/tw/native` | Source complete surface plus reset and classless native-element mappings; broadest global effects. |
|
|
191
191
|
| `@codenhub/styles/tw/typography` | Source theme plus typography utilities; sets theme selectors but no reset or classless mappings. |
|
|
192
192
|
| `@codenhub/styles/tw/utilities` | Source theme and typography composition plus layout and content utilities; safelists the package utility names. |
|
|
193
|
-
| `@codenhub/styles/tw/aesthetics` | Source aesthetics, combined. `/tw/aesthetics/neobrutalism`, `/glass`, `/pixel`,
|
|
193
|
+
| `@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. |
|
|
194
194
|
|
|
195
195
|
Avoid importing overlapping entrypoints in the same build unless duplicate generated CSS is acceptable; pick the narrowest entrypoint that covers what a page needs.
|
|
196
196
|
|
|
197
|
+
## Cascade layers
|
|
198
|
+
|
|
199
|
+
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:
|
|
200
|
+
|
|
201
|
+
| Layer | Holds |
|
|
202
|
+
| ------------ | ---------------------------------------------------------------------------------------------- |
|
|
203
|
+
| `theme` | Tailwind's theme, the foundation tokens, the theme selectors, and `/palette`. |
|
|
204
|
+
| `base` | The reset and the classless element styles. |
|
|
205
|
+
| `components` | The intent, presentation, elevation, and aesthetic classes. |
|
|
206
|
+
| `utilities` | Every component (`.btn`, `.card`, `.ipt`, ...), next to your own Tailwind utilities. |
|
|
207
|
+
| _unlayered_ | The `forced-colors` and reduced-motion overrides, the `<dialog>` fix, and the `-solo` classes. |
|
|
208
|
+
|
|
209
|
+
What that means in practice:
|
|
210
|
+
|
|
211
|
+
- **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.
|
|
212
|
+
- **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.
|
|
213
|
+
- **State beats your intent.** An `aria-invalid` field stays destructive even with an intent utility on it.
|
|
214
|
+
- **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.
|
|
215
|
+
|
|
197
216
|
## Requirements
|
|
198
217
|
|
|
199
218
|
- Consumer tooling must resolve package CSS imports.
|
|
219
|
+
- 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.
|
|
200
220
|
- 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).
|
|
201
221
|
- Tailwind CSS 4 or newer is required only for `/tw` source entrypoints.
|
|
202
222
|
- The package has no JavaScript runtime. Apps must provide semantic HTML, ARIA, keyboard behavior, focus management, validation, and announcements; see [Accessibility](docs/accessibility.md).
|
|
@@ -211,11 +231,11 @@ Read this before the usage guides. It explains the mental model every component,
|
|
|
211
231
|
|
|
212
232
|
Every component separates three independent choices, so each can change without a component-specific variant:
|
|
213
233
|
|
|
214
|
-
| Axis | Question | Classes
|
|
215
|
-
| ------------ | --------------- |
|
|
216
|
-
| Intent | Which color? | `.primary`, `.secondary`, `.success`, `.warning`, `.destructive`, `.info`
|
|
217
|
-
| Presentation | How much of it? | `.solid`, `.soft`, `.ghost`, `.edged`, `.edgeless`
|
|
218
|
-
| Aesthetic | Made of what? | `.neobrutalism`, `.glass`, `.pixel`, `.chunky-tile` from an optional aesthetic stylesheet | Cascades |
|
|
234
|
+
| Axis | Question | Classes | Inheritance |
|
|
235
|
+
| ------------ | --------------- | --------------------------------------------------------------------------------------------------- | ------------ |
|
|
236
|
+
| Intent | Which color? | `.primary`, `.secondary`, `.success`, `.warning`, `.destructive`, `.info` | Element only |
|
|
237
|
+
| Presentation | How much of it? | `.solid`, `.soft`, `.ghost`, `.edged`, `.edgeless` | Cascades |
|
|
238
|
+
| Aesthetic | Made of what? | `.neobrutalism`, `.glass`, `.pixel`, `.chunky-tile`, `.cyber` from an optional aesthetic stylesheet | Cascades |
|
|
219
239
|
|
|
220
240
|
```html
|
|
221
241
|
<section class="soft pixel">
|
|
@@ -342,7 +362,7 @@ The combinations mean exactly what they spell:
|
|
|
342
362
|
<!-- A field sunk into the page -->
|
|
343
363
|
```
|
|
344
364
|
|
|
345
|
-
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
|
|
365
|
+
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.
|
|
346
366
|
|
|
347
367
|
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](docs/usage/content-and-layout.md#table-rules) — because tying them to this axis made them arrive by implication rather than by request.
|
|
348
368
|
|
|
@@ -410,26 +430,26 @@ Presentation is two independent axes, so they get a column each. A `Yes` means t
|
|
|
410
430
|
|
|
411
431
|
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.
|
|
412
432
|
|
|
413
|
-
|
|
433
|
+
State and modifier classes such as `.interactive`, `.hoverable`, `.pressable`, `.invalid`, `.p-sm`, and `.vertical` sit above this map and are documented with their component.
|
|
414
434
|
|
|
415
435
|
## Elevation
|
|
416
436
|
|
|
417
437
|
Depth is a modifier, not an axis. Nothing is raised until an [aesthetic](docs/usage/aesthetics.md) draws depth or one of these classes asks for it.
|
|
418
438
|
|
|
419
|
-
| Class
|
|
420
|
-
|
|
|
421
|
-
| `.
|
|
422
|
-
| `.
|
|
423
|
-
| `.
|
|
439
|
+
| Class | Depth |
|
|
440
|
+
| ----------- | ------------------------------------------------------------------------ |
|
|
441
|
+
| `.flat` | Removes part-based elevation; glass surfaces keep their complete shadow. |
|
|
442
|
+
| `.raised` | One unit of the depth in scope. Cards, tiles, popovers that sit close. |
|
|
443
|
+
| `.floating` | Twice it, for menus and popovers. |
|
|
424
444
|
|
|
425
|
-
|
|
445
|
+
These are a different thing from the raw `--elevation-*` shadow tokens in [Theming](docs/usage/theming.md#foundation-tokens), which are fixed shadows for elements you style yourself.
|
|
426
446
|
|
|
427
447
|
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.
|
|
428
448
|
|
|
429
449
|
```html
|
|
430
|
-
<article class="card
|
|
431
|
-
<div class="
|
|
432
|
-
<article class="card
|
|
450
|
+
<article class="card raised">Lifted</article>
|
|
451
|
+
<div class="floating panel">A menu surface</div>
|
|
452
|
+
<article class="card flat">Flat, whatever the page or container says</article>
|
|
433
453
|
```
|
|
434
454
|
|
|
435
455
|
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.
|
|
@@ -550,7 +570,7 @@ Set them directly to define an intent this package does not ship. **State every
|
|
|
550
570
|
|
|
551
571
|
Foundation tokens are not aliases for one color. They define layout, shape, motion, focus, depth, and layering behavior used by helper classes.
|
|
552
572
|
|
|
553
|
-
The four `--elevation-*` values below are raw shadows for elements you style yourself. They are a separate thing from `.
|
|
573
|
+
The four `--elevation-*` values below are raw shadows for elements you style yourself. They are a separate thing from `.flat`/`.raised`/`.floating`, which scale a _component's own_ shadow geometry and default to no shadow at all until an aesthetic or one of those classes asks for depth — see [Composing → Elevation](docs/usage/composing.md#elevation) for that system. The two share `none`/`sm`/`md`/`lg` naming for the same weight of depth, but one is a fixed value and the other multiplies shadow parts, so they will not always paint identically.
|
|
554
574
|
|
|
555
575
|
| Token | Purpose |
|
|
556
576
|
| -------------------------- | ----------------------------------------------------------------------- |
|
|
@@ -603,7 +623,7 @@ Presentation tokens describe _how much_ of an intent a component shows, never _w
|
|
|
603
623
|
|
|
604
624
|
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.
|
|
605
625
|
|
|
606
|
-
No fill class writes `--ui-border` and no edge class writes `--ui-fill`. A filled box with no line is `.solid.edgeless`,
|
|
626
|
+
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.
|
|
607
627
|
|
|
608
628
|
```css
|
|
609
629
|
background: color-mix(in oklab, var(--color-primary) var(--ui-fill, 100%), transparent);
|
|
@@ -621,38 +641,55 @@ Material tokens describe what a component is _made of_ rather than which intent
|
|
|
621
641
|
|
|
622
642
|
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.
|
|
623
643
|
|
|
624
|
-
| Token
|
|
625
|
-
|
|
|
626
|
-
| `--ui-
|
|
627
|
-
| `--ui-
|
|
628
|
-
| `--ui-
|
|
629
|
-
| `--ui-
|
|
630
|
-
| `--ui-
|
|
631
|
-
| `--ui-
|
|
632
|
-
| `--ui-
|
|
633
|
-
| `--ui-
|
|
634
|
-
| `--ui-
|
|
635
|
-
| `--ui-
|
|
636
|
-
| `--ui-
|
|
637
|
-
| `--ui-
|
|
638
|
-
| `--ui-
|
|
639
|
-
| `--ui-
|
|
640
|
-
| `--ui-
|
|
641
|
-
| `--ui-
|
|
642
|
-
| `--ui-shadow-
|
|
643
|
-
| `--ui-shadow-
|
|
644
|
-
| `--ui-
|
|
645
|
-
| `--ui-
|
|
646
|
-
| `--ui-
|
|
647
|
-
| `--ui-
|
|
648
|
-
| `--ui-
|
|
649
|
-
| `--ui-
|
|
650
|
-
| `--ui-
|
|
651
|
-
| `--ui-
|
|
652
|
-
| `--ui-
|
|
644
|
+
| Token | Purpose | Fallback |
|
|
645
|
+
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------- |
|
|
646
|
+
| `--ui-corner` | Control corner at the default size; scaled by the size step. | `--radius-control` |
|
|
647
|
+
| `--ui-corner-surface` | Surface corner at the default padding; scaled by the size step. | `--radius-surface` |
|
|
648
|
+
| `--ui-corner-tl` | `0` or `1`: whether the top-left takes the corner. `-tr`, `-br`, and `-bl` for the others. | `1` |
|
|
649
|
+
| `--ui-radius` | A complete control radius, used as written: overrides the corner, the step, and the pattern. | Computed from the corner |
|
|
650
|
+
| `--ui-radius-surface` | A complete surface radius, used as written. | Computed from the corner |
|
|
651
|
+
| `--ui-scale` | Overrides the size step the size and padding classes set. | The step |
|
|
652
|
+
| `--ui-corner-shape` | What every corner draws: `round`, or `bevel` for a straight cut. Chromium only today. | `round` |
|
|
653
|
+
| `--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 |
|
|
654
|
+
| `--ui-radius-tight` | Complete radius for chips -- checkbox, `.kbd`, `.code` -- when set; otherwise a small computed default. | `min(--ui-radius or --ui-corner, small)` |
|
|
655
|
+
| `--ui-line-style` | Style of every line a component draws: `solid`, `dashed`, `dotted`, or `double` (3px wide or more). | `solid` |
|
|
656
|
+
| `--ui-border-width` | Edge thickness. | `--border-width` |
|
|
657
|
+
| `--ui-border-max` | Ceiling on computed edge width. | `100px` |
|
|
658
|
+
| `--ui-ink` | Neutral line color when no intent is set. | `--color-border` |
|
|
659
|
+
| `--ui-control-ink` | Neutral line color of fields, selects, checkboxes, radios, and switches when no intent is set. | `--ui-ink`, then `--color-control-border` |
|
|
660
|
+
| `--ui-rule` | Lines inside a table. Unset draws the head and foot boundaries only; `0%` draws none; `100%` rules every row. | unset |
|
|
661
|
+
| `--ui-shadow-x` | Shadow horizontal offset. | `0px` |
|
|
662
|
+
| `--ui-shadow-y` | Shadow vertical offset. | `0px` |
|
|
663
|
+
| `--ui-shadow-blur` | Shadow blur radius. | `0px` |
|
|
664
|
+
| `--ui-shadow-spread` | Shadow spread radius. | `0px` |
|
|
665
|
+
| `--ui-shadow-inset` | The `inset` keyword for an inner ring. | Empty |
|
|
666
|
+
| `--ui-hover-shadow-x` | Shadow horizontal offset while hovered. | `--ui-shadow-x` |
|
|
667
|
+
| `--ui-hover-shadow-y` | Shadow vertical offset while hovered. | `--ui-shadow-y` |
|
|
668
|
+
| `--ui-active-shadow-x` | Shadow horizontal offset while pressed. | `--ui-shadow-x` |
|
|
669
|
+
| `--ui-active-shadow-y` | Shadow vertical offset while pressed. | `--ui-shadow-y` |
|
|
670
|
+
| `--ui-active-transform` | Transform while pressed. `none` under `prefers-reduced-motion`. | `scale(0.97)` |
|
|
671
|
+
| `--ui-active-translate-x` | Distance a press travels into the element's depth; `-y` beside it. Scaled like the shadow. | `0px` |
|
|
672
|
+
| `--ui-shadow-ink` | Percentage of shadow color taken from intent ink. | `0%` |
|
|
673
|
+
| `--ui-halo-blur` | Blur of a halo around the element; `--ui-halo-spread` beside it. Elevation does not scale it. | `0px` |
|
|
674
|
+
| `--ui-halo-ink` | The halo's share of the intent colour, over nothing. Unset, there is no halo. | Unset |
|
|
675
|
+
| `--ui-shadow-edge` | Declared, even empty, when the shadow is the element's edge rather than its depth. Read for presence. | Unset |
|
|
676
|
+
| `--ui-elevation` | Unitless multiplier over shadow geometry. | `1` |
|
|
677
|
+
| `--ui-surface-shadow` | Complete multi-layer shadow accepted by surfaces only. | Unset |
|
|
678
|
+
| `--ui-surface-ground` | Ground a surface sits on. | `--color-background` |
|
|
679
|
+
| `--ui-bg-alpha` | Multiplier over fill for translucent materials. | `1` |
|
|
680
|
+
| `--ui-backdrop` | Backdrop filter accepted by surfaces only. | `none` |
|
|
681
|
+
| `--ui-surface-image` | A painted layer over a surface's plate: any `background-image` value. Surfaces only. | `none` |
|
|
682
|
+
| `--ui-hover-transform` | Transform while an interactive element is hovered. | `none` |
|
|
683
|
+
| `--ui-clip` | Structural component silhouette. | `none` |
|
|
684
|
+
| `--ui-clip-tight` | Compact component silhouette. | `--ui-clip` |
|
|
685
|
+
| `--ui-focus-inset` | Inset focus layer width. | Unset |
|
|
686
|
+
| `--ui-label-weight` | Label weight of `.btn` (and, with `/native`, a bare `<button>`) and `.badge`. | Semibold on a button, bold on a badge |
|
|
687
|
+
| `--ui-label-tracking` | Label letter spacing. Unset, the label inherits it. | Unset |
|
|
688
|
+
| `--ui-label-case` | Label `text-transform`. | `none` on a button; inherited on a badge |
|
|
689
|
+
| `--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 |
|
|
653
690
|
|
|
654
691
|
```html
|
|
655
|
-
<section style="--ui-
|
|
692
|
+
<section style="--ui-corner: 0; --ui-border-width: 3px">
|
|
656
693
|
<button class="btn primary">Square and heavy</button>
|
|
657
694
|
<input class="ipt" placeholder="Matches" />
|
|
658
695
|
</section>
|
|
@@ -660,10 +697,32 @@ Components read each with a fallback, so leaving them unset produces the default
|
|
|
660
697
|
|
|
661
698
|
> **Material token contract**: components read these; aesthetic classes and consumer overrides set them.
|
|
662
699
|
|
|
700
|
+
### Corner size and pattern
|
|
701
|
+
|
|
702
|
+
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.
|
|
703
|
+
|
|
704
|
+
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.
|
|
705
|
+
|
|
706
|
+
### Lines, layers, and labels
|
|
707
|
+
|
|
708
|
+
`--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.
|
|
709
|
+
|
|
710
|
+
`--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.
|
|
711
|
+
|
|
712
|
+
`--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.
|
|
713
|
+
|
|
714
|
+
`--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.
|
|
715
|
+
|
|
716
|
+
Under forced colours each of these draws its plain version: a solid line, no halo, no painted layer, and no label shadow.
|
|
717
|
+
|
|
663
718
|
### Shape and ring composition
|
|
664
719
|
|
|
665
720
|
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`.
|
|
666
721
|
|
|
722
|
+
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.
|
|
723
|
+
|
|
724
|
+
`--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.
|
|
725
|
+
|
|
667
726
|
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.
|
|
668
727
|
|
|
669
728
|
The token is read for its presence, not its value: declare it empty to switch the ring on, and `initial` to switch it back off in an aesthetic nested inside one that declares it.
|
|
@@ -689,18 +748,30 @@ Variables prefixed `--_` are internal composition outputs — `--_bg`, `--_fg`,
|
|
|
689
748
|
|
|
690
749
|
The shipped [aesthetic classes](docs/usage/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.
|
|
691
750
|
|
|
692
|
-
| Token
|
|
693
|
-
|
|
|
694
|
-
| `--neo-offset`
|
|
695
|
-
| `--glass-radius`
|
|
696
|
-
| `--glass-radius-surface`
|
|
697
|
-
| `--pixel-unit`
|
|
698
|
-
| `--font-pixel`
|
|
699
|
-
| `--tile-radius`
|
|
700
|
-
| `--tile-lift`
|
|
701
|
-
| `--font-rounded`
|
|
702
|
-
|
|
703
|
-
|
|
751
|
+
| Token | Aesthetic | Purpose | Default |
|
|
752
|
+
| --------------------------------- | ---------------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
|
|
753
|
+
| `--neo-offset` | `.neobrutalism` | Hard shadow offset and distance the press travels. | `4px` |
|
|
754
|
+
| `--glass-radius` | `.glass` | Control corner radius. | `0.75rem` |
|
|
755
|
+
| `--glass-radius-surface` | `.glass` | Surface corner radius. | `1rem` |
|
|
756
|
+
| `--pixel-unit` | `.pixel` | One pixel of the grid. The corner cut and the ring are one. | `4px` |
|
|
757
|
+
| `--font-pixel` | `.pixel` | Consumer-supplied pixel font stack. | Falls back to the monospace stack |
|
|
758
|
+
| `--tile-radius` | `.chunky-tile` | Corner radius, on controls and surfaces alike. | `0.75rem` |
|
|
759
|
+
| `--tile-lift` | `.chunky-tile` | Depth of the seated bar, and how far a press travels. | `4px` |
|
|
760
|
+
| `--font-rounded` | `.chunky-tile` | Consumer-supplied rounded font stack. | Falls back to the page stack |
|
|
761
|
+
| `--cyber-cut` | `.cyber` | The cut at the default size, on controls and surfaces alike; controls scale it with the step. | `0.625rem` |
|
|
762
|
+
| `--cyber-shape` | `.cyber` | Where controls take the cut: any `border-radius` value. | `<cut> 0` (top-left, bottom-right) |
|
|
763
|
+
| `--cyber-shape-surface` | `.cyber` | Where surfaces take the cut: any `border-radius` value. | `0 <cut>` (top-right, bottom-left) |
|
|
764
|
+
| `--cyber-glow` | `.cyber` | Blur of the glow. | `8px` |
|
|
765
|
+
| `--cyber-ink` | `.cyber` | Neutral line and glow colour, where no intent sets one. | Theme ink (near-black, near-white) |
|
|
766
|
+
| `--font-cyber` | `.cyber` | Consumer-supplied technical font stack. | Falls back to the monospace stack |
|
|
767
|
+
| `--sketch-radius` | `.sketch` | Control outline radius: any `border-radius` value. | Irregular box outline with sibling variation |
|
|
768
|
+
| `--sketch-radius-surface` | `.sketch` | Surface container outline radius: any `border-radius` value. | Sharp irregular square outline with sibling variation |
|
|
769
|
+
| `--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 |
|
|
770
|
+
| `--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 |
|
|
771
|
+
| `--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 |
|
|
772
|
+
| `--font-sketch` | `.sketch` | Consumer-supplied handwriting font stack. | Falls back to `cursive` |
|
|
773
|
+
|
|
774
|
+
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`:
|
|
704
775
|
|
|
705
776
|
```html
|
|
706
777
|
<section class="pixel" style="--pixel-unit: 6px">
|
|
@@ -718,7 +789,9 @@ All four aesthetics reach the same way: each knob is _read_ with its default as
|
|
|
718
789
|
|
|
719
790
|
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.
|
|
720
791
|
|
|
721
|
-
Shipped aesthetics set the shared material tokens above. `.
|
|
792
|
+
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.
|
|
793
|
+
|
|
794
|
+
The same knobs tune each aesthetic's [solo class](docs/usage/aesthetics.md#solo-classes), which reads them on its own element.
|
|
722
795
|
|
|
723
796
|
## Generated palette
|
|
724
797
|
|
|
@@ -785,6 +858,8 @@ Like presentation, an aesthetic class cascades to any subtree:
|
|
|
785
858
|
| `.glass` | Translucent surfaces over a blurred backdrop with a hairline highlight edge. |
|
|
786
859
|
| `.pixel` | Corners cut by one grid unit, a chunky outline drawn as an inset ring, and the consumer-supplied `--font-pixel` over monospace. |
|
|
787
860
|
| `.chunky-tile` | Rounded slabs seated on a darker shade of themselves, with a press that moves the element down into its own bar. |
|
|
861
|
+
| `.cyber` | Bevelled corners, a thin bright edge, and a glow in the component's own colour. |
|
|
862
|
+
| `.sketch` | Varying elliptical corners, a solid ink line with dashed accents, a small offset shadow, and an optional handwriting face. |
|
|
788
863
|
|
|
789
864
|
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.
|
|
790
865
|
|
|
@@ -792,6 +867,8 @@ An explicit presentation on the element still wins over the aesthetic's defaults
|
|
|
792
867
|
|
|
793
868
|
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.
|
|
794
869
|
|
|
870
|
+
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](docs/setup.md#cascade-layers).
|
|
871
|
+
|
|
795
872
|
Each aesthetic that scales from one number publishes it as a knob — see [Customizing → Aesthetic tokens](docs/usage/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.
|
|
796
873
|
|
|
797
874
|
## Neobrutalism
|
|
@@ -826,8 +903,10 @@ The shadow is cast in the component's own intent, so a success button throws a g
|
|
|
826
903
|
|
|
827
904
|
**Exceptions:**
|
|
828
905
|
|
|
906
|
+
- Every surface in a glass region is glass, a neutral `.card.soft`, `.panel`, and `.alert` included.
|
|
829
907
|
- 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.
|
|
830
908
|
- Under `prefers-reduced-transparency: reduce`, glass surfaces drop the blur and become opaque.
|
|
909
|
+
- 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.
|
|
831
910
|
|
|
832
911
|
## Pixel
|
|
833
912
|
|
|
@@ -870,10 +949,121 @@ The bar is a darker shade of the element's own colour rather than a shadow under
|
|
|
870
949
|
```
|
|
871
950
|
|
|
872
951
|
- `--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.
|
|
873
|
-
-
|
|
952
|
+
- 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.
|
|
874
953
|
- `.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.
|
|
875
954
|
- 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.
|
|
876
955
|
- Depth in this aesthetic is the bar, never a blurred drop shadow. Anything the registry rests flat sits flush on the page.
|
|
956
|
+
- 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.
|
|
957
|
+
|
|
958
|
+
## Cyber
|
|
959
|
+
|
|
960
|
+
Bevelled corners, a 1px edge, and a glow in the component's own colour: a success button glows green, a destructive card red. The bevel is drawn with `corner-shape`, so the border, the glow, and the focus outline all follow the cut rather than being clipped by it.
|
|
961
|
+
|
|
962
|
+
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.
|
|
963
|
+
|
|
964
|
+
`--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.
|
|
965
|
+
|
|
966
|
+
```html
|
|
967
|
+
<section class="cyber" style="--cyber-ink: rgb(0 229 255); --cyber-cut: 0.75rem">
|
|
968
|
+
<button class="btn">Jack in</button>
|
|
969
|
+
</section>
|
|
970
|
+
```
|
|
971
|
+
|
|
972
|
+
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.
|
|
973
|
+
|
|
974
|
+
| Shape | Value |
|
|
975
|
+
| ---------------------- | --------------------- |
|
|
976
|
+
| All four corners | `0.625rem` |
|
|
977
|
+
| The other diagonal | `0 0.625rem` |
|
|
978
|
+
| Hexagon (pointed ends) | `0.625rem / 50%` |
|
|
979
|
+
| Parallelogram | `0.625rem 0 / 100% 0` |
|
|
980
|
+
| One notch, top-right | `0 0.625rem 0 0` |
|
|
981
|
+
|
|
982
|
+
```html
|
|
983
|
+
<section class="cyber" style="--cyber-shape: 0.625rem / 50%">
|
|
984
|
+
<button class="btn primary">Hexagonal buttons</button>
|
|
985
|
+
</section>
|
|
986
|
+
```
|
|
987
|
+
|
|
988
|
+
A parallelogram slants its sides into the content, so give a surface that takes one extra inline padding.
|
|
989
|
+
|
|
990
|
+
**Exceptions:**
|
|
991
|
+
|
|
992
|
+
- 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.
|
|
993
|
+
- 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.
|
|
994
|
+
- 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`.
|
|
995
|
+
- 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.
|
|
996
|
+
- `--font-cyber` is yours to supply. The package ships no font binary, so the aesthetic falls back to the monospace stack.
|
|
997
|
+
- Casing is left alone, for the reason [Chunky tile](#chunky-tile) gives.
|
|
998
|
+
|
|
999
|
+
## Sketch
|
|
1000
|
+
|
|
1001
|
+
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`.
|
|
1002
|
+
|
|
1003
|
+
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.
|
|
1004
|
+
|
|
1005
|
+
`--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.
|
|
1006
|
+
|
|
1007
|
+
```html
|
|
1008
|
+
<section class="sketch" style='--font-sketch: "Comic Sans MS", cursive'>
|
|
1009
|
+
<button class="btn primary">Send note</button>
|
|
1010
|
+
<button class="btn ghost edged" style="--ui-line-style: dashed">Draft note</button>
|
|
1011
|
+
</section>
|
|
1012
|
+
```
|
|
1013
|
+
|
|
1014
|
+
The dashed button is `ghost edged` because a filled button has no separate line to dash.
|
|
1015
|
+
|
|
1016
|
+
`.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.
|
|
1017
|
+
|
|
1018
|
+
```html
|
|
1019
|
+
<section class="sketch sketch-rounded">
|
|
1020
|
+
<div class="card">
|
|
1021
|
+
<button class="btn primary">Rounded action</button>
|
|
1022
|
+
</div>
|
|
1023
|
+
</section>
|
|
1024
|
+
```
|
|
1025
|
+
|
|
1026
|
+
**Exceptions:**
|
|
1027
|
+
|
|
1028
|
+
- 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.
|
|
1029
|
+
- 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.
|
|
1030
|
+
- 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.
|
|
1031
|
+
- `--font-sketch` is yours to supply. The package ships no handwriting font and falls back to the platform `cursive` family.
|
|
1032
|
+
- Buttons press with the plain `scale(0.97)`; reduced motion turns it off.
|
|
1033
|
+
- Forced-colours mode draws the dashed accents solid, like every other material line.
|
|
1034
|
+
|
|
1035
|
+
## Solo classes
|
|
1036
|
+
|
|
1037
|
+
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:
|
|
1038
|
+
|
|
1039
|
+
| Aesthetic | Solo class | Paints |
|
|
1040
|
+
| --------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
1041
|
+
| `.glass` | `.glass-solo` | Translucent ground, hairline edge, blur, the tucked two-layer shadow, the surface corner. |
|
|
1042
|
+
| `.neobrutalism` | `.neobrutalism-solo` | 2px ink edge, square corners, the hard offset slab. |
|
|
1043
|
+
| `.pixel` | `.pixel-solo` | The stepped silhouette, the inset ring in place of a border, the pixel font. |
|
|
1044
|
+
| `.chunky-tile` | `.chunky-tile-solo` | The tile corner, 2px edge, the bar under it, the rounded font. |
|
|
1045
|
+
| `.cyber` | `.cyber-solo` | The surface diagonal (the control one on an action), 1px edge, the glow, the font. |
|
|
1046
|
+
| `.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. |
|
|
1047
|
+
|
|
1048
|
+
```css
|
|
1049
|
+
/* The only stylesheet from this package on the page. */
|
|
1050
|
+
@import "@codenhub/styles/aesthetics/glass";
|
|
1051
|
+
```
|
|
1052
|
+
|
|
1053
|
+
```html
|
|
1054
|
+
<div class="toast glass-solo">A pane over whatever is behind it.</div>
|
|
1055
|
+
```
|
|
1056
|
+
|
|
1057
|
+
A solo class ships in the same entrypoint as its aesthetic, and needs nothing else loaded:
|
|
1058
|
+
|
|
1059
|
+
- **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.
|
|
1060
|
+
- **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.
|
|
1061
|
+
- **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.
|
|
1062
|
+
- **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.
|
|
1063
|
+
- **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.
|
|
1064
|
+
- **Dark values need a colour scheme.** Light and dark pairs are `light-dark()`, which follows the element's `color-scheme`. The package theme sets it; a page without it gets the light values.
|
|
1065
|
+
|
|
1066
|
+
Do not put a solo class on this package's own components. On a `.card` it would replace the composed fill, edge, and intent with material alone; use the aesthetic class there.
|
|
877
1067
|
|
|
878
1068
|
<!-- Source: docs/usage/buttons.md -->
|
|
879
1069
|
|
|
@@ -885,15 +1075,15 @@ Intent classes map color tokens into button tone slots. [Presentation](docs/usag
|
|
|
885
1075
|
|
|
886
1076
|
Intent classes:
|
|
887
1077
|
|
|
888
|
-
| Class
|
|
889
|
-
|
|
|
890
|
-
| `.neutral` _(default)_
|
|
891
|
-
| `.primary`
|
|
892
|
-
| `.secondary`
|
|
893
|
-
| `.success`
|
|
894
|
-
| `.warning`
|
|
895
|
-
| `.destructive
|
|
896
|
-
| `.info`
|
|
1078
|
+
| Class | Meaning |
|
|
1079
|
+
| ---------------------- | ------------------------------ |
|
|
1080
|
+
| `.neutral` _(default)_ | No specific intent. |
|
|
1081
|
+
| `.primary` | Primary action. |
|
|
1082
|
+
| `.secondary` | Secondary/accent action. |
|
|
1083
|
+
| `.success` | Successful or positive action. |
|
|
1084
|
+
| `.warning` | Warning/caution action. |
|
|
1085
|
+
| `.destructive` | Destructive or error action. |
|
|
1086
|
+
| `.info` | Informational action. |
|
|
897
1087
|
|
|
898
1088
|
Every component that supports intent accepts the same list and reads the same [intent tokens](docs/usage/theming.md#intent-tokens), so a custom intent class works everywhere without touching a component.
|
|
899
1089
|
|
|
@@ -903,12 +1093,12 @@ Size and shape classes:
|
|
|
903
1093
|
|
|
904
1094
|
| Class | Purpose |
|
|
905
1095
|
| ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
906
|
-
| `.pill` | Fully rounded button corners
|
|
1096
|
+
| `.pill` | Fully rounded button corners by default; under sketch it takes organic hand-drawn pill contours avoiding egg-shaped distortion. |
|
|
907
1097
|
| `.sm` | Smaller button. |
|
|
908
1098
|
| `.lg` | Larger button. |
|
|
909
|
-
| `.p-xs
|
|
910
|
-
| `.p-sm
|
|
911
|
-
| `.p-lg
|
|
1099
|
+
| `.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. |
|
|
1100
|
+
| `.p-sm` | Compact padding modifier (`px-2.5 py-1`; icon `p-1`). |
|
|
1101
|
+
| `.p-lg` | Spacious padding modifier (`px-6 py-3`; icon `p-3`). |
|
|
912
1102
|
| `.icon` | Square icon button, sized to its own padding rather than to `--control-height`. Use an accessible name in HTML. |
|
|
913
1103
|
| `.disabled`, `[disabled]`, `[aria-disabled="true"]`, `[data-disabled]` | Disabled styling. |
|
|
914
1104
|
|
|
@@ -943,7 +1133,7 @@ Use `<button>` for actions or an accessible link for navigation; see [Accessibil
|
|
|
943
1133
|
| `.field` | Vertical field wrapper. |
|
|
944
1134
|
| `.label` | Form label text. |
|
|
945
1135
|
| `.hint` | Secondary helper text. |
|
|
946
|
-
| `.hint.
|
|
1136
|
+
| `.hint.destructive` | Helper text with destructive intent. |
|
|
947
1137
|
| `.surface` | Shared public container composition utility. |
|
|
948
1138
|
| `.text-control` | Shared public text-control composition utility. |
|
|
949
1139
|
| `.ipt` | Input control styling. |
|
|
@@ -1003,15 +1193,15 @@ The gap between the control and its adornment is `--input-group-gap`, `0.5rem` b
|
|
|
1003
1193
|
|
|
1004
1194
|
`.checkbox`, `.radio`, and `.switch` accept the same intent classes as buttons to set the checked color:
|
|
1005
1195
|
|
|
1006
|
-
| Class
|
|
1007
|
-
|
|
|
1008
|
-
| `.neutral` _(default)_
|
|
1009
|
-
| `.primary`
|
|
1010
|
-
| `.secondary`
|
|
1011
|
-
| `.success`
|
|
1012
|
-
| `.warning`
|
|
1013
|
-
| `.destructive
|
|
1014
|
-
| `.info`
|
|
1196
|
+
| Class | Meaning |
|
|
1197
|
+
| ---------------------- | ----------------------- |
|
|
1198
|
+
| `.neutral` _(default)_ | Text color, capped. |
|
|
1199
|
+
| `.primary` | Primary color. |
|
|
1200
|
+
| `.secondary` | Secondary/accent color. |
|
|
1201
|
+
| `.success` | Success color. |
|
|
1202
|
+
| `.warning` | Warning color. |
|
|
1203
|
+
| `.destructive` | Destructive color. |
|
|
1204
|
+
| `.info` | Info color. |
|
|
1015
1205
|
|
|
1016
1206
|
All three toggles rest at `.soft`. Presentation decides the _unchecked_ plate; checked is pinned to one look regardless of which class is on the element, so a checkbox, a radio, and a switch each have a single "on" identity rather than one per presentation:
|
|
1017
1207
|
|
|
@@ -1058,7 +1248,7 @@ The boundary is the edge axis's, and it splits the same way. A container's `.edg
|
|
|
1058
1248
|
<label class="field">
|
|
1059
1249
|
<span class="label">Email</span>
|
|
1060
1250
|
<input class="ipt" type="email" aria-invalid="true" aria-describedby="email-error" />
|
|
1061
|
-
<span class="hint
|
|
1251
|
+
<span class="hint destructive" id="email-error">Enter a valid email.</span>
|
|
1062
1252
|
</label>
|
|
1063
1253
|
<label style="display: flex; gap: 0.5rem; align-items: center">
|
|
1064
1254
|
<input type="checkbox" class="checkbox success" />
|
|
@@ -1117,7 +1307,7 @@ Loader size modifiers:
|
|
|
1117
1307
|
| `.sm` | Small (`1.25rem`). |
|
|
1118
1308
|
| `.lg` | Large (`2.25rem`). |
|
|
1119
1309
|
|
|
1120
|
-
Alerts, badges, progress bars, skeletons, and loaders accept `.primary`, `.secondary`, `.success`, `.warning`, `.destructive`,
|
|
1310
|
+
Alerts, badges, progress bars, skeletons, and loaders accept `.primary`, `.secondary`, `.success`, `.warning`, `.destructive`, and `.info`. Without an intent, they use the text palette, except `.loader`, which keeps `currentColor` so it matches whatever content surrounds it.
|
|
1121
1311
|
|
|
1122
1312
|
Skeletons, loaders, and dividers are indicators: they read intent but ignore fill and edge [presentation](docs/usage/composing.md#presentation). `.progress` is not one of them — its track reads both, `.soft.edgeless` by default; only the moving value fill stays intent-colored at full strength regardless of presentation. `.solid` is unsupported on the track, and `.ghost.edgeless` renders but is discouraged, since neither leaves the track a visible frame. See [Composing → Component axis reference](docs/usage/composing.md#component-axis-reference) for the full table.
|
|
1123
1313
|
|
|
@@ -1353,19 +1543,19 @@ Use `.table-wrap` around `.data-table` when table width may exceed its container
|
|
|
1353
1543
|
|
|
1354
1544
|
## Surfaces
|
|
1355
1545
|
|
|
1356
|
-
| Class
|
|
1357
|
-
|
|
|
1358
|
-
| `.card`
|
|
1359
|
-
| `.panel`
|
|
1360
|
-
| `.interactive`
|
|
1361
|
-
| `.hoverable`
|
|
1362
|
-
| `.pressable`
|
|
1363
|
-
| `.p-xs
|
|
1364
|
-
| `.p-sm
|
|
1365
|
-
| `.p-lg
|
|
1366
|
-
| `.flush`
|
|
1546
|
+
| Class | Purpose |
|
|
1547
|
+
| -------------- | ------------------------------------------------------------------------------------- |
|
|
1548
|
+
| `.card` | Bordered container, surface radius, padded. Rests at elevation `1`. |
|
|
1549
|
+
| `.panel` | Flush container for sidebars, toolbars, and wells. No elevation. |
|
|
1550
|
+
| `.interactive` | On `.card`. Adds pointer cursor, hover and press response, and a focus ring. |
|
|
1551
|
+
| `.hoverable` | On `.card`. The hover half of `.interactive`: hover response only, no pointer cursor. |
|
|
1552
|
+
| `.pressable` | On `.card`. The press half of `.interactive`: press response and pointer cursor. |
|
|
1553
|
+
| `.p-xs` | On `.card` or `.panel`. Reduces padding further than `.p-sm`. |
|
|
1554
|
+
| `.p-sm` | On `.card` or `.panel`. Reduces padding. |
|
|
1555
|
+
| `.p-lg` | On `.card` or `.panel`. Increases padding. |
|
|
1556
|
+
| `.flush` | On `.card` or `.panel`. Removes padding, for edge-to-edge content. |
|
|
1367
1557
|
|
|
1368
|
-
Both read intent, [presentation](docs/usage/composing.md#presentation), and [material tokens](docs/usage/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](docs/usage/aesthetics.md) supplies shadow geometry or `.
|
|
1558
|
+
Both read intent, [presentation](docs/usage/composing.md#presentation), and [material tokens](docs/usage/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](docs/usage/aesthetics.md) supplies shadow geometry or `.raised`/`.floating` asks for it; see [Composing → Elevation](docs/usage/composing.md#elevation).
|
|
1369
1559
|
|
|
1370
1560
|
`.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.
|
|
1371
1561
|
|
|
@@ -1680,14 +1870,14 @@ This package provides CSS hooks for accessible states. It does not provide seman
|
|
|
1680
1870
|
|
|
1681
1871
|
### Control boundaries
|
|
1682
1872
|
|
|
1683
|
-
| Feature | Behavior
|
|
1684
|
-
| -------------------- |
|
|
1685
|
-
| Control boundaries | Text controls rest at `--_line-rest` of their intent, under 3:1 by choice
|
|
1686
|
-
| Toggle boundaries | `.checkbox`, `.radio`, and `.switch` draw their line whole, because it is the only thing marking an unchecked box.
|
|
1687
|
-
| Cascaded `.edgeless` | Floored on every text control: a container cannot erase the line of a field or toggle nobody classed.
|
|
1688
|
-
| Own `.edgeless` | On the element, `.ipt`, `.textarea`, `.select`, and `.switch` do drop their line and do not meet 1.4.11 at rest, except `.switch.ghost`: `.ghost` already asks for zero fill, so dropping the line too would leave no boundary at all, and `.switch.ghost.edgeless` keeps it up instead.
|
|
1689
|
-
| `.checkbox`/`.radio` | Never drop their line, on the element or from a container. `.edgeless` on them is unsupported, not merely discouraged.
|
|
1690
|
-
| Progress track |
|
|
1873
|
+
| Feature | Behavior |
|
|
1874
|
+
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1875
|
+
| Control boundaries | Text controls rest at `--_line-rest` of their intent, under 3:1 by choice, so hover and focus have a whole tone to move the line to. |
|
|
1876
|
+
| Toggle boundaries | `.checkbox`, `.radio`, and `.switch` draw their line whole, because it is the only thing marking an unchecked box. |
|
|
1877
|
+
| Cascaded `.edgeless` | Floored on every text control: a container cannot erase the line of a field or toggle nobody classed. |
|
|
1878
|
+
| Own `.edgeless` | On the element, `.ipt`, `.textarea`, `.select`, and `.switch` do drop their line and do not meet 1.4.11 at rest, except `.switch.ghost`: `.ghost` already asks for zero fill, so dropping the line too would leave no boundary at all, and `.switch.ghost.edgeless` keeps it up instead. |
|
|
1879
|
+
| `.checkbox`/`.radio` | Never drop their line, on the element or from a container. `.edgeless` on them is unsupported, not merely discouraged. |
|
|
1880
|
+
| Progress track | By choice, the value carries the reading and the track is a quiet secondary cue. `.progress`'s registered default, `.soft.edgeless`, rests its track at ~1.1-1.3:1 against the page; the value clears 3:1 against that track for every intent but warning in light (~2.7:1) and info in dark (~2.9:1). `.ghost.edged` clears 3:1 for both the track's outline and the value, for every intent, in both themes -- choose it where the track itself must meet 1.4.11. |
|
|
1691
1881
|
|
|
1692
1882
|
### Motion and transparency
|
|
1693
1883
|
|
|
@@ -1701,14 +1891,14 @@ The loader fallback is embedded in loader CSS, so focused imports that include l
|
|
|
1701
1891
|
|
|
1702
1892
|
### Color and contrast
|
|
1703
1893
|
|
|
1704
|
-
| Feature | Behavior
|
|
1705
|
-
| ------------------ |
|
|
1706
|
-
| Filled labels | Every intent's `.solid` label meets 1.4.3 (4.5:1) as normal text, in both themes. Lowest is success at 5.14:1.
|
|
1707
|
-
| Warning ink | `--color-warning-contrast` is the near-black tone, not the page tone. Amber dark enough to carry white is not amber.
|
|
1708
|
-
| Partial fills | Contrast ink appears only past a half fill, so a capped plate keeps `--intent-strong` rather than walking toward the page.
|
|
1709
|
-
| Intent hue in dark | `--intent-strong` is the `-300` shade in dark, so a soft or ghost label keeps its own hue instead of reading white.
|
|
1710
|
-
| Toggle marks | A checked mark meets 3:1 as a state indicator on every plate its fill class can paint, in both themes.
|
|
1711
|
-
| Soft-edged border | `.alert`, `.panel`, `.badge`, `.kbd`, and `.code`/`.pre`'s `.edged` border
|
|
1894
|
+
| Feature | Behavior |
|
|
1895
|
+
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1896
|
+
| Filled labels | Every intent's `.solid` label meets 1.4.3 (4.5:1) as normal text, in both themes. Lowest is success at 5.14:1. |
|
|
1897
|
+
| Warning ink | `--color-warning-contrast` is the near-black tone, not the page tone. Amber dark enough to carry white is not amber. |
|
|
1898
|
+
| Partial fills | Contrast ink appears only past a half fill, so a capped plate keeps `--intent-strong` rather than walking toward the page. |
|
|
1899
|
+
| Intent hue in dark | `--intent-strong` is the `-300` shade in dark, so a soft or ghost label keeps its own hue instead of reading white. |
|
|
1900
|
+
| Toggle marks | A checked mark meets 3:1 as a state indicator on every plate its fill class can paint, in both themes. |
|
|
1901
|
+
| Soft-edged border | `.alert`, `.panel`, `.badge`, `.kbd`, and `.code`/`.pre`'s `.edged` border fades out by the component's fill amount; at `.soft`'s 12% fill this misses 3:1 against the fill for some intents, and which ones misses depends on the theme. Known, not fixed -- `--color-border`/`--intent-border` is a shared blend seam every one of them reads, so a targeted fix would need to touch it for one component without moving it for the rest. |
|
|
1712
1902
|
|
|
1713
1903
|
### Forced colors and direction
|
|
1714
1904
|
|
|
@@ -1756,6 +1946,53 @@ Use ARIA or data attributes when native attributes are not available for the ele
|
|
|
1756
1946
|
|
|
1757
1947
|
`aria-disabled="true"` communicates disabled state but does not prevent activation. JavaScript or element choice must prevent activation when required.
|
|
1758
1948
|
|
|
1949
|
+
<!-- Source: docs/changelog/0.5.0.md -->
|
|
1950
|
+
|
|
1951
|
+
# 0.5.0
|
|
1952
|
+
|
|
1953
|
+
A foundation update with an opt-in sketch aesthetic and rounded sketch variant.
|
|
1954
|
+
|
|
1955
|
+
## Breaking
|
|
1956
|
+
|
|
1957
|
+
- **The package sits in named cascade layers.** Every entrypoint declares Tailwind's layer order first and places everything in it: foundation tokens and the palette in `theme`, resets in `base`, the intent, presentation, elevation, and aesthetic classes in `components`, and every component in `utilities` -- including on `/components` and `/native`, which emitted them unlayered. Your own utility or unlayered CSS now beats all four class families on the same element, and an aesthetic on `<html>` keeps its tokens over the theme's in any load order. CSS that relied on a package class beating it now loses to it, and a rule of yours in `@layer components` contests the class families by specificity instead of losing outright. See [Setup](docs/setup.md).
|
|
1958
|
+
- **Aesthetics set `--ui-corner`, not `--ui-radius`.** The corner is now a length at the default size that scales with the element (below); `--ui-radius` and `--ui-radius-surface` take a complete radius used as written, and every shipped aesthetic sets `--ui-corner` and `--ui-corner-surface` instead. If you set `--ui-radius` yourself, nothing changes for you. An aesthetic of your own moves to `--ui-corner` to get the scale and the corner pattern. `--ui-radius-pill` and `--ui-radius-tight` fall back through `--ui-radius`, then `--ui-corner`.
|
|
1959
|
+
- **`--ui-button-weight` and `--ui-button-tracking` are `--ui-label-weight` and `--ui-label-tracking`**, read by `.badge` as well as `.btn`. The old names are removed without an alias. Under `.chunky-tile`, badges now take the heavier label too.
|
|
1960
|
+
- **Explicit chip radii are no longer capped.** Checkbox, `.kbd`, and `.code` keep a small default radius when `--ui-radius-tight` is unset, but a supplied value now applies as a complete `border-radius`, including elliptical shapes. A consumer setting a large value now gets the large corner it asked for instead of the previous `--radius-small` ceiling.
|
|
1961
|
+
- **Alias classes removed**, each a second name for a class that already had one: `.dense`, `.compact`, and `.spacious` (use `.p-xs`, `.p-sm`, and `.p-lg`); `.danger` and `.error` (use `.destructive`, and `.hint.destructive` for `.hint.error`); and `.elevation-none`, `.elevation-sm`, and `.elevation-md` (use `.flat`, `.raised`, and `.floating`). `.theme-light` and `.theme-dark` stay.
|
|
1962
|
+
- **`.cyber` glows everything, flat or not.** Its glow moved from depth onto the new halo, so fields, chips, badges, and alerts glow too, `.flat` no longer puts the glow out, and `.raised` and `.floating` add no shadow under it.
|
|
1963
|
+
|
|
1964
|
+
## Added
|
|
1965
|
+
|
|
1966
|
+
- **`.sketch`, `.sketch-rounded`, and `.sketch-solo`**: a hand-drawn treatment with uneven elliptical corners, a solid ink line (dashed checkboxes and rules under `.sketch`), a small offset shadow, and an optional consumer-supplied handwriting font. Sibling components rotate between four stable outlines; pill buttons take organic hand-drawn rounded pill contours without oval distortion; switch tracks, knobs, and chips take compact irregular box outlines, and radios stay subtly circular. The opt-in `.sketch-rounded` modifier class provides subtle, organic hand-drawn rounded contours across controls, surfaces, chips, and solo elements with 4-step sibling rotation and no egg-shaped distortion on wide elements. The solo class paints an unstyled element directly; the cascading class restyles package components. Both ship in the aesthetic aggregate and dedicated compiled and Tailwind CSS entrypoints. See [Aesthetics](docs/usage/aesthetics.md#sketch).
|
|
1967
|
+
- **Corner scale.** `.p-xs` sets a size step of `0.5`, `.sm` and `.p-sm` `0.75`, and `.lg` and `.p-lg` `1.25`, and the corner is multiplied by it; when a size and a padding class sit on one element, the smaller step wins. A bevel stays a true 45 degrees, so `.cyber`'s 25% cap is gone. Depth follows the step down, never up: a `.p-xs` button sits on half its aesthetic's shadow, which also retires chunky tile's one selector list. `--ui-scale` overrides the step. A press that travels into the depth -- `--ui-active-translate-x` and `-y`, which chunky tile and neobrutalism now set instead of a translating `--ui-active-transform` -- scales the same way, elevation included, so it always lands flat on the slab, and a `.flat` button under either no longer drops. See [Customizing → Corner size and pattern](docs/usage/customizing.md#corner-size-and-pattern).
|
|
1968
|
+
- **Corner pattern.** `.cut-diagonal` keeps the top-left and bottom-right corners and squares the other two, `.cut-diagonal-reverse` the opposite pair, wherever the corner is computed -- on a control under `.cyber`, but not a surface, which keeps its own shape. Both set `--ui-corner-tl`, `-tr`, `-br`, and `-bl`, which you can set yourself.
|
|
1969
|
+
- **`--ui-line-style`**: `solid`, `dashed`, `dotted`, or `double` for every line a component draws -- the box's edge, the progress track, and dividers and table rules. `--ui-rule-style` overrides only dividers and table rules.
|
|
1970
|
+
- **A halo**, `--ui-halo-blur`, `--ui-halo-spread`, and `--ui-halo-ink`: light in the element's own intent colour, which elevation does not scale and `.flat` does not remove.
|
|
1971
|
+
- **`--ui-surface-image`**, a painted layer over a surface's plate -- cards, panels, alerts, and tooltips, not controls. Your own `background-image` on a surface still wins.
|
|
1972
|
+
- **`--ui-label-case` and `--ui-label-shadow`**, beside the weight and tracking: the label's `text-transform`, and a `text-shadow` written without a colour so it takes the label's own.
|
|
1973
|
+
- **`--ui-control-ink`**, a neutral line for controls read ahead of `--ui-ink`. Glass and chunky tile set it, so an unchecked checkbox under glass (1.33:1 before) and a field under chunky tile (1.65:1 before) draw a boundary that reads.
|
|
1974
|
+
|
|
1975
|
+
Under forced colours, each new part draws its plain version: a solid line, no halo, no painted layer, and no label shadow.
|
|
1976
|
+
|
|
1977
|
+
## Fixed
|
|
1978
|
+
|
|
1979
|
+
- **A stylesheet survives being inlined.** The loader art's SVG data URIs carried a literal `</style>`, so a stylesheet pasted into an HTML `<style>` element ended at the first loader and silently dropped every rule after it. It is now percent-encoded.
|
|
1980
|
+
- **Every entry ships the theme it promises.** `/components`, `/tw/components`, `/tw/feedback`, and `/tw/tooltip` shipped no colour token at all, and every other focused `/tw` component entry lost the palette ramp the tokens are built from. Each entry now declares every colour it reads, and `/components` works alone.
|
|
1981
|
+
- **A line fades into a translucent plate instead of ringing it.** A neutral `.solid.edged`, and any plate `--ui-bg-alpha` thins, drew a ring 1.54:1 against its own fill; the line now fades toward transparent as the fill fills in. The generated palette's edge tokens follow.
|
|
1982
|
+
- **A select's options read in the dark theme.** The open list is painted over the select's own background, and a ghost `.select` has none, so Chromium drew its default white popup under options that inherited the near-white text. Options and option groups now take the page's ground and text colour.
|
|
1983
|
+
- **A region nested inside glass keeps its own surfaces.** Neobrutalism, pixel, chunky tile, and cyber left glass's translucent ground, fill alpha, and two-layer surface shadow in place, so their cards inside a glass region came out as half glass. Every aesthetic now clears them.
|
|
1984
|
+
- **Surfaces under glass stay glass.** A neutral `.card.soft`, `.panel`, and `.alert` sat opaque inside a glass region, and `.card.soft.glass` did on the same element; their quiet ground is now a private default beneath `--ui-surface-ground`.
|
|
1985
|
+
|
|
1986
|
+
<!-- Source: docs/changelog/0.4.0.md -->
|
|
1987
|
+
|
|
1988
|
+
# 0.4.0
|
|
1989
|
+
|
|
1990
|
+
## Added
|
|
1991
|
+
|
|
1992
|
+
- **`.cyber`**, a fifth aesthetic from `@codenhub/styles/aesthetics/cyber` (and `/tw/aesthetics/cyber`, and both aggregates): bevelled corners, a 1px edge, and a glow in each component's own colour. Controls cut top-left and bottom-right, surfaces top-right and bottom-left; what is fully round (a radio, a switch, a pill, a badge) cuts to diamonds and pointed hexagons, and chips square. Knobs: `--cyber-cut`, `--cyber-shape`, `--cyber-shape-surface`, `--cyber-glow`, `--cyber-ink`, and the consumer-supplied `--font-cyber`. The bevel is drawn with `corner-shape`, which only Chromium supports today; Firefox and Safari get square cut corners and round round ones. See [Aesthetics → Cyber](docs/usage/aesthetics.md#cyber).
|
|
1993
|
+
- **A solo class for every aesthetic**: `.glass-solo`, `.neobrutalism-solo`, `.pixel-solo`, `.chunky-tile-solo`, and `.cyber-solo` paint the aesthetic's look onto the one element carrying the class, for an element this package does not style -- a toast from another library, or a `<div>` on a page without the base stylesheet. Each ships in its aesthetic's existing entrypoint and needs nothing else loaded. See [Aesthetics → Solo classes](docs/usage/aesthetics.md#solo-classes).
|
|
1994
|
+
- **Three material tokens**: `--ui-corner-shape` (what a corner draws: `round`, or a `bevel` cut), `--ui-radius-pill` (the corner of what is fully round by default), and `--ui-radius-tight` (the corner of chips, before their `--radius-small` cap). All three default to today's look, so nothing changes unless an aesthetic or your own CSS sets them. See [Customizing → Material tokens](docs/usage/customizing.md#material-tokens).
|
|
1995
|
+
|
|
1759
1996
|
<!-- Source: docs/changelog/0.3.0.md -->
|
|
1760
1997
|
|
|
1761
1998
|
# 0.3.0
|