@carissa-io/theme-default 0.3.9 → 0.3.11
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/DESIGN.md +74 -64
- package/README.md +2 -2
- package/dist/index.css +225 -2
- package/package.json +17 -2
- package/scss/_tokens.scss +1 -1
- package/scss/index.scss +82 -27
package/DESIGN.md
CHANGED
|
@@ -10,7 +10,7 @@ never changes to the components.
|
|
|
10
10
|
|
|
11
11
|
## Principles
|
|
12
12
|
- **Objective clarity:** information is prioritized over decoration.
|
|
13
|
-
- **Mathematical grid:** precise alignment and spacing, square corners.
|
|
13
|
+
- **Mathematical grid:** precise alignment and spacing, square corners. "Square" means the token `$radius: 0`: every component reads that one token (the radio dot is the only round shape, and the date range band stays unrounded so it is unbroken), so the theme is square because the token is 0, and changing the token rounds all of it.
|
|
14
14
|
- **High contrast:** absolute black (`#000`) for primary actions and focus; neutral scales for meta-data.
|
|
15
15
|
|
|
16
16
|
## Palette
|
|
@@ -18,9 +18,9 @@ never changes to the components.
|
|
|
18
18
|
| :--- | :--- |
|
|
19
19
|
| Primary | `#000000` |
|
|
20
20
|
| Surface | `#fafafa` / `#f5f5f5` |
|
|
21
|
-
| Border (fields) | `#
|
|
21
|
+
| Border (fields) | `#666666` (hover and focus: `#000`, focus adds a 1px ring) |
|
|
22
22
|
| Text (body) | `#171717` |
|
|
23
|
-
| Text (meta, placeholder) | `#
|
|
23
|
+
| Text (meta, placeholder) | `#666666` (5.7:1; lighter greys only for disabled states) |
|
|
24
24
|
|
|
25
25
|
The same palette is available as Sass tokens (`$black`, `$muted`, `$surface`, `$error`...) in
|
|
26
26
|
[scss/_tokens.scss](scss/_tokens.scss), the machine-readable palette: apps read them (for example to configure Bootstrap)
|
|
@@ -35,7 +35,7 @@ Both modes ship in the same package; dark is **opt-in per app** with `data-mode`
|
|
|
35
35
|
| :--- | :--- | :--- |
|
|
36
36
|
| `background` | `#ffffff` | `#0a0a0a` |
|
|
37
37
|
| `text` | `#171717` | `#f5f5f5` |
|
|
38
|
-
| `muted` | `#
|
|
38
|
+
| `muted` | `#666666` | `#a3a3a3` |
|
|
39
39
|
| `surface` | `#f5f5f5` | `#171717` |
|
|
40
40
|
| `surface-active` | `#e5e5e5` | `#262626` |
|
|
41
41
|
| `primary` | `#000000` | `#ffffff` |
|
|
@@ -63,8 +63,9 @@ Contrast (WCAG 2.x): text 4.5:1, borders and the focus ring 3:1.
|
|
|
63
63
|
| Pair | Light | Dark |
|
|
64
64
|
| :--- | :--- | :--- |
|
|
65
65
|
| `text` on `background` | 17.93 | 18.16 |
|
|
66
|
-
| `muted` on `background` (labels, placeholders, field borders) |
|
|
67
|
-
| `muted` on `surface` |
|
|
66
|
+
| `muted` on `background` (labels, placeholders, field borders) | 5.74 | 7.85 |
|
|
67
|
+
| `muted` on `surface` | 5.27 | 7.11 |
|
|
68
|
+
| `muted` on `surface-active` | 4.56 | 6.00 |
|
|
68
69
|
| `on-primary` on `primary` | 21.00 | 21.00 |
|
|
69
70
|
| `error` on `background` | 4.53 | 7.16 |
|
|
70
71
|
| `focus` on `background` | 21.00 | 19.80 |
|
|
@@ -76,8 +77,8 @@ Contrast (WCAG 2.x): text 4.5:1, borders and the focus ring 3:1.
|
|
|
76
77
|
|
|
77
78
|
The light `error` on `surface` (4.15) is below 4.5 for text, so the Alert never sets text in the status color (only the icon and the accent border, which need 3:1).
|
|
78
79
|
|
|
79
|
-
`muted`
|
|
80
|
-
WCAG but are listed in the backlog for a contrast review. Known gap in dark: the 0-width listbox option separator keeps the component default
|
|
80
|
+
Every `muted` text pairing passes AA in both modes (a test asserts it): the light muted was `#737373`, which gave 4.35 on `surface` and 3.76 on
|
|
81
|
+
`surface-active`, so it is now `#666666` (5.74 / 5.27 / 4.56). The disabled states are exempt from WCAG but are listed in the backlog for a contrast review. Known gap in dark: the 0-width listbox option separator keeps the component default
|
|
81
82
|
(`#dee2e6`); it draws nothing today.
|
|
82
83
|
|
|
83
84
|
## Typography
|
|
@@ -114,7 +115,7 @@ Field text is 1rem (16px, which also avoids the zoom-on-focus of mobile browsers
|
|
|
114
115
|
Three variants from [components-button](components/components-button), all square, 44px tall, with the same uppercase,
|
|
115
116
|
bold, tracked 11px label as the field labels and 200ms color transitions.
|
|
116
117
|
- **Primary:** black background, white text; hover `#262626`, active `#404040`.
|
|
117
|
-
- **Secondary:** white background, 1px `#
|
|
118
|
+
- **Secondary:** white background, 1px `#666666` border; on hover the border turns black and the background becomes `#e5e5e5` (`--c-surface-active`), so the state reads without relying on the border alone.
|
|
118
119
|
- **Ghost:** transparent; a `#f5f5f5` surface appears on hover.
|
|
119
120
|
- **Disabled:** `#a3a3a3` text on a `#f5f5f5` surface (primary), or a lighter border (secondary, ghost); no hover.
|
|
120
121
|
- **Focus:** keyboard focus (`:focus-visible`) follows the general rule below: secondary and ghost thicken their border to
|
|
@@ -123,7 +124,7 @@ bold, tracked 11px label as the field labels and 200ms color transitions.
|
|
|
123
124
|
## Checkbox
|
|
124
125
|
From [components-checkbox](components/components-checkbox): the whole row (box and label) is the click target and is at
|
|
125
126
|
least 44px tall. The label is body text (1rem, `#171717`), not the uppercase field-label style.
|
|
126
|
-
- **Box:** 20px square, square corners, 1px `#
|
|
127
|
+
- **Box:** 20px square, square corners, 1px `#666666` border; the border turns black on hover.
|
|
127
128
|
- **Checked:** black background with a white Lucide `check` mark.
|
|
128
129
|
- **Disabled:** `#a3a3a3` label and mark on a `#f5f5f5` box with a `#d4d4d4` border; no hover.
|
|
129
130
|
- **Error:** `#dc3545`, 13px, under the row; the box border turns red too. The built-in error shows after the first
|
|
@@ -133,17 +134,17 @@ least 44px tall. The label is body text (1rem, `#171717`), not the uppercase fie
|
|
|
133
134
|
|
|
134
135
|
## Switch
|
|
135
136
|
From [components-switch](components/components-switch), a checkbox with `role="switch"`, same row, label and error.
|
|
136
|
-
- **Track:** 40 x 20px, square, white with a 1px `#
|
|
137
|
+
- **Track:** 40 x 20px, square, white with a 1px `#666666` border (black on hover); a `#666666` square thumb.
|
|
137
138
|
- **On:** black track, white thumb; the thumb slides in 200ms, like the other color transitions.
|
|
138
139
|
- **Disabled:** `#f5f5f5` track with a `#d4d4d4` border and an `#a3a3a3` thumb.
|
|
139
140
|
- **Focus:** an off track thickens its border to 2px; an on (black) track draws a 1px black ring offset by 2px.
|
|
140
141
|
|
|
141
142
|
## Radio group
|
|
142
143
|
From [components-radio-group](components/components-radio-group): a fieldset whose legend uses the field-label style
|
|
143
|
-
(11px, bold, uppercase, tracked, `#
|
|
144
|
+
(11px, bold, uppercase, tracked, `#666666`). Each option row (dot and label) is the click target and is at least 44px
|
|
144
145
|
tall; the label is body text (1rem, `#171717`).
|
|
145
146
|
- **Dot:** 20px circle (the one round shape in the theme: a radio is a circle, so its radius is not the square `$radius`),
|
|
146
|
-
1px `#
|
|
147
|
+
1px `#666666` border; the border turns black on hover.
|
|
147
148
|
- **Checked:** black border with a 10px black inner dot on white.
|
|
148
149
|
- **Disabled:** `#a3a3a3` label on a `#f5f5f5` dot with a `#d4d4d4` border; no hover. A single option can be disabled too.
|
|
149
150
|
- **Error:** `#dc3545`, 13px, under the options; the dots get a red border. The built-in error shows after the first
|
|
@@ -153,7 +154,7 @@ tall; the label is body text (1rem, `#171717`).
|
|
|
153
154
|
|
|
154
155
|
## Textarea
|
|
155
156
|
From [components-textarea](components/components-textarea), which is the input with `multiline`: it uses exactly the
|
|
156
|
-
input's look (notched uppercase label, 1px `#
|
|
157
|
+
input's look (notched uppercase label, 1px `#666666` border that turns black on hover and focus, 1px black focus ring,
|
|
157
158
|
`#dc3545` error). Only the control differs:
|
|
158
159
|
- **Height:** at least 6rem (about three lines of 16px text) and resizable vertically only, so it never breaks the grid;
|
|
159
160
|
`rows` sets the initial height.
|
|
@@ -161,9 +162,9 @@ input's look (notched uppercase label, 1px `#737373` border that turns black on
|
|
|
161
162
|
|
|
162
163
|
## Slider
|
|
163
164
|
From [components-slider](components/components-slider), a native range input; the row is at least 44px tall. The label
|
|
164
|
-
uses the field-label style (11px, bold, uppercase, tracked, `#
|
|
165
|
+
uses the field-label style (11px, bold, uppercase, tracked, `#666666`); the optional live value, on the same line at
|
|
165
166
|
the right, is body text (1rem, `#171717`).
|
|
166
|
-
- **Track:** a 2px `#
|
|
167
|
+
- **Track:** a 2px `#666666` line, square; the part before the thumb is black.
|
|
167
168
|
- **Thumb:** 20px black square with a 1px white border (so it stays distinct where it crosses the track); `#262626` on
|
|
168
169
|
hover, `#404040` while dragging.
|
|
169
170
|
- **Disabled:** `#a3a3a3` label, thumb and fill on a `#d4d4d4` track; no hover.
|
|
@@ -171,7 +172,7 @@ the right, is body text (1rem, `#171717`).
|
|
|
171
172
|
|
|
172
173
|
## Popover
|
|
173
174
|
From [components-popover](components/components-popover), the floating panel behind the select, combobox and date picker:
|
|
174
|
-
white, a 1px `#
|
|
175
|
+
white, a 1px `#666666` border, square corners and no shadow (flat, like the rest of the theme), 4px below its anchor.
|
|
175
176
|
It fades in over 200ms and opens above the anchor when there is no room below. It has no padding of its own: the
|
|
176
177
|
content (a list, a calendar) brings its spacing.
|
|
177
178
|
|
|
@@ -181,32 +182,32 @@ least 44px tall, body text (1rem, `#171717`) with 0.75rem of horizontal padding.
|
|
|
181
182
|
- **Active** (hover or keyboard cursor): `#f5f5f5` surface.
|
|
182
183
|
- **Selected:** bold text with a 2px black bar on the inline-start edge.
|
|
183
184
|
- **Disabled:** `#a3a3a3`, no hover.
|
|
184
|
-
- **Empty:** a `#
|
|
185
|
+
- **Empty:** a `#666666` message with 0.75rem of padding.
|
|
185
186
|
- **Height:** at most 15rem; longer lists scroll.
|
|
186
187
|
|
|
187
188
|
## Select
|
|
188
189
|
From [components-select](components/components-select): a custom list, so it looks the same in every browser. The closed
|
|
189
|
-
field is the Input (notched uppercase label, 1px `#
|
|
190
|
-
as body text, and the placeholder is `#
|
|
190
|
+
field is the Input (notched uppercase label, 1px `#666666` border, black on hover and focus, 44px tall); the value reads
|
|
191
|
+
as body text, and the placeholder is `#666666` like the input placeholder. A 16px `#666666` chevron sits on the right
|
|
191
192
|
and turns black; when the list is open it rotates 180 degrees over 200ms and the border stays black. The open panel is
|
|
192
193
|
the Popover and the options are the Listbox, as wide as the field. Errors, required marker and disabled look are the
|
|
193
194
|
Input's.
|
|
194
195
|
|
|
195
196
|
## Combobox
|
|
196
197
|
From [components-combobox](components/components-combobox): the Select field with a text input in place of the button, so
|
|
197
|
-
the user can type to filter the list. Same Input look (notched uppercase label, 1px `#
|
|
198
|
-
focus, 44px tall), same 16px `#
|
|
199
|
-
is body text (`#171717`) and the placeholder `#
|
|
198
|
+
the user can type to filter the list. Same Input look (notched uppercase label, 1px `#666666` border, black on hover and
|
|
199
|
+
focus, 44px tall), same 16px `#666666` chevron that turns black and rotates 180 degrees when the list is open. The text
|
|
200
|
+
is body text (`#171717`) and the placeholder `#666666`. A press anywhere in the box focuses the input (the chevron is
|
|
200
201
|
decorative, not a button); the list opens when typing or with the arrow keys. The panel is the Popover and the options
|
|
201
202
|
the Listbox, as wide as the field; a message such as "No results" uses the Listbox empty style. Errors, required marker
|
|
202
203
|
and disabled look are the Input's.
|
|
203
204
|
|
|
204
205
|
## Upload
|
|
205
206
|
From [components-upload](components/components-upload): the Input field turned into a dropzone. The box keeps the
|
|
206
|
-
notched uppercase label and the 1px `#
|
|
207
|
-
border is black and the background `#f5f5f5`. The zone is at least 5.5rem tall and centers its content as muted (`#
|
|
207
|
+
notched uppercase label and the 1px `#666666` border but dashed, black on hover; while files are dragged over it the
|
|
208
|
+
border is black and the background `#f5f5f5`. The zone is at least 5.5rem tall and centers its content as muted (`#666666`)
|
|
208
209
|
body text, and the whole box is the click target. Chosen files are listed below the zone as 44px rows split by a 1px
|
|
209
|
-
`#e5e5e5` line: the name in body text with an ellipsis, and a 44px square remove button (a multiplication sign, `#
|
|
210
|
+
`#e5e5e5` line: the name in body text with an ellipsis, and a 44px square remove button (a multiplication sign, `#666666`,
|
|
210
211
|
black on hover, 1px black focus ring). The focus ring of the box is the Input's. Errors, required marker and disabled look
|
|
211
212
|
(`#a3a3a3` on `#f5f5f5`) are the Input's.
|
|
212
213
|
|
|
@@ -214,7 +215,7 @@ black on hover, 1px black focus ring). The focus ring of the box is the Input's.
|
|
|
214
215
|
From [components-calendar](components/components-calendar): a standalone month grid (the date picker shows it inside the
|
|
215
216
|
Popover, which draws the only border). It has no outer border. The header is two 44px navigation buttons (muted
|
|
216
217
|
chevrons that turn black, 1px black focus ring drawn inside) around the month and year in the label style (11px, bold,
|
|
217
|
-
uppercase, `0.1em` tracking, `#
|
|
218
|
+
uppercase, `0.1em` tracking, `#666666`); the weekday row uses the same style. Days are 44px squares in body text
|
|
218
219
|
(`#171717`) with square corners and a `#f5f5f5` hover. The selected day is a black square with white text; today is a
|
|
219
220
|
1px black border, drawn inside the square so nothing shifts. Days outside `min..max` are `#a3a3a3` with no hover, and
|
|
220
221
|
the days of the neighbor months are left empty. The keyboard focus ring is 1px black, inset. The grid always shows six
|
|
@@ -222,20 +223,20 @@ weeks so the height never changes between months.
|
|
|
222
223
|
|
|
223
224
|
## Date picker
|
|
224
225
|
From [components-date-picker](components/components-date-picker): the Select field with a calendar in the panel. The closed
|
|
225
|
-
field is the Input (notched uppercase label, 1px `#
|
|
226
|
-
reads as body text (for example "Oct 14, 2026") and the placeholder is `#
|
|
226
|
+
field is the Input (notched uppercase label, 1px `#666666` border, black on hover and focus, 44px tall); the chosen date
|
|
227
|
+
reads as body text (for example "Oct 14, 2026") and the placeholder is `#666666`. A 16px `#666666` calendar icon sits on the
|
|
227
228
|
right and turns black on hover and while open; it does not rotate, and the border stays black while open. The open panel
|
|
228
|
-
is the Popover (1px `#
|
|
229
|
+
is the Popover (1px `#666666` border, no shadow) with 0.5rem of padding around the Calendar, as wide as the calendar
|
|
229
230
|
needs, not as the field. Errors, required marker and disabled look are the Input's.
|
|
230
231
|
|
|
231
232
|
## Search
|
|
232
233
|
From [components-search](components/components-search): the Input of type search with two inline parts built on the input's
|
|
233
|
-
`start` and `end` slots. The field is the Input's (notched uppercase label, 1px `#
|
|
234
|
-
44px tall; the keyboard focus rule below applies). A 20px `#
|
|
235
|
-
field has the focus. The clear button appears on the right only while there is text: a 16px `#
|
|
234
|
+
`start` and `end` slots. The field is the Input's (notched uppercase label, 1px `#666666` border, black on hover and focus,
|
|
235
|
+
44px tall; the keyboard focus rule below applies). A 20px `#666666` magnifier icon sits on the left and turns black while the
|
|
236
|
+
field has the focus. The clear button appears on the right only while there is text: a 16px `#666666` cross in the Input's
|
|
236
237
|
44px side-button box that turns black on hover; the browser's own clear button is hidden so the look is the same everywhere.
|
|
237
238
|
Errors, required marker and disabled look are the Input's. The Input and Textarea accept `start` and `end` content (a prefix
|
|
238
|
-
icon, a unit) in the same muted color (`#
|
|
239
|
+
icon, a unit) in the same muted color (`#666666`) with `0.5rem` between the content and the text.
|
|
239
240
|
|
|
240
241
|
## Card
|
|
241
242
|
From [components-card](components/components-card): `Card` with `CardHeader`, `CardBody` and `CardFooter`; the title and description are the Typography
|
|
@@ -275,7 +276,7 @@ placements. The look of each toast is the Alert's (see above), so its colors, ro
|
|
|
275
276
|
only the fade stays. The region is in the page, not in the browser's top layer, so a toast shown while a modal is open sits behind the modal's backdrop.
|
|
276
277
|
|
|
277
278
|
## Divider
|
|
278
|
-
From [components-divider](components/components-divider): `Divider`, a 1px line in `--c-muted` (the edge of the cards and fields:
|
|
279
|
+
From [components-divider](components/components-divider): `Divider`, a 1px line in `--c-muted` (the edge of the cards and fields: 5.74:1 on the background in light, 7.85:1 in dark),
|
|
279
280
|
1rem of space around it. With a label the text is the small `--c-muted` text (0.875rem, same contrast) with 0.75rem between it and each line. Horizontal is an `hr`, vertical and labelled
|
|
280
281
|
ones are `role="separator"`.
|
|
281
282
|
|
|
@@ -283,7 +284,7 @@ ones are `role="separator"`.
|
|
|
283
284
|
From [components-badge](components/components-badge): `Badge` in six variants and two sizes (`md` 0.75rem, `sm` 0.6875rem, bold), square like the rest, plus a `dot`. The variants are **tinted
|
|
284
285
|
like the Alert**: 12% of the role color (`--c-primary`, `--c-success`, `--c-warning`, `--c-error`, `--c-info`) over `--c-background` with `color-mix`, a 1px border at 35% of the same color.
|
|
285
286
|
**The text is always `--c-text`**, never the status color: it is 13.6:1 or more on every tint in both modes (light 13.63 to 15.32, dark 13.63 to 15.87), where the raw light `error` on its own tint would
|
|
286
|
-
fail. Neutral is `--c-surface` with a `--c-muted` border (text 16.44:1). The **dot** carries the role color (`--c-muted` for neutral) and is 3:1 or more as a graphic on its tint in both modes: in light 3.81 (error), 4.21 (warning), 4.27 (success), 5.56 (info), 15.97 (primary) and
|
|
287
|
+
fail. Neutral is `--c-surface` with a `--c-muted` border (text 16.44:1). The **dot** carries the role color (`--c-muted` for neutral) and is 3:1 or more as a graphic on its tint in both modes: in light 3.81 (error), 4.21 (warning), 4.27 (success), 5.56 (info), 15.97 (primary) and 5.27 (neutral); in dark 6.25 or more. A dot has no text, so the caller gives it `aria-label`.
|
|
287
288
|
|
|
288
289
|
## Tag
|
|
289
290
|
From [components-tag](components/components-tag): `Tag`, a chip with the same six tints, the same text rule (`--c-text`, same ratios) and square corners as the Badge, bold, 0.875rem (`md`) or 0.75rem (`sm`). A removable tag is
|
|
@@ -291,7 +292,7 @@ one tab stop and takes the theme focus ring (1px `--c-focus`, offset 2px). The r
|
|
|
291
292
|
|
|
292
293
|
## Link
|
|
293
294
|
From [components-link](components/components-link): `Link` in `default`, `subtle` and `inline`. The default is `--c-primary` (black in light, white in dark: 21:1 and 19.8:1 on the background), bold, **always underlined**: a black link
|
|
294
|
-
beside near-black text is told apart by the underline alone, so there is no un-underlined default. Hover is `--c-primary-hover`. `subtle` is `--c-muted` (
|
|
295
|
+
beside near-black text is told apart by the underline alone, so there is no un-underlined default. Hover is `--c-primary-hover`. `subtle` is `--c-muted` (5.74:1 light, 7.85:1 dark), `--c-text` on hover. Focus is the theme ring
|
|
295
296
|
(1px `--c-focus`, offset 2px). Disabled is `--c-disabled-text` at full opacity (exempt from contrast, as the other disabled states).
|
|
296
297
|
|
|
297
298
|
## Avatar
|
|
@@ -315,42 +316,42 @@ or focus, stays open while the pointer is over it and closes on `Escape`; the bu
|
|
|
315
316
|
## Prose
|
|
316
317
|
From [components-prose](components/components-prose): `Prose`, raw HTML content (markdown, a CMS, an article) with the same hierarchy as `Heading` and `Text`. Body text is `--c-text` at 1rem and a 1.6 line height, 65ch wide (small and
|
|
317
318
|
large scale the text and the headings by 0.875 and 1.125). Headings use the type scale tokens: `h1` and `h2` black (900), `h3` to `h6` bold, with the line heights of the typography block. Links are `--c-primary` and always underlined
|
|
318
|
-
(21:1 light, 19.8:1 dark), `--c-primary-hover` on hover (15.13:1 and 15.72:1). The quote edge, the `hr` and the table borders are `--c-muted` (
|
|
319
|
+
(21:1 light, 19.8:1 dark), `--c-primary-hover` on hover (15.13:1 and 15.72:1). The quote edge, the `hr` and the table borders are `--c-muted` (5.74:1 light, 7.85:1 dark, above the 3:1 of a graphic); the quote text and the figure
|
|
319
320
|
caption are `--c-muted` on the page background too. Code, `pre`, `kbd` and the table head sit on `--c-surface` with `--c-text` (16.44:1 in both modes); `kbd` has a `--c-muted` edge. Everything is square (`$radius`), code uses `$font-family-mono`.
|
|
320
|
-
`--c-muted`
|
|
321
|
+
`--c-muted` on `--c-surface` is 5.27:1 in light (AA), though the code and table text stay `--c-text`.
|
|
321
322
|
|
|
322
323
|
## Tabs
|
|
323
|
-
From [components-tabs](components/components-tabs): `Tabs`, `TabList`, `Tab` and `TabPanel`. A 1px `--c-muted` line runs under the list (
|
|
324
|
-
bold `--c-text` (17.93:1 / 18.16:1). The other tabs are bold `--c-muted` (
|
|
324
|
+
From [components-tabs](components/components-tabs): `Tabs`, `TabList`, `Tab` and `TabPanel`. A 1px `--c-muted` line runs under the list (5.74:1 light, 7.85:1 dark) and the selected tab has a 2px `--c-primary` indicator on it (21:1 light, 19.8:1 dark, well above the 3:1 of a graphic) with
|
|
325
|
+
bold `--c-text` (17.93:1 / 18.16:1). The other tabs are bold `--c-muted` (5.74:1 / 7.85:1) and turn `--c-text` on a `--c-surface` hover (16.44:1 in both modes); `--c-muted` on `--c-surface` is 5.27:1 in light (AA), and the hover still changes the text color too.
|
|
325
326
|
Square, 0.875rem, 1.25rem by 0.625rem of padding. The indicator is a bottom edge (horizontal) or an inline end edge (vertical). Keyboard focus is the theme's 1px `--c-focus` ring, drawn inside the tab so the scrolling list does not clip it.
|
|
326
327
|
|
|
327
328
|
## Accordion
|
|
328
|
-
From [components-accordion](components/components-accordion): `Accordion` and `AccordionItem`. The box and the rules between the items are 1px `--c-muted` (
|
|
329
|
+
From [components-accordion](components/components-accordion): `Accordion` and `AccordionItem`. The box and the rules between the items are 1px `--c-muted` (5.74:1 / 7.85:1); each header is a full-width bold `--c-text` button (17.93:1 / 18.16:1) with a `--c-surface` hover (16.44:1) and a chevron
|
|
329
330
|
that follows the text color and turns over when the item opens. 1.25rem of inline padding, 0.875rem of block padding on the header and 1rem on the content, square. Focus is the theme's 1px `--c-focus` ring, inside the header. The chevron is CSS, not an icon.
|
|
330
331
|
|
|
331
332
|
## Breadcrumb
|
|
332
|
-
From [components-breadcrumb](components/components-breadcrumb): `Breadcrumb` and `BreadcrumbItem`. Links and separators are `--c-muted` (
|
|
333
|
+
From [components-breadcrumb](components/components-breadcrumb): `Breadcrumb` and `BreadcrumbItem`. Links and separators are `--c-muted` (5.74:1 on the page in light, 7.85:1 in dark), links gain an underline and turn `--c-text` on hover (17.93:1 / 18.16:1), and the current page is bold `--c-text`
|
|
333
334
|
and not a link. 0.875rem text. Focus is the theme's 1px `--c-focus` ring, offset 2px. The separator is generated content, so screen readers do not read it.
|
|
334
335
|
|
|
335
336
|
## Pagination
|
|
336
337
|
From [components-pagination](components/components-pagination): `Pagination`. The controls follow the secondary button: `--c-background` with a 1px `--c-muted` border, bold `--c-text` (17.93:1 / 18.16:1), `--c-surface-active` on hover (14.23:1 / 13.88:1),
|
|
337
|
-
square, 44px minimum (the theme's touch target). The current page is filled: `--c-on-primary` on `--c-primary`, 21:1 in both modes. The ellipsis is `--c-muted` (
|
|
338
|
+
square, 44px minimum (the theme's touch target). The current page is filled: `--c-on-primary` on `--c-primary`, 21:1 in both modes. The ellipsis is `--c-muted` (5.74:1 / 7.85:1) and previous and next, drawn as CSS chevrons, are disabled
|
|
338
339
|
at the ends (half opacity). Focus is the theme's 1px `--c-focus` ring, offset 2px.
|
|
339
340
|
|
|
340
341
|
## Stepper
|
|
341
342
|
From [components-stepper](components/components-stepper): `Stepper` and `Step`. The status is carried by the marker shape and the hidden status text, never by color alone: a done step is a filled `--c-primary` marker with a `--c-on-primary` check (21:1), the current one an outlined 2px
|
|
342
343
|
`--c-primary` marker on `--c-background` with its number in `--c-text` (17.93:1 / 18.16:1), an upcoming one a `--c-surface-active` marker with its number in `--c-text` (14.23:1 / 13.88:1), and an error one a `--c-error` marker with a `--c-on-primary` mark
|
|
343
|
-
(4.53:1 light, 7.59:1 dark) and a `--c-error` title (4.53:1 / 7.16:1). Titles are bold `--c-text`; upcoming titles and the descriptions are `--c-muted` (
|
|
344
|
+
(4.53:1 light, 7.59:1 dark) and a `--c-error` title (4.53:1 / 7.16:1). Titles are bold `--c-text`; upcoming titles and the descriptions are `--c-muted` (5.74:1 / 7.85:1). The connectors are 2px `--c-muted` lines (5.74:1 / 7.85:1, above 3:1)
|
|
344
345
|
and `--c-primary` once the step is done. Clickable (completed) steps are buttons with the theme's 1px `--c-focus` ring, offset 2px.
|
|
345
346
|
|
|
346
347
|
## Sidebar
|
|
347
|
-
From [components-sidebar](components/components-sidebar): `Sidebar` and its parts. A `--c-surface` column (16rem, 4.5rem collapsed) with a 1px `--c-muted` edge (
|
|
348
|
+
From [components-sidebar](components/components-sidebar): `Sidebar` and its parts. A `--c-surface` column (16rem, 4.5rem collapsed) with a 1px `--c-muted` edge (5.74:1 light, 7.85:1 dark). Items are bold `--c-text` (16.44:1 on the surface in both modes), 0.875rem with 0.625rem of block padding, with a `--c-surface-active`
|
|
348
349
|
hover (14.23:1 light, 13.88:1 dark). The current page is filled: `--c-on-primary` on `--c-primary`, 21:1 in both modes, so it is told apart by shape and weight of fill, not by hue alone. Section titles use the label style (small, bold, uppercase, tracking) in `--c-text` and not
|
|
349
|
-
`--c-muted`, which is
|
|
350
|
+
`--c-muted`, which is 5.27:1 on the surface in light. A disabled item is half opacity and not a link. The toggle is a 44px square, `--c-text` on a `--c-surface-active` hover. Square; focus is the theme's 1px `--c-focus` ring, inside the item.
|
|
350
351
|
When collapsed the labels stay in the accessibility tree.
|
|
351
352
|
|
|
352
353
|
## Navbar
|
|
353
|
-
From [components-navbar](components/components-navbar): `Navbar` and its parts. A `--c-background` bar with a 1px `--c-muted` bottom edge. The brand is bold `--c-text` (17.93:1 light, 18.16:1 dark). Items read like the tabs: bold `--c-muted` (
|
|
354
|
+
From [components-navbar](components/components-navbar): `Navbar` and its parts. A `--c-background` bar with a 1px `--c-muted` bottom edge. The brand is bold `--c-text` (17.93:1 light, 18.16:1 dark). Items read like the tabs: bold `--c-muted` (5.74:1 / 7.85:1), `--c-text` on a `--c-surface` hover (16.44:1),
|
|
354
355
|
and `--c-text` for the current page (`aria-current="page"`). The content collapses behind a 44px toggle below 48rem (the component's Sass breakpoint, a media query, no JS). Square; focus is the theme's 1px `--c-focus` ring, inside the item.
|
|
355
356
|
|
|
356
357
|
## Drawer
|
|
@@ -360,62 +361,71 @@ The panel slides in over `$transition-duration`; with reduced motion it just app
|
|
|
360
361
|
|
|
361
362
|
## Menu
|
|
362
363
|
From [components-menu](components/components-menu): `Menu`, `MenuItem`, `MenuSeparator` and `MenuLabel`. The panel is the Popover's (`--c-background`, a 1px `--c-muted` border, flat). Items are `--c-text` with 0.625rem of block and 0.75rem of side padding, and hover and keyboard focus share a `--c-surface-active`
|
|
363
|
-
background (14.23:1 light, 13.88:1 dark) plus the theme's 1px `--c-focus` ring. Labels are small `--c-muted` text (
|
|
364
|
+
background (14.23:1 light, 13.88:1 dark) plus the theme's 1px `--c-focus` ring. Labels are small `--c-muted` text (5.74:1 / 7.85:1 on the panel), the separator a 1px `--c-muted` line, a disabled item is half opacity. Square. The trigger is the app's own button, so its look is not part of the theme.
|
|
364
365
|
|
|
365
366
|
## Table
|
|
366
367
|
From [components-table](components/components-table): `Table` and its parts. The header is `--c-surface` with bold `--c-text` (16.4:1 light, 16.4:1 dark), the rows are divided by 1px `--c-muted` lines, cells have 1rem by 0.75rem of padding (0.75rem by 0.375rem when dense) at the small size. **Row hover** is `--c-surface-active` (14.2:1 / 13.9:1 for `--c-text`), not `--c-surface`, so it still shows on a striped row (stripes are `--c-surface`). The **selected row** is a 12% tint of `--c-primary` over `--c-background`
|
|
367
|
-
(`color-mix`, light `#e0e0e0`, dark `#272727`), so `--c-text` is 13.6:1 / 13.7:1 on it and the tint follows the mode with no extra role. The **sticky header** background is `--c-surface`, a custom property and therefore opaque in both modes (rows never show through, and dark gets its own value; the component's neutral default is a literal white and must not be used in dark). The caption is `--c-muted` (
|
|
368
|
+
(`color-mix`, light `#e0e0e0`, dark `#272727`), so `--c-text` is 13.6:1 / 13.7:1 on it and the tint follows the mode with no extra role. The **sticky header** background is `--c-surface`, a custom property and therefore opaque in both modes (rows never show through, and dark gets its own value; the component's neutral default is a literal white and must not be used in dark). The caption is `--c-muted` (5.74:1 / 7.85:1 on the background). The sort arrows are CSS glyphs, so the direction is a shape and not only an opacity. Square, the theme's 1px `--c-focus` ring inside the cell and the scroll region.
|
|
368
369
|
|
|
369
370
|
## List
|
|
370
|
-
From [components-list](components/components-list): `List` and `ListItem`. Rows sit on the page background, divided (or bordered) by 1px `--c-muted` lines, with 1rem by 0.75rem of padding. A link or button row highlights with `--c-surface-active` on hover (`--c-text` 14.2:1 / 13.9:1) and the current item (`aria-current`) takes the same 12% `--c-primary` tint as a selected table row (13.6:1 / 13.7:1). The secondary text is `--c-text` at the small size on purpose: `--c-muted` is
|
|
371
|
+
From [components-list](components/components-list): `List` and `ListItem`. Rows sit on the page background, divided (or bordered) by 1px `--c-muted` lines, with 1rem by 0.75rem of padding. A link or button row highlights with `--c-surface-active` on hover (`--c-text` 14.2:1 / 13.9:1) and the current item (`aria-current`) takes the same 12% `--c-primary` tint as a selected table row (13.6:1 / 13.7:1). The secondary text is `--c-text` at the small size on purpose: `--c-muted` is 5.74:1 on the background but only 5.27:1 on `--c-surface` and 3.76:1 on `--c-surface-active`, both short of AA for text. Square, the theme's 1px `--c-focus` ring inside the row.
|
|
371
372
|
|
|
372
373
|
## Description list
|
|
373
|
-
From [components-description-list](components/components-description-list): `DescriptionList`, `DescriptionTerm`, `DescriptionDetail` and `DescriptionItem`. The term is a small bold `--c-muted` label (
|
|
374
|
+
From [components-description-list](components/components-description-list): `DescriptionList`, `DescriptionTerm`, `DescriptionDetail` and `DescriptionItem`. The term is a small bold `--c-muted` label (5.74:1 light, 7.85:1 dark on the background; do not put a description list on `--c-surface` in light, where it is 5.27:1) and the detail is `--c-text`. No fills or borders: the layout (vertical, horizontal, grid) is the only thing it sets, with 2rem between columns and 1rem between pairs.
|
|
374
375
|
|
|
375
376
|
## Stat
|
|
376
|
-
From [components-stat](components/components-stat): `Stat`. A card-like block on `--c-background` with a 1px `--c-muted` border (the Card's outlined look), square, 1.25rem by 1.5rem of padding. It is not on `--c-surface` because the delta colors are checked against the background: **delta up is `--c-success`** (5.02:1 light, 11.36:1 dark), **delta down is `--c-error`** (4.53:1 light, 7.16:1 dark) and **flat is `--c-muted`** (
|
|
377
|
+
From [components-stat](components/components-stat): `Stat`. A card-like block on `--c-background` with a 1px `--c-muted` border (the Card's outlined look), square, 1.25rem by 1.5rem of padding. It is not on `--c-surface` because the delta colors are checked against the background: **delta up is `--c-success`** (5.02:1 light, 11.36:1 dark), **delta down is `--c-error`** (4.53:1 light, 7.16:1 dark) and **flat is `--c-muted`** (5.74:1 / 7.85:1). On `--c-surface` the light `--c-error` would be 4.15:1, short of AA. The value is `--c-text` at the h1 size; the label and description are `--c-muted`. Color is never the only signal: the arrow glyph (up, down, flat) and the `delta_label` text for screen readers say the same. Whether "down" is good news (churn, cost) is the app's call: the color only follows the direction.
|
|
377
378
|
|
|
378
379
|
## Empty state
|
|
379
|
-
From [components-empty-state](components/components-empty-state): `EmptyState`. A centred block on the page background, with 3rem by 1.5rem of padding at the default size and 1rem between its parts. The icon is `--c-muted` (
|
|
380
|
+
From [components-empty-state](components/components-empty-state): `EmptyState`. A centred block on the page background, with 3rem by 1.5rem of padding at the default size and 1rem between its parts. The icon is `--c-muted` (5.74:1 light, 7.85:1 dark, above the 3:1 non-text minimum), the title is `--c-text`, bold, at the h3 size (h4 small, h2 large) and the description is `--c-muted` at the body size (5.74:1 / 7.85:1 on the background; on `--c-surface` it would be 5.27:1 in light, short of AA, so do not put an empty state on a surface panel without moving the description to `--c-text`). The actions are the app's own buttons. No fills, borders or radius.
|
|
380
381
|
|
|
381
382
|
## Timeline
|
|
382
|
-
From [components-timeline](components/components-timeline): `Timeline` and `TimelineItem`. The connector is a 1px `--c-muted` line. A **default** marker is a `--c-surface-active` dot with a 2px `--c-muted` ring; **success, warning, error and info** are solid dots in `--c-success`, `--c-warning`, `--c-error` and `--c-info` (light 5.02, 4.92, 4.53 and 6.70:1 on the background, dark 11.36, 11.86, 7.16 and 7.79:1: all above the 3:1 non-text minimum); the **current** step is a hollow `--c-primary` ring (21:1 / 19.8:1), a different shape from the dots, and the item carries `aria-current="step"`. An **icon marker** keeps a `--c-background` fill and takes the status as its 2px ring, so the `--c-text` icon is 17.93:1 / 18.16:1 in every status (a colored fill would not give one icon color AA in both modes). The status is also the visually hidden `status_label`, so colour is never the only signal. The title is bold `--c-text`, the time is `--c-muted` at the small size (
|
|
383
|
+
From [components-timeline](components/components-timeline): `Timeline` and `TimelineItem`. The connector is a 1px `--c-muted` line. A **default** marker is a `--c-surface-active` dot with a 2px `--c-muted` ring; **success, warning, error and info** are solid dots in `--c-success`, `--c-warning`, `--c-error` and `--c-info` (light 5.02, 4.92, 4.53 and 6.70:1 on the background, dark 11.36, 11.86, 7.16 and 7.79:1: all above the 3:1 non-text minimum); the **current** step is a hollow `--c-primary` ring (21:1 / 19.8:1), a different shape from the dots, and the item carries `aria-current="step"`. An **icon marker** keeps a `--c-background` fill and takes the status as its 2px ring, so the `--c-text` icon is 17.93:1 / 18.16:1 in every status (a colored fill would not give one icon color AA in both modes). The status is also the visually hidden `status_label`, so colour is never the only signal. The title is bold `--c-text`, the time is `--c-muted` at the small size (5.74:1 / 7.85:1 on the background) and the description is `--c-text`. Keep a timeline on `--c-background`. Deviation from the first plan: the default dot is outlined with `--c-muted` instead of being a bare `--c-surface-active` dot, which is 1.2:1 on white.
|
|
383
384
|
|
|
384
385
|
## Tree
|
|
385
386
|
From [components-tree](components/components-tree): `Tree` and `TreeItem`. Rows are 0.5rem by 0.75rem on the page background, 1.5rem of indent per level. **Hover** is `--c-surface-active` (`--c-text` 14.23:1 light, 13.88:1 dark); the **selected row** is the same 12% tint of `--c-primary` over `--c-background` as a selected table row (`color-mix`, light `#e0e0e0`, dark `#272727`) with `--c-text` (13.58:1 / 13.70:1), so a selected row still reads when hovered. The **chevron** is the component's CSS border chevron on `.c-tree__toggle` (parents only; right when closed, down when open), colored `--c-muted`: 3.76:1 on the hover and 3.59:1 on the selected tint in light, 6.00:1 and 5.92:1 in dark, above the 3:1 non-text minimum. A disabled item is half opacity (exempt from contrast). Square, the theme's 1px `--c-focus` ring inside the row.
|
|
386
387
|
|
|
387
388
|
## Code
|
|
388
|
-
From [components-code](components/components-code): `Code`, `Kbd` and `CodeBlock`. The font is the tokens' monospace stack. **Inline code** is `--c-text` on `--c-surface` (16.44:1 in both modes), square, 0.875em. A **kbd** is a `--c-background` key with a 1px `--c-muted` border and a 1px `--c-muted` bottom edge, text `--c-text` (17.93:1 / 18.16:1). The **block** is `--c-surface` with a 1px `--c-muted` border (
|
|
389
|
+
From [components-code](components/components-code): `Code`, `Kbd` and `CodeBlock`. The font is the tokens' monospace stack. **Inline code** is `--c-text` on `--c-surface` (16.44:1 in both modes), square, 0.875em. A **kbd** is a `--c-background` key with a 1px `--c-muted` border and a 1px `--c-muted` bottom edge, text `--c-text` (17.93:1 / 18.16:1). The **block** is `--c-surface` with a 1px `--c-muted` border (5.27:1 light, 7.11:1 dark against the surface, above 3:1) and `--c-text` at the small size; highlighted `children` are the app's to keep AA on `--c-surface`. The **copy button** reads like the secondary button: `--c-background` with a 1px `--c-muted` border, `--c-text` (17.93:1 / 18.16:1) and a `--c-surface-active` hover (`--c-text` 14.23:1 / 13.88:1), square, with the theme's 1px `--c-focus` ring inside it and on the focusable `pre`. The component has no uppercase label variables, so the button keeps the small body text instead of the secondary button's label style.
|
|
389
390
|
|
|
390
391
|
## Field
|
|
391
|
-
From [components-field](components/components-field): `Field`. The label is `--c-text`, bold, at the small size (17.93:1 light, 18.16:1 dark on the background) and not `--c-muted`, which is
|
|
392
|
+
From [components-field](components/components-field): `Field`. The label is `--c-text`, bold, at the small size (17.93:1 light, 18.16:1 dark on the background) and not `--c-muted`, which is 5.27:1 on `--c-surface` in light. The hint is `--c-muted` at the small size (5.74:1 / 7.85:1 on the background) and stays visible, linked with `aria-describedby`. The error is `--c-error` (4.53:1 / 7.16:1), the same color as the Input's error line, and the required asterisk is `--c-error` too; color is never the only signal because the error is text with `role="alert"`. 0.5rem between label, control, hint and error; the horizontal layout uses a 10rem label column and 1.5rem of gap. Keep a field on `--c-background`.
|
|
392
393
|
|
|
393
394
|
## Number input
|
|
394
|
-
From [components-number-input](components/components-number-input): `NumberInput`. The field is the Input's, so it keeps its notched label, `--c-muted` border (
|
|
395
|
+
From [components-number-input](components/components-number-input): `NumberInput`. The field is the Input's, so it keeps its notched label, `--c-muted` border (5.74:1 / 7.85:1) and thickened `--c-focus` border. The stepper buttons read like the secondary button inside the box: square, `--c-muted` glyphs (5.74:1 / 7.85:1, above the 3:1 non-text minimum) turning `--c-text` on a `--c-surface-active` hover (14.23:1 / 13.88:1), half opacity at a bound (exempt from contrast). They are out of the tab order (the arrow keys do the same), so the focus ring stays on the field.
|
|
395
396
|
|
|
396
397
|
## OTP input
|
|
397
|
-
From [components-otp-input](components/components-otp-input): `OtpInput`. Each box is built like the Input: `--c-background` with a 1px `--c-muted` border (
|
|
398
|
+
From [components-otp-input](components/components-otp-input): `OtpInput`. Each box is built like the Input: `--c-background` with a 1px `--c-muted` border (5.74:1 / 7.85:1), `--c-primary` on hover, and the keyboard focus thickens the border to `--c-focus` plus a 1px `--c-focus` shadow (2px in total, 21:1 / 19.8:1), the same rule as every outlined control. An invalid box is `--c-error` (4.53:1 / 7.16:1) with the message under the boxes in `--c-error`; a disabled one is `--c-surface` with `--c-disabled-text` (exempt). The digit is `--c-text` at the h3 size (17.93:1 / 18.16:1). Square, 3rem by 3.5rem (above the 44px touch target), 0.5rem between boxes; the group label is the field label style in `--c-muted`.
|
|
398
399
|
|
|
399
400
|
## Phone
|
|
400
|
-
From [components-phone](components/components-phone): `Phone`. The field is the Input's. The country select is a native `<select>` in the input's start slot, `--c-text` on a transparent background so the box color shows in both modes (17.93:1 / 18.16:1 on the background), with a 1px `--c-muted` divider before the number (
|
|
401
|
+
From [components-phone](components/components-phone): `Phone`. The field is the Input's. The country select is a native `<select>` in the input's start slot, `--c-text` on a transparent background so the box color shows in both modes (17.93:1 / 18.16:1 on the background), with a 1px `--c-muted` divider before the number (5.74:1 / 7.85:1) and the theme's 1px `--c-focus` outline when it is focused by keyboard; disabled is `--c-disabled-text` (exempt). The open list is drawn by the platform, so it follows `color-scheme` in dark.
|
|
401
402
|
|
|
402
403
|
## Tag input
|
|
403
404
|
From [components-tag-input](components/components-tag-input): `TagInput`. The box is the Input's (square, `--c-muted` border, thickened `--c-focus` border on focus) and the chips are the Tag's, so the tag tints, borders and `--c-text` labels (14.8:1 or more on every tint) are the ones documented in the Tag section; the block only sets 0.375rem between chips and the text field and a 6rem minimum for the text field before it wraps to its own row. The placeholder is `--c-muted` as in the Input. Errors (`duplicate`, `max`, `invalid`) use the Input's `--c-error` line.
|
|
404
405
|
|
|
405
406
|
## Time picker
|
|
406
|
-
From [components-time-picker](components/components-time-picker): `TimePicker`. The field is the Input's and the times are the Listbox's inside the Popover, so the `--c-muted` border (
|
|
407
|
+
From [components-time-picker](components/components-time-picker): `TimePicker`. The field is the Input's and the times are the Listbox's inside the Popover, so the `--c-muted` border (5.74:1 / 7.85:1), the thickened `--c-focus` border, the `--c-text` options (17.93:1 / 18.16:1), the `--c-surface` active option and the selected marker are the ones documented for the Select and the Combobox (reused, no new figure). The clock icon is the Select arrow's: 16px, `--c-muted` turning `--c-primary` on hover and when open, and `--c-disabled-text` when disabled (exempt). Open takes the `--c-focus` border; the placeholder is `--c-muted`. Errors (`invalid_time`, `out_of_range`) use the Input's `--c-error` line (4.53:1 / 7.16:1).
|
|
407
408
|
|
|
408
409
|
## Date range
|
|
409
410
|
From [components-date-range](components/components-date-range): `DateRange`. The trigger is the Date picker's and the days are the Calendar's (44px squares, `--c-text`, `--c-surface` hover), so those figures are reused. The two ends use the Calendar's selected look, `--c-on-primary` on `--c-primary` (21:1 / 19.8:1). The days between them are a `--c-surface-active` band with `--c-text` (14.23:1 / 13.88:1, the same pair as the Menu and Pagination hovers), square so the band is unbroken; it is painted on the cell and on the day, and it relies on the calendar grid keeping `border-spacing: 0` (a test asserts it). The band against the background is only 1.26:1 / 1.31:1, so it is not the only cue: the ends are solid black (or white in dark), and the days carry `aria-selected`. Two months sit side by side with 1rem between them, with 0.5rem of panel padding. Errors (`end_before_start`, `out_of_range`) use the Input's `--c-error` line.
|
|
410
411
|
|
|
411
412
|
## Rating
|
|
412
|
-
From [components-rating](components/components-rating): `Rating`. The filled part is `--c-primary` (21:1 / 19.8:1 on the background) and the empty part is `--c-muted` (
|
|
413
|
+
From [components-rating](components/components-rating): `Rating`. The filled part is `--c-primary` (21:1 / 19.8:1 on the background) and the empty part is `--c-muted` (5.74:1 / 7.85:1), both above the 3:1 minimum for graphics. A filled star is a solid shape and an empty one an outline, so the two never rely on colour alone; their lightness differs by 4.43:1 in light and 2.52:1 in dark (below 3:1 there, which the solid-versus-outline shape makes up for). The preview while hovering is `--c-primary-hover` (15.13:1 in light, 15.72:1 in dark on the background). Stars are 1.75rem apart by 0.25rem, and the keyboard ring is the theme's 1px `--c-focus` outline (21:1 / 19.8:1). The group label is the field label style in `--c-muted`; a disabled rating is at half opacity (exempt).
|
|
413
414
|
|
|
414
415
|
## Color picker
|
|
415
|
-
From [components-color-picker](components/components-color-picker): `ColorPicker`. The field is the Input's with a 1.25rem chip bordered in `--c-muted` (
|
|
416
|
+
From [components-color-picker](components/components-color-picker): `ColorPicker`. The field is the Input's with a 1.25rem chip bordered in `--c-muted` (5.74:1 / 7.85:1) next to the hex text in `--c-text`; the panel is the Popover's. The thumbs of the area and of the hue and alpha tracks are a 2px `--c-background` ring over a 1px `--c-text` ring, so one of the two contrasts with any colour under it in both modes (the ring pair is 17.93:1 / 18.16:1 between itself); the keyboard focus draws the theme's 1px `--c-focus` outline offset by 2px around the area or the track (21:1 / 19.8:1). The hue and brightness gradients are the colour data and keep their literal colours; the transparent checkerboard is `--c-surface-active` over `--c-background`. The hex input is built like the Input box: `--c-background`, a 1px `--c-muted` border, `--c-error` when invalid (4.53:1 / 7.16:1), the monospace stack at the small size. Swatches are 1.75rem squares with a `--c-muted` border and a `--c-primary` ring when selected; areas, tracks and chips are square.
|
|
416
417
|
|
|
417
418
|
## Async autocomplete
|
|
418
|
-
From [components-async-autocomplete](components/components-async-autocomplete): `AsyncAutocomplete`. The field, the panel and the options are the Combobox's (reused figures, no new contrast). While a request is pending the field shows a 16px spinner at the arrow's place: a 2px `--c-primary` arc (21:1 / 19.8:1) over a `--c-surface-active` track, slowed down under `prefers-reduced-motion`. The states are written in the panel: `loading` and `empty` in `--c-muted` (
|
|
419
|
+
From [components-async-autocomplete](components/components-async-autocomplete): `AsyncAutocomplete`. The field, the panel and the options are the Combobox's (reused figures, no new contrast). While a request is pending the field shows a 16px spinner at the arrow's place: a 2px `--c-primary` arc (21:1 / 19.8:1) over a `--c-surface-active` track, slowed down under `prefers-reduced-motion`. The states are written in the panel: `loading` and `empty` in `--c-muted` (5.74:1 / 7.85:1, the Listbox's empty message color) and `error` in `--c-error` (4.53:1 / 7.16:1 on the background, which is the panel's); the state is also exposed as `aria-busy` and `data-state`, so colour is never the only signal. Open takes the `--c-focus` border.
|
|
420
|
+
|
|
421
|
+
## Section and container
|
|
422
|
+
From [components-section](components/components-section): `Container` and `Section`. Layout only: gutters of 1rem growing to 2rem at 40rem, container widths of 40, 48, 64 and 80rem, and vertical rhythms of 2, 4 and 6rem. The section title is `--c-text` in the h2 style (17.93:1 / 18.16:1 on the background) and the lead paragraph is `--c-muted` at the lead size (5.74:1 / 7.85:1 on the background, 5.27:1 / 7.11:1 on `--c-surface`), so both pass AA on either ground. A section with a title is a landmark named by it.
|
|
423
|
+
|
|
424
|
+
## Faq
|
|
425
|
+
From [components-faq](components/components-faq): `Faq`. It is the Accordion (the box, the `--c-muted` rules, the `--c-surface` header hover and the 1px `--c-focus` ring documented in the Accordion section), so no new figure for the questions. The answers are `--c-text` (17.93:1 / 18.16:1) at a 1.6 line height and the list is capped at 48rem. The block must stay after the accordion block, because the FAQ stylesheet forwards the accordion's.
|
|
426
|
+
|
|
427
|
+
## Carousel
|
|
428
|
+
From [components-carousel](components/components-carousel): `Carousel`. The arrows and the pause / play button are the secondary button's: square, 2.75rem, a 1px `--c-muted` border (5.74:1 / 7.85:1 on the background), a `--c-surface-active` hover and a `--c-text` glyph (17.93:1 / 18.16:1; 14.23:1 / 13.88:1 on the hover). The glyphs (corner, bars, triangle) are drawn with borders in `currentColor`, so they follow the mode and need no new colour. Disabled arrows are at half opacity (exempt). The dots are 0.625rem circles in `--c-muted` (5.74:1 / 7.85:1 on the background, 5.27:1 / 7.11:1 on `--c-surface`, above the 3:1 minimum for graphics) and the current one is `--c-primary` (21:1 / 19.8:1) and 1.5rem long. Colour is not the only cue: the current dot is a bar against circles, and it also carries `aria-current`; the lightness gap between the two colours is 3.66:1 in light and 2.52:1 in dark (below 3:1 there, which the shape makes up for). The keyboard ring is the theme's 1px `--c-focus` outline offset by 2px (21:1 / 19.8:1). Transitions run at 0.2s and stop under `prefers-reduced-motion`.
|
|
419
429
|
|
|
420
430
|
## Keyboard focus (all controls)
|
|
421
431
|
One rule keeps the controls coherent: **an outlined control thickens its own border from 1px to 2px, black** (text fields,
|
package/README.md
CHANGED
|
@@ -78,7 +78,7 @@ change.
|
|
|
78
78
|
| `$black` | `#000` | primary, hover and focus |
|
|
79
79
|
| `$white` | `#fff` | surfaces |
|
|
80
80
|
| `$text` | `#171717` | body text |
|
|
81
|
-
| `$muted` | `#
|
|
81
|
+
| `$muted` | `#666666` | labels, field borders, placeholders |
|
|
82
82
|
| `$surface` | `#f5f5f5` | hover surface, disabled background |
|
|
83
83
|
| `$surface-active` | `#e5e5e5` | pressed surface, dividers |
|
|
84
84
|
| `$primary-hover` | `#262626` | primary action on hover |
|
|
@@ -142,7 +142,7 @@ it: check the names against the theme's `scss/_tokens.scss` before you switch.
|
|
|
142
142
|
|
|
143
143
|
## What it configures
|
|
144
144
|
`components-input`, `-button`, `-checkbox`, `-switch`, `-radio-group`, `-slider`, `-popover`, `-listbox`, `-select`,
|
|
145
|
-
`-combobox`, `-upload`, `-calendar`, `-date-picker`, `-search`, `-typography`, `-card`, `-alert`, `-spinner`, `-modal`, `-toast`, `-divider`, `-badge`, `-tag`, `-link`, `-avatar`, `-skeleton`, `-progress`, `-tooltip`, `-prose`, `-tabs`, `-accordion`, `-breadcrumb`, `-pagination`, `-stepper`, `-sidebar`, `-navbar`, `-drawer`, `-menu`, `-table`, `-list`, `-description-list`, `-stat`, `-empty-state`, `-timeline`, `-tree`, `-code`, `-field`, `-number-input`, `-otp-input`, `-phone`, `-tag-input`, `-time-picker`, `-date-range`, `-rating`, `-color-picker` and `-
|
|
145
|
+
`-combobox`, `-upload`, `-calendar`, `-date-picker`, `-search`, `-typography`, `-card`, `-alert`, `-spinner`, `-modal`, `-toast`, `-divider`, `-badge`, `-tag`, `-link`, `-avatar`, `-skeleton`, `-progress`, `-tooltip`, `-prose`, `-tabs`, `-accordion`, `-breadcrumb`, `-pagination`, `-stepper`, `-sidebar`, `-navbar`, `-drawer`, `-menu`, `-table`, `-list`, `-description-list`, `-stat`, `-empty-state`, `-timeline`, `-tree`, `-code`, `-field`, `-number-input`, `-otp-input`, `-phone`, `-tag-input`, `-time-picker`, `-date-range`, `-rating`, `-color-picker`, `-async-autocomplete`, `-section`, `-faq` and `-carousel`. `components-email`, `-password`, `-url` and `-textarea`
|
|
146
146
|
are styled through the input.
|
|
147
147
|
|
|
148
148
|
## Change a value
|
package/dist/index.css
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
:root {
|
|
3
3
|
--c-background: #fff;
|
|
4
4
|
--c-text: #171717;
|
|
5
|
-
--c-muted: #
|
|
5
|
+
--c-muted: #666666;
|
|
6
6
|
--c-surface: #f5f5f5;
|
|
7
7
|
--c-surface-active: #e5e5e5;
|
|
8
8
|
--c-primary: #000;
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
:root[data-mode=light] {
|
|
23
23
|
--c-background: #fff;
|
|
24
24
|
--c-text: #171717;
|
|
25
|
-
--c-muted: #
|
|
25
|
+
--c-muted: #666666;
|
|
26
26
|
--c-surface: #f5f5f5;
|
|
27
27
|
--c-surface-active: #e5e5e5;
|
|
28
28
|
--c-primary: #000;
|
|
@@ -4407,6 +4407,10 @@ ol.c-list {
|
|
|
4407
4407
|
outline-offset: -2px;
|
|
4408
4408
|
}
|
|
4409
4409
|
|
|
4410
|
+
.c-code-block--has-copy .c-code-block__pre {
|
|
4411
|
+
padding-top: 2.5rem;
|
|
4412
|
+
}
|
|
4413
|
+
|
|
4410
4414
|
.c-code-block__code {
|
|
4411
4415
|
font-size: inherit;
|
|
4412
4416
|
}
|
|
@@ -5042,3 +5046,222 @@ ol.c-list {
|
|
|
5042
5046
|
animation-duration: 2s;
|
|
5043
5047
|
}
|
|
5044
5048
|
}
|
|
5049
|
+
.c-container {
|
|
5050
|
+
box-sizing: border-box;
|
|
5051
|
+
width: 100%;
|
|
5052
|
+
margin-inline: auto;
|
|
5053
|
+
padding-inline: 1rem;
|
|
5054
|
+
}
|
|
5055
|
+
@media (min-width: 40rem) {
|
|
5056
|
+
.c-container {
|
|
5057
|
+
padding-inline: 2rem;
|
|
5058
|
+
}
|
|
5059
|
+
}
|
|
5060
|
+
|
|
5061
|
+
.c-container--sm {
|
|
5062
|
+
max-width: 40rem;
|
|
5063
|
+
}
|
|
5064
|
+
|
|
5065
|
+
.c-container--md {
|
|
5066
|
+
max-width: 48rem;
|
|
5067
|
+
}
|
|
5068
|
+
|
|
5069
|
+
.c-container--lg {
|
|
5070
|
+
max-width: 64rem;
|
|
5071
|
+
}
|
|
5072
|
+
|
|
5073
|
+
.c-container--xl {
|
|
5074
|
+
max-width: 80rem;
|
|
5075
|
+
}
|
|
5076
|
+
|
|
5077
|
+
.c-container--full {
|
|
5078
|
+
max-width: none;
|
|
5079
|
+
}
|
|
5080
|
+
|
|
5081
|
+
.c-section {
|
|
5082
|
+
box-sizing: border-box;
|
|
5083
|
+
}
|
|
5084
|
+
|
|
5085
|
+
.c-section--sm {
|
|
5086
|
+
padding-block: 2rem;
|
|
5087
|
+
}
|
|
5088
|
+
|
|
5089
|
+
.c-section--md {
|
|
5090
|
+
padding-block: 4rem;
|
|
5091
|
+
}
|
|
5092
|
+
|
|
5093
|
+
.c-section--lg {
|
|
5094
|
+
padding-block: 6rem;
|
|
5095
|
+
}
|
|
5096
|
+
|
|
5097
|
+
.c-section__header {
|
|
5098
|
+
display: flex;
|
|
5099
|
+
flex-direction: column;
|
|
5100
|
+
gap: 0.75rem;
|
|
5101
|
+
max-width: 40rem;
|
|
5102
|
+
margin-bottom: 2rem;
|
|
5103
|
+
}
|
|
5104
|
+
|
|
5105
|
+
.c-section__title {
|
|
5106
|
+
margin: 0;
|
|
5107
|
+
font-size: 1.75rem;
|
|
5108
|
+
font-weight: 900;
|
|
5109
|
+
line-height: 1.2;
|
|
5110
|
+
color: var(--c-text);
|
|
5111
|
+
}
|
|
5112
|
+
|
|
5113
|
+
.c-section__description {
|
|
5114
|
+
margin: 0;
|
|
5115
|
+
font-size: 1.25rem;
|
|
5116
|
+
line-height: 1.6;
|
|
5117
|
+
color: var(--c-muted);
|
|
5118
|
+
}
|
|
5119
|
+
|
|
5120
|
+
.c-faq {
|
|
5121
|
+
max-width: 48rem;
|
|
5122
|
+
}
|
|
5123
|
+
|
|
5124
|
+
.c-faq .c-accordion__content {
|
|
5125
|
+
line-height: 1.6;
|
|
5126
|
+
color: var(--c-text);
|
|
5127
|
+
}
|
|
5128
|
+
|
|
5129
|
+
.c-carousel {
|
|
5130
|
+
box-sizing: border-box;
|
|
5131
|
+
}
|
|
5132
|
+
|
|
5133
|
+
.c-carousel__viewport {
|
|
5134
|
+
overflow: hidden;
|
|
5135
|
+
}
|
|
5136
|
+
|
|
5137
|
+
.c-carousel__track {
|
|
5138
|
+
position: relative;
|
|
5139
|
+
display: flex;
|
|
5140
|
+
gap: 1rem;
|
|
5141
|
+
overflow-x: auto;
|
|
5142
|
+
overscroll-behavior-x: contain;
|
|
5143
|
+
scroll-snap-type: x mandatory;
|
|
5144
|
+
scrollbar-width: none;
|
|
5145
|
+
touch-action: pan-x pan-y pinch-zoom;
|
|
5146
|
+
}
|
|
5147
|
+
.c-carousel__track::-webkit-scrollbar {
|
|
5148
|
+
display: none;
|
|
5149
|
+
}
|
|
5150
|
+
|
|
5151
|
+
.c-carousel__slide {
|
|
5152
|
+
box-sizing: border-box;
|
|
5153
|
+
flex: 0 0 calc((100% - 1rem * (var(--c-carousel-per-view, 1) - 1)) / var(--c-carousel-per-view, 1));
|
|
5154
|
+
min-width: 0;
|
|
5155
|
+
scroll-snap-align: start;
|
|
5156
|
+
}
|
|
5157
|
+
|
|
5158
|
+
.c-carousel__controls {
|
|
5159
|
+
display: flex;
|
|
5160
|
+
gap: 1rem;
|
|
5161
|
+
align-items: center;
|
|
5162
|
+
justify-content: center;
|
|
5163
|
+
margin-top: 1rem;
|
|
5164
|
+
}
|
|
5165
|
+
|
|
5166
|
+
.c-carousel__arrow,
|
|
5167
|
+
.c-carousel__toggle {
|
|
5168
|
+
position: relative;
|
|
5169
|
+
box-sizing: border-box;
|
|
5170
|
+
flex: none;
|
|
5171
|
+
width: 2.75rem;
|
|
5172
|
+
height: 2.75rem;
|
|
5173
|
+
padding: 0;
|
|
5174
|
+
color: var(--c-text);
|
|
5175
|
+
cursor: pointer;
|
|
5176
|
+
background: var(--c-background);
|
|
5177
|
+
border: 1px solid var(--c-muted);
|
|
5178
|
+
border-radius: 0;
|
|
5179
|
+
transition: background-color 0.2s ease-out;
|
|
5180
|
+
}
|
|
5181
|
+
.c-carousel__arrow:hover:not(:disabled),
|
|
5182
|
+
.c-carousel__toggle:hover:not(:disabled) {
|
|
5183
|
+
background: var(--c-surface-active);
|
|
5184
|
+
}
|
|
5185
|
+
.c-carousel__arrow:focus-visible,
|
|
5186
|
+
.c-carousel__toggle:focus-visible {
|
|
5187
|
+
outline: 1px solid var(--c-focus);
|
|
5188
|
+
outline-offset: 2px;
|
|
5189
|
+
}
|
|
5190
|
+
.c-carousel__arrow:disabled,
|
|
5191
|
+
.c-carousel__toggle:disabled {
|
|
5192
|
+
cursor: not-allowed;
|
|
5193
|
+
opacity: 0.5;
|
|
5194
|
+
}
|
|
5195
|
+
.c-carousel__arrow::before,
|
|
5196
|
+
.c-carousel__toggle::before {
|
|
5197
|
+
position: absolute;
|
|
5198
|
+
top: 50%;
|
|
5199
|
+
left: 50%;
|
|
5200
|
+
box-sizing: border-box;
|
|
5201
|
+
content: "";
|
|
5202
|
+
}
|
|
5203
|
+
|
|
5204
|
+
.c-carousel__arrow::before {
|
|
5205
|
+
width: 0.5rem;
|
|
5206
|
+
height: 0.5rem;
|
|
5207
|
+
border-top: 2px solid currentColor;
|
|
5208
|
+
border-right: 2px solid currentColor;
|
|
5209
|
+
}
|
|
5210
|
+
|
|
5211
|
+
.c-carousel__arrow--next::before {
|
|
5212
|
+
transform: translate(-65%, -50%) rotate(45deg);
|
|
5213
|
+
}
|
|
5214
|
+
|
|
5215
|
+
.c-carousel__arrow--prev::before {
|
|
5216
|
+
transform: translate(-35%, -50%) rotate(-135deg);
|
|
5217
|
+
}
|
|
5218
|
+
|
|
5219
|
+
.c-carousel__toggle--playing::before {
|
|
5220
|
+
width: 0.5rem;
|
|
5221
|
+
height: 0.75rem;
|
|
5222
|
+
border-right: 3px solid currentColor;
|
|
5223
|
+
border-left: 3px solid currentColor;
|
|
5224
|
+
transform: translate(-50%, -50%);
|
|
5225
|
+
}
|
|
5226
|
+
|
|
5227
|
+
.c-carousel__toggle--paused::before {
|
|
5228
|
+
border-top: 0.375rem solid transparent;
|
|
5229
|
+
border-bottom: 0.375rem solid transparent;
|
|
5230
|
+
border-left: 0.625rem solid currentColor;
|
|
5231
|
+
transform: translate(-35%, -50%);
|
|
5232
|
+
}
|
|
5233
|
+
|
|
5234
|
+
.c-carousel__dots {
|
|
5235
|
+
display: flex;
|
|
5236
|
+
gap: 0.5rem;
|
|
5237
|
+
align-items: center;
|
|
5238
|
+
}
|
|
5239
|
+
|
|
5240
|
+
.c-carousel__dot {
|
|
5241
|
+
box-sizing: border-box;
|
|
5242
|
+
width: 0.625rem;
|
|
5243
|
+
height: 0.625rem;
|
|
5244
|
+
padding: 0;
|
|
5245
|
+
cursor: pointer;
|
|
5246
|
+
background: var(--c-muted);
|
|
5247
|
+
border: 0;
|
|
5248
|
+
border-radius: 0;
|
|
5249
|
+
transition: width 0.2s ease-out, background-color 0.2s ease-out;
|
|
5250
|
+
}
|
|
5251
|
+
.c-carousel__dot:focus-visible {
|
|
5252
|
+
outline: 1px solid var(--c-focus);
|
|
5253
|
+
outline-offset: 2px;
|
|
5254
|
+
}
|
|
5255
|
+
|
|
5256
|
+
.c-carousel__dot--current {
|
|
5257
|
+
width: 1.5rem;
|
|
5258
|
+
background: var(--c-primary);
|
|
5259
|
+
}
|
|
5260
|
+
|
|
5261
|
+
@media (prefers-reduced-motion: reduce) {
|
|
5262
|
+
.c-carousel__arrow,
|
|
5263
|
+
.c-carousel__toggle,
|
|
5264
|
+
.c-carousel__dot {
|
|
5265
|
+
transition: none;
|
|
5266
|
+
}
|
|
5267
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@carissa-io/theme-default",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.11",
|
|
4
4
|
"description": "Carissa UI: the default theme (Swiss minimalism) as SCSS variable overrides of the Carissa components, with a compiled CSS build",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"style": "dist/index.css",
|
|
@@ -93,7 +93,10 @@
|
|
|
93
93
|
"@carissa-io/components-date-range": "^0.1.0",
|
|
94
94
|
"@carissa-io/components-rating": "^0.1.0",
|
|
95
95
|
"@carissa-io/components-color-picker": "^0.1.0",
|
|
96
|
-
"@carissa-io/components-async-autocomplete": "^0.1.0"
|
|
96
|
+
"@carissa-io/components-async-autocomplete": "^0.1.0",
|
|
97
|
+
"@carissa-io/components-section": "^0.1.0",
|
|
98
|
+
"@carissa-io/components-faq": "^0.1.0",
|
|
99
|
+
"@carissa-io/components-carousel": "^0.1.0"
|
|
97
100
|
},
|
|
98
101
|
"peerDependenciesMeta": {
|
|
99
102
|
"@carissa-io/components-input": {
|
|
@@ -275,6 +278,15 @@
|
|
|
275
278
|
},
|
|
276
279
|
"@carissa-io/components-async-autocomplete": {
|
|
277
280
|
"optional": true
|
|
281
|
+
},
|
|
282
|
+
"@carissa-io/components-section": {
|
|
283
|
+
"optional": true
|
|
284
|
+
},
|
|
285
|
+
"@carissa-io/components-faq": {
|
|
286
|
+
"optional": true
|
|
287
|
+
},
|
|
288
|
+
"@carissa-io/components-carousel": {
|
|
289
|
+
"optional": true
|
|
278
290
|
}
|
|
279
291
|
},
|
|
280
292
|
"devDependencies": {
|
|
@@ -287,6 +299,7 @@
|
|
|
287
299
|
"@carissa-io/components-button": "^0.1.1",
|
|
288
300
|
"@carissa-io/components-calendar": "^0.1.1",
|
|
289
301
|
"@carissa-io/components-card": "^0.1.0",
|
|
302
|
+
"@carissa-io/components-carousel": "^0.1.0",
|
|
290
303
|
"@carissa-io/components-checkbox": "^0.1.1",
|
|
291
304
|
"@carissa-io/components-code": "^0.1.0",
|
|
292
305
|
"@carissa-io/components-color-picker": "^0.1.0",
|
|
@@ -297,6 +310,7 @@
|
|
|
297
310
|
"@carissa-io/components-divider": "^0.1.0",
|
|
298
311
|
"@carissa-io/components-drawer": "^0.1.0",
|
|
299
312
|
"@carissa-io/components-empty-state": "^0.1.0",
|
|
313
|
+
"@carissa-io/components-faq": "^0.1.0",
|
|
300
314
|
"@carissa-io/components-field": "^0.1.0",
|
|
301
315
|
"@carissa-io/components-input": "^0.2.1",
|
|
302
316
|
"@carissa-io/components-link": "^0.1.0",
|
|
@@ -315,6 +329,7 @@
|
|
|
315
329
|
"@carissa-io/components-radio-group": "^0.1.1",
|
|
316
330
|
"@carissa-io/components-rating": "^0.1.0",
|
|
317
331
|
"@carissa-io/components-search": "^0.1.1",
|
|
332
|
+
"@carissa-io/components-section": "^0.1.0",
|
|
318
333
|
"@carissa-io/components-select": "^0.1.1",
|
|
319
334
|
"@carissa-io/components-sidebar": "^0.1.0",
|
|
320
335
|
"@carissa-io/components-skeleton": "^0.1.0",
|
package/scss/_tokens.scss
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
$black: #000; // primary, hover and focus
|
|
10
10
|
$white: #fff;
|
|
11
11
|
$text: #171717;
|
|
12
|
-
$muted: #
|
|
12
|
+
$muted: #666666; // labels, field borders, placeholders (5.7:1 on white)
|
|
13
13
|
$surface: #f5f5f5; // hover surface, disabled background
|
|
14
14
|
$surface-active: #e5e5e5;
|
|
15
15
|
$primary-hover: #262626;
|
package/scss/index.scss
CHANGED
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
$c-button-primary-background-disabled: $var-surface,
|
|
79
79
|
$c-button-primary-border-color-disabled: $var-surface,
|
|
80
80
|
|
|
81
|
-
// Secondary: 1px #
|
|
81
|
+
// Secondary: 1px #666666 border, black on hover
|
|
82
82
|
$c-button-secondary-color: $var-text,
|
|
83
83
|
$c-button-secondary-background: $var-background,
|
|
84
84
|
$c-button-secondary-border-color: $var-muted,
|
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
$c-checkbox-gap: 0.75rem,
|
|
126
126
|
$c-checkbox-transition: (color $transition-duration ease, background-color $transition-duration ease, border-color $transition-duration ease, opacity $transition-duration ease),
|
|
127
127
|
|
|
128
|
-
// Box: 20px square, 1px #
|
|
128
|
+
// Box: 20px square, 1px #666666 border, black on hover
|
|
129
129
|
$c-checkbox-box-size: 1.25rem,
|
|
130
130
|
$c-checkbox-border-color: $var-muted,
|
|
131
131
|
$c-checkbox-border-color-hover: $var-primary,
|
|
@@ -155,7 +155,7 @@
|
|
|
155
155
|
);
|
|
156
156
|
|
|
157
157
|
@use '@carissa-io/components-switch/scss' as switch with (
|
|
158
|
-
// Track: square, 40 x 20px, white with a 1px #
|
|
158
|
+
// Track: square, 40 x 20px, white with a 1px #666666 border; black when on
|
|
159
159
|
$c-switch-track-width: 2.5rem,
|
|
160
160
|
$c-switch-track-height: 1.25rem,
|
|
161
161
|
$c-switch-track-radius: $radius,
|
|
@@ -168,7 +168,7 @@
|
|
|
168
168
|
$c-switch-track-background-disabled: $var-surface,
|
|
169
169
|
$c-switch-track-border-color-disabled: $var-disabled-border,
|
|
170
170
|
|
|
171
|
-
// Thumb: square, #
|
|
171
|
+
// Thumb: square, #666666 when off, white when on
|
|
172
172
|
$c-switch-thumb-size: 0.875rem,
|
|
173
173
|
$c-switch-thumb-offset: 0.125rem,
|
|
174
174
|
$c-switch-thumb-radius: $radius,
|
|
@@ -203,7 +203,7 @@
|
|
|
203
203
|
$c-radio-group-dot-gap: 0.75rem,
|
|
204
204
|
$c-radio-group-transition: (color $transition-duration ease, background-color $transition-duration ease, border-color $transition-duration ease, background-size $transition-duration ease),
|
|
205
205
|
|
|
206
|
-
// Dot: 20px circle (a radio is round, so the radius stays 50%), 1px #
|
|
206
|
+
// Dot: 20px circle (a radio is round, so the radius stays 50%), 1px #666666 border, black on hover
|
|
207
207
|
$c-radio-group-dot-size: 1.25rem,
|
|
208
208
|
$c-radio-group-border-color: $var-muted,
|
|
209
209
|
$c-radio-group-border-color-hover: $var-primary,
|
|
@@ -246,7 +246,7 @@
|
|
|
246
246
|
$c-slider-min-height: $min-height,
|
|
247
247
|
$c-slider-transition: (background-color $transition-duration ease, border-color $transition-duration ease),
|
|
248
248
|
|
|
249
|
-
// Track: 2px #
|
|
249
|
+
// Track: 2px #666666 line with a black fill
|
|
250
250
|
$c-slider-track-height: 2px,
|
|
251
251
|
$c-slider-track-color: $var-muted,
|
|
252
252
|
$c-slider-track-fill-color: $var-primary,
|
|
@@ -274,7 +274,7 @@
|
|
|
274
274
|
);
|
|
275
275
|
|
|
276
276
|
@use '@carissa-io/components-popover/scss' as popover with (
|
|
277
|
-
// Panel: white, 1px #
|
|
277
|
+
// Panel: white, 1px #666666 border, square, flat (no shadow), 4px below the anchor
|
|
278
278
|
$c-popover-background: $var-background,
|
|
279
279
|
$c-popover-color: $var-text,
|
|
280
280
|
$c-popover-border-width: 1px,
|
|
@@ -356,7 +356,7 @@
|
|
|
356
356
|
// Upload: the Input field with a dashed box as the dropzone. Its index forwards the input styles, already loaded and
|
|
357
357
|
// configured above, so it must come after them.
|
|
358
358
|
@use '@carissa-io/components-upload/scss' as upload with (
|
|
359
|
-
// Box: dashed 1px #
|
|
359
|
+
// Box: dashed 1px #666666 (the input border), black on hover and while files are dragged over it
|
|
360
360
|
$c-upload-border-style: dashed,
|
|
361
361
|
$c-upload-transition: (border-color $transition-duration ease, background-color $transition-duration ease, box-shadow $transition-duration ease, color $transition-duration ease),
|
|
362
362
|
$c-upload-dragging-border-color: $var-primary,
|
|
@@ -788,7 +788,7 @@
|
|
|
788
788
|
);
|
|
789
789
|
|
|
790
790
|
// Link: --c-primary (black in light, white in dark) with an underline, because a black link on black text is told apart
|
|
791
|
-
// by the underline alone; --c-primary-hover on hover. Subtle is --c-muted (
|
|
791
|
+
// by the underline alone; --c-primary-hover on hover. Subtle is --c-muted (5.7:1 on the background) and turns --c-text.
|
|
792
792
|
// Disabled is --c-disabled-text at full opacity. The focus ring is the theme's 1px ring, offset 2px.
|
|
793
793
|
@use '@carissa-io/components-link/scss' as link with (
|
|
794
794
|
$c-link-color: $var-primary,
|
|
@@ -939,7 +939,7 @@
|
|
|
939
939
|
);
|
|
940
940
|
|
|
941
941
|
// Tabs: a --c-muted underline under the list and a 2px --c-primary indicator under the selected tab. Tabs read --c-muted
|
|
942
|
-
// (
|
|
942
|
+
// (5.7:1 on the background, 7.9:1 in dark), turn --c-text on a --c-surface hover and the selected one is --c-text and bold.
|
|
943
943
|
// Square, bold, the theme's 1px focus ring inside the tab. No other block forwards it.
|
|
944
944
|
@use '@carissa-io/components-tabs/scss' as tabs with (
|
|
945
945
|
$c-tabs-list-border-width: 1px,
|
|
@@ -985,7 +985,7 @@
|
|
|
985
985
|
$c-accordion-transition-duration: $transition-duration
|
|
986
986
|
);
|
|
987
987
|
|
|
988
|
-
// Breadcrumb: links and separators in --c-muted (
|
|
988
|
+
// Breadcrumb: links and separators in --c-muted (5.7:1 on the background), the current page in --c-text and bold. Links turn
|
|
989
989
|
// --c-text and underline on hover. The theme's 1px focus ring, offset 2px.
|
|
990
990
|
@use '@carissa-io/components-breadcrumb/scss' as breadcrumb with (
|
|
991
991
|
$c-breadcrumb-font-size: $font-size-small,
|
|
@@ -1062,7 +1062,7 @@
|
|
|
1062
1062
|
|
|
1063
1063
|
// Sidebar: a --c-surface column with a 1px --c-muted edge. Items are --c-text (16.4:1 on the surface) with a --c-surface-active
|
|
1064
1064
|
// hover (14.2:1); the current page is filled --c-primary with --c-on-primary (21:1), a shape and not only a hue. Section titles
|
|
1065
|
-
// are the small uppercase label style in --c-text, because --c-muted on --c-surface is
|
|
1065
|
+
// are the small uppercase label style in --c-text, because --c-muted on --c-surface is 5.27:1 in light (it passes, the label stays text for emphasis). Square, the
|
|
1066
1066
|
// theme's 1px focus ring inside the item. No other block forwards it.
|
|
1067
1067
|
@use '@carissa-io/components-sidebar/scss' as sidebar with (
|
|
1068
1068
|
$c-sidebar-width: 16rem,
|
|
@@ -1098,7 +1098,7 @@
|
|
|
1098
1098
|
$c-sidebar-transition-duration: $transition-duration
|
|
1099
1099
|
);
|
|
1100
1100
|
|
|
1101
|
-
// Navbar: a --c-background bar with a 1px --c-muted bottom edge. Items read like the tabs: bold --c-muted (
|
|
1101
|
+
// Navbar: a --c-background bar with a 1px --c-muted bottom edge. Items read like the tabs: bold --c-muted (5.7:1 on the
|
|
1102
1102
|
// background), --c-text on a --c-surface hover, and --c-text for the current page. The breakpoint is the Sass default (48rem).
|
|
1103
1103
|
// Square, 44px toggle, the theme's 1px focus ring inside the item. No other block forwards it.
|
|
1104
1104
|
@use '@carissa-io/components-navbar/scss' as navbar with (
|
|
@@ -1155,7 +1155,7 @@
|
|
|
1155
1155
|
);
|
|
1156
1156
|
|
|
1157
1157
|
// Menu: the panel is the Popover's (--c-background, 1px --c-muted border, flat). Items are --c-text with a --c-surface-active
|
|
1158
|
-
// hover and keyboard focus (14.2:1) and the theme's 1px focus ring; labels are small --c-muted text (
|
|
1158
|
+
// hover and keyboard focus (14.2:1) and the theme's 1px focus ring; labels are small --c-muted text (5.7:1 on the panel) and
|
|
1159
1159
|
// the separator a 1px --c-muted line. Square. Its index forwards the popover styles, already loaded and configured above:
|
|
1160
1160
|
// this block goes after the Popover one.
|
|
1161
1161
|
@use '@carissa-io/components-menu/scss' as menu with (
|
|
@@ -1204,7 +1204,7 @@
|
|
|
1204
1204
|
);
|
|
1205
1205
|
|
|
1206
1206
|
// List: rows on the page background, divided by 1px --c-muted lines. The secondary text is --c-text at the small size, not
|
|
1207
|
-
// --c-muted, because the row sits on --c-surface-active when hovered and --c-muted is
|
|
1207
|
+
// --c-muted, because the row sits on --c-surface-active when hovered and --c-muted is 4.56:1 there (5.27:1 on --c-surface), so the text color keeps the hover clearly readable.
|
|
1208
1208
|
// Hover is --c-surface-active; the current item is the same 12% --c-primary tint as a selected table row. Square, the theme's
|
|
1209
1209
|
// 1px focus ring inside the row.
|
|
1210
1210
|
@use '@carissa-io/components-list/scss' as list with (
|
|
@@ -1229,7 +1229,7 @@
|
|
|
1229
1229
|
$c-list-transition-duration: $transition-duration
|
|
1230
1230
|
);
|
|
1231
1231
|
|
|
1232
|
-
// Description list: the term is a small bold --c-muted label (
|
|
1232
|
+
// Description list: the term is a small bold --c-muted label (5.7:1 on the background, so use it on --c-background, where
|
|
1233
1233
|
// --c-muted is not enough on --c-surface) and the detail is --c-text. No fills or borders.
|
|
1234
1234
|
@use '@carissa-io/components-description-list/scss' as description-list with (
|
|
1235
1235
|
$c-description-list-gap-x: 2rem,
|
|
@@ -1245,7 +1245,7 @@
|
|
|
1245
1245
|
|
|
1246
1246
|
// Stat: a card-like block on the page background with a 1px --c-muted border (the Card's outlined look), not on --c-surface:
|
|
1247
1247
|
// the delta colors are checked against --c-background, where --c-success is 5:1 and --c-error 4.5:1 in light (4.15:1 for
|
|
1248
|
-
// --c-error on --c-surface). The label and the description are --c-muted (
|
|
1248
|
+
// --c-error on --c-surface). The label and the description are --c-muted (5.7:1), the value is --c-text. The delta is
|
|
1249
1249
|
// success when up, error when down and muted when flat; the arrow and the screen-reader text say the same, so color is never
|
|
1250
1250
|
// the only signal. In dark the status colors are lighter (7.1:1 and above on the background).
|
|
1251
1251
|
@use '@carissa-io/components-stat/scss' as stat with (
|
|
@@ -1271,9 +1271,9 @@
|
|
|
1271
1271
|
$c-stat-delta-flat-color: $var-muted
|
|
1272
1272
|
);
|
|
1273
1273
|
|
|
1274
|
-
// Empty state: a centred block on the page background. The icon is --c-muted (
|
|
1275
|
-
// minimum), the title --c-text at the h3 size and bold, the description --c-muted (
|
|
1276
|
-
// --c-surface, where light is
|
|
1274
|
+
// Empty state: a centred block on the page background. The icon is --c-muted (5.7:1 light, 7.9:1 dark, above the 3:1 non-text
|
|
1275
|
+
// minimum), the title --c-text at the h3 size and bold, the description --c-muted (5.7:1 on the background, so keep it off
|
|
1276
|
+
// --c-surface, where light is 5.27:1). The actions are the app's buttons. Square, nothing else to set.
|
|
1277
1277
|
@use '@carissa-io/components-empty-state/scss' as empty-state with (
|
|
1278
1278
|
$c-empty-state-padding: 3rem 1.5rem,
|
|
1279
1279
|
$c-empty-state-padding-sm: 1.5rem 1rem,
|
|
@@ -1299,7 +1299,7 @@
|
|
|
1299
1299
|
// success, warning, error and info are solid dots in their status color (4.5:1 or more against the background in light, 7:1 in
|
|
1300
1300
|
// dark, above the 3:1 non-text minimum); the current step is a hollow --c-primary ring. An icon marker keeps a --c-background
|
|
1301
1301
|
// fill and takes the status as its ring, so the --c-text icon is 17.9:1 / 18.2:1 in every status. The status text is the
|
|
1302
|
-
// hidden status_label, the time is --c-muted (
|
|
1302
|
+
// hidden status_label, the time is --c-muted (5.7:1 / 7.9:1 on the background) and the title --c-text, bold. Color is never the
|
|
1303
1303
|
// only signal.
|
|
1304
1304
|
@use '@carissa-io/components-timeline/scss' as timeline with (
|
|
1305
1305
|
$c-timeline-gap: 1.5rem,
|
|
@@ -1391,8 +1391,8 @@
|
|
|
1391
1391
|
);
|
|
1392
1392
|
|
|
1393
1393
|
// Field: the label, hint and error around a control with no label of its own (radio group, slider, custom control). The label is
|
|
1394
|
-
// --c-text (17.93:1 / 18.16:1 on the background) in the label size and weight, not --c-muted, which is
|
|
1395
|
-
// light. The hint is --c-muted (
|
|
1394
|
+
// --c-text (17.93:1 / 18.16:1 on the background) in the label size and weight, not --c-muted, which is 5.27:1 on --c-surface in
|
|
1395
|
+
// light. The hint is --c-muted (5.74:1 / 7.85:1 on the background) and the error is --c-error (4.53:1 / 7.16:1), the same
|
|
1396
1396
|
// color as the Input's error line, with the component's required asterisk. Keep a field on --c-background.
|
|
1397
1397
|
@use '@carissa-io/components-field/scss' as field with (
|
|
1398
1398
|
$c-field-font-family: $font-family,
|
|
@@ -1412,7 +1412,7 @@
|
|
|
1412
1412
|
);
|
|
1413
1413
|
|
|
1414
1414
|
// Number input: the field is the Input's (configured at the top; this module forwards it). The steppers read like the
|
|
1415
|
-
// secondary button inside the box: --c-muted glyphs (
|
|
1415
|
+
// secondary button inside the box: --c-muted glyphs (5.74:1 / 7.85:1, above the 3:1 non-text minimum) turning --c-text on a
|
|
1416
1416
|
// --c-surface-active hover (--c-text 14.23:1 / 13.88:1), square, half opacity at a bound.
|
|
1417
1417
|
@use '@carissa-io/components-number-input/scss' as number-input with (
|
|
1418
1418
|
$c-number-input-stepper-size: 1.5rem,
|
|
@@ -1427,7 +1427,7 @@
|
|
|
1427
1427
|
$c-number-input-text-align: start
|
|
1428
1428
|
);
|
|
1429
1429
|
|
|
1430
|
-
// OTP input: one box per character, built like the Input box: --c-background with a 1px --c-muted border (
|
|
1430
|
+
// OTP input: one box per character, built like the Input box: --c-background with a 1px --c-muted border (5.74:1 / 7.85:1),
|
|
1431
1431
|
// --c-primary on hover, and the keyboard focus thickens the border to the theme's black ring (--c-focus, 21:1 / 19.8:1). An
|
|
1432
1432
|
// invalid box is --c-error (4.53:1 / 7.16:1) and the message under the boxes is --c-error too; a disabled one is --c-surface
|
|
1433
1433
|
// with --c-disabled-text (exempt from contrast). The digit is --c-text (17.93:1 / 18.16:1). Square, 3rem by 3.5rem.
|
|
@@ -1520,7 +1520,7 @@
|
|
|
1520
1520
|
$c-date-range-open-border-color: $var-focus
|
|
1521
1521
|
);
|
|
1522
1522
|
|
|
1523
|
-
// Rating: the stars are --c-primary (21:1 / 19.8:1 on the background) over --c-muted ones (
|
|
1523
|
+
// Rating: the stars are --c-primary (21:1 / 19.8:1 on the background) over --c-muted ones (5.74:1 / 7.85:1), so the filled
|
|
1524
1524
|
// and the empty part differ by shape (a solid star against an outline one) and by lightness (4.43:1 / 2.52:1 between them),
|
|
1525
1525
|
// never by hue alone; the preview while hovering is --c-primary-hover (15.13:1 in light). The keyboard ring is the theme's --c-focus. The label is the field label style in --c-muted.
|
|
1526
1526
|
@use '@carissa-io/components-rating/scss' as rating with (
|
|
@@ -1582,7 +1582,7 @@
|
|
|
1582
1582
|
|
|
1583
1583
|
// Async autocomplete: the Combobox's field (a text input over the Listbox in the Popover, configured above) with a spinner
|
|
1584
1584
|
// while a request is pending (--c-primary arc over a --c-surface-active track) and one message in the panel per state:
|
|
1585
|
-
// loading and empty in --c-muted (
|
|
1585
|
+
// loading and empty in --c-muted (5.74:1 / 7.85:1, the Listbox's empty message color) and an error in --c-error (4.53:1 / 7.16:1).
|
|
1586
1586
|
@use '@carissa-io/components-async-autocomplete/scss' as async-autocomplete with (
|
|
1587
1587
|
$c-async-autocomplete-color: $var-text,
|
|
1588
1588
|
$c-async-autocomplete-min-height: 1.5em,
|
|
@@ -1597,3 +1597,58 @@
|
|
|
1597
1597
|
$c-async-autocomplete-empty-color: $var-muted,
|
|
1598
1598
|
$c-async-autocomplete-error-color: $var-error
|
|
1599
1599
|
);
|
|
1600
|
+
|
|
1601
|
+
// Section and container: layout only. Gutters of 1rem growing to 2rem and the three vertical rhythms are plain lengths; the
|
|
1602
|
+
// section title is --c-text (17.93:1 / 18.16:1) in the theme's h2 style and the lead paragraph is --c-muted (5.74:1 / 7.85:1).
|
|
1603
|
+
@use '@carissa-io/components-section/scss' as section with (
|
|
1604
|
+
$c-container-gutter: 1rem,
|
|
1605
|
+
$c-container-gutter-wide: 2rem,
|
|
1606
|
+
$c-section-spacing-sm: 2rem,
|
|
1607
|
+
$c-section-spacing-md: 4rem,
|
|
1608
|
+
$c-section-spacing-lg: 6rem,
|
|
1609
|
+
$c-section-header-gap: 0.75rem,
|
|
1610
|
+
$c-section-header-margin-bottom: 2rem,
|
|
1611
|
+
$c-section-title-font-size: $font-size-h2,
|
|
1612
|
+
$c-section-title-font-weight: $font-weight-black,
|
|
1613
|
+
$c-section-title-line-height: 1.2,
|
|
1614
|
+
$c-section-title-color: $var-text,
|
|
1615
|
+
$c-section-description-font-size: $font-size-lead,
|
|
1616
|
+
$c-section-description-line-height: 1.6,
|
|
1617
|
+
$c-section-description-color: $var-muted
|
|
1618
|
+
);
|
|
1619
|
+
|
|
1620
|
+
// FAQ: the accordion block above does the look (its stylesheet is forwarded by the faq one, so keep this block after it); the
|
|
1621
|
+
// answers are --c-text (17.93:1 / 18.16:1) at a 1.6 line height and the list is capped at a readable measure.
|
|
1622
|
+
@use '@carissa-io/components-faq/scss' as faq with (
|
|
1623
|
+
$c-faq-max-width: 48rem,
|
|
1624
|
+
$c-faq-answer-color: $var-text,
|
|
1625
|
+
$c-faq-answer-line-height: 1.6
|
|
1626
|
+
);
|
|
1627
|
+
|
|
1628
|
+
// Carousel: the arrows and the pause / play button are the secondary button (--c-muted border, --c-text glyph at 17.93:1 / 18.16:1, a
|
|
1629
|
+
// --c-surface-active hover), square like every control of the theme. Inactive dots are --c-muted and the
|
|
1630
|
+
// current one is --c-primary and longer (1.5rem against 0.625rem), so position is not told by colour alone. The ring is the
|
|
1631
|
+
// theme's --c-focus.
|
|
1632
|
+
@use '@carissa-io/components-carousel/scss' as carousel with (
|
|
1633
|
+
$c-carousel-gap: 1rem,
|
|
1634
|
+
$c-carousel-transition-duration: $transition-duration,
|
|
1635
|
+
$c-carousel-controls-gap: 1rem,
|
|
1636
|
+
$c-carousel-controls-margin-top: 1rem,
|
|
1637
|
+
$c-carousel-button-size: $min-height,
|
|
1638
|
+
$c-carousel-button-radius: $radius,
|
|
1639
|
+
$c-carousel-button-border-width: 1px,
|
|
1640
|
+
$c-carousel-button-border-color: $var-muted,
|
|
1641
|
+
$c-carousel-button-color: $var-text,
|
|
1642
|
+
$c-carousel-button-background: $var-background,
|
|
1643
|
+
$c-carousel-button-background-hover: $var-surface-active,
|
|
1644
|
+
$c-carousel-button-disabled-opacity: 0.5,
|
|
1645
|
+
$c-carousel-icon-size: 0.5rem,
|
|
1646
|
+
$c-carousel-icon-thickness: 2px,
|
|
1647
|
+
$c-carousel-dot-size: 0.625rem,
|
|
1648
|
+
$c-carousel-dot-size-current: 1.5rem,
|
|
1649
|
+
$c-carousel-dot-gap: 0.5rem,
|
|
1650
|
+
$c-carousel-dot-color: $var-muted,
|
|
1651
|
+
$c-carousel-dot-color-current: $var-primary,
|
|
1652
|
+
$c-carousel-focus-outline: $focus-width solid $var-focus,
|
|
1653
|
+
$c-carousel-focus-outline-offset: 2px
|
|
1654
|
+
);
|