@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
package/docs/concepts.md
CHANGED
|
@@ -1,69 +1,211 @@
|
|
|
1
1
|
---
|
|
2
|
-
title:
|
|
3
|
-
description:
|
|
4
|
-
order:
|
|
2
|
+
title: Building a screen
|
|
3
|
+
description: Lay out the settings page, set its type, and add cards and buttons while learning intent, fill, edge, and aesthetic.
|
|
4
|
+
order: 3
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
#
|
|
7
|
+
# Building a screen
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
This page turns the empty shell from [Setup](./setup.md) into the first real part of the settings screen: a page header, a profile card with Save and Cancel buttons, and a plan summary beside a usage card. On the way it introduces the three choices every component makes, intent, presentation, and aesthetic, at the moment the screen needs each one. Everything else in these docs builds on this model.
|
|
10
10
|
|
|
11
|
-
## The
|
|
11
|
+
## The smallest screen
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
A page header and one card with one button:
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
```html
|
|
16
|
+
<main class="section">
|
|
17
|
+
<div class="section-content narrow stack">
|
|
18
|
+
<h1 class="text-title">Account settings</h1>
|
|
19
|
+
<section class="card stack">
|
|
20
|
+
<h2 class="text-title-sm">Profile</h2>
|
|
21
|
+
<p>Your name appears on invoices and shared projects.</p>
|
|
22
|
+
<button class="btn primary" type="button">Save changes</button>
|
|
23
|
+
</section>
|
|
24
|
+
</div>
|
|
25
|
+
</main>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Each class does one job:
|
|
29
|
+
|
|
30
|
+
- `.section` pads the page: a responsive gutter at the sides (1 to 2rem) and generous space above and below (4 to 7rem).
|
|
31
|
+
- `.section-content` centers a column with a maximum width; `.narrow` makes that 48rem instead of 80rem, a comfortable width for a form.
|
|
32
|
+
- `.stack` lays its children out vertically with a 1rem gap.
|
|
33
|
+
- `.text-title` and `.text-title-sm` set heading sizes: 1.875rem bold and 1.25rem semibold.
|
|
34
|
+
- `.card` is a bordered container with rounded corners and 1.25rem of padding.
|
|
35
|
+
- `.btn` makes a button, and `.primary` gives it the primary color.
|
|
36
|
+
|
|
37
|
+
Headings are not sized by their tag: the reset gives an `<h1>` with no type class the same size and weight as the text around it. That keeps the document structure, which heading level an element is, separate from the size you want it to look. If you want headings styled automatically, see [Setup → Classless HTML](./setup.md#classless-html).
|
|
38
|
+
|
|
39
|
+
## Lay out the page
|
|
40
|
+
|
|
41
|
+
Three layout helpers cover most screens, and all three use the same gap, `--layout-gap` (1rem):
|
|
42
|
+
|
|
43
|
+
- `.stack` for vertical lists of blocks.
|
|
44
|
+
- `.cluster` for a row that wraps when it runs out of room, such as a group of buttons. Add `.between` to push the first and last items to opposite ends.
|
|
45
|
+
- `.auto-grid` for a grid of equal cards that adds or drops columns as the space changes. A column is never narrower than `--layout-grid-min` (16rem) unless the container itself is.
|
|
46
|
+
|
|
47
|
+
`.tight` (0.5rem) and `.loose` (1.5rem) change the gap of the layout they sit on. A layout nested inside keeps its own gap.
|
|
48
|
+
|
|
49
|
+
Add a header and put the buttons in a row:
|
|
20
50
|
|
|
21
51
|
```html
|
|
22
|
-
<
|
|
23
|
-
<
|
|
24
|
-
|
|
25
|
-
</
|
|
52
|
+
<main class="section">
|
|
53
|
+
<div class="section-content narrow stack loose">
|
|
54
|
+
<header class="stack tight">
|
|
55
|
+
<h1 class="text-title">Account settings</h1>
|
|
56
|
+
<p>Manage your profile, plan, and security.</p>
|
|
57
|
+
</header>
|
|
58
|
+
|
|
59
|
+
<section class="card stack" aria-labelledby="profile-title">
|
|
60
|
+
<h2 class="text-title-sm" id="profile-title">Profile</h2>
|
|
61
|
+
<p>Your name appears on invoices and shared projects.</p>
|
|
62
|
+
<div class="cluster">
|
|
63
|
+
<button class="btn primary" type="button">Save changes</button>
|
|
64
|
+
<button class="btn ghost" type="button">Cancel</button>
|
|
65
|
+
</div>
|
|
66
|
+
</section>
|
|
67
|
+
</div>
|
|
68
|
+
</main>
|
|
26
69
|
```
|
|
27
70
|
|
|
28
|
-
|
|
71
|
+
[Content and layout](./usage/content-and-layout.md) lists every layout helper, including `.view`, `.divider`, and `.visually-hidden`, and the full type scale.
|
|
72
|
+
|
|
73
|
+
## Intent: which color
|
|
74
|
+
|
|
75
|
+
The Save button is `.primary` and the Cancel button has no intent, which makes it neutral. An intent class picks a color role:
|
|
76
|
+
|
|
77
|
+
| Class | Use it for | Default color |
|
|
78
|
+
| -------------- | ------------------------------------- | --------------------------------------- |
|
|
79
|
+
| _none_ | Anything without a meaning of its own | The page's text and border grays |
|
|
80
|
+
| `.primary` | The main action on a screen | Near-black on light, near-white on dark |
|
|
81
|
+
| `.secondary` | A second, quieter action | Mid gray |
|
|
82
|
+
| `.success` | Confirmation and completed states | Emerald green |
|
|
83
|
+
| `.warning` | Something that needs attention soon | Amber, with dark text |
|
|
84
|
+
| `.destructive` | Deleting, revoking, and errors | Rose red |
|
|
85
|
+
| `.info` | Neutral notices and help | Indigo |
|
|
86
|
+
|
|
87
|
+
Intent stays on the element that carries it. Putting `.destructive` on a `<section>` does not turn every button inside it red; you write it on each button. This is deliberate: a container that silently recolored everything inside it would turn a red danger zone's Cancel button red too.
|
|
88
|
+
|
|
89
|
+
`.neutral` names the default explicitly. You rarely need it, because no intent class already means neutral; it matters where color would otherwise come from elsewhere, such as a table row, which inherits its table's intent.
|
|
90
|
+
|
|
91
|
+
## Presentation: how much color
|
|
92
|
+
|
|
93
|
+
The Cancel button is `.ghost`: no fill, just colored text, so it reads as less important than Save. That is the presentation axis, two independent choices:
|
|
94
|
+
|
|
95
|
+
- **Fill:** `.solid` fills the component with its intent color and switches the text to the contrasting color. `.soft` mixes in a light 12% tint and keeps the text in the intent color. `.ghost` has no fill at rest.
|
|
96
|
+
- **Edge:** `.edged` draws a border in the intent color; `.edgeless` draws none.
|
|
97
|
+
|
|
98
|
+
```html
|
|
99
|
+
<button class="btn primary">Save changes</button>
|
|
100
|
+
<button class="btn primary soft">Preview</button>
|
|
101
|
+
<button class="btn primary ghost edged">Export data</button>
|
|
102
|
+
<button class="btn ghost">Cancel</button>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Every component has its own default when no presentation class applies. A button is solid with no border. A card has no fill and a border. A form field has no fill and a border. [Composing](./usage/composing.md#component-defaults) lists the default of every component.
|
|
106
|
+
|
|
107
|
+
Unlike intent, presentation passes down. A `.soft` on a container makes everything inside it soft unless an element says otherwise, and a class on the element itself always beats one inherited from a container:
|
|
108
|
+
|
|
109
|
+
```html
|
|
110
|
+
<div class="cluster soft">
|
|
111
|
+
<button class="btn primary">Soft primary</button>
|
|
112
|
+
<button class="btn success">Soft success</button>
|
|
113
|
+
<button class="btn primary solid">Solid: its own class wins</button>
|
|
114
|
+
</div>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Some components limit what presentation can do, to protect something they need. A form field inherited into a `.solid` container fills to only 6%, so typed text stays readable. A checkbox always keeps its border, because the border is the only thing that shows an unchecked box. These limits are listed with each component and collected in [Composing](./usage/composing.md).
|
|
118
|
+
|
|
119
|
+
## Finish the first screen
|
|
120
|
+
|
|
121
|
+
Add a plan summary next to a usage card in a grid, and give the summary a soft primary tint so it stands out as the account's current state:
|
|
122
|
+
|
|
123
|
+
```html
|
|
124
|
+
<main class="section">
|
|
125
|
+
<div class="section-content narrow stack loose">
|
|
126
|
+
<header class="stack tight">
|
|
127
|
+
<h1 class="text-title">Account settings</h1>
|
|
128
|
+
<p>Manage your profile, plan, and security.</p>
|
|
129
|
+
</header>
|
|
130
|
+
|
|
131
|
+
<section class="card stack" aria-labelledby="profile-title">
|
|
132
|
+
<h2 class="text-title-sm" id="profile-title">Profile</h2>
|
|
133
|
+
<p>Your name appears on invoices and shared projects.</p>
|
|
134
|
+
<div class="cluster">
|
|
135
|
+
<button class="btn primary" type="button">Save changes</button>
|
|
136
|
+
<button class="btn ghost" type="button">Cancel</button>
|
|
137
|
+
</div>
|
|
138
|
+
</section>
|
|
139
|
+
|
|
140
|
+
<div class="auto-grid">
|
|
141
|
+
<section class="card soft primary stack tight" aria-labelledby="plan-title">
|
|
142
|
+
<h2 class="text-label" id="plan-title">Current plan</h2>
|
|
143
|
+
<p class="text-title-sm">Team, billed yearly</p>
|
|
144
|
+
<p class="text-body">Renews on 12 March 2027.</p>
|
|
145
|
+
</section>
|
|
146
|
+
<section class="card stack tight" aria-labelledby="usage-title">
|
|
147
|
+
<h2 class="text-label" id="usage-title">Storage</h2>
|
|
148
|
+
<p class="text-title-sm">48 GB of 100 GB</p>
|
|
149
|
+
<p class="text-body">Shared by 6 members.</p>
|
|
150
|
+
</section>
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
</main>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
On a wide window the two cards sit side by side; when the column is too narrow for two 16rem columns and the gap between them, they stack. The [Feedback](./usage/feedback.md) page turns the storage card's number into a usage bar.
|
|
157
|
+
|
|
158
|
+
A `.card` rests at one unit of depth, but on the base look that depth has no visible shadow; it appears when an aesthetic draws one or when you add `.raised` or `.floating`. [Composing → Elevation](./usage/composing.md#elevation) covers depth.
|
|
159
|
+
|
|
160
|
+
## Aesthetic: what it is made of
|
|
161
|
+
|
|
162
|
+
The third axis changes the material of everything inside it: corners, border width, shadows, and sometimes the font. It needs its own import (see [Setup → Add an aesthetic](./setup.md#add-an-aesthetic-optional)):
|
|
163
|
+
|
|
164
|
+
```html
|
|
165
|
+
<main class="section neobrutalism">
|
|
166
|
+
<!-- The same settings screen: square corners, thick dark lines, hard offset shadows -->
|
|
167
|
+
</main>
|
|
168
|
+
```
|
|
29
169
|
|
|
30
|
-
|
|
170
|
+
Like presentation, an aesthetic passes down, and a component inside it can carry a different one. You do not need it to build the screen; [Aesthetics](./usage/aesthetics.md) compares all six.
|
|
31
171
|
|
|
32
|
-
|
|
33
|
-
- [Usage → Aesthetics](./usage/aesthetics.md) covers each aesthetic and its documented exceptions in depth.
|
|
172
|
+
## Words these docs use
|
|
34
173
|
|
|
35
|
-
|
|
174
|
+
Some pages describe how a component is painted. These words have one meaning each:
|
|
36
175
|
|
|
37
|
-
|
|
176
|
+
| Word | Meaning |
|
|
177
|
+
| --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
178
|
+
| Fill | How much of the intent color covers the component, from 0% (`.ghost`) to 100% (`.solid`). |
|
|
179
|
+
| Cap | The highest fill a component allows. A form field caps an inherited fill at 6%, for example. |
|
|
180
|
+
| Plate | The component's painted background: the fill, mixed over the ground. |
|
|
181
|
+
| Ground | The color the fill is mixed over. Usually the page itself shows through; a few components set their own, such as the light intent tint under `.kbd` and `.code`. |
|
|
182
|
+
| Edge | The border around the component. It is separate from rules, the lines inside a table. |
|
|
183
|
+
| Ink | A color used to draw lines: the edge, a table's rules, a checkbox's mark. "Text ink" means the color of text printed on a plate. |
|
|
184
|
+
| Material | What an aesthetic changes: corner radius and shape, border width and style, shadow, and transparency. |
|
|
185
|
+
| Slab | A hard, unblurred shadow offset down and to one side, as `.neobrutalism` and `.chunky-tile` draw. |
|
|
186
|
+
| Elevation | How much of the shadow in scope an element takes: none (`.flat`), one unit (`.raised`), or two (`.floating`). |
|
|
38
187
|
|
|
39
|
-
|
|
40
|
-
| ------------ | ------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
|
|
41
|
-
| Color | The palette: primary, accent, success, warning, destructive, info, text, borders, surfaces. | [Usage → Theming](./usage/theming.md#color-tokens) |
|
|
42
|
-
| Intent | Which color slot a component reads once an intent class is applied. | [Usage → Theming](./usage/theming.md#intent-tokens) |
|
|
43
|
-
| Foundation | Layout, shape, motion, focus, depth, and layering defaults shared across components. | [Usage → Theming](./usage/theming.md#foundation-tokens) |
|
|
44
|
-
| Presentation | How much of an intent a component shows — fill and border percentages. | [Usage → Customizing](./usage/customizing.md#presentation-tokens) |
|
|
45
|
-
| Material | What a component is made of — radius, border width, shadow geometry, translucency. | [Usage → Customizing](./usage/customizing.md#material-tokens) |
|
|
46
|
-
| Aesthetic | Per-aesthetic knobs such as `--pixel-unit` or `--tile-lift`. | [Usage → Customizing](./usage/customizing.md#aesthetic-tokens) |
|
|
188
|
+
## Tokens behind the classes
|
|
47
189
|
|
|
48
|
-
|
|
190
|
+
Every class reads CSS custom properties, called tokens, so you can change the result without rewriting a class:
|
|
49
191
|
|
|
50
|
-
|
|
192
|
+
| Kind | Controls | Where it is listed |
|
|
193
|
+
| ------------ | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
|
|
194
|
+
| Color | The palette: intent colors, text, borders, and backgrounds, for light and dark. | [Theming → Color tokens](./usage/theming.md#color-tokens) |
|
|
195
|
+
| Foundation | Layout widths and gaps, corner radii, control height, focus, motion. | [Theming → Foundation tokens](./usage/theming.md#foundation-tokens) |
|
|
196
|
+
| Intent | The color slots a component reads after an intent class picks a role. | [Theming → Intent tokens](./usage/theming.md#intent-tokens) |
|
|
197
|
+
| Presentation | The fill and border percentages the presentation classes set. | [Customizing → Presentation tokens](./usage/customizing.md#presentation-tokens) |
|
|
198
|
+
| Material | Radius, border width, shadow geometry, and transparency. | [Customizing → Material tokens](./usage/customizing.md#material-tokens) |
|
|
199
|
+
| Aesthetic | One knob per aesthetic, such as `--pixel-unit` or `--tile-lift`. | [Customizing → Aesthetic tokens](./usage/customizing.md#aesthetic-tokens) |
|
|
51
200
|
|
|
52
|
-
The
|
|
201
|
+
Color and foundation tokens are what most apps change first, to match a brand. The rest are lower level: components read them, and the presentation and aesthetic classes set them for you.
|
|
53
202
|
|
|
54
|
-
|
|
55
|
-
| ----- | ------------------------------------------------ |
|
|
56
|
-
| Light | `.light`, `.theme-light`, `[data-theme="light"]` |
|
|
57
|
-
| Dark | `.dark`, `.theme-dark`, `[data-theme="dark"]` |
|
|
203
|
+
## Limits to know now
|
|
58
204
|
|
|
59
|
-
-
|
|
60
|
-
-
|
|
61
|
-
- A
|
|
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
|
-
- The Tailwind source entrypoints' `dark:` variant tracks this rule for the explicit-selector-versus-system-preference choice: it fires under an explicit dark selector, or under the system preference when the subtree carries no explicit selector at all. It does not track the previous rule the same way: that one holds because `color-scheme` inherits, so the nearest declaration always wins regardless of depth, while `dark:` matches by selector -- `.dark *` matches every descendant of a `.dark` element, with no way to stop at a nearer `.light` in between. A `.light` subtree nested inside `.dark` themes its tokens correctly but still matches `dark:`'s explicit arm. See [Setup → Dark variant](./setup.md#dark-variant).
|
|
205
|
+
- **Intent does not pass down.** Write it on each element that shows it. The only exception is table rows.
|
|
206
|
+
- **Classes are styling only.** `<div class="btn">` looks like a button but cannot be focused or pressed with a keyboard. Use `<button>` or `<a href>`, and see [Accessibility](./accessibility.md).
|
|
207
|
+
- **A combination the docs do not describe is not supported.** It may render, but it can change in any release; see [Introduction → What counts as supported](./index.md#what-counts-as-supported).
|
|
66
208
|
|
|
67
|
-
|
|
209
|
+
## Next
|
|
68
210
|
|
|
69
|
-
|
|
211
|
+
The screen has one primary action and one quiet one. [Buttons](./usage/buttons.md) adds the rest: a destructive action for the danger zone, icon buttons, sizes, and disabled states.
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Accesibilidad
|
|
3
|
+
description: Lo que hace el CSS con el foco, los estados, el movimiento, el contraste, los colores forzados y el texto de derecha a izquierda, y lo que tu aplicación todavía les debe a sus usuarios.
|
|
4
|
+
order: 5
|
|
5
|
+
source: dc1a745e9e6853a31ca4a8cf7a334031bab1ec7d
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Accesibilidad
|
|
9
|
+
|
|
10
|
+
La pantalla de ajustes está construida, y el CSS ha hecho su parte por el camino: cada campo muestra dónde está el foco, un email inválido se vuelve rojo y el spinner se detiene para los usuarios que piden menos movimiento. El resto depende de tu HTML y tu JavaScript. Este paquete da estilo a los estados; no aporta elementos semánticos, atributos ARIA, comportamiento de teclado, gestión del foco, validación ni el momento de los anuncios.
|
|
11
|
+
|
|
12
|
+
Esta página enumera las dos mitades: lo que aporta el CSS y lo que tu aplicación tiene que añadir.
|
|
13
|
+
|
|
14
|
+
## Lo que aporta el CSS
|
|
15
|
+
|
|
16
|
+
### Foco y estado
|
|
17
|
+
|
|
18
|
+
| Característica | Comportamiento |
|
|
19
|
+
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
20
|
+
| `:focus-visible` | Un contorno de foco en cada elemento, dibujado con `--focus-ring`, `--focus-ring-width` y `--focus-ring-offset`. |
|
|
21
|
+
| Foco en controles de formulario | `.ipt`, `.textarea` y `.select` dibujan el contorno de foco y cambian su borde al color de la intención. El texto escrito en un campo con una clase de intención usa el tono legible de esa intención, `--intent-strong`. |
|
|
22
|
+
| Controles inválidos | `aria-invalid="true"` en un control de formulario vuelve destructivos su borde, su color de foco y el texto escrito, este último en el tono legible destructivo. |
|
|
23
|
+
| Controles deshabilitados | `disabled`, `aria-disabled="true"`, `data-disabled` y `.disabled` muestran el cursor y la opacidad de deshabilitado, y un control deshabilitado no reacciona al hover, tampoco dentro de un `.input-group`. |
|
|
24
|
+
| Estado abierto | `data-state="open"` en un `.tooltip` muestra su burbuja sin hover ni foco, y `data-state="closed"` la oculta aunque tenga hover o foco. Ningún otro componente lee ninguno de los dos. |
|
|
25
|
+
| `<dialog>` nativo | Un `<dialog>` con `.card`, `.panel` o `.surface` permanece oculto hasta que se abre, y se abre centrado. Un margen que pongas en el diálogo, como utilidad o en tu propio CSS, sigue sobrescribiendo el centrado. Los demás diálogos no se tocan. Atrapar el foco, cerrar con Escape y dejar inerte la página de detrás es cosa de tu aplicación. |
|
|
26
|
+
|
|
27
|
+
### Contenido visualmente oculto
|
|
28
|
+
|
|
29
|
+
`.visually-hidden` oculta contenido en pantalla y lo mantiene para los lectores de pantalla, como hace el `<caption>` de la tabla de claves de API en [Contenido y layout → Tablas](./usage/content-and-layout.md#tablas). Viene con las utilidades de layout: en `.`, `./native`, `./tw`, `./tw/native` y `./tw/utilities`. No está en `./components` ni en los puntos de entrada de componentes `./tw/components` y `./tw/*`.
|
|
30
|
+
|
|
31
|
+
### Límites de los controles
|
|
32
|
+
|
|
33
|
+
WCAG 1.4.11 pide que el límite de un control que necesitas ver para usarlo tenga un contraste de al menos 3:1 con lo que lo rodea.
|
|
34
|
+
|
|
35
|
+
| Característica | Comportamiento |
|
|
36
|
+
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
37
|
+
| Controles de texto en reposo | El borde de un control de texto reposa más claro que el borde completo de su intención, por debajo de 3:1 a propósito, para que el hover y el foco tengan un tono más intenso al que cambiar. |
|
|
38
|
+
| Toggles | `.checkbox`, `.radio` y `.switch` dibujan su borde completo, porque el borde es lo único que muestra una casilla sin marcar. Un `.switch` con su propio `.edgeless` es la excepción, más abajo. |
|
|
39
|
+
| `.edgeless` desde un contenedor | Lo ignoran todos los controles de texto y toggles: un contenedor no puede quitar el borde de un campo o toggle que contiene. |
|
|
40
|
+
| `.edgeless` en el control | `.ipt`, `.textarea`, `.select` y `.switch` pierden su borde y dejan de cumplir 1.4.11 en reposo. `.switch.ghost` conserva su borde incluso entonces, porque sin relleno y sin borde nada mostraría el carril. |
|
|
41
|
+
| `.checkbox`, `.radio` | Siempre dibujan su borde, venga `.edgeless` de un contenedor o lo lleven ellos mismos. `.edgeless` en ellos no está soportado. |
|
|
42
|
+
| Carril de progreso | A propósito, la parte rellena lleva el valor y el carril es un fondo discreto. El carril por defecto, `.soft.edgeless`, mide aproximadamente de 1.1:1 a 1.3:1 frente a la página. La parte rellena mide al menos 3:1 frente a ese carril para todas las intenciones excepto warning en claro (unos 2.7:1) e info en oscuro (unos 2.9:1). Donde el propio carril deba cumplir 1.4.11, usa `.ghost.edged` con una clase de intención; consulta [Contornos de progreso](#contornos-de-progreso) más abajo. |
|
|
43
|
+
|
|
44
|
+
### Contornos de progreso
|
|
45
|
+
|
|
46
|
+
En un `.progress.ghost.edged`, el carril es la página, y tanto su contorno como la parte rellena se dibujan en el color de la intención. Medido frente a la página, sin estética:
|
|
47
|
+
|
|
48
|
+
| Intención | Página clara | Página oscura | Cumple 3:1 |
|
|
49
|
+
| -------------- | ------------ | ------------- | ----------------------------------------------------------------------------- |
|
|
50
|
+
| `.primary` | 18.96:1 | 18.96:1 | Sí |
|
|
51
|
+
| `.secondary` | 7.47:1 | 7.63:1 | Sí |
|
|
52
|
+
| `.success` | 5.14:1 | 3.69:1 | Sí |
|
|
53
|
+
| `.warning` | 3.06:1 | 6.20:1 | Sí |
|
|
54
|
+
| `.destructive` | 5.80:1 | 3.27:1 | Sí |
|
|
55
|
+
| `.info` | 6.17:1 | 3.07:1 | Sí |
|
|
56
|
+
| Sin intención | 2.48:1 | 1.91:1 | No: el contorno no cumple, aunque la parte rellena, en el color del texto, sí |
|
|
57
|
+
|
|
58
|
+
Sin clase de intención, el contorno es el gris discreto de los bordes, `--color-border`. Para que un carril neutro cumpla 1.4.11, dale a la barra una clase de intención, o define `--progress-edge` con un color más intenso, como `var(--color-accent)`, que mide 7.47:1 en una página clara y 7.63:1 en una oscura. Warning en una página clara e info en una oscura superan 3:1 por poco margen, así que vuelve a medir si cambias esos colores.
|
|
59
|
+
|
|
60
|
+
### Movimiento y transparencia
|
|
61
|
+
|
|
62
|
+
| Característica | Comportamiento |
|
|
63
|
+
| ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
64
|
+
| Movimiento reducido, componentes | Con `prefers-reduced-motion: reduce`, cada componente detiene sus propias transiciones y animaciones: el brillo del skeleton y del progreso, la barra indeterminada, el tooltip, las marcas de los toggles y la pulsación. |
|
|
65
|
+
| Movimiento reducido, toda la página | El reset también acorta todas las demás animaciones y transiciones de la página. |
|
|
66
|
+
| Transparencia reducida | Con `prefers-reduced-transparency: reduce`, `.glass` y `.glass-liquid` pierden su desenfoque y su lente y se vuelven opacos. |
|
|
67
|
+
|
|
68
|
+
La regla de movimiento reducido de cada componente viene con el componente, así que cada punto de entrada que lo incluye respeta el movimiento reducido sin el reset, incluidos `@codenhub/styles/components`, `@codenhub/styles/tw/components` y cada punto de entrada de componente `/tw/*`. Los puntos de entrada completo y native añaden la regla del reset para toda la página.
|
|
69
|
+
|
|
70
|
+
La regla del reset es `!important` dentro de la capa `base`, y un `!important` con capa gana a uno sin capa, así que tu propio `!important` no puede volver a activar una animación. Para mantener una en marcha para los usuarios que piden movimiento reducido, como un spinner de subida que consideres esencial, declárala `!important` en una capa ordenada antes de `base`. La primera sentencia `@layer` que lee el navegador fija el orden, así que la tuya va antes del paquete:
|
|
71
|
+
|
|
72
|
+
```css
|
|
73
|
+
@layer essential-motion, theme, base, components, utilities;
|
|
74
|
+
@import "@codenhub/styles";
|
|
75
|
+
|
|
76
|
+
@layer essential-motion {
|
|
77
|
+
@media (prefers-reduced-motion: reduce) {
|
|
78
|
+
.upload-spinner {
|
|
79
|
+
animation-duration: 1s !important;
|
|
80
|
+
animation-iteration-count: infinite !important;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Respetar el movimiento reducido no es todo lo que se pide. El movimiento que sigue en marcha junto al contenido, como un brillo que queda en una tarjeta después de que ha cargado, necesita una forma de detenerlo para todos los usuarios; consulta [Feedback → Animación que no se detiene](./usage/feedback.md#animación-que-no-se-detiene).
|
|
87
|
+
|
|
88
|
+
### Color y contraste
|
|
89
|
+
|
|
90
|
+
Las mediciones de abajo corresponden a los colores incluidos. En cuanto cambies un token de color, vuelve a medir tus propios pares; [Temas → Cambiar el color de marca](./usage/theming.md#cambiar-el-color-de-marca) muestra qué pares comprobar.
|
|
91
|
+
|
|
92
|
+
| Característica | Comportamiento |
|
|
93
|
+
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
94
|
+
| Etiquetas rellenas | La etiqueta `.solid` de cada intención cumple 4.5:1 (WCAG 1.4.3) como texto normal, en ambos temas. La más baja es success, con 5.14:1. |
|
|
95
|
+
| Texto de warning | `--color-warning-contrast` es casi negro, no el color de la página, porque un ámbar lo bastante oscuro para llevar texto blanco ya no parece ámbar. |
|
|
96
|
+
| Rellenos parciales | El color de texto de contraste solo aparece en rellenos por encima de la mitad de intensidad, así que el relleno limitado de un control de texto conserva el color de texto propio de la intención. |
|
|
97
|
+
| Color de intención en oscuro | En modo oscuro, una etiqueta `.soft` o `.ghost` usa el tono `-300` de su intención, así que conserva su matiz en lugar de volverse blanca. |
|
|
98
|
+
| Marcas de los toggles | Una marca activada mide al menos 3:1 frente a cada relleno que su presentación pueda darle, en ambos temas. |
|
|
99
|
+
| Rellenos soft con borde | `.edged` en un `.alert`, `.panel`, `.badge`, `.kbd`, `.code` o `.pre` `.soft` dibuja un borde que mide menos de 3:1 frente al relleno del 12% en algunas intenciones, cuáles depende del tema. Mide el par antes de confiar en ese borde como límite de un control. |
|
|
100
|
+
|
|
101
|
+
### Colores forzados y dirección
|
|
102
|
+
|
|
103
|
+
| Característica | Comportamiento |
|
|
104
|
+
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
105
|
+
| Colores forzados | Con `forced-colors: active`, los bordes, los estados activados y el chevron de un `.select` siguen visibles, dibujados con colores del sistema, bajo cualquier estética. Una estética que dibuja su borde como una sombra interior, como `.pixel`, dibuja en su lugar un borde real. |
|
|
106
|
+
| Dirección del texto | Con `dir="rtl"`, la barra de las citas, el icono de la alerta, el relleno del progreso, el divisor vertical, la perilla del switch, la alineación de las tablas y el chevron de un select cambian de lado. No hace falta ninguna clase. |
|
|
107
|
+
|
|
108
|
+
Con colores forzados, `.text-control`, `.ipt`, `.textarea`, `.select` y los toggles muestran un contorno de foco `Highlight` de 2px. El punto de entrada native da el mismo contorno a los inputs de texto, selects, textareas, checkboxes y radios sin clase.
|
|
109
|
+
|
|
110
|
+
Los checkboxes, radios y switches usan los colores del sistema `Canvas`, `CanvasText`, `Highlight` y `HighlightText`, así que activado y desactivado siguen siendo distinguibles: un toggle activado se rellena con `Highlight` y su marca es `HighlightText`, tanto en las clases como en el punto de entrada native. La forma, el tamaño y el espaciado no cambian.
|
|
111
|
+
|
|
112
|
+
## Lo que hace falta fuera del CSS
|
|
113
|
+
|
|
114
|
+
Usa el elemento HTML que corresponde a lo que hace el componente, y añade el comportamiento que el CSS no puede dar.
|
|
115
|
+
|
|
116
|
+
| Interfaz | Lo que añade tu aplicación |
|
|
117
|
+
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
118
|
+
| Botones | `<button>` para acciones y `<a href>` para navegación. Un nombre accesible, como `aria-label`, en cada `.btn.icon`. |
|
|
119
|
+
| Formularios | Un `<label>` para cada control, el `type` correcto, validación y `aria-describedby` enlazando pistas y errores. Mantén las pistas y los errores fuera del `<label>`, y dale a un `.switch` `role="switch"`. |
|
|
120
|
+
| Alertas | `role="status"` para una confirmación como "Perfil guardado", o `role="alert"` para un error que necesita atención inmediata. |
|
|
121
|
+
| Toasts | Una región live, una forma de cerrarlo, reglas de foco y una pausa en cualquier temporizador. |
|
|
122
|
+
| Tooltips | Un `id` real y `role="tooltip"` en la burbuja, referenciado desde el `aria-describedby` del disparador. El cierre con Escape escribiendo `data-state="closed"`; consulta [Tooltips](./usage/tooltips.md#hover-permanencia-y-escape). La burbuja ya admite hover. |
|
|
123
|
+
| Progreso | Un elemento `<progress>`, o `role="progressbar"` o `role="meter"` con valores ARIA, cuando el valor debe anunciarse. |
|
|
124
|
+
| Skeletons | `aria-hidden="true"` en los elementos visuales de carga, incluido un spinner que aportes tú, y el estado de carga anunciado de otra forma cuando haga falta. |
|
|
125
|
+
| Movimiento continuo | Una forma de pausar, detener u ocultar el movimiento que no es esencial; consulta [Feedback → Animación que no se detiene](./usage/feedback.md#animación-que-no-se-detiene). |
|
|
126
|
+
| Popovers, modales | Atrapar el foco, cerrar con Escape, un fondo inerte, etiquetas y roles. |
|
|
127
|
+
|
|
128
|
+
## Atributos de estado
|
|
129
|
+
|
|
130
|
+
Prefiere los atributos nativos:
|
|
131
|
+
|
|
132
|
+
```html
|
|
133
|
+
<button class="btn primary" disabled>Saving…</button> <input class="ipt" type="email" aria-invalid="true" aria-describedby="email-error" />
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Usa atributos ARIA o data donde el elemento o tu librería de componentes no tenga uno nativo:
|
|
137
|
+
|
|
138
|
+
```html
|
|
139
|
+
<a class="btn secondary" aria-disabled="true">Export data</a>
|
|
140
|
+
<span class="tooltip" data-state="open">
|
|
141
|
+
<button type="button" class="tooltip-icon" aria-label="About public profiles" aria-describedby="public-profile-help">?</button>
|
|
142
|
+
<span class="tooltip-bubble" role="tooltip" id="public-profile-help">Anyone with the link can see your name and photo.</span>
|
|
143
|
+
</span>
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
`aria-disabled="true"` indica a las tecnologías de asistencia que el control está deshabilitado, pero no impide un clic ni una pulsación de tecla. Usa el atributo `disabled`, o detén la acción en JavaScript.
|
|
147
|
+
|
|
148
|
+
## Siguiente paso
|
|
149
|
+
|
|
150
|
+
Con esto termina el orden de lectura. La [Introducción](./index.md) enlaza todas las páginas, y [Composición](./usage/composing.md), [Personalización](./usage/customizing.md) y [Contenido y layout](./usage/content-and-layout.md) son las páginas de consulta para más adelante.
|