@codenhub/styles 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE +18 -16
- package/README.es.md +61 -0
- package/README.md +21 -16
- package/README.pt-BR.md +61 -0
- package/dist/aesthetics/chunky-tile.css +1 -1
- package/dist/aesthetics/cyber.css +1 -1
- package/dist/aesthetics/glass.css +1 -1
- package/dist/aesthetics/index.css +2 -2
- package/dist/aesthetics/neobrutalism.css +1 -1
- package/dist/aesthetics/pixel.css +1 -1
- package/dist/aesthetics/sketch.css +1 -1
- package/dist/components.css +2 -2
- package/dist/index.css +2 -2
- package/dist/native.css +2 -2
- package/dist/palette.css +1 -1
- package/dist/theme.css +2 -2
- package/dist/tw/aesthetics/chunky-tile.css +81 -23
- package/dist/tw/aesthetics/cyber.css +86 -29
- package/dist/tw/aesthetics/glass.css +177 -50
- package/dist/tw/aesthetics/neobrutalism.css +98 -22
- package/dist/tw/aesthetics/pixel.css +93 -8
- package/dist/tw/aesthetics/sketch.css +87 -22
- package/dist/tw/box.css +21 -2
- package/dist/tw/components/feedback.css +2 -2
- package/dist/tw/components/form.css +58 -19
- package/dist/tw/components/index.css +3 -4
- package/dist/tw/components/surface.css +15 -6
- package/dist/tw/index.css +1 -1
- package/dist/tw/intent.css +6 -5
- package/dist/tw/native.css +8 -8
- package/dist/tw/palette.css +6 -6
- package/dist/tw/reset.css +15 -15
- package/dist/tw/theme.css +29 -17
- package/dist/tw/utilities/content.css +43 -1
- package/dist/tw/utilities/layout.css +26 -12
- package/docs/accessibility.md +89 -60
- package/docs/changelog/0.1.1.md +1 -0
- package/docs/changelog/0.2.0.md +1 -0
- package/docs/changelog/0.3.0.md +1 -0
- package/docs/changelog/0.4.0.md +1 -0
- package/docs/changelog/0.5.0.md +8 -3
- package/docs/changelog/0.6.0.md +2 -1
- package/docs/changelog/0.7.0.md +50 -0
- package/docs/changelog/index.md +1 -0
- package/docs/concepts.md +188 -46
- package/docs/es/accessibility.md +150 -0
- package/docs/es/concepts.md +212 -0
- package/docs/es/index.md +104 -0
- package/docs/es/integrating/astro.md +35 -0
- package/docs/es/integrating/index.md +47 -0
- package/docs/es/integrating/nextjs.md +67 -0
- package/docs/es/integrating/svelte.md +45 -0
- package/docs/es/integrating/tailwind.md +78 -0
- package/docs/es/integrating/vue.md +31 -0
- package/docs/es/integrating/without-a-bundler.md +115 -0
- package/docs/es/setup.md +180 -0
- package/docs/es/usage/aesthetics.md +276 -0
- package/docs/es/usage/buttons.md +131 -0
- package/docs/es/usage/composing.md +164 -0
- package/docs/es/usage/content-and-layout.md +215 -0
- package/docs/es/usage/customizing.md +298 -0
- package/docs/es/usage/feedback.md +153 -0
- package/docs/es/usage/forms.md +231 -0
- package/docs/es/usage/index.md +29 -0
- package/docs/es/usage/solo.md +84 -0
- package/docs/es/usage/theming.md +296 -0
- package/docs/es/usage/tooltips.md +127 -0
- package/docs/index.md +85 -26
- package/docs/integrating/astro.md +3 -4
- package/docs/integrating/index.md +18 -13
- package/docs/integrating/nextjs.md +3 -4
- package/docs/integrating/svelte.md +5 -4
- package/docs/integrating/tailwind.md +16 -3
- package/docs/integrating/vue.md +3 -4
- package/docs/integrating/without-a-bundler.md +114 -0
- package/docs/pt-BR/accessibility.md +150 -0
- package/docs/pt-BR/concepts.md +212 -0
- package/docs/pt-BR/index.md +104 -0
- package/docs/pt-BR/integrating/astro.md +35 -0
- package/docs/pt-BR/integrating/index.md +47 -0
- package/docs/pt-BR/integrating/nextjs.md +67 -0
- package/docs/pt-BR/integrating/svelte.md +45 -0
- package/docs/pt-BR/integrating/tailwind.md +78 -0
- package/docs/pt-BR/integrating/vue.md +31 -0
- package/docs/pt-BR/integrating/without-a-bundler.md +115 -0
- package/docs/pt-BR/setup.md +180 -0
- package/docs/pt-BR/usage/aesthetics.md +276 -0
- package/docs/pt-BR/usage/buttons.md +131 -0
- package/docs/pt-BR/usage/composing.md +164 -0
- package/docs/pt-BR/usage/content-and-layout.md +215 -0
- package/docs/pt-BR/usage/customizing.md +298 -0
- package/docs/pt-BR/usage/feedback.md +153 -0
- package/docs/pt-BR/usage/forms.md +231 -0
- package/docs/pt-BR/usage/index.md +29 -0
- package/docs/pt-BR/usage/solo.md +84 -0
- package/docs/pt-BR/usage/theming.md +296 -0
- package/docs/pt-BR/usage/tooltips.md +127 -0
- package/docs/setup.md +134 -91
- package/docs/usage/aesthetics.md +76 -66
- package/docs/usage/buttons.md +108 -40
- package/docs/usage/composing.md +105 -92
- package/docs/usage/content-and-layout.md +157 -126
- package/docs/usage/customizing.md +107 -37
- package/docs/usage/feedback.md +134 -71
- package/docs/usage/forms.md +176 -107
- package/docs/usage/index.md +18 -14
- package/docs/usage/solo.md +83 -0
- package/docs/usage/theming.md +260 -118
- package/docs/usage/tooltips.md +90 -49
- package/llms-full.txt +2358 -1313
- package/llms.txt +24 -22
- package/package.json +25 -32
- package/dist/tw/components/loader.css +0 -116
|
@@ -78,6 +78,11 @@
|
|
|
78
78
|
--table-head-plate: color-mix(in oklab, var(--intent-subtle) var(--table-ground), transparent);
|
|
79
79
|
--table-head-bg: color-mix(in oklab, var(--intent-color) var(--table-fill), var(--table-head-plate));
|
|
80
80
|
--table-head-fg: color-mix(in oklab, var(--intent-contrast) var(--_on-fill), var(--intent-strong));
|
|
81
|
+
/* The table's own contrast ink, resolved here so a row with its own intent
|
|
82
|
+
prints on the table's plate in the ink that plate takes: the row's
|
|
83
|
+
`--intent-contrast` is chosen for the row's fill, which a row does not
|
|
84
|
+
paint, and a light one on a light plate reads at 1:1. */
|
|
85
|
+
--_table-contrast: var(--intent-contrast);
|
|
81
86
|
|
|
82
87
|
/* Untinted rather than mixed, the same call `.card.soft` makes: 12% ink onto
|
|
83
88
|
`--intent-subtle` still reads as `.solid` on neutral, since neutral's ink
|
|
@@ -315,7 +320,44 @@
|
|
|
315
320
|
|
|
316
321
|
/* Rows deliberately inherit the table's intent instead of resetting it, so a
|
|
317
322
|
`.data-table.success` tints its own rows. A `<tr class="warning">` still wins,
|
|
318
|
-
because an intent class on the element beats an inherited value.
|
|
323
|
+
because an intent class on the element beats an inherited value.
|
|
324
|
+
|
|
325
|
+
The class only changes the row's intent slots, though, and everything the
|
|
326
|
+
row paints was resolved on the table: the text, the rule and the hover
|
|
327
|
+
step are each a custom property whose `var()`s resolved against the
|
|
328
|
+
table's intent, so they inherited down already-green to a destructive row.
|
|
329
|
+
A row with its own intent resolves them again against it. The plate stays
|
|
330
|
+
the table's, so the ink keeps the table's ramp -- `--_on-fill`, inherited
|
|
331
|
+
as a resolved percentage -- and a solid table's rows still print the
|
|
332
|
+
table's contrast ink on it. Only a row that names an intent: an ordinary row would resolve
|
|
333
|
+
the same values, but a `color` declared on every row would override a
|
|
334
|
+
colour a consumer set on the table. */
|
|
335
|
+
& tbody tr:is(.neutral, .primary, .secondary, .success, .warning, .destructive, .info) {
|
|
336
|
+
--table-rule-tone: color-mix(
|
|
337
|
+
in oklab,
|
|
338
|
+
var(--table-rule-plated) var(--ui-fill, var(--_d-fill)),
|
|
339
|
+
var(--intent-border)
|
|
340
|
+
);
|
|
341
|
+
--table-rule: color-mix(in oklab, var(--table-rule-tone) var(--table-rule-amount), transparent);
|
|
342
|
+
--table-hover-tone: color-mix(in oklab, currentColor var(--ui-fill, var(--_d-fill)), var(--intent-hover));
|
|
343
|
+
--table-row-hover: color-mix(in oklab, var(--table-hover-tone) 12%, transparent);
|
|
344
|
+
|
|
345
|
+
color: color-mix(in oklab, var(--_table-contrast) var(--_on-fill), var(--intent-strong));
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/* A neutral solid table caps its fill at 20%, so its plate is a light grey
|
|
349
|
+
and the ramp keeps `--_on-fill` low: the row's ink is then mostly the
|
|
350
|
+
row's `--intent-strong`, which is chosen against the row's own subtle
|
|
351
|
+
ground rather than a grey one, and success, warning and destructive fall
|
|
352
|
+
under 4.5:1 on it. Those rows print the table's own ink, `--_fg`,
|
|
353
|
+
inherited already resolved against the table, and keep their intent in
|
|
354
|
+
the rule and the hover. */
|
|
355
|
+
&.solid:not(.primary, .secondary, .success, .warning, .destructive, .info)
|
|
356
|
+
tbody
|
|
357
|
+
tr:is(.neutral, .primary, .secondary, .success, .warning, .destructive, .info) {
|
|
358
|
+
color: var(--_fg);
|
|
359
|
+
}
|
|
360
|
+
|
|
319
361
|
& tbody tr > * {
|
|
320
362
|
transition: background-color var(--motion-duration-fast) var(--motion-ease);
|
|
321
363
|
}
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
+
/* The gap is a private each layout declares from `--layout-gap`, and the
|
|
2
|
+
density modifiers write the private. A container's `--layout-gap` still
|
|
3
|
+
reaches every layout inside it, because each one reads the token afresh; a
|
|
4
|
+
`.tight` or `.loose` stays on its own element, the way `.p-xs` stays on a
|
|
5
|
+
card, because the layout inside declares its own private over the one it
|
|
6
|
+
would inherit. */
|
|
1
7
|
@utility view {
|
|
2
|
-
@apply flex gap-(--
|
|
8
|
+
@apply flex gap-(--_gap);
|
|
9
|
+
|
|
10
|
+
--_gap: var(--layout-gap);
|
|
3
11
|
|
|
4
12
|
&.vertical {
|
|
5
13
|
@apply flex-col;
|
|
@@ -10,53 +18,59 @@
|
|
|
10
18
|
}
|
|
11
19
|
|
|
12
20
|
&.tight {
|
|
13
|
-
--
|
|
21
|
+
--_gap: 0.5rem;
|
|
14
22
|
}
|
|
15
23
|
|
|
16
24
|
&.loose {
|
|
17
|
-
--
|
|
25
|
+
--_gap: 1.5rem;
|
|
18
26
|
}
|
|
19
27
|
}
|
|
20
28
|
|
|
21
29
|
@utility stack {
|
|
22
|
-
@apply flex flex-col gap-(--
|
|
30
|
+
@apply flex flex-col gap-(--_gap);
|
|
31
|
+
|
|
32
|
+
--_gap: var(--layout-gap);
|
|
23
33
|
|
|
24
34
|
&.tight {
|
|
25
|
-
--
|
|
35
|
+
--_gap: 0.5rem;
|
|
26
36
|
}
|
|
27
37
|
|
|
28
38
|
&.loose {
|
|
29
|
-
--
|
|
39
|
+
--_gap: 1.5rem;
|
|
30
40
|
}
|
|
31
41
|
}
|
|
32
42
|
|
|
33
43
|
@utility cluster {
|
|
34
|
-
@apply flex flex-wrap items-center gap-(--
|
|
44
|
+
@apply flex flex-wrap items-center gap-(--_gap);
|
|
45
|
+
|
|
46
|
+
--_gap: var(--layout-gap);
|
|
35
47
|
|
|
36
48
|
&.between {
|
|
37
49
|
@apply justify-between;
|
|
38
50
|
}
|
|
39
51
|
|
|
40
52
|
&.tight {
|
|
41
|
-
--
|
|
53
|
+
--_gap: 0.5rem;
|
|
42
54
|
}
|
|
43
55
|
|
|
44
56
|
&.loose {
|
|
45
|
-
--
|
|
57
|
+
--_gap: 1.5rem;
|
|
46
58
|
}
|
|
47
59
|
}
|
|
48
60
|
|
|
49
61
|
@utility auto-grid {
|
|
50
|
-
@apply grid gap-(--
|
|
62
|
+
@apply grid gap-(--_gap);
|
|
63
|
+
|
|
64
|
+
--_gap: var(--layout-gap);
|
|
51
65
|
|
|
52
66
|
grid-template-columns: repeat(auto-fit, minmax(min(var(--layout-grid-min), 100%), 1fr));
|
|
53
67
|
|
|
54
68
|
&.tight {
|
|
55
|
-
--
|
|
69
|
+
--_gap: 0.5rem;
|
|
56
70
|
}
|
|
57
71
|
|
|
58
72
|
&.loose {
|
|
59
|
-
--
|
|
73
|
+
--_gap: 1.5rem;
|
|
60
74
|
}
|
|
61
75
|
}
|
|
62
76
|
|
package/docs/accessibility.md
CHANGED
|
@@ -1,52 +1,72 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Accessibility
|
|
3
|
+
description: What the CSS does for focus, states, motion, contrast, forced colors, and right-to-left text, and what your application still owes its users.
|
|
3
4
|
order: 5
|
|
4
5
|
---
|
|
5
6
|
|
|
6
|
-
# Accessibility
|
|
7
|
+
# Accessibility
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
The settings screen is built, and the CSS has done its part along the way: every field shows where focus is, an invalid email turns red, and the spinner stops for users who ask for less motion. The rest is up to your HTML and JavaScript. This package styles states; it does not provide semantic elements, ARIA attributes, keyboard behavior, focus management, validation, or the timing of announcements.
|
|
10
|
+
|
|
11
|
+
This page lists both halves: what the CSS provides, and what your application has to add.
|
|
9
12
|
|
|
10
13
|
## Provided by CSS
|
|
11
14
|
|
|
12
15
|
### Focus and state
|
|
13
16
|
|
|
14
|
-
| Feature | Behavior
|
|
15
|
-
| ------------------ |
|
|
16
|
-
| `:focus-visible` |
|
|
17
|
-
| Form control focus | `.ipt`, `.textarea`, and `.select` draw the
|
|
18
|
-
| Invalid controls | `
|
|
19
|
-
| Disabled controls | `
|
|
20
|
-
| Open state | `
|
|
21
|
-
| Native `<dialog>` |
|
|
17
|
+
| Feature | Behavior |
|
|
18
|
+
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
19
|
+
| `:focus-visible` | A focus outline on every element, drawn with `--focus-ring`, `--focus-ring-width`, and `--focus-ring-offset`. |
|
|
20
|
+
| Form control focus | `.ipt`, `.textarea`, and `.select` draw the focus outline and change their border to the intent color. Typed text in a field with an intent class is in the intent's readable tone, `--intent-strong`. |
|
|
21
|
+
| Invalid controls | `aria-invalid="true"` on a form control turns its border, focus color, and typed text destructive, the text in the destructive readable tone. |
|
|
22
|
+
| Disabled controls | `disabled`, `aria-disabled="true"`, `data-disabled`, and `.disabled` show the disabled cursor and opacity, and a disabled control does not react to hover, including inside an `.input-group`. |
|
|
23
|
+
| Open state | `data-state="open"` on a `.tooltip` shows its bubble without hover or focus, and `data-state="closed"` hides it while hovered or focused. No other component reads either. |
|
|
24
|
+
| Native `<dialog>` | A `<dialog>` with `.card`, `.panel`, or `.surface` stays hidden until it is opened, and opens centered. A margin you set on the dialog, as a utility or in your own CSS, still overrides the centering. Other dialogs are left alone. Trapping focus, closing on Escape, and making the page behind it inert are up to your application. |
|
|
22
25
|
|
|
23
26
|
### Visually hidden content
|
|
24
27
|
|
|
25
|
-
`.visually-hidden` hides content
|
|
28
|
+
`.visually-hidden` hides content on screen and keeps it for screen readers, as the API keys table's `<caption>` does in [Content and layout → Tables](./usage/content-and-layout.md#tables). It ships with the layout utilities: in `.`, `./native`, `./tw`, `./tw/native`, and `./tw/utilities`. It is not in `./components` or the `./tw/components` and `./tw/*` component entrypoints.
|
|
26
29
|
|
|
27
30
|
### Control boundaries
|
|
28
31
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
|
32
|
-
|
|
|
33
|
-
|
|
|
34
|
-
|
|
|
35
|
-
| `.
|
|
36
|
-
|
|
|
32
|
+
WCAG 1.4.11 asks that the boundary of a control you need to see to use it measures at least 3:1 against what is next to it.
|
|
33
|
+
|
|
34
|
+
| Feature | Behavior |
|
|
35
|
+
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
36
|
+
| Text controls at rest | A text control's border rests lighter than its intent's full border, below 3:1 by choice, so hover and focus have a stronger tone to change to. |
|
|
37
|
+
| Toggles | `.checkbox`, `.radio`, and `.switch` draw their full border, because the border is the only thing that shows an unchecked box. A `.switch` with its own `.edgeless` is the exception, below. |
|
|
38
|
+
| `.edgeless` from a container | Ignored by every text control and toggle: a container cannot remove the border of a field or toggle inside it. |
|
|
39
|
+
| `.edgeless` on the control | `.ipt`, `.textarea`, `.select`, and `.switch` drop their border and no longer meet 1.4.11 at rest. `.switch.ghost` keeps its border even then, because with no fill and no border nothing would show the track. |
|
|
40
|
+
| `.checkbox`, `.radio` | Always draw their border, from a container or with their own `.edgeless`. `.edgeless` on them is not supported. |
|
|
41
|
+
| Progress track | By choice, the filled part carries the value and the track is a quiet background. The default track, `.soft.edgeless`, measures about 1.1:1 to 1.3:1 against the page. The filled part measures at least 3:1 against that track for every intent except warning in light (about 2.7:1) and info in dark (about 2.9:1). Where the track itself must meet 1.4.11, use `.ghost.edged` with an intent class; see [Progress outlines](#progress-outlines) below. |
|
|
42
|
+
|
|
43
|
+
### Progress outlines
|
|
44
|
+
|
|
45
|
+
On a `.progress.ghost.edged`, the track is the page, and its outline and the filled part are both drawn in the intent's color. Measured against the page, with no aesthetic:
|
|
46
|
+
|
|
47
|
+
| Intent | Light page | Dark page | Meets 3:1 |
|
|
48
|
+
| -------------- | ---------- | --------- | ------------------------------------------------------------------------ |
|
|
49
|
+
| `.primary` | 18.96:1 | 18.96:1 | Yes |
|
|
50
|
+
| `.secondary` | 7.47:1 | 7.63:1 | Yes |
|
|
51
|
+
| `.success` | 5.14:1 | 3.69:1 | Yes |
|
|
52
|
+
| `.warning` | 3.06:1 | 6.20:1 | Yes |
|
|
53
|
+
| `.destructive` | 5.80:1 | 3.27:1 | Yes |
|
|
54
|
+
| `.info` | 6.17:1 | 3.07:1 | Yes |
|
|
55
|
+
| No intent | 2.48:1 | 1.91:1 | No: the outline fails, though the filled part, in the text color, passes |
|
|
56
|
+
|
|
57
|
+
With no intent class, the outline is the quiet border gray, `--color-border`. To make a neutral track meet 1.4.11, give the bar an intent class, or set `--progress-edge` to a stronger color, such as `var(--color-accent)`, which measures 7.47:1 on a light page and 7.63:1 on a dark one. Warning on a light page and info on a dark one clear 3:1 by a small margin, so measure again if you change those colors.
|
|
37
58
|
|
|
38
59
|
### Motion and transparency
|
|
39
60
|
|
|
40
|
-
| Feature
|
|
41
|
-
|
|
|
42
|
-
| Reduced
|
|
43
|
-
| Reduced
|
|
44
|
-
| Reduced
|
|
45
|
-
| Reduced transparency | `.glass` and `.glass-liquid` drop their blur and lens and become an opaque surface when `prefers-reduced-transparency: reduce` matches. |
|
|
61
|
+
| Feature | Behavior |
|
|
62
|
+
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
63
|
+
| Reduced motion, components | With `prefers-reduced-motion: reduce`, every component stops its own transitions and animations: the skeleton and progress shimmer, the indeterminate bar, the tooltip, the toggle marks, and the press. |
|
|
64
|
+
| Reduced motion, whole page | The reset also shortens every other animation and transition on the page. |
|
|
65
|
+
| Reduced transparency | With `prefers-reduced-transparency: reduce`, `.glass` and `.glass-liquid` drop their blur and lens and become opaque. |
|
|
46
66
|
|
|
47
|
-
|
|
67
|
+
Each component's reduced-motion rule ships with the component, so every entrypoint that includes it respects reduced motion without the reset, including `@codenhub/styles/components`, `@codenhub/styles/tw/components`, and each `/tw/*` component entrypoint. The complete and native entrypoints add the reset's page-wide rule.
|
|
48
68
|
|
|
49
|
-
The reset's rule is `!important` inside the `base` layer, and a layered `!important` beats an unlayered one, so your own `!important` cannot
|
|
69
|
+
The reset's rule is `!important` inside the `base` layer, and a layered `!important` beats an unlayered one, so your own `!important` cannot turn an animation back on. To keep one running for users who ask for reduced motion, such as an upload spinner you consider essential, declare it `!important` in a layer ordered before `base`. The first `@layer` statement the browser reads sets the order, so yours goes before the package:
|
|
50
70
|
|
|
51
71
|
```css
|
|
52
72
|
@layer essential-motion, theme, base, components, utilities;
|
|
@@ -62,59 +82,68 @@ The reset's rule is `!important` inside the `base` layer, and a layered `!import
|
|
|
62
82
|
}
|
|
63
83
|
```
|
|
64
84
|
|
|
85
|
+
Respecting reduced motion is not the whole requirement. Motion that keeps going next to content, such as a shimmer left on a card after it has loaded, needs a way to stop it for every user; see [Feedback → Animation that keeps running](./usage/feedback.md#animation-that-keeps-running).
|
|
86
|
+
|
|
65
87
|
### Color and contrast
|
|
66
88
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
|
70
|
-
|
|
|
71
|
-
|
|
|
72
|
-
|
|
|
73
|
-
|
|
|
74
|
-
|
|
|
89
|
+
The measurements below are for the shipped colors. Once you change a color token, measure your own pairs again; [Theming → Change the brand color](./usage/theming.md#change-the-brand-color) shows which pairs to check.
|
|
90
|
+
|
|
91
|
+
| Feature | Behavior |
|
|
92
|
+
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
93
|
+
| Filled labels | Every intent's `.solid` label meets 4.5:1 (WCAG 1.4.3) as normal text, in both themes. The lowest is success, at 5.14:1. |
|
|
94
|
+
| Warning text | `--color-warning-contrast` is near-black, not the page color, because an amber dark enough to carry white text no longer looks amber. |
|
|
95
|
+
| Partial fills | The contrast text color appears only on fills above half strength, so a text control's capped fill keeps the intent's own text color. |
|
|
96
|
+
| Intent color in dark | In dark mode a `.soft` or `.ghost` label uses the `-300` shade of its intent, so it keeps its hue instead of turning white. |
|
|
97
|
+
| Toggle marks | A checked mark measures at least 3:1 against every fill its presentation can give it, in both themes. |
|
|
98
|
+
| Soft fills with borders | `.edged` on a `.soft` `.alert`, `.panel`, `.badge`, `.kbd`, `.code`, or `.pre` draws a border that measures below 3:1 against the 12% fill for some intents, which ones depending on the theme. Measure the pair before relying on that border as a control's boundary. |
|
|
75
99
|
|
|
76
100
|
### Forced colors and direction
|
|
77
101
|
|
|
78
|
-
| Feature | Behavior
|
|
79
|
-
| -------------- |
|
|
80
|
-
| Forced colors | `forced-colors: active
|
|
81
|
-
| Text direction |
|
|
102
|
+
| Feature | Behavior |
|
|
103
|
+
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
104
|
+
| Forced colors | With `forced-colors: active`, borders, checked states, and a `.select`'s chevron stay visible, drawn in system colors, under every aesthetic. An aesthetic that draws its border as an inner shadow, such as `.pixel`, draws a real border instead. |
|
|
105
|
+
| Text direction | Under `dir="rtl"`, the quote bar, the alert icon, the progress fill, the vertical divider, the switch knob, table alignment, and a select's chevron all switch sides. No class is needed. |
|
|
82
106
|
|
|
83
|
-
In forced colors,
|
|
107
|
+
In forced colors, `.text-control`, `.ipt`, `.textarea`, `.select`, and the toggles show a 2px `Highlight` focus outline. The native entrypoint gives unclassed text inputs, selects, textareas, checkboxes, and radios the same outline.
|
|
84
108
|
|
|
85
|
-
|
|
109
|
+
Checkboxes, radios, and switches use the system colors `Canvas`, `CanvasText`, `Highlight`, and `HighlightText`, so checked and unchecked stay distinct: a checked toggle is filled with `Highlight` and its mark is `HighlightText`, on the classes and in the native entrypoint alike. Shape, size, and spacing do not change.
|
|
86
110
|
|
|
87
111
|
## Required outside CSS
|
|
88
112
|
|
|
89
|
-
Use
|
|
113
|
+
Use the HTML element that matches what the component does, and add the behavior the CSS cannot.
|
|
90
114
|
|
|
91
|
-
| UI
|
|
92
|
-
|
|
|
93
|
-
| Buttons
|
|
94
|
-
| Forms
|
|
95
|
-
| Alerts
|
|
96
|
-
| Toasts
|
|
97
|
-
| Tooltips
|
|
98
|
-
| Progress
|
|
99
|
-
| Skeletons
|
|
100
|
-
|
|
|
115
|
+
| UI | What your application adds |
|
|
116
|
+
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
117
|
+
| Buttons | `<button>` for actions and `<a href>` for navigation. An accessible name, such as `aria-label`, on every `.btn.icon`. |
|
|
118
|
+
| Forms | A `<label>` for each control, the right `type`, validation, and `aria-describedby` linking hints and errors. Keep hints and errors outside the `<label>`, and give a `.switch` `role="switch"`. |
|
|
119
|
+
| Alerts | `role="status"` for a confirmation such as "Profile saved", or `role="alert"` for an error that needs attention now. |
|
|
120
|
+
| Toasts | A live region, a way to dismiss it, focus rules, and a pause on any timeout. |
|
|
121
|
+
| Tooltips | A real `id` and `role="tooltip"` on the bubble, referenced from the trigger's `aria-describedby`. Dismissal on Escape by writing `data-state="closed"`; see [Tooltips](./usage/tooltips.md#hover-linger-and-escape). The bubble can already be hovered. |
|
|
122
|
+
| Progress | A `<progress>` element, or `role="progressbar"` or `role="meter"` with ARIA values, when the value must be announced. |
|
|
123
|
+
| Skeletons | `aria-hidden="true"` on loading visuals, including a spinner you bring, and the loading state announced some other way when needed. |
|
|
124
|
+
| Ongoing motion | A way to pause, stop, or hide motion that is not essential; see [Feedback → Animation that keeps running](./usage/feedback.md#animation-that-keeps-running). |
|
|
125
|
+
| Popovers, modals | Focus trapping, closing on Escape, an inert background, labels, and roles. |
|
|
101
126
|
|
|
102
|
-
## State
|
|
127
|
+
## State attributes
|
|
103
128
|
|
|
104
|
-
Prefer native attributes
|
|
129
|
+
Prefer native attributes:
|
|
105
130
|
|
|
106
131
|
```html
|
|
107
|
-
<button class="btn primary" disabled>Saving
|
|
132
|
+
<button class="btn primary" disabled>Saving…</button> <input class="ipt" type="email" aria-invalid="true" aria-describedby="email-error" />
|
|
108
133
|
```
|
|
109
134
|
|
|
110
|
-
Use ARIA or data attributes
|
|
135
|
+
Use ARIA or data attributes where the element or your component library has no native one:
|
|
111
136
|
|
|
112
137
|
```html
|
|
113
|
-
<a class="btn secondary" aria-disabled="true">
|
|
138
|
+
<a class="btn secondary" aria-disabled="true">Export data</a>
|
|
114
139
|
<span class="tooltip" data-state="open">
|
|
115
|
-
<button type="button" class="tooltip-icon" aria-label="
|
|
116
|
-
<span class="tooltip-bubble" role="tooltip" id="
|
|
140
|
+
<button type="button" class="tooltip-icon" aria-label="About public profiles" aria-describedby="public-profile-help">?</button>
|
|
141
|
+
<span class="tooltip-bubble" role="tooltip" id="public-profile-help">Anyone with the link can see your name and photo.</span>
|
|
117
142
|
</span>
|
|
118
143
|
```
|
|
119
144
|
|
|
120
|
-
`aria-disabled="true"`
|
|
145
|
+
`aria-disabled="true"` tells assistive technology the control is disabled, but it does not stop a click or a key press. Use the `disabled` attribute, or stop the action in JavaScript.
|
|
146
|
+
|
|
147
|
+
## Next
|
|
148
|
+
|
|
149
|
+
That completes the reading path. The [Introduction](./index.md) links every page, and [Composing](./usage/composing.md), [Customizing](./usage/customizing.md), and [Content and layout](./usage/content-and-layout.md) are the lookup pages for later.
|
package/docs/changelog/0.1.1.md
CHANGED
package/docs/changelog/0.2.0.md
CHANGED
package/docs/changelog/0.3.0.md
CHANGED
package/docs/changelog/0.4.0.md
CHANGED
package/docs/changelog/0.5.0.md
CHANGED
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: 0.5.0
|
|
3
|
+
date: 2026-09-27
|
|
4
|
+
description: Named cascade layers, corners that scale with size, the sketch aesthetic, and new material tokens. Breaks several 0.4.0 names and defaults, each listed under Changed and Removed.
|
|
3
5
|
---
|
|
4
6
|
|
|
5
7
|
# 0.5.0
|
|
6
8
|
|
|
7
|
-
A foundation update with an opt-in sketch aesthetic and rounded sketch variant.
|
|
9
|
+
A foundation update with an opt-in sketch aesthetic and rounded sketch variant. Everything under [Changed](#changed) and [Removed](#removed) breaks against `0.4.0`.
|
|
8
10
|
|
|
9
|
-
##
|
|
11
|
+
## Changed
|
|
10
12
|
|
|
11
13
|
- **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](../setup.md).
|
|
12
14
|
- **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`.
|
|
13
15
|
- **`--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.
|
|
14
16
|
- **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.
|
|
15
|
-
- **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.
|
|
16
17
|
- **`.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.
|
|
17
18
|
|
|
19
|
+
## Removed
|
|
20
|
+
|
|
21
|
+
- **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.
|
|
22
|
+
|
|
18
23
|
## Added
|
|
19
24
|
|
|
20
25
|
- **`.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](../usage/aesthetics.md#sketch).
|
package/docs/changelog/0.6.0.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: 0.6.0
|
|
3
3
|
date: 2026-09-29
|
|
4
|
+
description: Liquid glass, hoverable tooltips, native field decorations, indeterminate checkboxes and list-box selects, and a round of fixes on every entrypoint.
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# 0.6.0
|
|
@@ -10,7 +11,7 @@ A liquid-glass modifier, glass that keeps every presentation's fill whole, hover
|
|
|
10
11
|
## Added
|
|
11
12
|
|
|
12
13
|
- **`.glass-liquid`**, a modifier of `.glass`: continuous corners, a bright rim, a lighter blur, a clearer ground, and a lens that bends what is behind a surface at its edges (Chromium today; Firefox and Safari keep the rim, blur, and ground). Put it beside `.glass` on the region, or on one surface inside a glass region; `.glass-solo.glass-liquid` paints the same pane on an element the package does not style. Without `.glass` in scope it changes the corners and nothing else. See [Aesthetics → Liquid glass](../usage/aesthetics.md#liquid-glass).
|
|
13
|
-
- **`.unadorned`** removes the browser's own field decorations -- the date picker button, number spin buttons, and search clear button and magnifier -- on a control or on its `.input-group`, for a field whose adornments you draw yourself. See [Forms →
|
|
14
|
+
- **`.unadorned`** removes the browser's own field decorations -- the date picker button, number spin buttons, and search clear button and magnifier -- on a control or on its `.input-group`, for a field whose adornments you draw yourself. See [Forms → Browser decorations](../usage/forms.md#browser-decorations).
|
|
14
15
|
- **`[data-state="closed"]` on `.tooltip`** hides the bubble while it is hovered or focused, for an Escape handler, and **`--tooltip-linger`** (300ms) sets how long a bubble stays after the pointer leaves its trigger. See [Tooltips](../usage/tooltips.md).
|
|
15
16
|
- **An indeterminate `.checkbox`** (and a native one under `/native`) draws the checked plate with a dash for its mark, and a Highlight plate in forced colors. See [Forms → Toggles](../usage/forms.md#toggles).
|
|
16
17
|
- **A multi-row `.select`** -- `multiple`, or a `size` above 1 -- draws as a list box: no chevron, as tall as its rows, with the chevron's room given back. It used to keep the chevron and a one-row height.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 0.7.0
|
|
3
|
+
date: 2026-11-04
|
|
4
|
+
description: Liquid glass buttons, solo classes that compose with presentation, intent, and elevation, the shipped loaders removed in favor of icon spinners, and fixes to layout gaps, dialog margins, tables, switches, field groups, and forced colors.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.7.0
|
|
8
|
+
|
|
9
|
+
A button can be a liquid glass pane, the solo classes compose with presentation, intent, and elevation the way components do, the loaders are gone in favor of a spinner from an icon set, and a round of fixes to nested layout gaps, dialog placement, table rows, right-to-left switches, field groups, and forced colors.
|
|
10
|
+
|
|
11
|
+
## Added
|
|
12
|
+
|
|
13
|
+
- **Liquid glass buttons.** A `.btn` carrying `.glass-liquid` itself, in a glass scope, takes the blur, lens, and rim of a liquid pane, with a lens sized for a control. The fill is still the presentation's: `.solid` is an opaque plate under the rim, `.ghost` and `.soft` are clear panes. A liquid region alone still leaves its controls solid. See [Aesthetics → Liquid buttons](../usage/aesthetics.md#liquid-buttons).
|
|
14
|
+
- **Solo classes compose with presentation, intent, and elevation.** Fill and edge come from the element or a container, intent and elevation from the element's own class, so `.pixel-solo.edgeless` drops its ring, `.glass-solo.solid.success` is an opaque green pane, and `.neobrutalism-solo.flat` has no slab. With none of those classes a solo element paints what it did. See [Aesthetics → Solo classes](../usage/aesthetics.md#solo-classes).
|
|
15
|
+
- **`--font-mono` is a documented token.** It sets the font of the `kbd`, `code`, and `pre` helpers and of `<kbd>`, `<code>`, and `<pre>` under `/native`, and joins the other font tokens in [Theming → Fonts](../usage/theming.md#fonts), which also shows how to load a web font.
|
|
16
|
+
- **Linking without a bundler.** [Integrating → Without a bundler](../integrating/without-a-bundler.md) covers plain HTML, Rails, Django, and a CDN `<link>`, which load the compiled files by path rather than by package name.
|
|
17
|
+
- **A stated versioning policy.** Below 1.0 a minor release may break and a patch release never does; see [Versioning](../index.md#versioning).
|
|
18
|
+
|
|
19
|
+
## Changed
|
|
20
|
+
|
|
21
|
+
- **A solo element inside a `.solid`, `.soft`, or `.ghost` container takes that fill and the theme's text color**, since presentation cascades to it now as it does to components. A solo element whose own background does not follow the theme -- a dark toast on a light page -- inside such a container prints the theme's text; keep it out of the container, or give it `.solid` with an intent.
|
|
22
|
+
- **`.tight` and `.loose` stay on their own element.** They wrote `--layout-gap`, which inherits, so a plain `.stack`, `.view`, `.cluster`, or `.auto-grid` nested inside one took its gap. A nested layout keeps the default gap now; set `--layout-gap` on a container to change the gap of every layout inside it.
|
|
23
|
+
- **Your margin places a component dialog.** The centring of an open `<dialog class="card">` (or `.panel`, `.surface`) overruled your margin utilities and unlayered CSS; it now sits in `utilities` at zero specificity, so `mt-8` or your own rule wins, and it still beats a `base` reset such as Preflight's. A margin reset in a cascade layer of your own, declared after the package's, now wins over the centring too, as it already does over every component property.
|
|
24
|
+
- **`.cyber` glows from the outline.** Its glow is the intent color at 60% with a 1px spread, up from 40% with none, so the brightest point sits on the element's outline. An edgeless button, badge, or panel read as backlit -- a shadow on a dark page -- because the glow just outside it was brighter than its own fill. `.cyber-solo` takes the same glow. In the light theme the near-black glow of a neutral component is heavier too; a hued `--cyber-ink` is still the way to make it read as light there.
|
|
25
|
+
- **The neutral palette values carry no hue.** `--palette-border`, `--palette-surface`, and `--palette-text` are `oklch(… 0 none)` in both themes, where they were `oklch(… 0 0)`. The colors themselves are unchanged, but a missing hue takes its partner's in polar interpolation: `color-mix(in oklch, var(--palette-text), oklch(60% 0.2 240))` now lands on hue 240, a blue, where it travelled from hue 0 and landed on a purple. To keep the old result, give the neutral its old hue: `color-mix(in oklch, oklch(from var(--palette-text) l c 0), oklch(60% 0.2 240))`. Mixing in `oklab` does not, since a hueless neutral adds no hue there and the mix stays blue.
|
|
26
|
+
|
|
27
|
+
## Removed
|
|
28
|
+
|
|
29
|
+
- **The loaders.** `.loader`, its `.sm` and `.lg` sizes, the nine variants (`.dots-wave`, `.dots-fade`, `.dots-queue`, `.dots-rotate`, `.dots-grow`, `.dots-grow-alternate`, `.dot-bounce`, `.bars-wave`, `.pulse-ring`), `.loader-mask`, and the `@codenhub/styles/tw/loader` entrypoint are gone. Importing `/tw/loader` now fails to resolve, and `<span class="loader dots-wave">` in the complete CSS renders nothing. `.sm` and `.lg` on other components are unchanged. Use a spinner from an icon set instead, such as `@codenhub/icons`, which this package does not import: a glyph with `ic-anim-spin` (`ic-lucide-loader-circle ic-anim-spin`) or the animated `svg-spinners` family, both in `currentColor`. Under `prefers-reduced-motion: reduce` every loader showed a still ring; a glyph with `ic-anim-spin` stops there too, but `svg-spinners` artwork keeps moving, so choose the glyph where that matters. See [Feedback](../usage/feedback.md) for loading the icons.
|
|
30
|
+
|
|
31
|
+
## Fixed
|
|
32
|
+
|
|
33
|
+
- **A focused `.solid.primary` control under `.pixel` shows its focus.** The inset focus ring is the primary color, so it vanished into the fill; a line of the page color now sits inside it. `.pixel-solo` takes the same line.
|
|
34
|
+
- **Controls and surfaces under `.pixel` keep an edge in forced colors.** Pixel draws its edge as an inset shadow, which forced colors remove, so buttons, fields, and cards had no boundary; forced colors now draw a solid border and drop the clip. `.pixel-solo` draws an inward outline there.
|
|
35
|
+
- **A `.disabled` text field holds still under the pointer.** The class spelling of disabled still darkened an `.ipt`'s line on hover, unlike `disabled`, `aria-disabled`, and `data-disabled`.
|
|
36
|
+
- **`.sketch-rounded` beside `.sketch-solo` stays on the solo element.** Its radius tokens inherited into the element's contents, so a `.btn` inside a rounded sketch toast drew a sketch outline on a page with no sketch in scope.
|
|
37
|
+
- **A checked native radio looks like a checked `.radio` in forced colors.** Under `/native` it drew a Highlight ring and dot on Canvas, where `.radio` draws a Highlight disc with a HighlightText dot, so `<input type="radio" class="radio">` changed look with the entrypoint. Both draw the disc now.
|
|
38
|
+
- **`/theme` declares every documented color and foundation token**, except `--focus-ring-offset`, which is computed on the focused element, and the `/tw`-only `--breakpoint-xs`. The compiled entry left out `--color-background`, `--color-foreground`, `--color-text-secondary`, and `--font-default`, because nothing in it read them, so `var(--color-background)` in your own CSS over `/theme` alone resolved to nothing.
|
|
39
|
+
- **A liquid region blurs what takes no liquid layers.** A bare `<table>` under `/native` or your own `@apply surface` inside a `.glass-liquid` region took its clearer ground with nothing blurred behind it; it takes liquid's lighter blur now.
|
|
40
|
+
- **Liquid's corners stay off a solo element's contents.** `.glass-solo.glass-liquid` no longer hands liquid's corner tokens to what it holds, so a `.btn` inside a liquid solo toast keeps the page's corners.
|
|
41
|
+
- **A checked `.switch` stays in its track right to left.** Under `dir="rtl"` the checked knob moved the left-to-right way, out past the track's right edge; it sits at the inline end, the left, now.
|
|
42
|
+
- **A table row shows its own intent.** A `<tr class="destructive">` in a `.data-table.success` kept the table's green text, rule, and hover, because the table resolved them before the row's intent applied. A row with an intent draws them in its own now; on a `.solid` table its text keeps the table's ink -- the contrast ink on a hued table, the table's own text color on a neutral one -- which that plate needs. Other rows keep the table's.
|
|
43
|
+
- **A button in an `.input-group` keeps its own edge.** The field's line reached every component inside the group, so a `.ghost` or `.edgeless` clear button drew a border the field's color. It rests as it does outside the group now, and the group keeps its line.
|
|
44
|
+
- **An `.alert` in another aesthetic nested under `.neobrutalism` casts no slab.** Neobrutalism raised the elevation of every alert below it, so one inside a `.chunky-tile`, `.glass`, `.pixel`, `.cyber`, or `.sketch` region took neobrutalism's shadow, unlike a card there. It takes the nested aesthetic's look now, and a `.neobrutalism` region nested inside that one still rests its alerts on the slab.
|
|
45
|
+
- **A select keeps its drop-down arrow in forced colors.** The chevron is drawn with gradients, which forced colors remove, so in Chromium and Firefox a `.select` or a native `<select>` under `/native` read as a text field. A single-row select shows the platform's arrow there now.
|
|
46
|
+
- **An `.input-group` holding a disabled control holds still under the pointer.** The group dimmed and showed the not-allowed cursor, but its line still darkened on hover; it no longer does.
|
|
47
|
+
- **A padding modifier pads only its own card or panel.** `.p-xs`, `.p-sm`, `.p-lg`, and `.flush` on a `.card` or `.panel` reached every card and panel nested inside it, so a card in a `.card.p-xs` sat at 8px instead of its 20px, and one in a `.flush` card had none. A nested surface keeps its own padding now; give it a modifier of its own to change it.
|
|
48
|
+
- **A long select label in an `.input-group` stops short of the chevron.** The group took the select's inline padding, so a label too long for the field ran under the drop-down arrow, at the right or, right to left, at the left. A single-row select keeps room for its chevron at the inline end now.
|
|
49
|
+
- **Typed text in a hued or invalid field reads at 4.5:1.** The text in `.ipt`, `.textarea`, and `.select` was the intent's base color, which fell as low as 2.5:1 against the field: a `.warning` field in the light theme, and `.success`, `.destructive`, `.info`, and `aria-invalid="true"` fields in the dark one, worst on `.soft` and `.solid`. It is the intent's strong tone now, darker in light and lighter in dark, at 4.5:1 or better for every intent and presentation in both themes. The field's line, focus ring, and fill are unchanged. Native fields under `/native` take the same text. A field with no intent class takes the neutral strong tone too, so its text is a shade different from 0.6.
|
|
50
|
+
- **The package's NOTICE covers the checkbox marks' Feather origin.** The checkbox check and indeterminate minus come from Lucide icons derived from Feather, and NOTICE now carries Feather's MIT notice beside Lucide's ISC one.
|