@fusion.dev/helix-docs 0.205.2 → 0.207.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/README.md +22 -2
- package/content/angular.mdx +37 -4
- package/content/browser-support.mdx +3 -3
- package/content/building-on-the-headless-tier.mdx +84 -21
- package/content/charting.mdx +50 -0
- package/content/coding-agents.mdx +2 -1
- package/content/color-modes.mdx +2 -2
- package/content/color.mdx +35 -5
- package/content/diagnostics.mdx +255 -0
- package/content/graphs.mdx +6 -0
- package/content/iconography.mdx +31 -13
- package/content/installation.mdx +34 -10
- package/content/intent-reference.mdx +27 -3
- package/content/introduction.mdx +3 -2
- package/content/localization.mdx +86 -4
- package/content/maps.mdx +65 -13
- package/content/metrics.mdx +252 -249
- package/content/other-frameworks.mdx +52 -12
- package/content/overriding-a-component.mdx +11 -10
- package/content/react.mdx +15 -1
- package/content/recipes.mdx +18 -2
- package/content/sandbox.mdx +75 -25
- package/content/server-rendering.mdx +2 -2
- package/content/state-and-control.mdx +7 -1
- package/content/surfaces-and-separation.mdx +2 -1
- package/content/svelte.mdx +54 -8
- package/content/theme-builder.mdx +15 -3
- package/content/theming.mdx +5 -1
- package/content/tiers.mdx +15 -14
- package/content/using-helix-with-an-agent.mdx +12 -5
- package/content/using-the-elements.mdx +24 -23
- package/content/versioning.mdx +15 -8
- package/content/visual-axes.mdx +11 -4
- package/content/vue.mdx +28 -1
- package/content/without-a-bundler.mdx +9 -7
- package/dist/index.d.ts +1 -3
- package/dist/index.js +0 -1
- package/dist/pages.generated.js +7 -1
- package/dist/reference.d.ts +70 -6
- package/dist/reference.js +13 -2
- package/dist/sources.generated.js +1343 -458
- package/package.json +13 -12
package/README.md
CHANGED
|
@@ -1,15 +1,35 @@
|
|
|
1
1
|
# @fusion.dev/helix-docs
|
|
2
2
|
|
|
3
|
-
The Helix documentation as content: the pages,
|
|
3
|
+
The Helix documentation as content: the pages, the registry that names them,
|
|
4
|
+
and the renderer for the component reference.
|
|
4
5
|
|
|
5
6
|
```sh
|
|
6
7
|
npm install @fusion.dev/helix-docs
|
|
7
8
|
```
|
|
8
9
|
|
|
9
10
|
```js
|
|
10
|
-
import {
|
|
11
|
+
import { docSources, findPage, navigation, reference } from '@fusion.dev/helix-docs'
|
|
11
12
|
```
|
|
12
13
|
|
|
14
|
+
- `pages` is every page, each with its `slug`, `title`, `section`, and
|
|
15
|
+
`description`. `findPage(slug)` returns one page.
|
|
16
|
+
- `navigation()` returns the sidebar: each section in order, the pages under it
|
|
17
|
+
in the order a sidebar renders them, and each page's children.
|
|
18
|
+
- `sections` is the sections in order, and `findSection(title)` returns one.
|
|
19
|
+
- `docSources` holds each page's MDX, keyed by slug.
|
|
20
|
+
- `contentPath(page)` takes a page from `pages` and returns the path of its MDX
|
|
21
|
+
in the package, such as `content/theming.mdx`. Import the file as
|
|
22
|
+
`@fusion.dev/helix-docs/content/theming.mdx`.
|
|
23
|
+
- `reference(manifest, options)` renders a `custom-elements.json` as the
|
|
24
|
+
markdown component reference. `referenceFamilies(manifest)` returns each
|
|
25
|
+
family and its parts in the order the reference prints them.
|
|
26
|
+
|
|
27
|
+
The component catalog ships in each tier as `api.json` and `examples.json`,
|
|
28
|
+
such as `@fusion.dev/helix/api.json`: every family with its elements, imports,
|
|
29
|
+
and examples. An add-on package ships them too, listing the elements it adds
|
|
30
|
+
to a family: `@fusion.dev/helix-sandbox/api.json` lists its editor under the
|
|
31
|
+
Sandbox family.
|
|
32
|
+
|
|
13
33
|
Published as a package rather than served only from a site so that the
|
|
14
34
|
documentation carries the version of the library it documents. A docs package at
|
|
15
35
|
version x describes Helix at version x, which is why versioning here is per
|
package/content/angular.mdx
CHANGED
|
@@ -31,7 +31,8 @@ typos, in your other components.
|
|
|
31
31
|
|
|
32
32
|
```html
|
|
33
33
|
<helix-input
|
|
34
|
-
|
|
34
|
+
#field
|
|
35
|
+
(change)="name = field.value"
|
|
35
36
|
[value]="name"
|
|
36
37
|
/>
|
|
37
38
|
```
|
|
@@ -39,6 +40,10 @@ typos, in your other components.
|
|
|
39
40
|
`[prop]` sets a property, which a value that is not a string needs. `(event)`
|
|
40
41
|
binds with `addEventListener`, so use the event's own name.
|
|
41
42
|
|
|
43
|
+
`#field` gives the template a reference to the element, typed as its class once
|
|
44
|
+
you import its family. Under `strictTemplates`, `$event.target` is an
|
|
45
|
+
`EventTarget | null`, which has no `value`.
|
|
46
|
+
|
|
42
47
|
**Do not use `attr.` for a stateful property.** `[attr.value]="name"` writes the
|
|
43
48
|
attribute. The attribute seeds the control and is out of date as soon as someone
|
|
44
49
|
types in it. The property holds the current value.
|
|
@@ -50,9 +55,17 @@ checking that typings would feed, so Angular would not enforce a generated file.
|
|
|
50
55
|
We publish the manifest as `@fusion.dev/helix/custom-elements.json`, so you can
|
|
51
56
|
generate your own files from it.
|
|
52
57
|
|
|
53
|
-
As a result, a misspelled property fails without an error in Angular.
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
As a result, a misspelled property fails without an error in Angular. Check
|
|
59
|
+
property names in code review.
|
|
60
|
+
|
|
61
|
+
The other frameworks check a misspelled name to different degrees:
|
|
62
|
+
|
|
63
|
+
- In React, TypeScript reports a misspelled prop unless its name has a hyphen.
|
|
64
|
+
See [React](./react).
|
|
65
|
+
- In Vue, `vue-tsc` reports one only when `checkUnknownProps` is on. See
|
|
66
|
+
[Vue](./vue).
|
|
67
|
+
- In Svelte, `svelte-check` reports an attribute that the Helix tag does not
|
|
68
|
+
declare.
|
|
56
69
|
|
|
57
70
|
## Refuse a change
|
|
58
71
|
|
|
@@ -60,3 +73,23 @@ code review.
|
|
|
60
73
|
value you set and then applies its own changes. To refuse a change, listen for
|
|
61
74
|
the `helix-before-*` event and call `preventDefault()`. See
|
|
62
75
|
[State and control](./state-and-control).
|
|
76
|
+
|
|
77
|
+
To write your own value into a field you type into, set your signal and then
|
|
78
|
+
call `detectChanges()` on the component's `ChangeDetectorRef`:
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
private readonly view = inject(ChangeDetectorRef)
|
|
82
|
+
|
|
83
|
+
protected takeHandle(event: Event): void {
|
|
84
|
+
event.preventDefault()
|
|
85
|
+
const { value } = (event as CustomEvent<{ value: string }>).detail
|
|
86
|
+
this.handle.set(clean(value))
|
|
87
|
+
this.view.detectChanges()
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Without zone.js, Angular renders a signal change in a later task. A key that
|
|
92
|
+
arrives before that task lands in the text from before your value, and the keys
|
|
93
|
+
typed in between are lost. A barcode scanner, a password manager, and a test
|
|
94
|
+
send keys that fast. `detectChanges()` renders the change before your handler
|
|
95
|
+
returns.
|
|
@@ -13,7 +13,7 @@ support in older browsers. Your browser needs every feature Helix uses.
|
|
|
13
13
|
|
|
14
14
|
## What we test
|
|
15
15
|
|
|
16
|
-
We test in Chromium, through Playwright. The DOM specs run in it, and
|
|
16
|
+
We test in Chromium, through Playwright. The DOM specs run in it, and the pixel
|
|
17
17
|
baselines are captured in it, on Linux, with the network blocked.
|
|
18
18
|
|
|
19
19
|
We do not run the tests in Firefox or Safari. The rest of this page lists the
|
|
@@ -27,9 +27,9 @@ something broken, please report it. Our tests would not have caught it.
|
|
|
27
27
|
| Custom elements and shadow DOM | Everything |
|
|
28
28
|
| `ElementInternals` | Form participation, and ARIA that has to cross a shadow boundary |
|
|
29
29
|
| Popover API | Every overlay: menu, tooltip, select, combobox, dialog |
|
|
30
|
-
| `light-dark()` |
|
|
30
|
+
| `light-dark()` | Every color token, and each component color that differs between the modes |
|
|
31
31
|
| `oklch()` | Every color in the system |
|
|
32
|
-
| `:has()` |
|
|
32
|
+
| `:has()` | Relational styling, mostly of slotted content |
|
|
33
33
|
| `@starting-style` | Entry transitions on overlays |
|
|
34
34
|
| `:state()` | Every boolean state the library publishes: `open`, `checked`, `selected`, `invalid`, `read`, `has-label`, `settled`, `empty`, `controls` |
|
|
35
35
|
| `CSS.highlights` | Filter-match highlighting, in `Command` and `Combobox` |
|
|
@@ -47,9 +47,10 @@ headless manifest carries the static, so you can find it there.
|
|
|
47
47
|
**When a component renders another component, register both.**
|
|
48
48
|
|
|
49
49
|
If you register `acme-combobox` without `acme-listbox`, the panel renders a tag
|
|
50
|
-
that is not defined.
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
that is not defined. An unregistered custom element is an inert, unstyled inline
|
|
51
|
+
box, so the panel shows every option with no list around them, and typing
|
|
52
|
+
filters nothing. In development, the combobox says so once in the console and
|
|
53
|
+
names the tag to define.
|
|
53
54
|
|
|
54
55
|
[//]: # (renders)
|
|
55
56
|
|
|
@@ -89,7 +90,8 @@ everything those families render in turn. For example, `command` reaches
|
|
|
89
90
|
**The elements you write inside a component are yours to register as well.**
|
|
90
91
|
A select renders none of the options you write in it, so `acme-select` needs
|
|
91
92
|
your `acme-option` registered beside it. In development, a component holding a
|
|
92
|
-
child of its tier that nobody registered says so once
|
|
93
|
+
child of its tier that nobody registered says so once and names the tag to
|
|
94
|
+
define.
|
|
93
95
|
A listbox given `items` and a filter input given a `source` draw options of
|
|
94
96
|
your tier from data, and those need `acme-option` registered too.
|
|
95
97
|
|
|
@@ -102,7 +104,7 @@ generated table is always current.
|
|
|
102
104
|
|
|
103
105
|
### A `:not(:defined)` rule
|
|
104
106
|
|
|
105
|
-
`@fusion.dev/helix` ships an `elements.css` that hides each of its tags until
|
|
107
|
+
`@fusion.dev/helix-styles` ships an `elements.css` that hides each of its tags until
|
|
106
108
|
the tag's definition loads. Your page then does not show unstyled text that
|
|
107
109
|
changes into components. The headless package ships no such file, and no tool
|
|
108
110
|
can generate one for tags you have not named yet. Write the rule for your own
|
|
@@ -115,26 +117,85 @@ acme-listbox:not(:defined) {
|
|
|
115
117
|
}
|
|
116
118
|
```
|
|
117
119
|
|
|
118
|
-
|
|
120
|
+
The rule hides each element until its definition loads, and the layout
|
|
121
|
+
settles when the elements upgrade.
|
|
122
|
+
|
|
123
|
+
### A rule that hides the `live` parts
|
|
124
|
+
|
|
125
|
+
A `live` part is a live region. It holds words only a screen reader should
|
|
126
|
+
read, such as how many options a filter left, and the headless tier draws it
|
|
127
|
+
as ordinary text. Hide each one visually with a clip, which keeps it in the
|
|
128
|
+
accessibility tree:
|
|
129
|
+
|
|
130
|
+
```css
|
|
131
|
+
acme-combobox::part(live),
|
|
132
|
+
acme-combobox::part(listbox-live) {
|
|
133
|
+
block-size: 1px;
|
|
134
|
+
clip-path: inset(50%);
|
|
135
|
+
inline-size: 1px;
|
|
136
|
+
overflow: hidden;
|
|
137
|
+
position: absolute;
|
|
138
|
+
white-space: nowrap;
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
`display: none` and `visibility: hidden` take a region out of the
|
|
143
|
+
accessibility tree as well, and a screen reader then hears nothing. A
|
|
144
|
+
component forwards the `live` part of a component it renders under a name of
|
|
145
|
+
its own, such as `listbox-live` on Combobox. The styled tier hides every one
|
|
146
|
+
of them.
|
|
119
147
|
|
|
120
148
|
### Typings for your tags
|
|
121
149
|
|
|
122
|
-
Your typings come from a manifest of your package
|
|
123
|
-
`@
|
|
124
|
-
inherit from ours. Name each Helix package you extend and where its manifest is:
|
|
150
|
+
Your typings come from a custom elements manifest of your package, written by
|
|
151
|
+
`@custom-elements-manifest/analyzer`:
|
|
125
152
|
|
|
126
153
|
```sh
|
|
127
|
-
|
|
128
|
-
--
|
|
129
|
-
--dependency @fusion.dev/helix-headless=node_modules/@fusion.dev/helix-headless/custom-elements.json \
|
|
130
|
-
--dependency @fusion.dev/helix-core=node_modules/@fusion.dev/helix-core/custom-elements.json \
|
|
131
|
-
> custom-elements.json
|
|
154
|
+
npx @custom-elements-manifest/analyzer analyze --litelement --dependencies \
|
|
155
|
+
--globs "src/**/*.ts"
|
|
132
156
|
```
|
|
133
157
|
|
|
134
|
-
|
|
158
|
+
Each flag does one job, and the manifest is incomplete without either:
|
|
159
|
+
|
|
160
|
+
- `--dependencies` reads the `custom-elements.json` each Helix package ships
|
|
161
|
+
and names in its `package.json`, so `acme-combobox` gets the members,
|
|
162
|
+
attributes, events, slots and parts it inherits from ours.
|
|
163
|
+
- `--litelement` reads Lit's decorators, so the properties you declare with
|
|
164
|
+
`@property` are attributes too.
|
|
165
|
+
|
|
166
|
+
Then run a typings generator over the manifest. Our own typings start from
|
|
135
167
|
`@wc-toolkit/jsx-types` and `@wc-toolkit/vuejs-types`. The typings for
|
|
136
|
-
`acme-combobox` then include the
|
|
137
|
-
|
|
168
|
+
`acme-combobox` then include the members it inherits, as well as the ones you
|
|
169
|
+
wrote.
|
|
170
|
+
|
|
171
|
+
The generated file names Helix's event classes, such as
|
|
172
|
+
`HelixBeforeChangeEvent`, without importing them. Add one line at its top that
|
|
173
|
+
imports the names TypeScript reports as missing:
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
import type { HelixBeforeChangeEvent, HelixFilterEvent } from '@fusion.dev/helix-core'
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Without that line, a project that sets `skipLibCheck` gets no error, and each
|
|
180
|
+
of those event handlers is typed `any`.
|
|
181
|
+
|
|
182
|
+
For a few tags in React, you can skip the generator. Each headless family
|
|
183
|
+
publishes its props in `@fusion.dev/helix-headless/jsx`, and your tag takes
|
|
184
|
+
them:
|
|
185
|
+
|
|
186
|
+
```ts
|
|
187
|
+
import type { HelixHeadlessComboboxProps } from '@fusion.dev/helix-headless/jsx'
|
|
188
|
+
|
|
189
|
+
declare module 'react' {
|
|
190
|
+
namespace JSX {
|
|
191
|
+
interface IntrinsicElements {
|
|
192
|
+
'acme-combobox': HelixHeadlessComboboxProps
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
A subclass that adds properties joins its own to them with `&`.
|
|
138
199
|
|
|
139
200
|
`@fusion.dev/helix-cem`, the step that runs those generators for our packages
|
|
140
201
|
and corrects what they write, is not published. It is build tooling for this
|
|
@@ -202,10 +263,12 @@ findings as data. The rules check what your components document and write:
|
|
|
202
263
|
|
|
203
264
|
### Tree-shaking
|
|
204
265
|
|
|
205
|
-
`@fusion.dev/helix-headless` declares `sideEffects:
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
266
|
+
`@fusion.dev/helix-headless` declares `"sideEffects": true`, because its
|
|
267
|
+
modules register elements when you import them. A bundler that treated them as
|
|
268
|
+
free of side effects would drop a registration, and a tag would never upgrade.
|
|
269
|
+
Import each family from its own entry, such as
|
|
270
|
+
`@fusion.dev/helix-headless/combobox`, so your bundle carries only the families
|
|
271
|
+
you use.
|
|
209
272
|
|
|
210
273
|
### Documented parts
|
|
211
274
|
|
package/content/charting.mdx
CHANGED
|
@@ -169,6 +169,56 @@ bar there, and a heatmap draws the cell with no tone. The readings after the gap
|
|
|
169
169
|
stay under their own labels, and the tooltip for that row still shows the
|
|
170
170
|
row's cells.
|
|
171
171
|
|
|
172
|
+
A cell holds a number when its whole text reads as one, such as `1200` or
|
|
173
|
+
`-3.5`. A formatted number, such as `1,200` or `$1.2k`, is a gap. To chart a
|
|
174
|
+
formatted cell, write its number in `data-value`:
|
|
175
|
+
|
|
176
|
+
```html
|
|
177
|
+
<tr><th>Q1</th><td data-value="1200">$1.2k</td><td data-value="800">$800</td></tr>
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
The chart reads `data-value` when a cell has one, and the cell's text otherwise.
|
|
181
|
+
The table and the tooltip still show `$1.2k`.
|
|
182
|
+
|
|
183
|
+
## Charts with many readings
|
|
184
|
+
|
|
185
|
+
A chart builds what it can show, and that is bounded by its size. The readings
|
|
186
|
+
themselves are read again each time the table or the data changes.
|
|
187
|
+
|
|
188
|
+
- **Names on the axis.** `Line Chart`, `Area Chart`, and `Bar Chart` draw every
|
|
189
|
+
reading's name where every name fits. Where they do not, the chart draws a
|
|
190
|
+
regular share of them, and always the first and the last. Where every row
|
|
191
|
+
header holds a `<time>`, the names drawn start a period, such as the first
|
|
192
|
+
reading of each month or each year. Where the names are numbers in order,
|
|
193
|
+
such as years, they are round numbers. Other names are drawn every so many
|
|
194
|
+
readings, counted from the first. The chart works out the share again when it
|
|
195
|
+
is resized. The tooltip and the keys still say each reading's own name.
|
|
196
|
+
- **Gridlines.** `gridlines="category"` rules the readings whose names are
|
|
197
|
+
drawn.
|
|
198
|
+
- **Lines.** Where a line has more readings than the plot has pixels across, it
|
|
199
|
+
is drawn through the points those pixels can show: in each column of pixels,
|
|
200
|
+
the first reading, the lowest, the highest, and the last.
|
|
201
|
+
- **Markers.** `markers` marks every reading, with one path for each series.
|
|
202
|
+
- **Columns.** `Bar Chart` draws each column as an element while every column
|
|
203
|
+
and the space between two categories are at least a pixel wide. Past that, it
|
|
204
|
+
draws each series' columns as one path, each column of pixels as tall as the
|
|
205
|
+
tallest column in it, and draws the category the tooltip describes again over
|
|
206
|
+
them, at least two pixels thick.
|
|
207
|
+
- **Points.** `Scatter Chart` draws each series' points as paths. Points that
|
|
208
|
+
overlap are drawn in separate groups, up to four deep, so each keeps its edge
|
|
209
|
+
and a cluster reads darker. The point the keys rest on is drawn again over
|
|
210
|
+
them.
|
|
211
|
+
- **The table drawn from `data`.** Past a few hundred readings, the hidden table
|
|
212
|
+
holds one page of them at a time. Its markup gives a screen reader the number
|
|
213
|
+
of rows in the whole table and the place of each row, and the words after it
|
|
214
|
+
say which readings the page holds. Two buttons after it show the previous and
|
|
215
|
+
the next page. You press them with a screen reader as you read. They are left
|
|
216
|
+
out of the tab order, so the plot stays the chart's one tab stop. The keys on
|
|
217
|
+
the plot move through every reading.
|
|
218
|
+
- **A table on the page.** A chart reads the whole table that `for` names, and
|
|
219
|
+
the table is part of your page, however many rows it has. Where the readings
|
|
220
|
+
are too many to put in the document, draw the chart from `data`.
|
|
221
|
+
|
|
172
222
|
## Series colors
|
|
173
223
|
|
|
174
224
|
Helix has twenty-four series color tokens, in order, from
|
|
@@ -163,7 +163,8 @@ agent uses most:
|
|
|
163
163
|
`helix scan`, `helix diagnostics --once`, and `helix theme audit` check what an
|
|
164
164
|
agent wrote, and the MCP server runs the same checks.
|
|
165
165
|
[Using Helix with an agent](./using-helix-with-an-agent#check-the-code-you-wrote)
|
|
166
|
-
lists what each finds
|
|
166
|
+
lists what each finds, and [Diagnostics](./diagnostics) sets the checks up in
|
|
167
|
+
your app and in CI.
|
|
167
168
|
|
|
168
169
|
## The index
|
|
169
170
|
|
package/content/color-modes.mdx
CHANGED
|
@@ -22,8 +22,8 @@ class, or a second copy of any value.
|
|
|
22
22
|
Each token is written once, with its light and dark values in `light-dark()`.
|
|
23
23
|
The `color-scheme` property alone decides which value applies. `color-scheme`
|
|
24
24
|
inherits, so one property sets the mode for an element and everything inside
|
|
25
|
-
it.
|
|
26
|
-
|
|
25
|
+
it. A component that sets a color of its own for each mode uses `light-dark()`
|
|
26
|
+
the same way.
|
|
27
27
|
|
|
28
28
|
## Set the mode
|
|
29
29
|
|
package/content/color.mdx
CHANGED
|
@@ -34,11 +34,20 @@ Choose a surface by where the element sits relative to the page. This is the
|
|
|
34
34
|
choice people most often get wrong. See [Surfaces and
|
|
35
35
|
separation](./surfaces-and-separation).
|
|
36
36
|
|
|
37
|
+
A field is filled with `well`: 5% of `foreground` laid over whatever the field
|
|
38
|
+
sits on, so its color depends on the surface under the field.
|
|
39
|
+
|
|
37
40
|
### Inks
|
|
38
41
|
|
|
39
42
|
Inks are the colors that go on grounds. The base ink is `foreground`.
|
|
40
43
|
|
|
41
|
-
- `foreground-muted`
|
|
44
|
+
- `foreground-muted` is for text that recedes and is still read, such as a
|
|
45
|
+
placeholder, a hint, or a caption. The engine solves it to the contrast
|
|
46
|
+
target.
|
|
47
|
+
- `foreground-subtle` recedes further. It is for marks that are not text, such
|
|
48
|
+
as a separator, a chevron, or a grip, and for the text of a disabled control.
|
|
49
|
+
It is a fixed step of the gray ramp, and the engine does not solve it, so its
|
|
50
|
+
contrast is not guaranteed. Use `foreground-muted` for text that is read.
|
|
42
51
|
- Text on a filled color takes the ink named for that fill:
|
|
43
52
|
- `foreground-on-primary` on `primary-surface`
|
|
44
53
|
- `foreground-on-accent` on `accent-surface`
|
|
@@ -52,8 +61,16 @@ Intent colors show what something means.
|
|
|
52
61
|
`-subtle` variants. With no brand color set, both are ink: near-black in
|
|
53
62
|
light mode and near-white in dark mode.
|
|
54
63
|
- `info`, `success`, `warning`, and `danger` are for status. Each has a
|
|
55
|
-
`-surface`
|
|
56
|
-
|
|
64
|
+
`-surface` variant, the filled ground that carries `foreground-on-status`,
|
|
65
|
+
such as a danger button or a badge in a status tone, and a `-surface-hover`
|
|
66
|
+
variant for that fill under the pointer.
|
|
67
|
+
|
|
68
|
+
### Rise and fall
|
|
69
|
+
|
|
70
|
+
`rise` and `fall` color a value by which way it moved, such as a price. They
|
|
71
|
+
are `success` and `danger` unless you set them. Mainland China, Taiwan, and
|
|
72
|
+
Japan draw a rise in red, so a page for one of those markets swaps the two. See
|
|
73
|
+
[Rise and fall colors](./localization#rise-and-fall-colors).
|
|
57
74
|
|
|
58
75
|
### Series
|
|
59
76
|
|
|
@@ -98,8 +115,21 @@ OKLCH lets the theme engine *solve* for a palette from your brand color. See
|
|
|
98
115
|
|
|
99
116
|
The engine measures each ink against the ground it will be painted on. A brand
|
|
100
117
|
color that already meets the target there is used as it is. For any other color,
|
|
101
|
-
the engine searches for the lightness that meets the target.
|
|
102
|
-
|
|
118
|
+
the engine searches for the lightness that meets the target. A pair that cannot
|
|
119
|
+
meet its target, such as one with a color you pinned, is reported in
|
|
120
|
+
`violations`.
|
|
121
|
+
|
|
122
|
+
`foreground` and `foreground-muted` are also written in fields, so the engine
|
|
123
|
+
solves them against the well over the page, a card, a raised surface, a dialog,
|
|
124
|
+
and a sunken surface. The report names each of these grounds as the well over
|
|
125
|
+
its surface, such as `color-well over color-surface`.
|
|
126
|
+
|
|
127
|
+
`foreground-subtle` is the one ink the engine does not solve. The range of
|
|
128
|
+
readable grays has room for one quiet ink, and `foreground-muted` is that ink, so
|
|
129
|
+
`foreground-subtle` stays a fixed step of the stylesheet's gray ramp and its
|
|
130
|
+
contrast is not guaranteed. A component paints its quiet text in
|
|
131
|
+
`foreground-muted`, and keeps `foreground-subtle` for marks that are not text and
|
|
132
|
+
for the text of a disabled control.
|
|
103
133
|
|
|
104
134
|
The engine can solve only the pairs it knows about, so we check two things:
|
|
105
135
|
|