@codenhub/styles 0.5.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 +27 -22
- 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 +120 -62
- package/dist/tw/aesthetics/cyber.css +102 -40
- package/dist/tw/aesthetics/glass.css +371 -19
- package/dist/tw/aesthetics/index.css +2 -1
- package/dist/tw/aesthetics/neobrutalism.css +121 -33
- package/dist/tw/aesthetics/pixel.css +111 -16
- package/dist/tw/aesthetics/sketch.css +100 -28
- package/dist/tw/box.css +69 -28
- package/dist/tw/components/button.css +35 -14
- package/dist/tw/components/feedback.css +61 -58
- package/dist/tw/components/form.css +255 -142
- package/dist/tw/components/index.css +4 -9
- package/dist/tw/components/surface.css +80 -68
- package/dist/tw/components/tooltip.css +75 -41
- package/dist/tw/elevation.css +14 -22
- package/dist/tw/index.css +15 -19
- package/dist/tw/intent.css +35 -27
- package/dist/tw/native.css +22 -12
- package/dist/tw/palette.css +14 -11
- package/dist/tw/presentation.css +16 -30
- package/dist/tw/reset.css +36 -43
- package/dist/tw/surface.css +11 -12
- package/dist/tw/theme.css +87 -103
- package/dist/tw/utilities/content.css +311 -200
- package/dist/tw/utilities/layout.css +41 -37
- package/docs/accessibility.md +104 -58
- 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 +53 -0
- package/docs/changelog/0.7.0.md +50 -0
- package/docs/changelog/index.md +2 -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 +89 -21
- package/docs/integrating/astro.md +3 -4
- package/docs/integrating/index.md +18 -13
- package/docs/integrating/nextjs.md +4 -5
- package/docs/integrating/svelte.md +5 -4
- package/docs/integrating/tailwind.md +29 -8
- 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 +102 -65
- package/docs/usage/buttons.md +108 -40
- package/docs/usage/composing.md +105 -92
- package/docs/usage/content-and-layout.md +159 -127
- package/docs/usage/customizing.md +112 -43
- package/docs/usage/feedback.md +135 -70
- package/docs/usage/forms.md +184 -99
- package/docs/usage/index.md +18 -14
- package/docs/usage/solo.md +83 -0
- package/docs/usage/theming.md +260 -119
- package/docs/usage/tooltips.md +103 -42
- package/llms-full.txt +2465 -1272
- package/llms.txt +25 -17
- package/package.json +28 -35
- package/dist/tw/components/loader.css +0 -117
package/docs/usage/forms.md
CHANGED
|
@@ -1,145 +1,230 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Forms
|
|
3
|
-
description:
|
|
4
|
-
order:
|
|
3
|
+
description: Labeled fields, hints and errors, icons and fixed prefixes, selects, and checkbox, radio, and switch toggles.
|
|
4
|
+
order: 2
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Forms
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
| --------------------------------------------------------------------- | ------------------------------------------------------------------------ |
|
|
11
|
-
| `.field` | Vertical field wrapper. |
|
|
12
|
-
| `.label` | Form label text. |
|
|
13
|
-
| `.hint` | Secondary helper text. |
|
|
14
|
-
| `.hint.destructive` | Helper text with destructive intent. |
|
|
15
|
-
| `.surface` | Shared public container composition utility. |
|
|
16
|
-
| `.text-control` | Shared public text-control composition utility. |
|
|
17
|
-
| `.ipt` | Input control styling. |
|
|
18
|
-
| `.input-group` | Wrapper that owns the field box so a control can carry an icon or affix. |
|
|
19
|
-
| `.textarea` | Textarea control styling. |
|
|
20
|
-
| `.select` | Select control styling. |
|
|
21
|
-
| `input[type="checkbox"].checkbox` | Custom checkbox control styling. |
|
|
22
|
-
| `input[type="radio"].radio` | Custom radio control styling. |
|
|
23
|
-
| `input[type="checkbox"].switch` | Custom switch control styling. |
|
|
24
|
-
| `[aria-invalid="true"]` on controls | Destructive border and focus color. |
|
|
25
|
-
| `[disabled]`, `[aria-disabled="true"]`, `[data-disabled]` on controls | Disabled styling. |
|
|
9
|
+
The profile card has a Save button but nothing to save. This page fills it in: a display name with a hint, an email address that shows a validation error, a profile address with a fixed prefix, a language select, and the toggles for notifications, billing, and profile visibility. The package styles each control; your HTML provides the labels, the validation, and the error messages, and this page shows how to connect them.
|
|
26
10
|
|
|
27
|
-
##
|
|
11
|
+
## A labeled field
|
|
28
12
|
|
|
29
|
-
|
|
13
|
+
A field is a label, a control, and an optional hint, stacked:
|
|
30
14
|
|
|
31
|
-
|
|
15
|
+
```html
|
|
16
|
+
<div class="field">
|
|
17
|
+
<label class="label" for="display-name">Display name</label>
|
|
18
|
+
<input class="ipt" id="display-name" name="display-name" aria-describedby="display-name-hint" />
|
|
19
|
+
<span class="hint" id="display-name-hint">Shown on invoices and shared projects.</span>
|
|
20
|
+
</div>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
- `.field` stacks its children with a small gap (0.35rem) and takes the full width.
|
|
24
|
+
- `.label` sets label text: 1rem, medium weight.
|
|
25
|
+
- `.hint` is smaller, secondary-colored helper text. Keep it outside the `<label>` and point `aria-describedby` at it, so a screen reader announces it as a description instead of reading it as part of the field's name.
|
|
26
|
+
- `.ipt` styles an `<input>`. Use `.textarea` for a `<textarea>` and `.select` for a `<select>`.
|
|
32
27
|
|
|
33
|
-
|
|
28
|
+
A text control is at least 2.5rem tall (`--control-height`), the same height as a default button, so a field and a button line up in a row. Its default look is no fill and a border. A `.textarea` is at least 7rem tall and can be resized vertically.
|
|
29
|
+
|
|
30
|
+
## Show a validation error
|
|
31
|
+
|
|
32
|
+
Mark the control invalid with `aria-invalid="true"` and give the error message `.hint.destructive`:
|
|
34
33
|
|
|
35
34
|
```html
|
|
36
|
-
<
|
|
37
|
-
<
|
|
38
|
-
<
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
35
|
+
<div class="field">
|
|
36
|
+
<label class="label" for="email">Email</label>
|
|
37
|
+
<input class="ipt" type="email" id="email" name="email" value="ada@" aria-invalid="true" aria-describedby="email-error" />
|
|
38
|
+
<span class="hint destructive" id="email-error">Enter a full email address, such as ada@example.com.</span>
|
|
39
|
+
</div>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
An invalid control draws its border, focus ring, and typed text in the destructive color, whatever intent class it has. The text uses the readable tone of that color, `--intent-strong`, so it stays legible on the page. The package only paints the state: deciding that the value is invalid, setting and clearing `aria-invalid`, and writing the message are your code. Remove `aria-invalid` once the value is valid again; leaving it set keeps the field red.
|
|
43
|
+
|
|
44
|
+
## Put the profile form together
|
|
45
|
+
|
|
46
|
+
```html
|
|
47
|
+
<form class="card stack" aria-labelledby="profile-title">
|
|
48
|
+
<h2 class="text-title-sm" id="profile-title">Profile</h2>
|
|
49
|
+
|
|
50
|
+
<div class="field">
|
|
51
|
+
<label class="label" for="display-name">Display name</label>
|
|
52
|
+
<input class="ipt" id="display-name" name="display-name" value="Ada Lovelace" aria-describedby="display-name-hint" />
|
|
53
|
+
<span class="hint" id="display-name-hint">Shown on invoices and shared projects.</span>
|
|
44
54
|
</div>
|
|
45
|
-
|
|
46
|
-
<
|
|
47
|
-
|
|
55
|
+
|
|
56
|
+
<div class="field">
|
|
57
|
+
<label class="label" for="email">Email</label>
|
|
58
|
+
<input class="ipt" type="email" id="email" name="email" value="ada@example.com" />
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<div class="field">
|
|
62
|
+
<label class="label" for="bio">Bio</label>
|
|
63
|
+
<textarea class="textarea" id="bio" name="bio" rows="3"></textarea>
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<div class="field">
|
|
67
|
+
<label class="label" for="language">Language</label>
|
|
68
|
+
<select class="select" id="language" name="language">
|
|
69
|
+
<option>English</option>
|
|
70
|
+
<option>Português</option>
|
|
71
|
+
<option>Español</option>
|
|
72
|
+
</select>
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
<div class="cluster">
|
|
76
|
+
<button class="btn primary" type="submit">Save changes</button>
|
|
77
|
+
<button class="btn ghost" type="reset">Cancel</button>
|
|
78
|
+
</div>
|
|
79
|
+
</form>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
A `.select` draws its own arrow. With `multiple` or a `size` above 1 it becomes a list box instead: no arrow, as tall as the rows it shows. The open list of options is drawn by the browser and the operating system, so it does not take the package's look.
|
|
83
|
+
|
|
84
|
+
## Add an icon or a fixed prefix
|
|
85
|
+
|
|
86
|
+
`.input-group` puts an icon or a piece of text inside a field's border. The group draws the border, background, focus ring, and invalid and disabled states; the control inside it gives up its own, so the border is drawn once. Place the adornment before the control to put it at the start, after it to put it at the end.
|
|
87
|
+
|
|
88
|
+
The profile address always starts with the same host, so it is a fixed prefix:
|
|
89
|
+
|
|
90
|
+
```html
|
|
91
|
+
<div class="field">
|
|
92
|
+
<label class="label" for="profile-url">Profile address</label>
|
|
93
|
+
<div class="input-group" style="--input-group-gap: 0">
|
|
94
|
+
<span>app.example.com/u/</span>
|
|
95
|
+
<input class="ipt" id="profile-url" name="profile-url" value="ada" />
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The gap between the control and its adornment is `--input-group-gap`, 0.5rem by default. That suits an icon, but text meant to read as part of the value looks broken with a space after it, so the example sets it to `0`. Set it on the `.input-group` itself: the group declares its own default, so a value set on a parent element has no effect. It is one of six [public component variables](./customizing.md#component-variables).
|
|
101
|
+
|
|
102
|
+
A members search, with an icon at the start (the `ic-lucide-*` classes need `@codenhub/icons` loaded; see [Buttons → Loading icons](./buttons.md#loading-icons)):
|
|
103
|
+
|
|
104
|
+
```html
|
|
105
|
+
<div class="field">
|
|
106
|
+
<label class="label" for="member-search">Find a member</label>
|
|
48
107
|
<div class="input-group">
|
|
49
|
-
<
|
|
50
|
-
<
|
|
108
|
+
<i class="ic-lucide-search" aria-hidden="true"></i>
|
|
109
|
+
<input class="ipt" type="search" id="member-search" name="q" />
|
|
51
110
|
</div>
|
|
52
|
-
</
|
|
111
|
+
</div>
|
|
53
112
|
```
|
|
54
113
|
|
|
55
|
-
|
|
114
|
+
A `.select` works in a group too. The group removes the control's side padding, except at the end of a single-row select, which keeps 1.75rem so the chosen option's text does not run under the arrow.
|
|
115
|
+
|
|
116
|
+
Any element works as the adornment: an icon class, an inline `<svg>`, an `<img>`, or text. The package ships no icons for fields, because a built-in image could not follow your text color, theme, or aesthetic.
|
|
56
117
|
|
|
57
|
-
|
|
118
|
+
The group reads intent and presentation the way a lone `.ipt` does: `.input-group.primary` colors the border, and `.input-group.soft.edgeless` is a field sunk into the page. `aria-invalid="true"` or `disabled` on the control inside applies to the whole group, and so does either on the group itself. The focus ring appears when anything inside the group has focus, so unlike a lone field it also shows after a mouse click.
|
|
58
119
|
|
|
59
|
-
|
|
120
|
+
## Browser decorations
|
|
121
|
+
|
|
122
|
+
Some input types come with built-in buttons: a date or time field's picker button, a number field's up and down arrows, and a search field's clear button. The package keeps them, because each one also does something: the picker button is the only way to open the picker with a mouse, and the clear button empties the field.
|
|
123
|
+
|
|
124
|
+
`.unadorned` removes them, for a field where you draw your own. Put it on the control, or on its `.input-group`. Removing a decoration removes what it did, so connect your replacement yourself: `input.showPicker()` opens a picker, `stepUp()` and `stepDown()` replace the arrows, and setting `value` to `""` and dispatching an `input` event replaces a clear button. Typing keeps working either way. Firefox gives no way to remove its date picker button, so it stays there.
|
|
60
125
|
|
|
61
126
|
```html
|
|
62
|
-
<div class="
|
|
63
|
-
<
|
|
64
|
-
<
|
|
127
|
+
<div class="field">
|
|
128
|
+
<label class="label" for="member-filter">Find a member</label>
|
|
129
|
+
<div class="input-group unadorned">
|
|
130
|
+
<i class="ic-lucide-search" aria-hidden="true"></i>
|
|
131
|
+
<input class="ipt" type="search" id="member-filter" name="q" />
|
|
132
|
+
<button class="btn icon ghost p-xs" type="button" aria-label="Clear search">
|
|
133
|
+
<i class="ic-lucide-x" aria-hidden="true"></i>
|
|
134
|
+
</button>
|
|
135
|
+
</div>
|
|
65
136
|
</div>
|
|
66
137
|
```
|
|
67
138
|
|
|
68
|
-
The
|
|
139
|
+
The clear button above is a real `<button>` with an accessible name. A button inside a group keeps its own classes: a `.btn.ghost` has no fill and, like every button by default, no border, so it sits inside the field's border without drawing one of its own.
|
|
69
140
|
|
|
70
141
|
## Toggles
|
|
71
142
|
|
|
72
|
-
|
|
143
|
+
The settings screen has three kinds of toggle: a checkbox to opt into invoice emails, radio buttons to choose a billing period, and a switch to make the profile public. Each class goes on a native `<input>` of the matching type:
|
|
144
|
+
|
|
145
|
+
```html
|
|
146
|
+
<fieldset class="stack tight">
|
|
147
|
+
<legend class="label">Notifications</legend>
|
|
148
|
+
<label class="cluster tight">
|
|
149
|
+
<input class="checkbox" type="checkbox" name="invoice-email" checked />
|
|
150
|
+
Email me when an invoice is ready
|
|
151
|
+
</label>
|
|
152
|
+
</fieldset>
|
|
153
|
+
|
|
154
|
+
<fieldset class="stack tight">
|
|
155
|
+
<legend class="label">Billing period</legend>
|
|
156
|
+
<label class="cluster tight">
|
|
157
|
+
<input class="radio" type="radio" name="period" value="monthly" />
|
|
158
|
+
Monthly
|
|
159
|
+
</label>
|
|
160
|
+
<label class="cluster tight">
|
|
161
|
+
<input class="radio" type="radio" name="period" value="yearly" checked />
|
|
162
|
+
Yearly, two months free
|
|
163
|
+
</label>
|
|
164
|
+
</fieldset>
|
|
165
|
+
|
|
166
|
+
<label class="cluster tight">
|
|
167
|
+
<input class="switch primary" type="checkbox" role="switch" name="public-profile" />
|
|
168
|
+
Public profile
|
|
169
|
+
</label>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
- `.checkbox` goes on `type="checkbox"`, `.radio` on `type="radio"`, and `.switch` on `type="checkbox"`. Give a switch `role="switch"` yourself, so it is announced as on or off rather than checked.
|
|
173
|
+
- `.cluster.tight` on the `<label>` lines the control up with its text and leaves a 0.5rem gap.
|
|
174
|
+
- A checkbox whose `indeterminate` property is set, for a group where only some items are checked, shows a dash, and keeps the dash while also `checked`, as the browser's own checkbox does. Set it from script (`input.indeterminate = true`); there is no attribute for it.
|
|
73
175
|
|
|
74
|
-
|
|
75
|
-
| ---------------------- | ----------------------- |
|
|
76
|
-
| `.neutral` _(default)_ | Text color, capped. |
|
|
77
|
-
| `.primary` | Primary color. |
|
|
78
|
-
| `.secondary` | Secondary/accent color. |
|
|
79
|
-
| `.success` | Success color. |
|
|
80
|
-
| `.warning` | Warning color. |
|
|
81
|
-
| `.destructive` | Destructive color. |
|
|
82
|
-
| `.info` | Info color. |
|
|
176
|
+
### Checked and unchecked colors
|
|
83
177
|
|
|
84
|
-
|
|
178
|
+
An intent class sets the checked color. With no intent, a checked toggle is filled with the text color, and the mark is drawn in the page color: a black box with a white check on a light page. Unlike a neutral button, a neutral toggle fills all the way when checked.
|
|
85
179
|
|
|
86
|
-
|
|
87
|
-
| ---------------- | --------- | ---------------------------------------- |
|
|
88
|
-
| `.ghost` | 0% | 100%, mark in the contrast tone (pinned) |
|
|
89
|
-
| `.soft`, default | 12% | 100%, mark in the contrast tone (pinned) |
|
|
90
|
-
| `.solid` | 40% | 100%, mark in the contrast tone (pinned) |
|
|
180
|
+
Presentation changes only the unchecked look. Every toggle rests at `.soft`; once checked, each has one look whatever its presentation:
|
|
91
181
|
|
|
92
|
-
|
|
182
|
+
| Toggle | Unchecked fill | Checked |
|
|
183
|
+
| ---------------- | -------------- | ---------------------------------------------- |
|
|
184
|
+
| `.ghost` | 0% | 100% fill, with the mark in the contrast color |
|
|
185
|
+
| `.soft`, default | 12% | 100% fill, with the mark in the contrast color |
|
|
186
|
+
| `.solid` | 40% | 100% fill, with the mark in the contrast color |
|
|
93
187
|
|
|
94
|
-
|
|
188
|
+
A checked checkbox and a checked switch cut their mark out of the filled plate. A checked radio thickens its ring to twice the resting line width, up to 3px, takes the full intent color on it, and shows a dot. The 3px limit keeps the ring from swallowing the dot under an aesthetic with a thick line.
|
|
95
189
|
|
|
96
|
-
|
|
190
|
+
`.checkbox` and `.radio` always draw their border, even with `.edgeless`, because the border is the only thing that shows an unchecked box. `.switch.ghost` keeps its border too, since with no fill and no border nothing would mark the track. These are listed in [Composing](./composing.md#component-axis-reference).
|
|
97
191
|
|
|
98
|
-
|
|
192
|
+
An aesthetic that draws its border as an inner shadow, such as `.pixel`, cannot make that shadow wider than the toggle's border width. A 16px checkbox or a 20px switch has no room for a thicker inner ring without covering the mark. This only matters if you set `--ui-shadow-spread` yourself; see [Customizing → Material tokens](./customizing.md#material-tokens).
|
|
193
|
+
|
|
194
|
+
## Fill and border on text controls
|
|
195
|
+
|
|
196
|
+
Text controls take intent, which colors the border, the focus ring, and the typed text, the text in the intent's readable tone (`--intent-strong`). They also take both presentation axes. Their fill is capped low, so typed text stays readable:
|
|
197
|
+
|
|
198
|
+
| On a text control | Fill |
|
|
199
|
+
| ----------------------------------------------- | ---- |
|
|
200
|
+
| `.ghost`, default | 0% |
|
|
201
|
+
| Any fill from a container (`.soft` or `.solid`) | 6% |
|
|
202
|
+
| `.soft` on the control | 12% |
|
|
203
|
+
| `.solid` on the control | 20% |
|
|
204
|
+
|
|
205
|
+
A container's fill is meant for the surfaces in it, so a field nobody classed takes only a faint 6% of it. Put the class on the field itself for more.
|
|
206
|
+
|
|
207
|
+
The border works the same way. An `.edgeless` inherited from a container is ignored, so a toolbar cannot leave a field with no visible edge. `.edgeless` written on the control itself is honored: that is how you ask for a borderless field. A borderless field does not meet the WCAG 1.4.11 contrast requirement for a control's boundary, so it is never a default; its focus ring still shows.
|
|
99
208
|
|
|
100
209
|
```html
|
|
101
|
-
<input class="ipt success" placeholder="
|
|
102
|
-
<input class="ipt
|
|
103
|
-
<input class="ipt soft edged" placeholder="Tinted with a border" />
|
|
210
|
+
<input class="ipt success" placeholder="Matches your current password" />
|
|
211
|
+
<input class="ipt soft edged" placeholder="Tinted, with a border" />
|
|
104
212
|
<input class="ipt soft edgeless" placeholder="Sunk into the page" />
|
|
105
213
|
<div class="soft">
|
|
106
|
-
<input class="ipt" placeholder="
|
|
107
|
-
</div>
|
|
108
|
-
<div class="edgeless">
|
|
109
|
-
<input class="ipt" placeholder="Keeps its line; the floor holds" />
|
|
214
|
+
<input class="ipt" placeholder="A container's .soft gives a 6% tint" />
|
|
110
215
|
</div>
|
|
111
216
|
```
|
|
112
217
|
|
|
113
|
-
|
|
218
|
+
At rest, a field's border is deliberately lighter than 3:1 against the page, so hover and focus have a visible change to make. [Accessibility → Control boundaries](../accessibility.md#control-boundaries) explains the trade-off and how to get a stronger border.
|
|
114
219
|
|
|
115
|
-
|
|
116
|
-
<div class="surface glass">Blurred, translucent, glass corners</div>
|
|
117
|
-
<div class="surface pixel">Cut corners and an inset ring</div>
|
|
118
|
-
<div class="surface primary solid">Any intent, any presentation</div>
|
|
119
|
-
```
|
|
220
|
+
## Disabled controls
|
|
120
221
|
|
|
121
|
-
|
|
222
|
+
`disabled`, `aria-disabled="true"`, `data-disabled`, or `.disabled` on a control draws it at reduced opacity with a not-allowed cursor. As with buttons, only the `disabled` attribute stops input; the others change the look only.
|
|
122
223
|
|
|
123
|
-
##
|
|
224
|
+
## Building your own control
|
|
124
225
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
<input class="ipt" type="email" aria-invalid="true" aria-describedby="email-error" />
|
|
129
|
-
<span class="hint destructive" id="email-error">Enter a valid email.</span>
|
|
130
|
-
</label>
|
|
131
|
-
<label style="display: flex; gap: 0.5rem; align-items: center">
|
|
132
|
-
<input type="checkbox" class="checkbox success" />
|
|
133
|
-
<span>Accept terms</span>
|
|
134
|
-
</label>
|
|
135
|
-
<label style="display: flex; gap: 0.5rem; align-items: center">
|
|
136
|
-
<input type="radio" class="radio secondary" name="plan" />
|
|
137
|
-
<span>Standard plan</span>
|
|
138
|
-
</label>
|
|
139
|
-
<label style="display: flex; gap: 0.5rem; align-items: center">
|
|
140
|
-
<input type="checkbox" class="switch destructive" />
|
|
141
|
-
<span>Enable</span>
|
|
142
|
-
</label>
|
|
143
|
-
```
|
|
226
|
+
For a text-like control the package does not ship, `.text-control` gives an element the same border, placeholder, hover, focus, invalid, and disabled styles as `.ipt`, without its height or padding. [Customizing → Composition helpers](./customizing.md#composition-helpers) explains it with the other building blocks.
|
|
227
|
+
|
|
228
|
+
## Next
|
|
144
229
|
|
|
145
|
-
|
|
230
|
+
The form can be filled in and submitted. [Feedback](./feedback.md) shows what the screen does next: a Save button that says it is saving, a success message, a plan badge, and a storage usage bar.
|
package/docs/usage/index.md
CHANGED
|
@@ -1,24 +1,28 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Overview
|
|
3
|
-
description:
|
|
3
|
+
description: The guides that finish the settings screen, then the lookup pages for every class, token, and default.
|
|
4
4
|
group: Usage
|
|
5
|
-
order:
|
|
5
|
+
order: 4
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Usage
|
|
9
9
|
|
|
10
|
-
These guides
|
|
10
|
+
These guides finish the settings screen started in [Building a screen](../concepts.md). Read the first seven in order: each one adds a part of the screen and assumes the ones before it. The last three are lookup pages; you will be sent to them when a guide needs the full table, and you can come back whenever you need a default or a rule.
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
- [Theming](./theming.md): The color, intent, and foundation token reference.
|
|
14
|
-
- [Customizing](./customizing.md): The presentation and material token reference, aesthetic knobs, and defining a custom intent.
|
|
15
|
-
- [Aesthetics](./aesthetics.md): Each shipped aesthetic in depth, including its documented exceptions.
|
|
16
|
-
- [Buttons](./buttons.md)
|
|
17
|
-
- [Forms](./forms.md)
|
|
18
|
-
- [Feedback](./feedback.md)
|
|
19
|
-
- [Tooltips](./tooltips.md)
|
|
20
|
-
- [Content and layout](./content-and-layout.md): Layout helpers, tables, quotes, code, surfaces, and typography utilities.
|
|
12
|
+
Guides, in order:
|
|
21
13
|
|
|
22
|
-
|
|
14
|
+
1. [Buttons](./buttons.md): the danger zone's destructive action, icon buttons, sizes, link buttons, and disabled states, plus how to load icons.
|
|
15
|
+
2. [Forms](./forms.md): the profile form, with labels, hints, validation errors, an input with an icon or a fixed prefix, a select, and checkbox, radio, and switch toggles.
|
|
16
|
+
3. [Feedback](./feedback.md): what the screen shows while saving and after: a loading button, a success alert, a plan badge, a loading placeholder, and a storage usage bar.
|
|
17
|
+
4. [Tooltips](./tooltips.md): help text beside a form field, how to wire it for keyboard and screen reader users, and where a tooltip can be cut off.
|
|
18
|
+
5. [Theming](./theming.md): light and dark mode, replacing the palette with brand colors, and defining an intent of your own, with the full color and foundation token tables.
|
|
19
|
+
6. [Aesthetics](./aesthetics.md): the six optional looks, what each one changes, and its limits.
|
|
20
|
+
7. [Solo classes](./solo.md): painting an aesthetic onto a component from another library.
|
|
23
21
|
|
|
24
|
-
|
|
22
|
+
Lookup pages:
|
|
23
|
+
|
|
24
|
+
- [Composing](./composing.md): the complete rules for combining intent, presentation, and elevation, every component's defaults, and which axes each component reads.
|
|
25
|
+
- [Customizing](./customizing.md): presentation and material tokens, aesthetic knobs, the six public component variables, the generated palette, and the composition helpers for building your own components.
|
|
26
|
+
- [Content and layout](./content-and-layout.md): every layout helper, the type scale, cards and panels, tables, quotes, code, and keyboard keys.
|
|
27
|
+
|
|
28
|
+
When you finish, [Accessibility](../accessibility.md) collects what the CSS does for you and what your application still owes its users.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Solo classes
|
|
3
|
+
description: Painting an aesthetic onto one element from another library, such as a toast or a dialog, and what a solo class reads and ignores.
|
|
4
|
+
order: 7
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Solo classes
|
|
8
|
+
|
|
9
|
+
Suppose the settings screen shows "Profile saved" in a toast from a notification library, not in this package's alert. Under `.neobrutalism`, every card and button has the thick outline and the hard shadow, and the toast does not: an aesthetic class only sets values that this package's components read, so it changes nothing on an element the package does not style. A solo class paints the aesthetic directly onto the one element that carries it:
|
|
10
|
+
|
|
11
|
+
```html
|
|
12
|
+
<div class="toast neobrutalism-solo success" role="status">Profile saved.</div>
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## The six solo classes
|
|
16
|
+
|
|
17
|
+
Each aesthetic ships its solo class in the same entrypoint, and a solo class needs nothing else loaded:
|
|
18
|
+
|
|
19
|
+
```css
|
|
20
|
+
/* The only stylesheet from this package on the page. */
|
|
21
|
+
@import "@codenhub/styles/aesthetics/glass";
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
```html
|
|
25
|
+
<div class="toast glass-solo">A pane over whatever is behind it.</div>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
| Aesthetic | Solo class | Paints |
|
|
29
|
+
| --------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
30
|
+
| `.glass` | `.glass-solo` | A translucent background, a thin light edge, the blur, a soft two-layer shadow, and the surface corner. With `.glass-liquid`, the liquid pane, drawn on its `::before` and `::after`. |
|
|
31
|
+
| `.neobrutalism` | `.neobrutalism-solo` | A 2px ink edge, square corners, and the hard offset shadow. |
|
|
32
|
+
| `.pixel` | `.pixel-solo` | The stepped outline, the inner ring in place of a border, and the pixel font. |
|
|
33
|
+
| `.chunky-tile` | `.chunky-tile-solo` | The tile corner, a 2px edge, the bar under it, and the rounded font. |
|
|
34
|
+
| `.cyber` | `.cyber-solo` | The surface diagonal (the control diagonal on a button or link), a 1px edge, the glow, and the font. |
|
|
35
|
+
| `.sketch` | `.sketch-solo` | Uneven elliptical corners (a sharper outline on a pane, a looser one on a button or link, and small rounded ones with `.sketch-rounded`), a 1px solid ink line, the 2px offset shadow, and the handwriting font. |
|
|
36
|
+
|
|
37
|
+
Do not put a solo class on this package's own components. A `.card` already draws its fill, edge, and intent, and a solo class would paint a second edge and fill over them. Use the aesthetic class there; it also works on a single element: `<button class="btn pixel">`.
|
|
38
|
+
|
|
39
|
+
## What a solo class reads
|
|
40
|
+
|
|
41
|
+
A solo element takes the same presentation, intent, and elevation classes a `.card` would:
|
|
42
|
+
|
|
43
|
+
```html
|
|
44
|
+
<div class="toast pixel-solo edgeless">No ring</div>
|
|
45
|
+
<div class="toast glass-solo solid success">An opaque green pane</div>
|
|
46
|
+
<div class="toast neobrutalism-solo flat">No offset shadow</div>
|
|
47
|
+
|
|
48
|
+
<section class="soft edged">
|
|
49
|
+
<div class="toast chunky-tile-solo info">Soft and edged from the container, info from itself</div>
|
|
50
|
+
</section>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
| What | Read from |
|
|
54
|
+
| ------------------------------------- | --------------------------------------------------------------------------------------------------- |
|
|
55
|
+
| Fill and edge (`.solid`, `.edged`, …) | The element, or any container: presentation passes down, as it does to components. |
|
|
56
|
+
| Intent (`.success`, …) | The element only, as on components. A `.success` container leaves a solo element inside it neutral. |
|
|
57
|
+
| Elevation (`.flat`, `.raised`, …) | The element only, as on components. It scales the offset shadow, the bar, and sketch's shadow. |
|
|
58
|
+
| The aesthetic around it (`.pixel`, …) | Never. See [What a solo class ignores](#what-a-solo-class-ignores). |
|
|
59
|
+
|
|
60
|
+
With none of those classes, a solo class paints the material alone (edge, corner, depth, outline, blur, font, and press) and leaves the element's own background and text color as they were.
|
|
61
|
+
|
|
62
|
+
- **Only the six built-in intents.** A solo class takes an intent from `.primary`, `.secondary`, `.success`, `.warning`, `.destructive`, and `.info` only. An intent class you defined yourself, as in [Theming → Your own intent](./theming.md#your-own-intent), is not read, and the element is drawn neutral. To give a solo element a custom color, retheme one of the built-in intents on it or a container, as that section describes.
|
|
63
|
+
- **The fill is a layer over the element's own background.** Five of the six paint the fill as an inner shadow and do not set `background`, so a `.soft` solo toast is a tint over whatever the toast already was, and a `.solid` one with a colored intent is opaque. Glass sets its own background, because the translucent background is its material, and mixes the fill over it. A neutral `.solid` is a 20% tint, not the opaque gray a component draws.
|
|
64
|
+
- **The text color assumes the theme.** It is set only where a fill or an intent is asked for, and it is the color the theme uses on the page or on the fill. On an element whose own background does not follow the theme, such as a white toast on a dark page, a `.soft` or `.ghost` intent can put light text on a light background; use `.solid`, or leave the intent off.
|
|
65
|
+
- **There is no hover tint.** A solo element is not known to be clickable, so it does not get the hover color a `.btn` gets.
|
|
66
|
+
- **It reads its aesthetic's knobs and the theme's tokens, with the shipped values as fallbacks.** `--glass-radius-surface`, `--neo-offset`, `--pixel-unit`, `--tile-lift`, `--tile-radius`, `--cyber-cut`, `--cyber-shape`, `--cyber-shape-surface`, `--cyber-glow`, `--cyber-ink`, `--sketch-radius`, `--sketch-radius-surface`, `--sketch-radius-rounded`, `--sketch-radius-surface-rounded`, and the font tokens such as `--font-sketch` all work, set on the element or any ancestor. With the theme loaded, it follows the theme; without it, it renders the shipped look.
|
|
67
|
+
- **Dark values need a color scheme.** Light and dark pairs use `light-dark()`, which follows the element's `color-scheme`. The package's theme sets it; a page without the theme gets the light values.
|
|
68
|
+
- **The classes it reads come from the theme.** `.solid`, `.edgeless`, `.success`, `.flat`, and the rest ship in the base stylesheet and in `@codenhub/styles/theme`. With an aesthetic entrypoint alone on the page, those classes do nothing, and the solo class paints its unclassed look.
|
|
69
|
+
|
|
70
|
+
## What a solo class ignores
|
|
71
|
+
|
|
72
|
+
- **The aesthetic around it.** It reads none of the values an aesthetic class sets, and not `--elevation-color`. A `.glass-solo` inside a `.pixel` region keeps its own corners, and `--ui-radius` or `--ui-border-width` set on it or above it do nothing. Tune it through its knobs.
|
|
73
|
+
- **Its own children.** A solo element is not an aesthetic region. A component inside it keeps the look of the page around it, even with `.glass-liquid` or `.sketch-rounded` beside the solo class. It passes down only what any container does: the solo class's font, and the fill or edge of a presentation class on it, so a `.card` inside a `.glass-solo.solid` pane is solid, as inside any `.solid` container.
|
|
74
|
+
- **Glass's shadow and `.flat`.** `.flat` does not remove the shadow from `.glass-solo`, as it does not under `.glass`.
|
|
75
|
+
|
|
76
|
+
## How it wins and when it moves
|
|
77
|
+
|
|
78
|
+
- **It beats the other library's styles.** The rules are unlayered and one class deep, so they win over a component's layered rules, and over its zero-specificity ones, wherever the two load. An unlayered foreign rule that is more specific, or as specific and later in the page, still wins. The other side of this is that a Tailwind utility on the same element, such as `rounded-none`, loses to the solo class: tune it through its knobs instead.
|
|
79
|
+
- **It presses only an action.** Neobrutalism, chunky tile, and cyber press a `button`, `a[href]`, `[role="button"]`, `summary`, or button-type `input` that is not disabled. Anything else stays put, so a toast does not sink when clicked. Reduced motion removes the movement. Chunky tile's heavier label follows the same rule.
|
|
80
|
+
|
|
81
|
+
## Next
|
|
82
|
+
|
|
83
|
+
The guides end here. [Composing](./composing.md), [Customizing](./customizing.md), and [Content and layout](./content-and-layout.md) are the lookup pages, and [Accessibility](../accessibility.md) lists what the CSS does for your users and what your application still owes them.
|