@codenhub/styles 0.1.0 → 0.1.1
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 +7 -69
- package/dist/aesthetics/chunky-tile.css +1 -1
- package/dist/aesthetics/index.css +1 -1
- package/dist/components.css +1 -1
- package/dist/index.css +1 -1
- package/dist/native.css +1 -1
- package/dist/theme.css +1 -1
- package/dist/tw/aesthetics/chunky-tile.css +4 -2
- package/dist/tw/box.css +21 -0
- package/dist/tw/components/button.css +23 -3
- package/dist/tw/components/form.css +0 -2
- package/dist/tw/components/index.css +16 -6
- package/dist/tw/components/surface.css +29 -5
- package/dist/tw/elevation.css +14 -7
- package/dist/tw/index.css +20 -5
- package/dist/tw/intent.css +20 -0
- package/dist/tw/native.css +4 -20
- package/dist/tw/reset.css +20 -33
- package/dist/tw/theme.css +12 -7
- package/dist/tw/utilities/content.css +14 -2
- package/docs/accessibility.md +58 -48
- package/docs/changelog/0.1.0.md +37 -0
- package/docs/changelog/0.1.1.md +10 -0
- package/docs/changelog/index.md +10 -0
- package/docs/concepts.md +20 -46
- package/docs/index.md +18 -45
- package/docs/integrating/astro.md +13 -7
- package/docs/integrating/index.md +25 -16
- package/docs/integrating/nextjs.md +31 -8
- package/docs/integrating/svelte.md +14 -8
- package/docs/integrating/tailwind.md +31 -15
- package/docs/integrating/vue.md +13 -7
- package/docs/setup.md +35 -55
- package/docs/usage/aesthetics.md +30 -107
- package/docs/usage/buttons.md +19 -35
- package/docs/usage/composing.md +25 -100
- package/docs/usage/content-and-layout.md +56 -81
- package/docs/usage/customizing.md +25 -90
- package/docs/usage/feedback.md +11 -49
- package/docs/usage/forms.md +16 -58
- package/docs/usage/index.md +9 -17
- package/docs/usage/theming.md +25 -81
- package/docs/usage/tooltips.md +15 -21
- package/llms-full.txt +1060 -1506
- package/package.json +121 -44
package/docs/accessibility.md
CHANGED
|
@@ -1,54 +1,66 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Accessibility
|
|
3
|
+
order: 5
|
|
3
4
|
---
|
|
4
5
|
|
|
5
6
|
# Accessibility responsibilities
|
|
6
7
|
|
|
7
8
|
This package provides CSS hooks for accessible states. It does not provide semantic HTML, ARIA attributes, keyboard behavior, focus management, validation, announcement timing, or JavaScript behavior.
|
|
8
9
|
|
|
9
|
-
## Provided
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
|
14
|
-
|
|
|
15
|
-
|
|
|
16
|
-
|
|
|
17
|
-
|
|
|
18
|
-
|
|
|
19
|
-
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
|
24
|
-
|
|
|
25
|
-
|
|
|
26
|
-
|
|
|
27
|
-
|
|
|
28
|
-
|
|
|
29
|
-
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
native entrypoints include both that fallback and the reset's broader animation
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
10
|
+
## Provided by CSS
|
|
11
|
+
|
|
12
|
+
### Focus and state
|
|
13
|
+
|
|
14
|
+
| Feature | Behavior |
|
|
15
|
+
| ------------------ | ------------------------------------------------------------------------------------------------------------------------- |
|
|
16
|
+
| `:focus-visible` | Global focus-visible outline using `--focus-ring`, `--focus-ring-width`, and `--focus-ring-offset`. |
|
|
17
|
+
| Form control focus | `.ipt`, `.textarea`, and `.select` draw the global focus ring and move their line to the intent color. |
|
|
18
|
+
| Invalid controls | `[aria-invalid="true"]` applies destructive border/focus color on form controls. |
|
|
19
|
+
| Disabled controls | `[disabled]`, `[aria-disabled="true"]`, `[data-disabled]`, and `.disabled` apply disabled cursor/opacity where supported. |
|
|
20
|
+
| Open state | `[data-state="open"]` styles supported surfaces and tooltips. |
|
|
21
|
+
|
|
22
|
+
### Control boundaries
|
|
23
|
+
|
|
24
|
+
| Feature | Behavior |
|
|
25
|
+
| -------------------- | ---------------------------------------------------------------------------------------------------------------------- |
|
|
26
|
+
| Control boundaries | Text controls rest at `--_line-rest` of their intent, under 3:1 by choice; hover and focus take the tone whole. |
|
|
27
|
+
| Toggle boundaries | `.checkbox`, `.radio`, and `.switch` draw their line whole, because it is the only thing marking an unchecked box. |
|
|
28
|
+
| Cascaded `.edgeless` | Floored on every text control: a container cannot erase the line of a field or toggle nobody classed. |
|
|
29
|
+
| Own `.edgeless` | On the element, `.ipt`, `.textarea`, `.select`, and `.switch` do drop their line and do not meet 1.4.11 at rest. |
|
|
30
|
+
| `.checkbox`/`.radio` | Never drop their line, on the element or from a container. `.edgeless` on them is unsupported, not merely discouraged. |
|
|
31
|
+
|
|
32
|
+
### Motion and transparency
|
|
33
|
+
|
|
34
|
+
| Feature | Behavior |
|
|
35
|
+
| ----------------------- | ------------------------------------------------------------------------------------------------------------------- |
|
|
36
|
+
| Reduced-motion loaders | Loader variants use animated embedded SVGs normally and static masks when `prefers-reduced-motion: reduce` matches. |
|
|
37
|
+
| Reduced-motion document | The reset additionally shortens document animations and transitions when `prefers-reduced-motion: reduce` matches. |
|
|
38
|
+
| Reduced transparency | `.glass` drops its blur and becomes an opaque surface when `prefers-reduced-transparency: reduce` matches. |
|
|
39
|
+
|
|
40
|
+
The loader fallback is embedded in loader CSS, so focused imports that include loaders honor reduced motion without the reset. This includes `@codenhub/styles/components`, `@codenhub/styles/tw/components`, and `@codenhub/styles/tw/loader`. The complete and native entrypoints include both that fallback and the reset's broader animation and transition shortening.
|
|
41
|
+
|
|
42
|
+
### Color and contrast
|
|
43
|
+
|
|
44
|
+
| Feature | Behavior |
|
|
45
|
+
| ------------------ | -------------------------------------------------------------------------------------------------------------------------- |
|
|
46
|
+
| 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. |
|
|
47
|
+
| Warning ink | `--color-warning-contrast` is the near-black tone, not the page tone. Amber dark enough to carry white is not amber. |
|
|
48
|
+
| Partial fills | Contrast ink appears only past a half fill, so a capped plate keeps `--intent-strong` rather than walking toward the page. |
|
|
49
|
+
| 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. |
|
|
50
|
+
| Toggle marks | A checked mark meets 3:1 as a state indicator on every plate its fill class can paint, in both themes. |
|
|
51
|
+
|
|
52
|
+
### Forced colors and direction
|
|
53
|
+
|
|
54
|
+
| Feature | Behavior |
|
|
55
|
+
| -------------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
56
|
+
| Forced colors | `forced-colors: active` preserves visible borders and checked states using system colors. |
|
|
57
|
+
| Text direction | Quote bar, alert icon, progress fill, vertical divider, and switch knob mirror under `dir="rtl"`. No class needed. |
|
|
58
|
+
|
|
59
|
+
In forced colors, class-based form controls including `.text-control` receive a 2px `Highlight` system-color focus outline. The native entrypoint provides the same visible system outline for unclassed text inputs, selects, textareas, checkboxes, and radios.
|
|
60
|
+
|
|
61
|
+
Custom checkboxes and radios use the system `Canvas`, `CanvasText`, `Highlight`, and `HighlightText` colors in forced-colors mode so checked and unchecked states remain distinct. Shape, size, and spacing remain unchanged.
|
|
62
|
+
|
|
63
|
+
## Required outside CSS
|
|
52
64
|
|
|
53
65
|
Use semantic HTML and behavior appropriate for the component.
|
|
54
66
|
|
|
@@ -63,20 +75,18 @@ Use semantic HTML and behavior appropriate for the component.
|
|
|
63
75
|
| Skeletons/loaders | Mark decorative loading visuals with `aria-hidden="true"` and expose loading state elsewhere when needed. |
|
|
64
76
|
| Popovers/modals | Provide focus trapping, escape handling, inert background behavior, labels, and roles outside this CSS package. |
|
|
65
77
|
|
|
66
|
-
## State
|
|
78
|
+
## State attribute guidance
|
|
67
79
|
|
|
68
80
|
Prefer native attributes first:
|
|
69
81
|
|
|
70
82
|
```html
|
|
71
|
-
<button class="btn primary" disabled>Saving</button>
|
|
72
|
-
<input class="ipt" aria-invalid="true" aria-describedby="email-error" />
|
|
83
|
+
<button class="btn primary" disabled>Saving</button> <input class="ipt" aria-invalid="true" aria-describedby="email-error" />
|
|
73
84
|
```
|
|
74
85
|
|
|
75
86
|
Use ARIA or data attributes when native attributes are not available for the element or library:
|
|
76
87
|
|
|
77
88
|
```html
|
|
78
|
-
<a class="btn secondary" aria-disabled="true">Unavailable</a>
|
|
79
|
-
<button class="tooltip tooltip-icon" data-state="open" data-tooltip="More details" aria-label="More details">?</button>
|
|
89
|
+
<a class="btn secondary" aria-disabled="true">Unavailable</a> <button class="tooltip tooltip-icon" data-state="open" data-tooltip="More details" aria-label="More details">?</button>
|
|
80
90
|
```
|
|
81
91
|
|
|
82
92
|
`aria-disabled="true"` communicates disabled state but does not prevent activation. JavaScript or element choice must prevent activation when required.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 0.1.0
|
|
3
|
+
date: 2026-08-31
|
|
4
|
+
description: The three-axis styling model, split presentation, opt-in aesthetics, and Tailwind v4 source entrypoints.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.1.0
|
|
8
|
+
|
|
9
|
+
`0.1.0` replaces the model published in `0.0.4` wholesale. The old model had three orthogonal axes with per-component clamps and no chosen default: a plain element got whatever `var()` fallback each component happened to declare. This release makes each decision explicitly and is the baseline the `0.x` line builds on. Nearly everything below is breaking against `0.0.4`; there are no compatibility aliases.
|
|
10
|
+
|
|
11
|
+
## Changed
|
|
12
|
+
|
|
13
|
+
- **Every element now composes from three named axes.** _Intent_ (`.primary`, `.success`, `.destructive`, …) sets hue only. _Presentation_ sets how much of that hue fills the element and whether it draws an edge. _Aesthetic_ sets the material — radius, edge width, shadow, silhouette, type. Intent is redeclared per component; presentation and aesthetic cascade, so a container can set the look of a subtree while any element opts out. [Concepts](../concepts.md) and [Composing](../usage/composing.md) describe the full model.
|
|
14
|
+
- **Presentation is two independent questions.** Fill is `.solid` / `.soft` / `.ghost`; edge is `.edged` / `.edgeless`. Exactly one of each applies, and they never decide each other. The common web button — a subtle fill with a border — is `.soft.edged`, which had no spelling before.
|
|
15
|
+
- **`.bare` is renamed `.ghost`.** `.bare` and `.edgeless` both read as "less of something", so the name is now a fill and only a fill: no fill at rest, a tint on hover.
|
|
16
|
+
- **Hover is derived, not declared.** A hovered element takes its resting fill plus one published step and its `--intent-hover` colour. There are no hover tokens to set. An outline button therefore tints on hover rather than filling completely.
|
|
17
|
+
- **A sunk text field is `.soft.edgeless`.** Two classes saying two things, where `.soft` alone used to silently suppress the field's border.
|
|
18
|
+
- **Table row rules are opt-in via `.ruled`.** Rules no longer arrive by implication from a component's edge default. The head and foot separators stay at every presentation.
|
|
19
|
+
- **Depth is a modifier, not part of a component.** `surface` no longer carries a structural shadow, so cards, buttons, and chips on a plain page rest flat. Use `.raised` / `.floating` (or `.elevation-sm` / `.elevation-md`) to add depth, and `.flat` to remove an aesthetic's.
|
|
20
|
+
- **The Tailwind v4 entrypoint moved from `/overrides` to `/native`.**
|
|
21
|
+
|
|
22
|
+
## Added
|
|
23
|
+
|
|
24
|
+
- **Opt-in aesthetics.** `.neobrutalism`, `.glass`, `.pixel`, and `.chunky-tile`, each shipped as its own entrypoint (`@codenhub/styles/aesthetics/pixel`, …) and as an aggregate (`@codenhub/styles/aesthetics`). An aesthetic sets material tokens only; it never repaints hue. See [Aesthetics](../usage/aesthetics.md).
|
|
25
|
+
- **An elevation modifier.** `.flat` / `.raised` / `.floating` (and the `.elevation-none` / `-sm` / `-md` names) multiply an aesthetic's shadow geometry. Unitless, so a container can flatten a whole toolbar and any element can opt back in.
|
|
26
|
+
- **Granular Tailwind v4 source entrypoints.** `@codenhub/styles/tw` and per-family subpaths (`/tw/button`, `/tw/form`, `/tw/feedback`, `/tw/tooltip`, `/tw/utilities`, `/tw/aesthetics/*`, …) for consumers compiling their own build. `package.json` is also exported.
|
|
27
|
+
- **`.input-group`.** A wrapper that draws one box and lets the control inside give up its own paint, so an icon can sit alongside a field. The package ships no icons — any element works in the slot.
|
|
28
|
+
- **`registry.json`.** A machine-readable record of every supported class, each component's default fill/edge/elevation, the axes it reads, and every bound and exception with its reason.
|
|
29
|
+
- **`--intent-strong`**, the intent tone chosen to be read on a page, used wherever a fill is partial.
|
|
30
|
+
|
|
31
|
+
## Removed
|
|
32
|
+
|
|
33
|
+
- **`.out` and `.fill`.** Outline is now `.ghost.edged`; there is no class that makes an outline button fill completely on hover.
|
|
34
|
+
- **`--ui-border-scale` / `.out`'s doubled border.** The edge width comes from the aesthetic and nothing else, which removed the per-component border ceilings small components needed.
|
|
35
|
+
- **`--color-text-subtle`**, which nothing read.
|
|
36
|
+
- **`--layout-stack-gap` and `--layout-cluster-gap`**, replaced by a single `--layout-gap`.
|
|
37
|
+
- **The bundled input-field icons.** Icons were a `background-image` data URI with a light and a dark copy per glyph; they are gone, and `.input-group` carries a consumer-supplied icon instead.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 0.1.1
|
|
3
|
+
date: 2026-09-10
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 0.1.1
|
|
7
|
+
|
|
8
|
+
## Fixed
|
|
9
|
+
|
|
10
|
+
- `.p-xs` and its alias `.dense` now clear a button's `--control-height` minimum, so a chip-sized button fits inside a table cell or a dense toolbar. Before this, every button kept the full control-height floor even at the tightest padding, so a button that small could not be built. Every other size and padding class still keeps the floor, so a plain button is unchanged. An icon-only `.p-xs`/`.dense` button also gives up its `min-width`; size the glyph yourself, as the package sizes no icons.
|
package/docs/concepts.md
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Concepts
|
|
3
3
|
description: The three-axis model, the token system, and how theme selection works.
|
|
4
|
+
order: 2
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Concepts
|
|
7
8
|
|
|
8
|
-
Read this before the usage guides. It explains the mental model every
|
|
9
|
-
component, token, and class in this package shares.
|
|
9
|
+
Read this before the usage guides. It explains the mental model every component, token, and class in this package shares.
|
|
10
10
|
|
|
11
11
|
## The three axes
|
|
12
12
|
|
|
13
|
-
Every component separates three independent choices, so each can change
|
|
14
|
-
without a component-specific variant:
|
|
13
|
+
Every component separates three independent choices, so each can change without a component-specific variant:
|
|
15
14
|
|
|
16
15
|
| Axis | Question | Classes | Inheritance |
|
|
17
16
|
| ------------ | --------------- | ----------------------------------------------------------------------------------------- | ------------ |
|
|
@@ -26,25 +25,16 @@ without a component-specific variant:
|
|
|
26
25
|
</section>
|
|
27
26
|
```
|
|
28
27
|
|
|
29
|
-
Intent stays on the component so a semantic container cannot accidentally
|
|
30
|
-
recolor nested controls. Presentation and aesthetic cascade from a container;
|
|
31
|
-
putting either class directly on a component overrides the inherited choice.
|
|
32
|
-
Components apply documented clamps when an axis would remove an essential edge
|
|
33
|
-
or overwhelm compact geometry.
|
|
28
|
+
Intent stays on the component so a semantic container cannot accidentally recolor nested controls. Presentation and aesthetic cascade from a container; putting either class directly on a component overrides the inherited choice. Components apply documented clamps when an axis would remove an essential edge or overwhelm compact geometry.
|
|
34
29
|
|
|
35
|
-
The maintained contract is the intersection of the combinations documented in
|
|
36
|
-
[Usage](./usage/index.md) and demonstrated by the playground. Undocumented and
|
|
37
|
-
undemonstrated combinations may produce CSS but are not supported behavior.
|
|
30
|
+
The maintained contract is the intersection of the combinations documented in [Usage](./usage/index.md) and demonstrated by the playground. Undocumented and undemonstrated combinations may produce CSS but are not supported behavior.
|
|
38
31
|
|
|
39
|
-
- [Usage → Composing](./usage/composing.md) shows how the three axes combine
|
|
40
|
-
|
|
41
|
-
- [Usage → Aesthetics](./usage/aesthetics.md) covers each aesthetic and its
|
|
42
|
-
documented exceptions in depth.
|
|
32
|
+
- [Usage → Composing](./usage/composing.md) shows how the three axes combine on each component, with the full axis-support matrix.
|
|
33
|
+
- [Usage → Aesthetics](./usage/aesthetics.md) covers each aesthetic and its documented exceptions in depth.
|
|
43
34
|
|
|
44
35
|
## The token system
|
|
45
36
|
|
|
46
|
-
Tokens are CSS custom properties, grouped by what they control rather than
|
|
47
|
-
where they're used:
|
|
37
|
+
Tokens are CSS custom properties, grouped by what they control rather than where they're used:
|
|
48
38
|
|
|
49
39
|
| Category | Controls | Reference |
|
|
50
40
|
| ------------ | ------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
|
|
@@ -55,40 +45,24 @@ where they're used:
|
|
|
55
45
|
| Material | What a component is made of — radius, border width, shadow geometry, translucency. | [Usage → Customizing](./usage/customizing.md#material-tokens) |
|
|
56
46
|
| Aesthetic | Per-aesthetic knobs such as `--pixel-unit` or `--tile-lift`. | [Usage → Customizing](./usage/customizing.md#aesthetic-tokens) |
|
|
57
47
|
|
|
58
|
-
Color and foundation tokens are the ones most apps touch first, to match a
|
|
59
|
-
brand palette or spacing scale. Intent, presentation, and material tokens are
|
|
60
|
-
lower-level: components read them, and only presentation classes, aesthetic
|
|
61
|
-
classes, or a consumer override should set them.
|
|
48
|
+
Color and foundation tokens are the ones most apps touch first, to match a brand palette or spacing scale. Intent, presentation, and material tokens are lower-level: components read them, and only presentation classes, aesthetic classes, or a consumer override should set them.
|
|
62
49
|
|
|
63
50
|
## Theme selection
|
|
64
51
|
|
|
65
|
-
The root follows the operating-system `color-scheme` preference until an
|
|
66
|
-
explicit selector overrides it.
|
|
52
|
+
The root follows the operating-system `color-scheme` preference until an explicit selector overrides it.
|
|
67
53
|
|
|
68
54
|
| Theme | Equivalent selectors |
|
|
69
55
|
| ----- | ------------------------------------------------ |
|
|
70
56
|
| Light | `.light`, `.theme-light`, `[data-theme="light"]` |
|
|
71
57
|
| Dark | `.dark`, `.theme-dark`, `[data-theme="dark"]` |
|
|
72
58
|
|
|
73
|
-
- Theme selectors set `color-scheme` and nothing else. Because `color-scheme`
|
|
74
|
-
|
|
75
|
-
-
|
|
76
|
-
|
|
77
|
-
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
not rely on this conflict behavior; apply one theme per element.
|
|
84
|
-
- Component colors resolve from tokens or `currentColor`, so they follow the
|
|
85
|
-
theme without separate dark-variant rules, with no exception: every glyph
|
|
86
|
-
the package draws is a `currentColor` mask. Icon artwork a consumer brings
|
|
87
|
-
is theirs to theme.
|
|
88
|
-
|
|
89
|
-
Setting `color-scheme` yourself on an element also re-themes the tokens below
|
|
90
|
-
it, because that is the only signal the palette reads. This also themes native
|
|
91
|
-
UI such as scrollbars and form-control internals to match.
|
|
92
|
-
|
|
93
|
-
This mechanism works from Chrome 123, Safari 17.5, and Firefox 120; the package
|
|
94
|
-
overall requires Firefox 121 for `:has()` (see [Setup](./setup.md#requirements)).
|
|
59
|
+
- Theme selectors set `color-scheme` and nothing else. Because `color-scheme` inherits, a selector themes its entire subtree.
|
|
60
|
+
- With no explicit selector, `:root` uses `color-scheme: light dark`, so the system preference decides.
|
|
61
|
+
- A theme selector on `:root` overrides the system preference in either direction.
|
|
62
|
+
- A nested explicit selector overrides an inherited theme, so the nearest themed ancestor controls that subtree at any depth.
|
|
63
|
+
- If conflicting light and dark selectors are placed on the same element, the dark declaration wins because it appears later with equal specificity. Do not rely on this conflict behavior; apply one theme per element.
|
|
64
|
+
- Component colors resolve from tokens or `currentColor`, so they follow the theme without separate dark-variant rules, with no exception: every glyph the package draws is a `currentColor` mask. Icon artwork a consumer brings is theirs to theme.
|
|
65
|
+
|
|
66
|
+
Setting `color-scheme` yourself on an element also re-themes the tokens below it, because that is the only signal the palette reads. This also themes native UI such as scrollbars and form-control internals to match.
|
|
67
|
+
|
|
68
|
+
This mechanism works from Chrome 123, Safari 17.5, and Firefox 120; the package overall requires Firefox 121 for `:has()` (see [Setup](./setup.md#requirements)).
|
package/docs/index.md
CHANGED
|
@@ -5,58 +5,31 @@ description: What @codenhub/styles is, what it covers, and where to go next.
|
|
|
5
5
|
|
|
6
6
|
# @codenhub/styles
|
|
7
7
|
|
|
8
|
-
`@codenhub/styles` is a CSS-only design system: tokens, a reset, typography and
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
which color, how much of it, and what it's made of — so changing one never
|
|
12
|
-
requires a component-specific variant. Four optional aesthetics
|
|
13
|
-
(`.neobrutalism`, `.glass`, `.pixel`, `.chunky-tile`) restyle that same
|
|
14
|
-
component set without touching markup.
|
|
15
|
-
|
|
16
|
-
The package ships as ready-to-import compiled CSS, or as Tailwind CSS v4
|
|
17
|
-
source entrypoints for a project that already runs Tailwind. Both cover the
|
|
18
|
-
same classes; the difference is which build processes them.
|
|
8
|
+
`@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. Four optional aesthetics (`.neobrutalism`, `.glass`, `.pixel`, `.chunky-tile`) restyle that same component set without touching markup.
|
|
9
|
+
|
|
10
|
+
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.
|
|
19
11
|
|
|
20
12
|
## What it does
|
|
21
13
|
|
|
22
|
-
- Publishes color, foundation, intent, presentation, and material design
|
|
23
|
-
|
|
24
|
-
- Provides
|
|
25
|
-
|
|
26
|
-
- Provides
|
|
27
|
-
badges, loaders, progress, cards/panels, tables, quotes, code, and
|
|
28
|
-
tooltips.
|
|
29
|
-
- Provides four opt-in aesthetics that restyle the same components by setting
|
|
30
|
-
material tokens, not by adding component variants.
|
|
31
|
-
- Provides classless mappings so plain HTML elements pick up base styling
|
|
32
|
-
without added classes, from a dedicated entrypoint.
|
|
14
|
+
- Publishes color, foundation, intent, presentation, and material design tokens as CSS custom properties, themed with `light-dark()`.
|
|
15
|
+
- Provides a reset, focus-visible handling, and responsive layout/content utilities.
|
|
16
|
+
- Provides composable classes for buttons, form controls and toggles, alerts, badges, loaders, progress, cards/panels, tables, quotes, code, and tooltips.
|
|
17
|
+
- Provides four opt-in aesthetics that restyle the same components by setting material tokens, not by adding component variants.
|
|
18
|
+
- Provides classless mappings so plain HTML elements pick up base styling without added classes, from a dedicated entrypoint.
|
|
33
19
|
- Publishes Tailwind CSS v4 source entrypoints alongside the compiled output.
|
|
34
20
|
|
|
35
21
|
## What it does not do
|
|
36
22
|
|
|
37
|
-
- No JavaScript. There is no runtime, no framework bindings, and no build-time
|
|
38
|
-
|
|
39
|
-
- No
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
- No theme-toggling logic. Theme selection is a class or attribute a consumer
|
|
43
|
-
applies; wiring a toggle to system preference, storage, or a user setting is
|
|
44
|
-
outside this package. The `@codenhub/theme` package covers that need for
|
|
45
|
-
consumers who want it.
|
|
46
|
-
- No shipped font binaries. `.pixel` and `.chunky-tile` accept a
|
|
47
|
-
consumer-supplied font and fall back to a system stack when none is given.
|
|
48
|
-
- No compatibility layer for removed tokens or classes. Breaking changes are
|
|
49
|
-
documented, not silently aliased.
|
|
23
|
+
- No JavaScript. There is no runtime, no framework bindings, and no build-time code generation beyond the CSS itself.
|
|
24
|
+
- No semantic HTML, ARIA, keyboard behavior, focus management, validation, or announcement timing. See [Accessibility](./accessibility.md) for the exact line between what the CSS provides and what an application must still add.
|
|
25
|
+
- 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.
|
|
26
|
+
- No shipped font binaries. `.pixel` and `.chunky-tile` accept a consumer-supplied font and fall back to a system stack when none is given.
|
|
27
|
+
- No compatibility layer for removed tokens or classes. Breaking changes are documented, not silently aliased.
|
|
50
28
|
|
|
51
29
|
## Next steps
|
|
52
30
|
|
|
53
|
-
- [Setup](./setup.md): Install the package, choose an entrypoint, and render a
|
|
54
|
-
|
|
55
|
-
- [
|
|
56
|
-
|
|
57
|
-
- [
|
|
58
|
-
aesthetics, and each component family.
|
|
59
|
-
- [Integrating](./integrating/index.md): Wiring the stylesheet into Next.js,
|
|
60
|
-
Vue, Svelte, Astro, or a Tailwind CSS v4 build.
|
|
61
|
-
- [Accessibility](./accessibility.md): CSS accessibility hooks and what
|
|
62
|
-
remains an application responsibility.
|
|
31
|
+
- [Setup](./setup.md): Install the package, choose an entrypoint, and render a first component.
|
|
32
|
+
- [Concepts](./concepts.md): The three-axis model, the token system, and how theme selection works — read this before the usage guides.
|
|
33
|
+
- [Usage](./usage/index.md): Guides for composing axes, theming, customizing, aesthetics, and each component family.
|
|
34
|
+
- [Integrating](./integrating/index.md): Wiring the stylesheet into Next.js, Vue, Svelte, Astro, or a Tailwind CSS v4 build.
|
|
35
|
+
- [Accessibility](./accessibility.md): CSS accessibility hooks and what remains an application responsibility.
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Astro
|
|
3
3
|
description: Loading the stylesheet in an Astro app.
|
|
4
|
+
order: 5
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Astro
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
Astro renders components statically by default, but a global stylesheet import still only needs to happen once — from a shared layout, not from individual pages or islands.
|
|
10
|
+
|
|
11
|
+
## Import the stylesheet
|
|
10
12
|
|
|
11
13
|
```astro
|
|
12
14
|
---
|
|
@@ -21,9 +23,13 @@ import "@codenhub/styles";
|
|
|
21
23
|
</html>
|
|
22
24
|
```
|
|
23
25
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
Every page that uses this layout loads the stylesheet once. Running Tailwind CSS v4? Import `@codenhub/styles/tw` through Astro's Tailwind integration instead — see [Tailwind CSS v4](./tailwind.md), including when an explicit `@source` is actually needed.
|
|
27
|
+
|
|
28
|
+
## Force a theme
|
|
29
|
+
|
|
30
|
+
Apply `.dark` or `.light` on `<html>` to force a theme instead of following the system preference; see [Setup → Configuration](../setup.md#configuration).
|
|
31
|
+
|
|
32
|
+
## See also
|
|
26
33
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
for the `@source` directive Astro needs to scan `src/`.
|
|
34
|
+
- [Setup → Import paths](../setup.md#import-paths): every entrypoint this package publishes.
|
|
35
|
+
- [Usage](../usage/index.md): component classes to compose once the stylesheet is loaded.
|
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
---
|
|
2
|
-
title:
|
|
3
|
-
description:
|
|
2
|
+
title: Overview
|
|
3
|
+
description: How the stylesheet loads in a framework build, and which guide to follow.
|
|
4
|
+
group: Integrating
|
|
5
|
+
order: 4
|
|
4
6
|
---
|
|
5
7
|
|
|
6
8
|
# Integrating
|
|
7
9
|
|
|
8
|
-
This package has no JavaScript and no framework bindings; see
|
|
9
|
-
[Introduction](../index.md#what-it-does-not-do). Integrating it into a
|
|
10
|
-
framework is entirely about where that framework loads a global stylesheet,
|
|
11
|
-
and whether the project runs Tailwind CSS v4.
|
|
10
|
+
This package has no JavaScript and no framework bindings; see [Introduction](../index.md#what-it-does-not-do). Integrating it into a framework is entirely about where that framework lets you load a global stylesheet, and whether the project runs Tailwind CSS v4.
|
|
12
11
|
|
|
13
|
-
|
|
12
|
+
## The shared model
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
Every stack does the same two imports, from the same kind of place — a root layout, an app entry file, or a global CSS file, never a page or a component further down the tree:
|
|
15
|
+
|
|
16
|
+
1. One [entrypoint](../setup.md#import-paths) — the compiled `@codenhub/styles` for any build, or `@codenhub/styles/tw` when the project already runs Tailwind CSS v4.
|
|
17
|
+
2. `@codenhub/styles/aesthetics` (or `/tw/aesthetics`) after it, only if the project uses an [aesthetic](../usage/aesthetics.md).
|
|
18
|
+
|
|
19
|
+
Importing from one place matters for two reasons. Some frameworks only _allow_ global CSS from a designated root file and fail the build otherwise — Next.js's Pages Router is one, see [Next.js → Troubleshooting](./nextjs.md#troubleshooting). Where a framework allows it more broadly, as Next.js's App Router does, importing from the root remains the recommended choice for predictable CSS ordering — and importing per-component instead would load the same reset and token rules once per component rather than once per app.
|
|
20
|
+
|
|
21
|
+
## Which guide to follow
|
|
21
22
|
|
|
22
23
|
| Stack | Guide |
|
|
23
24
|
| ---------------------------------------- | -------------------------------- |
|
|
@@ -27,6 +28,14 @@ Every stack does the same two things:
|
|
|
27
28
|
| Svelte / SvelteKit | [Svelte](./svelte.md) |
|
|
28
29
|
| Astro | [Astro](./astro.md) |
|
|
29
30
|
|
|
30
|
-
A project with no framework — a plain Vite, webpack, or Parcel build — needs
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
A project with no framework — a plain Vite, webpack, or Parcel build — needs nothing beyond [Setup → Quick start](../setup.md#quick-start): import the compiled stylesheet from the project's existing global CSS entry.
|
|
32
|
+
|
|
33
|
+
## Verifying it worked
|
|
34
|
+
|
|
35
|
+
After the import, render one styled element and confirm it picked up the package's tokens rather than the browser default:
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<button class="btn primary">Continue</button>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
A rounded, filled button in the primary color means the stylesheet loaded. Unstyled browser-default text most often means the import specifier didn't resolve — check the [import paths table](../setup.md#import-paths) for the exact one your entrypoint needs, and confirm your build tooling resolves package CSS imports at all, see [Setup → Requirements](../setup.md#requirements).
|
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Next.js
|
|
3
3
|
description: Loading the stylesheet in a Next.js / React app.
|
|
4
|
+
order: 2
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Next.js
|
|
7
8
|
|
|
8
|
-
Next.js
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
Next.js has two router architectures, and they treat global CSS differently:
|
|
10
|
+
|
|
11
|
+
- **App Router** (an `app/` directory): global CSS — including an external package's stylesheet like this one — can be imported from any layout, page, or component under `app/`. Importing it from the root layout is only a recommendation, for predictable CSS ordering across routes; Next.js does not enforce it and no error occurs if you import it elsewhere.
|
|
12
|
+
- **Pages Router** (a `pages/` directory, no `app/`): global CSS is restricted to `pages/_app.tsx`. Importing it from anywhere else fails the build — Next.js enforces this itself, not this package; see [Troubleshooting](#troubleshooting).
|
|
13
|
+
- **Both directories present** (mid-migration): import the stylesheet in both root files. The two routers serve their own routes independently, so a route under `pages/` never sees a stylesheet imported only in `app/layout.tsx`, and vice versa.
|
|
14
|
+
|
|
15
|
+
## Import the stylesheet
|
|
16
|
+
|
|
17
|
+
Add the import to the root file for your router:
|
|
18
|
+
|
|
19
|
+
**App Router**
|
|
11
20
|
|
|
12
21
|
```tsx
|
|
13
22
|
// app/layout.tsx
|
|
@@ -22,6 +31,8 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
|
|
22
31
|
}
|
|
23
32
|
```
|
|
24
33
|
|
|
34
|
+
**Pages Router**
|
|
35
|
+
|
|
25
36
|
```tsx
|
|
26
37
|
// pages/_app.tsx
|
|
27
38
|
import "@codenhub/styles";
|
|
@@ -32,13 +43,25 @@ export default function App({ Component, pageProps }: AppProps) {
|
|
|
32
43
|
}
|
|
33
44
|
```
|
|
34
45
|
|
|
35
|
-
|
|
36
|
-
|
|
46
|
+
Running Tailwind CSS v4? `@import "@codenhub/styles/tw"` is a CSS directive, so it belongs in a CSS file, not a bare import in `layout.tsx`/`_app.tsx` — add it (with `@import "tailwindcss"` and, if needed, `@source`) to your global CSS file, and import that file from the same root file shown above instead. See [Tailwind CSS v4](./tailwind.md).
|
|
47
|
+
|
|
48
|
+
## Force a theme
|
|
49
|
+
|
|
50
|
+
Apply `.dark` or `.light` on `<html>` to force a theme instead of following the system preference; see [Setup → Configuration](../setup.md#configuration).
|
|
37
51
|
|
|
38
52
|
```tsx
|
|
39
53
|
<html lang="en" className="dark">
|
|
40
54
|
```
|
|
41
55
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
56
|
+
## Troubleshooting
|
|
57
|
+
|
|
58
|
+
**Pages Router build fails with "Global CSS cannot be imported from files other than your Custom `<App>`"**
|
|
59
|
+
|
|
60
|
+
- **What happened:** Next.js rejected a global CSS `import` statement outside `pages/_app.tsx`. This restriction is specific to the Pages Router — Next.js enforces it itself, not this package, and it applies to any global CSS import, not specifically to `@codenhub/styles`. It does not apply to the App Router, where the same import works from any layout, page, or component.
|
|
61
|
+
- **Why:** the Pages Router has no per-route CSS boundary the way the App Router does, so Next.js requires one predictable file for global stylesheets to avoid ordering conflicts between pages.
|
|
62
|
+
- **Fix:** move the `import "@codenhub/styles"` line to `pages/_app.tsx`, and remove it from wherever it currently is.
|
|
63
|
+
|
|
64
|
+
## See also
|
|
65
|
+
|
|
66
|
+
- [Setup → Import paths](../setup.md#import-paths): every entrypoint this package publishes.
|
|
67
|
+
- [Usage](../usage/index.md): component classes to compose once the stylesheet is loaded.
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Svelte
|
|
3
3
|
description: Loading the stylesheet in a Svelte / SvelteKit app.
|
|
4
|
+
order: 4
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Svelte
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
## Import the stylesheet
|
|
10
|
+
|
|
11
|
+
**SvelteKit** — import from the root layout so it loads once for every route:
|
|
10
12
|
|
|
11
13
|
```svelte
|
|
12
14
|
<!-- src/routes/+layout.svelte -->
|
|
@@ -18,7 +20,7 @@ every route:
|
|
|
18
20
|
{@render children()}
|
|
19
21
|
```
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
**Plain Svelte + Vite** — import from the entry file instead:
|
|
22
24
|
|
|
23
25
|
```ts
|
|
24
26
|
// main.ts
|
|
@@ -29,9 +31,13 @@ import App from "./App.svelte";
|
|
|
29
31
|
mount(App, { target: document.getElementById("app")! });
|
|
30
32
|
```
|
|
31
33
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
Running Tailwind CSS v4? Import `@codenhub/styles/tw` from the app's CSS entry instead — see [Tailwind CSS v4](./tailwind.md).
|
|
35
|
+
|
|
36
|
+
## Force a theme
|
|
37
|
+
|
|
38
|
+
Apply `.dark` or `.light` on `<html>` (edit `src/app.html` in SvelteKit) to force a theme instead of following the system preference; see [Setup → Configuration](../setup.md#configuration).
|
|
39
|
+
|
|
40
|
+
## See also
|
|
35
41
|
|
|
36
|
-
|
|
37
|
-
|
|
42
|
+
- [Setup → Import paths](../setup.md#import-paths): every entrypoint this package publishes.
|
|
43
|
+
- [Usage](../usage/index.md): component classes to compose once the stylesheet is loaded.
|