@fusion.dev/helix-docs 0.104.1 → 0.105.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/content/accessibility.mdx +92 -71
- package/content/angular.mdx +26 -24
- package/content/browser-support.mdx +61 -58
- package/content/building-on-the-headless-tier.mdx +100 -74
- package/content/charting.mdx +98 -79
- package/content/coding-agents.mdx +87 -69
- package/content/color-modes.mdx +40 -37
- package/content/color.mdx +67 -54
- package/content/composition.mdx +85 -83
- package/content/elevation-and-material.mdx +32 -29
- package/content/events.mdx +77 -65
- package/content/forms.mdx +69 -58
- package/content/iconography.mdx +75 -71
- package/content/installation.mdx +77 -68
- package/content/intent-reference.mdx +59 -54
- package/content/introduction.mdx +25 -23
- package/content/localization.mdx +122 -82
- package/content/maps.mdx +222 -0
- package/content/metrics.mdx +294 -297
- package/content/motion.mdx +44 -36
- package/content/other-frameworks.mdx +33 -31
- package/content/overlays.mdx +72 -54
- package/content/overriding-a-component.mdx +85 -74
- package/content/react.mdx +72 -64
- package/content/recipes.mdx +64 -47
- package/content/routing.mdx +100 -93
- package/content/sandbox.mdx +39 -39
- package/content/server-rendering.mdx +95 -84
- package/content/shape-and-borders.mdx +44 -37
- package/content/size-and-density.mdx +51 -46
- package/content/space-and-size.mdx +41 -34
- package/content/state-and-control.mdx +63 -51
- package/content/surfaces-and-separation.mdx +55 -53
- package/content/svelte.mdx +20 -19
- package/content/theme-builder.mdx +42 -31
- package/content/theming.mdx +58 -51
- package/content/tiers.mdx +69 -61
- package/content/tokens.mdx +72 -53
- package/content/typography.mdx +47 -47
- package/content/using-helix-with-an-agent.mdx +147 -115
- package/content/using-the-elements.mdx +55 -50
- package/content/versioning.mdx +42 -35
- package/content/visual-axes.mdx +168 -146
- package/content/vue.mdx +24 -24
- package/content/without-a-bundler.mdx +40 -23
- package/dist/pages.generated.js +49 -43
- package/dist/sources.generated.js +3337 -2680
- package/package.json +3 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: The files an AI agent can read to write Helix code, and where to find each one.
|
|
3
3
|
order: 4
|
|
4
4
|
section: Getting started
|
|
5
5
|
title: Coding agents
|
|
@@ -7,9 +7,9 @@ title: Coding agents
|
|
|
7
7
|
|
|
8
8
|
# Coding agents
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
We publish Helix as text for agents that write Helix code, so an agent does not
|
|
11
|
+
need to read the rendered website. Three sources give it the library as text.
|
|
12
|
+
We generate all three from the same sources as this site.
|
|
13
13
|
|
|
14
14
|
## The manifest
|
|
15
15
|
|
|
@@ -18,43 +18,54 @@ https://fusion.dev/helix/custom-elements.json
|
|
|
18
18
|
@fusion.dev/helix/custom-elements.json
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
The URL and the package path serve the same file. A package path works only
|
|
22
|
+
from a `node_modules` folder. An agent that found Helix through `llms.txt` can
|
|
23
|
+
reach this site and has no checkout, so it needs the URL.
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
class, every slot, every part, every custom property. It is what the framework
|
|
27
|
-
typings, the reference documentation and the site's component pages are all
|
|
28
|
-
generated from, so it cannot disagree with them.
|
|
25
|
+
The manifest lists:
|
|
29
26
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
- every element
|
|
28
|
+
- every property, with its literal type union
|
|
29
|
+
- every event, with its class
|
|
30
|
+
- every slot
|
|
31
|
+
- every part
|
|
32
|
+
- every custom property
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
write, where `ButtonEmphasis` tells them to go and look somewhere else.
|
|
34
|
+
We generate the framework typings, the reference documentation, and the site's
|
|
35
|
+
component pages from the manifest, so they always match it.
|
|
37
36
|
|
|
38
|
-
|
|
37
|
+
**If a tag is not in the manifest, it does not exist.** An agent can check every
|
|
38
|
+
tag and value it writes against the file, so an invented component is caught. A
|
|
39
|
+
prop value outside a declared union is invalid.
|
|
40
|
+
|
|
41
|
+
For the same reason, the analyzer requires literal unions for property types.
|
|
42
|
+
`'ghost' | 'outlined' | 'solid' | 'subtle'` shows you what to write. A named
|
|
43
|
+
type such as `ButtonEmphasis` sends you somewhere else to look.
|
|
44
|
+
|
|
45
|
+
## Markdown and JSON for each component family
|
|
39
46
|
|
|
40
47
|
```
|
|
41
48
|
/components/<family>.md
|
|
42
49
|
/components/<family>.json
|
|
43
50
|
```
|
|
44
51
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
These are static files. The `.md` file has:
|
|
53
|
+
|
|
54
|
+
- the family's metadata
|
|
55
|
+
- every element's description and API tables
|
|
56
|
+
- the examples
|
|
57
|
+
|
|
58
|
+
The HTML page leaves the examples out on purpose. The page lists what a
|
|
59
|
+
component can do, and the sandbox beside it shows what the component looks
|
|
60
|
+
like. Keeping pictures out of the reference keeps it the one place you can trust
|
|
61
|
+
to be complete. An agent cannot use the sandbox, and it reads an example as
|
|
62
|
+
text, so the `.md` file includes the examples.
|
|
52
63
|
|
|
53
|
-
The `.json`
|
|
64
|
+
The `.json` file has the same family as structured data.
|
|
54
65
|
|
|
55
|
-
##
|
|
66
|
+
## Rules the build checks
|
|
56
67
|
|
|
57
|
-
|
|
68
|
+
Code that looks right can still fail these checks:
|
|
58
69
|
|
|
59
70
|
| Rule | Check |
|
|
60
71
|
|---|---|
|
|
@@ -63,11 +74,11 @@ These are the difference between code that looks right and code that passes:
|
|
|
63
74
|
| A documented CSS hook must be read | `helix component --only hooks` |
|
|
64
75
|
| A visual property draws from its axis | `helix component`'s `axes` |
|
|
65
76
|
| A form control styles with `:disabled` | `helix component --only disabled` |
|
|
66
|
-
| A component that animates
|
|
77
|
+
| A component that animates supports reduced motion | `helix component --only motion` |
|
|
67
78
|
| No component reads a primitive token | `helix component`'s `tokens` |
|
|
68
79
|
|
|
69
|
-
If you
|
|
70
|
-
|
|
80
|
+
If you generate Helix code, watch the first two rules. Breaking them produces
|
|
81
|
+
output that looks like it works and is wrong.
|
|
71
82
|
|
|
72
83
|
## The index
|
|
73
84
|
|
|
@@ -75,57 +86,64 @@ working-looking output that is wrong.
|
|
|
75
86
|
/llms.txt
|
|
76
87
|
```
|
|
77
88
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
89
|
+
`llms.txt` lists every page on the site, in groups. Each entry links to the
|
|
90
|
+
page's `.md` file and has a one-sentence summary. We generate it from the same
|
|
91
|
+
route registry as the sitemap. Every page appears in it, and every entry in it
|
|
92
|
+
is a page that exists.
|
|
82
93
|
|
|
83
|
-
Start
|
|
84
|
-
|
|
85
|
-
number typed into prose
|
|
94
|
+
Start with `llms.txt`. In one request, it names every page on the site and the
|
|
95
|
+
two machine-readable sources above. This guide gives no page count, because a
|
|
96
|
+
number typed into prose goes stale.
|
|
86
97
|
|
|
87
|
-
##
|
|
98
|
+
## Links on each component page
|
|
88
99
|
|
|
89
|
-
|
|
90
|
-
Markdown**, and links that hand the document's URL to Claude or to Cursor. The
|
|
91
|
-
URL rather than the contents, because the URL stays current and a pasted copy
|
|
92
|
-
starts going stale the moment it is pasted.
|
|
100
|
+
Each family page has a menu beside its title with:
|
|
93
101
|
|
|
94
|
-
|
|
102
|
+
- **View Markdown**
|
|
103
|
+
- **Copy Markdown**
|
|
104
|
+
- links that send the document's URL to Claude or to Cursor
|
|
105
|
+
|
|
106
|
+
The links send the URL, because the URL stays current. A pasted copy starts to
|
|
107
|
+
go stale as soon as you paste it.
|
|
108
|
+
|
|
109
|
+
## Compute a theme with `helix mcp`
|
|
95
110
|
|
|
96
111
|
```sh
|
|
97
112
|
helix mcp
|
|
98
113
|
```
|
|
99
114
|
|
|
100
|
-
The three
|
|
101
|
-
|
|
102
|
-
color
|
|
103
|
-
|
|
115
|
+
The three sources above are fixed sets. Every tag, token, and example is
|
|
116
|
+
published, and an agent can fetch it. None of them has the theme for *your*
|
|
117
|
+
brand color. The input is a color, and there are infinitely many colors, so
|
|
118
|
+
Helix has to compute the theme when an agent requests it.
|
|
119
|
+
|
|
120
|
+
`helix mcp` runs an MCP server over stdio with two tools:
|
|
121
|
+
|
|
122
|
+
- `helix_audit_theme` measures every foreground against the background it is
|
|
123
|
+
painted on. It reports each pair with its ratio and target.
|
|
124
|
+
- `helix_derive_theme` returns the CSS.
|
|
104
125
|
|
|
105
|
-
|
|
106
|
-
`helix_audit_theme`, which measures every foreground against the ground it is
|
|
107
|
-
really painted on and reports each pair with its ratio and target, and
|
|
108
|
-
`helix_derive_theme`, which returns the CSS. Both take the same JSON a
|
|
109
|
-
`helix.theme.json` holds.
|
|
126
|
+
Both take the same JSON that a `helix.theme.json` file holds.
|
|
110
127
|
|
|
111
|
-
|
|
112
|
-
`helix theme build
|
|
113
|
-
warning above it, and an agent does not read warnings.
|
|
128
|
+
**`helix mcp` does not return a palette that fails its own targets**, the same
|
|
129
|
+
as `helix theme build`. A failing palette pasted into a stylesheet is worse than
|
|
130
|
+
a warning above it, and an agent does not read warnings.
|
|
114
131
|
|
|
115
|
-
|
|
116
|
-
service
|
|
117
|
-
binary you installed
|
|
132
|
+
You run `helix mcp` yourself, and we do not host it. A server we operated would
|
|
133
|
+
be one more service between you and your own tokens. `helix mcp` is a
|
|
134
|
+
subcommand of a binary you installed. It talks to a client you chose and makes
|
|
135
|
+
no network requests.
|
|
118
136
|
|
|
119
|
-
## What
|
|
137
|
+
## What we do not publish for agents
|
|
120
138
|
|
|
121
|
-
**`llms-full.txt`, or any other whole-library download.**
|
|
122
|
-
page
|
|
123
|
-
|
|
139
|
+
**`llms-full.txt`, or any other whole-library download.** A single file with
|
|
140
|
+
every page goes out of date as soon as anything changes. Each link in `llms.txt`
|
|
141
|
+
can be cached on its own and stays current on its own.
|
|
124
142
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
143
|
+
The two sources already here cover what such a file would be for. `llms.txt` is
|
|
144
|
+
the index, in one request, and each family's `.md` file is its document. Fetch
|
|
145
|
+
the families you use.
|
|
128
146
|
|
|
129
|
-
**A search index.** The site has
|
|
130
|
-
query yet
|
|
131
|
-
than most search APIs
|
|
147
|
+
**A search index.** The site has a search index for people. There is nothing an
|
|
148
|
+
agent can query yet. Reading `llms.txt` and the documents it names takes less
|
|
149
|
+
work than learning most search APIs.
|
package/content/color-modes.mdx
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: Switch between light and dark mode with one attribute. Each token declares both values once.
|
|
3
3
|
section: Foundations
|
|
4
4
|
title: Color modes
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Color modes
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
One attribute switches between light and dark mode. Each token declares its
|
|
10
|
+
light and dark values together. You do not need a second stylesheet, a `.dark`
|
|
11
|
+
class, or a second copy of any value.
|
|
11
12
|
|
|
12
|
-
## How
|
|
13
|
+
## How color modes work
|
|
13
14
|
|
|
14
15
|
```css
|
|
15
16
|
:root {
|
|
@@ -18,21 +19,20 @@ stylesheet, no `.dark` class to toggle, and nothing to remember to update twice.
|
|
|
18
19
|
}
|
|
19
20
|
```
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
Each token is written once, with its light and dark values in `light-dark()`.
|
|
23
|
+
The `color-scheme` property alone decides which value applies. `color-scheme`
|
|
24
|
+
inherits, so one property sets the mode for an element and everything inside
|
|
25
|
+
it. The shipped stylesheets use `light-dark()` in 156 declarations, 71 of them
|
|
26
|
+
in the token layer.
|
|
26
27
|
|
|
27
|
-
##
|
|
28
|
+
## Set the mode
|
|
28
29
|
|
|
29
30
|
```html
|
|
30
31
|
<html data-color-mode="dark">
|
|
31
32
|
```
|
|
32
33
|
|
|
33
|
-
`[data-color-mode="light"]` and `[data-color-mode="dark"]` set `color-scheme
|
|
34
|
-
|
|
35
|
-
than only on the root:
|
|
34
|
+
`[data-color-mode="light"]` and `[data-color-mode="dark"]` set `color-scheme`.
|
|
35
|
+
Because `color-scheme` inherits, **the attribute works on any element**:
|
|
36
36
|
|
|
37
37
|
```html
|
|
38
38
|
<div data-color-mode="light">
|
|
@@ -40,24 +40,24 @@ than only on the root:
|
|
|
40
40
|
</div>
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
two documents.
|
|
43
|
+
The theme builder uses the same attribute to show a component in light and dark
|
|
44
|
+
mode side by side in one document.
|
|
46
45
|
|
|
47
|
-
##
|
|
46
|
+
## Follow the operating system
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
system decides.
|
|
48
|
+
When you do not set a mode, `:root` declares `color-scheme: light dark`, and the
|
|
49
|
+
operating system decides the mode. This is the default, and it is usually the
|
|
50
|
+
right choice.
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
from the mode
|
|
55
|
-
|
|
52
|
+
The token layer uses a `prefers-color-scheme` media query in one case.
|
|
53
|
+
`light-dark()` chooses between two values. A value that has to be *computed*
|
|
54
|
+
from the mode cannot use `light-dark()`, so a media query checks which mode is
|
|
55
|
+
current.
|
|
56
56
|
|
|
57
|
-
##
|
|
57
|
+
## Toast uses the opposite mode
|
|
58
58
|
|
|
59
|
-
`Toast` renders in the opposite mode to the page it is on
|
|
60
|
-
|
|
59
|
+
`Toast` renders in the opposite mode to the page it is on. The base layer sets
|
|
60
|
+
this with one rule:
|
|
61
61
|
|
|
62
62
|
```css
|
|
63
63
|
helix-toast:not([data-color-mode]) {
|
|
@@ -65,14 +65,13 @@ helix-toast:not([data-color-mode]) {
|
|
|
65
65
|
}
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
-
A toast
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
told.
|
|
68
|
+
A toast sits over the page. The opposite mode sets it apart from the page
|
|
69
|
+
without a border. To choose a toast's mode yourself, set `data-color-mode` on
|
|
70
|
+
it. The rule applies only to a toast without that attribute.
|
|
72
71
|
|
|
73
|
-
##
|
|
72
|
+
## Colors in your own CSS
|
|
74
73
|
|
|
75
|
-
Write `light-dark()
|
|
74
|
+
Write your own colors with `light-dark()`. You do not need anything else:
|
|
76
75
|
|
|
77
76
|
```css
|
|
78
77
|
.callout {
|
|
@@ -80,8 +79,12 @@ Write `light-dark()` for your own colors and set nothing else:
|
|
|
80
79
|
}
|
|
81
80
|
```
|
|
82
81
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
The color then follows:
|
|
83
|
+
|
|
84
|
+
- The page's mode
|
|
85
|
+
- The mode of a subtree that sets its own
|
|
86
|
+
- The operating system, when nothing sets a mode
|
|
87
|
+
|
|
88
|
+
Do not write a `prefers-color-scheme` query for it, and do not select on the
|
|
89
|
+
`data-color-mode` attribute. Both stop working when a subtree sets its own mode,
|
|
90
|
+
and this design exists to make that easy.
|
package/content/color.mdx
CHANGED
|
@@ -1,81 +1,95 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: The roles,
|
|
2
|
+
description: The color roles, why Helix uses OKLCH, and how the engine meets contrast targets.
|
|
3
3
|
section: Foundations
|
|
4
4
|
title: Color
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Color
|
|
8
8
|
|
|
9
|
-
Seventy-four of the library's 185 tokens are
|
|
10
|
-
theme
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
Seventy-four of the library's 185 tokens are colors, and they make up most of a
|
|
10
|
+
theme. Each color token is named for its role. No token is named for how it
|
|
11
|
+
looks, because a name like `--brand-blue-500` becomes wrong as soon as you change
|
|
12
|
+
the theme.
|
|
13
13
|
|
|
14
|
-
##
|
|
14
|
+
## Color roles
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
### Grounds
|
|
17
|
+
|
|
18
|
+
Grounds are the colors that content sits on. `background` is the page itself.
|
|
19
|
+
The surfaces above it form an ordered ladder:
|
|
18
20
|
|
|
19
21
|
[//]: # (tokens:surface-ladder)
|
|
20
22
|
|
|
21
23
|
| Token | Sample | For |
|
|
22
24
|
| --- | --- | --- |
|
|
23
|
-
| `--helix-color-background` | <span data-token-swatch style={{ background: 'var(--helix-color-background)' }} /> | The page.
|
|
24
|
-
| `--helix-color-surface` | <span data-token-swatch style={{ background: 'var(--helix-color-surface)' }} /> | A
|
|
25
|
-
| `--helix-color-surface-raised` | <span data-token-swatch style={{ background: 'var(--helix-color-surface-raised)' }} /> |
|
|
26
|
-
| `--helix-color-surface-overlay` | <span data-token-swatch style={{ background: 'var(--helix-color-surface-overlay)' }} /> |
|
|
27
|
-
| `--helix-color-surface-sunken` | <span data-token-swatch style={{ background: 'var(--helix-color-surface-sunken)' }} /> | A
|
|
25
|
+
| `--helix-color-background` | <span data-token-swatch style={{ background: 'var(--helix-color-background)' }} /> | The page background. Every other surface sits on it. |
|
|
26
|
+
| `--helix-color-surface` | <span data-token-swatch style={{ background: 'var(--helix-color-surface)' }} /> | A surface on the page, such as a card or a panel. The separation policy sets it apart with a fill, a border, or a shadow. |
|
|
27
|
+
| `--helix-color-surface-raised` | <span data-token-swatch style={{ background: 'var(--helix-color-surface-raised)' }} /> | A raised surface on the page, such as a selected tab or a hovered row. Its fill is one step down the ramp. |
|
|
28
|
+
| `--helix-color-surface-overlay` | <span data-token-swatch style={{ background: 'var(--helix-color-surface-overlay)' }} /> | A surface over the page, such as a menu, a popover, or a dialog. Its shadow sets it apart. |
|
|
29
|
+
| `--helix-color-surface-sunken` | <span data-token-swatch style={{ background: 'var(--helix-color-surface-sunken)' }} /> | A recessed surface that holds a value, such as an input, a track, or a groove. Its fill sets it apart. |
|
|
28
30
|
|
|
29
31
|
[//]: # (/tokens)
|
|
30
32
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
Choose a surface by where the element sits relative to the page. This is the
|
|
34
|
+
choice people most often get wrong. See [Surfaces and
|
|
33
35
|
separation](./surfaces-and-separation).
|
|
34
36
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
that
|
|
37
|
+
### Inks
|
|
38
|
+
|
|
39
|
+
Inks are the colors that go on grounds. The base ink is `foreground`.
|
|
40
|
+
|
|
41
|
+
- `foreground-muted` and `foreground-subtle` are for text that recedes.
|
|
42
|
+
- `foreground-on-accent` is for text on a filled accent color.
|
|
43
|
+
|
|
44
|
+
### Intent
|
|
45
|
+
|
|
46
|
+
Intent colors show what something means.
|
|
47
|
+
|
|
48
|
+
- `primary` and `accent` are for emphasis. Each has `-hover`, `-active`, and
|
|
49
|
+
`-subtle` variants.
|
|
50
|
+
- `info`, `success`, `warning`, and `danger` are for status. Each has a
|
|
51
|
+
`-surface` and a `-surface-hover` variant for the tinted box that holds the
|
|
52
|
+
message.
|
|
53
|
+
|
|
54
|
+
### Series
|
|
55
|
+
|
|
56
|
+
Helix has twenty-four series colors for charts. They are ordered, so a chart
|
|
57
|
+
with three lines uses the first three. We chose the colors so that the first
|
|
58
|
+
ones in the list stay easy to tell apart, however many a chart uses.
|
|
59
|
+
|
|
60
|
+
### Syntax
|
|
38
61
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
for the tinted box the message sits in.
|
|
62
|
+
The eight syntax roles for code are `callable`, `comment`, `constant`,
|
|
63
|
+
`invalid`, `keyword`, `name`, `string`, and `tag`. A full editor theme has more
|
|
64
|
+
roles. Helix has fewer because code in documentation only needs to be read.
|
|
43
65
|
|
|
44
|
-
|
|
45
|
-
chart with three lines uses the first three, and they are chosen to stay
|
|
46
|
-
distinguishable in that order rather than to look good as a full set.
|
|
66
|
+
## Why colors use OKLCH
|
|
47
67
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
68
|
+
Every Helix color is written in OKLCH. In sRGB, equal numeric steps do not look
|
|
69
|
+
equal, which makes ramps and contrast math unreliable. A ramp with even numeric
|
|
70
|
+
steps looks uneven. A contrast solver that works in sRGB cannot converge on a
|
|
71
|
+
target that it can measure.
|
|
51
72
|
|
|
52
|
-
|
|
73
|
+
OKLCH lets the theme engine *solve* for a palette from your brand color. See
|
|
74
|
+
[Deriving a theme](./theming).
|
|
53
75
|
|
|
54
|
-
|
|
55
|
-
perceptual steps, which makes both ramp generation and contrast arithmetic
|
|
56
|
-
unreliable: a ramp that is even by the numbers looks uneven, and a contrast
|
|
57
|
-
solver working in the wrong space cannot converge on a target it can measure.
|
|
76
|
+
## How the engine meets contrast targets
|
|
58
77
|
|
|
59
|
-
|
|
60
|
-
for
|
|
61
|
-
|
|
78
|
+
The engine measures each ink against the ground it will be painted on. It then
|
|
79
|
+
searches for the lightness that meets the target. Every pair it produces meets
|
|
80
|
+
the target.
|
|
62
81
|
|
|
63
|
-
|
|
82
|
+
The engine can solve only the pairs it knows about, so we check two things:
|
|
64
83
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
value and checking it afterwards. Every pairing it produces meets the target by
|
|
68
|
-
construction.
|
|
84
|
+
- We compare the engine's surface model with what the components paint.
|
|
85
|
+
- We measure every pair on a rendered page.
|
|
69
86
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
eleven rules in the library set an ink and a ground together, where 165 set only
|
|
75
|
-
an ink and 112 only a ground, and a pairing the cascade assembled is still a
|
|
76
|
-
pairing a reader has to be able to read.
|
|
87
|
+
The second check finds pairs that no single CSS rule states. Only eleven rules
|
|
88
|
+
in the library set an ink and a ground together. Another 165 set only an ink,
|
|
89
|
+
and 112 set only a ground. The cascade combines them into the rest of the
|
|
90
|
+
pairs, and each of those pairs must still be readable.
|
|
77
91
|
|
|
78
|
-
##
|
|
92
|
+
## Use only semantic tokens
|
|
79
93
|
|
|
80
94
|
```css
|
|
81
95
|
/* Yours to read. */
|
|
@@ -85,8 +99,7 @@ color: var(--helix-color-foreground-muted);
|
|
|
85
99
|
color: var(--_helix-neutral-500);
|
|
86
100
|
```
|
|
87
101
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
of which ramp it happened to be.
|
|
102
|
+
Primitive tokens such as `--_helix-neutral-500` belong to `helix/styles`. The
|
|
103
|
+
underscore marks them as private. Components use only semantic tokens, such as
|
|
104
|
+
`--helix-color-primary`. A theme can change what a semantic token resolves to,
|
|
105
|
+
and no component depends on which step of which ramp a color comes from.
|