@senakster/senui-tokens 0.0.0-stage → 1.1.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/CHANGELOG.md +27 -0
- package/LICENSE +21 -0
- package/README.md +163 -2
- package/dist/index.d.ts +469 -0
- package/dist/index.js +449 -0
- package/dist/tokens.css +112 -0
- package/package.json +37 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# @senakster/senui-tokens
|
|
2
|
+
|
|
3
|
+
## 1.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- e1cbee4: Adds `--senui-motion-duration-rotation` (960 ms): one turn of essential continuous rotation, such as a progress spinner, and nothing else. It has no reduced-motion value: slow it with the reduce factor instead, as `calc(var(--senui-motion-duration-rotation) * (4 - 3 * var(--senui-motion-reduce)))`, so a consumer who sets `--senui-motion-reduce` to `0` slows it too. The `motion.duration` descriptions now say that colour and opacity keep their duration under reduced motion.
|
|
8
|
+
|
|
9
|
+
## 1.0.0
|
|
10
|
+
|
|
11
|
+
### Major Changes
|
|
12
|
+
|
|
13
|
+
- 7952797: The first stable release. From 1.0.0 on, a component, prop, value, class, token or export is renamed or removed only in a major version, after a minor that deprecates it: a deprecated prop warns once in development and says what to use instead, and the docs mark it. New tokens, components and props come in minor versions.
|
|
14
|
+
|
|
15
|
+
`@senakster/senui-tokens` is a peer dependency of `@senakster/senui`, so an app has exactly one copy of the tokens: install both packages, and load `@senakster/senui-tokens/tokens.css` before any component styles. A major version of the tokens is always a major version of the components too.
|
|
16
|
+
|
|
17
|
+
`tokens.css` declares the cascade layers `senui.tokens`, `senui.base` and `senui.components`, so your own unlayered styles override every token and component without raising specificity. Colours follow the page's colour scheme through `light-dark()`, and motion follows `prefers-reduced-motion`. Override a token on `:root, [data-theme]`; a subtree with `data-theme="light"` or `data-theme="dark"` gets its own background and text colour.
|
|
18
|
+
|
|
19
|
+
Load every component's styles with `@senakster/senui/styles.css`, or only the ones you use with `@senakster/senui/styles/<Name>.css`. A component's stylesheet loads the styles of the components it renders, so `styles/Dialog.css` brings Button's. Every module is its own file in the package, so a bundler keeps only the components you import.
|
|
20
|
+
|
|
21
|
+
Each component's accessibility is documented as a contract in `components.json` and on its docs page, including what your app must still do. Some manual screen-reader and keyboard runs predate later changes to their component; the docs mark those runs as not re-tested.
|
|
22
|
+
|
|
23
|
+
### Minor Changes
|
|
24
|
+
|
|
25
|
+
- 9459bf1: Add the `--senui-motion-easing-linear` token, for continuous motion such as the loading spinner.
|
|
26
|
+
- 9459bf1: Add the `--senui-color-bg-backdrop` token (the scrim behind a modal) and `--senui-size-dialog-sm`, `-md` and `-lg` (dialog widths).
|
|
27
|
+
- 9459bf1: Add the `--senui-size-illustration-sm` and `-lg` tokens (an illustration beside text, and above it).
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 senakster
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,164 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @senakster/senui-tokens
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Design tokens for senui: CSS custom properties in `@layer senui.tokens`, plus a typed JS map.
|
|
4
|
+
|
|
5
|
+
```css
|
|
6
|
+
@import '@senakster/senui-tokens/tokens.css';
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { tokens } from '@senakster/senui-tokens';
|
|
11
|
+
tokens['color.fg.default'].cssVar; // '--senui-color-fg-default'
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Every token in `tokens.css` is public API. Renaming or removing one is a major version.
|
|
15
|
+
|
|
16
|
+
## Writing tokens
|
|
17
|
+
|
|
18
|
+
Tokens are written by hand in `src/*.tokens.json`, in the
|
|
19
|
+
[DTCG 2025.10](https://www.designtokens.org/tr/2025.10/format/) format, and built by
|
|
20
|
+
`pnpm build` (`node sd.config.mjs && tsdown`). The pipeline is described in ADR-0004.
|
|
21
|
+
|
|
22
|
+
[`examples/example.tokens.json`](examples/example.tokens.json) is a complete example covering
|
|
23
|
+
every category and every `$extensions.senui` key. It isn't built or shipped, but a test builds it,
|
|
24
|
+
so it always passes the pipeline's checks. Copy from it freely; the values are placeholders.
|
|
25
|
+
|
|
26
|
+
### Tiers
|
|
27
|
+
|
|
28
|
+
- **Primitives** go under a top-level `primitive` group: `primitive.color.blue.600`. They are
|
|
29
|
+
never emitted. A token that aliases one compiles to its resolved value, so consumers can't
|
|
30
|
+
depend on primitive names.
|
|
31
|
+
- **Semantic tokens** are every other top-level group (`color`, `space`, `radius`, `font`,
|
|
32
|
+
`motion`, `elevation`, `size`). The path becomes the custom property: `color.fg.danger` →
|
|
33
|
+
`--senui-color-fg-danger`.
|
|
34
|
+
- **Component tokens** (`--senui-button-bg`) are not defined here. Each component defines its own
|
|
35
|
+
with semantic defaults.
|
|
36
|
+
|
|
37
|
+
**State variants are suffixed siblings, never children** (ADR-0005): `color.bg.accent`,
|
|
38
|
+
`color.bg.accent-hover`, `color.bg.accent-active`. A base token stays a leaf, so adding a state
|
|
39
|
+
never renames it.
|
|
40
|
+
|
|
41
|
+
### Values
|
|
42
|
+
|
|
43
|
+
Use the DTCG object forms:
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{ "$type": "color", "$value": { "colorSpace": "oklch", "components": [0.55, 0.2, 260] } }
|
|
47
|
+
{ "$type": "dimension", "$value": { "value": 12, "unit": "px" } }
|
|
48
|
+
{ "$type": "duration", "$value": { "value": 120, "unit": "ms" } }
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Colours are authored in oklch and emitted as `oklch()`. Any colour space DTCG allows also works,
|
|
52
|
+
and it is kept as authored.
|
|
53
|
+
|
|
54
|
+
Make a shadow's `color` a reference to a public colour token (`"{color.shadow}"`). It is then
|
|
55
|
+
emitted as `var(--senui-color-shadow)`, so the shadow follows that token's dark value. A
|
|
56
|
+
primitive reference or an inline colour is resolved to a single value and stays the same in both
|
|
57
|
+
themes.
|
|
58
|
+
|
|
59
|
+
### `$extensions.senui`
|
|
60
|
+
|
|
61
|
+
| Key | On | Meaning |
|
|
62
|
+
| --------------- | ------------------- | -------------------------------------------------------------------------------------------- |
|
|
63
|
+
| `dark` | every public colour | Required. The dark-theme value or alias; the build emits `light-dark(<$value>, <dark>)`. |
|
|
64
|
+
| `contrast` | public colours | `[{ "against": "{color.bg.default}", "min": 4.5 }, …]`: at least one pair, unless `surface`. |
|
|
65
|
+
| `surface` | public colours | `true` opts the colour out of contrast pairs. For backgrounds and WCAG-exempt colours only. |
|
|
66
|
+
| `reducedMotion` | any token | The value under `prefers-reduced-motion: reduce`. |
|
|
67
|
+
|
|
68
|
+
`dark` is only allowed on colour tokens, because `light-dark()` only takes colours.
|
|
69
|
+
|
|
70
|
+
Every public colour needs either contrast pairs or `"surface": true` (ADR-0005). Use `surface` for
|
|
71
|
+
backgrounds and fills, and for colours WCAG exempts: disabled controls, decorative dividers and
|
|
72
|
+
shadows. Say which in the token's `$description`, because opting out has to be visible.
|
|
73
|
+
|
|
74
|
+
Each `contrast` pair is checked in both themes, after compositing translucent colours. An
|
|
75
|
+
out-of-sRGB colour is measured both gamut-mapped and clipped, and the lower ratio counts. Use 4.5
|
|
76
|
+
for text and 3 for non-text (borders, focus rings, icons). A pair below its minimum fails the build
|
|
77
|
+
and names the token, the background, the theme and the ratio, to three decimals. So does a
|
|
78
|
+
malformed pair, such as a missing or misspelled `min`.
|
|
79
|
+
|
|
80
|
+
### Rules the CSS adds
|
|
81
|
+
|
|
82
|
+
- **Themed subtrees are self-contained.** `tokens.css` sets `background-color`, `color` and
|
|
83
|
+
`accent-color` on every `[data-theme]` element, in `@layer senui.base`. A token set must define
|
|
84
|
+
`color.bg.default`, `color.fg.default` and `color.fg.accent`, or the build fails.
|
|
85
|
+
- **Motion is multiplied by `--senui-motion-reduce`**, which is `1` normally and `0` under reduced
|
|
86
|
+
motion. Components write `calc(var(--senui-motion-distance-md) * var(--senui-motion-reduce))`, so
|
|
87
|
+
a consumer who overrides a distance can't bring motion back.
|
|
88
|
+
- **Focus rings** are drawn as `outline: var(--senui-focus-ring-width) solid
|
|
89
|
+
var(--senui-color-focus-ring)` with `outline-offset: var(--senui-focus-ring-offset)`. That puts
|
|
90
|
+
the ring on the page background, which is what its contrast pairs are checked against. Never use
|
|
91
|
+
`box-shadow` for a ring: forced-colours mode removes it.
|
|
92
|
+
- **Elevated surfaces** (`bg.raised` plus an `elevation` shadow) also need a border, for the same
|
|
93
|
+
reason.
|
|
94
|
+
|
|
95
|
+
Example:
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"primitive": {
|
|
100
|
+
"color": {
|
|
101
|
+
"ink": {
|
|
102
|
+
"$type": "color",
|
|
103
|
+
"$value": { "colorSpace": "oklch", "components": [0.2, 0.02, 260] }
|
|
104
|
+
},
|
|
105
|
+
"paper": {
|
|
106
|
+
"$type": "color",
|
|
107
|
+
"$value": { "colorSpace": "oklch", "components": [0.98, 0.005, 260] }
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
"color": {
|
|
112
|
+
"bg": {
|
|
113
|
+
"default": {
|
|
114
|
+
"$type": "color",
|
|
115
|
+
"$value": "{primitive.color.paper}",
|
|
116
|
+
"$extensions": { "senui": { "dark": "{primitive.color.ink}", "surface": true } }
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
"fg": {
|
|
120
|
+
"default": {
|
|
121
|
+
"$type": "color",
|
|
122
|
+
"$description": "Body text",
|
|
123
|
+
"$value": "{primitive.color.ink}",
|
|
124
|
+
"$extensions": {
|
|
125
|
+
"senui": {
|
|
126
|
+
"dark": "{primitive.color.paper}",
|
|
127
|
+
"contrast": [{ "against": "{color.bg.default}", "min": 4.5 }]
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Theming
|
|
137
|
+
|
|
138
|
+
`color-scheme: light dark` is set on `:where(:root)`, so the default follows the operating system.
|
|
139
|
+
`data-theme="light"` or `data-theme="dark"` on any element fixes the theme for that subtree, and
|
|
140
|
+
that element gets its own background and text colour.
|
|
141
|
+
|
|
142
|
+
A light-only app opts out of dark mode with one unlayered rule:
|
|
143
|
+
|
|
144
|
+
```css
|
|
145
|
+
:root {
|
|
146
|
+
color-scheme: light;
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
To override a colour, give both themes. A single value replaces the dark value too, and it skips
|
|
151
|
+
the contrast check that the token passed:
|
|
152
|
+
|
|
153
|
+
```css
|
|
154
|
+
:root,
|
|
155
|
+
[data-theme] {
|
|
156
|
+
--senui-color-fg-accent: light-dark(oklch(50% 0.15 150), oklch(75% 0.15 150));
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Tokens are declared on `:root` and again on every `[data-theme]` element (ADR-0010). Build tools
|
|
161
|
+
that don't yet target `light-dark()`, including Vite's default production build, rewrite it into
|
|
162
|
+
variables that resolve where the token is declared; declaring it on each themed subtree keeps those
|
|
163
|
+
subtrees correct. The cost is that an override on `:root` alone stops at the first `data-theme`
|
|
164
|
+
element, so include `[data-theme]` in your selector.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
//#region src/generated/tokens.d.ts
|
|
2
|
+
export declare const tokens: {
|
|
3
|
+
readonly "border.width.default": {
|
|
4
|
+
readonly cssVar: "--senui-border-width-default";
|
|
5
|
+
readonly type: "dimension";
|
|
6
|
+
readonly value: "1px";
|
|
7
|
+
};
|
|
8
|
+
readonly "border.width.strong": {
|
|
9
|
+
readonly cssVar: "--senui-border-width-strong";
|
|
10
|
+
readonly type: "dimension";
|
|
11
|
+
readonly value: "2px";
|
|
12
|
+
readonly description: "Invalid and selected controls, so state is not shown by colour alone.";
|
|
13
|
+
};
|
|
14
|
+
readonly "color.bg.accent": {
|
|
15
|
+
readonly cssVar: "--senui-color-bg-accent";
|
|
16
|
+
readonly type: "color";
|
|
17
|
+
readonly value: "oklch(52% 0.18 260)";
|
|
18
|
+
readonly description: "Fill for primary actions.";
|
|
19
|
+
readonly dark: "oklch(72% 0.14 255)";
|
|
20
|
+
};
|
|
21
|
+
readonly "color.bg.accent-active": {
|
|
22
|
+
readonly cssVar: "--senui-color-bg-accent-active";
|
|
23
|
+
readonly type: "color";
|
|
24
|
+
readonly value: "oklch(40% 0.15 260)";
|
|
25
|
+
readonly description: "bg.accent while pressed.";
|
|
26
|
+
readonly dark: "oklch(86% 0.07 255)";
|
|
27
|
+
};
|
|
28
|
+
readonly "color.bg.accent-hover": {
|
|
29
|
+
readonly cssVar: "--senui-color-bg-accent-hover";
|
|
30
|
+
readonly type: "color";
|
|
31
|
+
readonly value: "oklch(46% 0.17 260)";
|
|
32
|
+
readonly description: "bg.accent under the pointer.";
|
|
33
|
+
readonly dark: "oklch(80% 0.11 255)";
|
|
34
|
+
};
|
|
35
|
+
readonly "color.bg.backdrop": {
|
|
36
|
+
readonly cssVar: "--senui-color-bg-backdrop";
|
|
37
|
+
readonly type: "color";
|
|
38
|
+
readonly value: "rgb(0% 0% 0% / 0.5)";
|
|
39
|
+
readonly description: "The scrim behind a modal (the dialog's ::backdrop). Translucent, so the page stays visible but recedes. Darker in dark mode, where the page is already dark. Never a text background.";
|
|
40
|
+
readonly dark: "rgb(0% 0% 0% / 0.7)";
|
|
41
|
+
};
|
|
42
|
+
readonly "color.bg.danger": {
|
|
43
|
+
readonly cssVar: "--senui-color-bg-danger";
|
|
44
|
+
readonly type: "color";
|
|
45
|
+
readonly value: "oklch(53% 0.2 27)";
|
|
46
|
+
readonly description: "Fill for destructive actions.";
|
|
47
|
+
readonly dark: "oklch(72% 0.16 25)";
|
|
48
|
+
};
|
|
49
|
+
readonly "color.bg.danger-active": {
|
|
50
|
+
readonly cssVar: "--senui-color-bg-danger-active";
|
|
51
|
+
readonly type: "color";
|
|
52
|
+
readonly value: "oklch(41% 0.17 27)";
|
|
53
|
+
readonly description: "bg.danger while pressed.";
|
|
54
|
+
readonly dark: "oklch(86% 0.07 25)";
|
|
55
|
+
};
|
|
56
|
+
readonly "color.bg.danger-hover": {
|
|
57
|
+
readonly cssVar: "--senui-color-bg-danger-hover";
|
|
58
|
+
readonly type: "color";
|
|
59
|
+
readonly value: "oklch(47% 0.19 27)";
|
|
60
|
+
readonly description: "bg.danger under the pointer.";
|
|
61
|
+
readonly dark: "oklch(80% 0.11 25)";
|
|
62
|
+
};
|
|
63
|
+
readonly "color.bg.default": {
|
|
64
|
+
readonly cssVar: "--senui-color-bg-default";
|
|
65
|
+
readonly type: "color";
|
|
66
|
+
readonly value: "oklch(99% 0.003 260)";
|
|
67
|
+
readonly description: "Page and surface background.";
|
|
68
|
+
readonly dark: "oklch(16% 0.012 260)";
|
|
69
|
+
};
|
|
70
|
+
readonly "color.bg.disabled": {
|
|
71
|
+
readonly cssVar: "--senui-color-bg-disabled";
|
|
72
|
+
readonly type: "color";
|
|
73
|
+
readonly value: "oklch(97% 0.005 260)";
|
|
74
|
+
readonly description: "Fill of a disabled control. Exempt from contrast (WCAG 1.4.3, 1.4.11).";
|
|
75
|
+
readonly dark: "oklch(22% 0.015 260)";
|
|
76
|
+
};
|
|
77
|
+
readonly "color.bg.raised": {
|
|
78
|
+
readonly cssVar: "--senui-color-bg-raised";
|
|
79
|
+
readonly type: "color";
|
|
80
|
+
readonly value: "oklch(99% 0.003 260)";
|
|
81
|
+
readonly description: "Popovers, menus, dialogs. Lighter than bg.default in dark mode, because shadows barely show there. Pair with a border: forced-colours mode removes shadows.";
|
|
82
|
+
readonly dark: "oklch(19% 0.013 260)";
|
|
83
|
+
};
|
|
84
|
+
readonly "color.bg.subtle": {
|
|
85
|
+
readonly cssVar: "--senui-color-bg-subtle";
|
|
86
|
+
readonly type: "color";
|
|
87
|
+
readonly value: "oklch(97% 0.005 260)";
|
|
88
|
+
readonly description: "Recessed areas: wells, table stripes, secondary buttons.";
|
|
89
|
+
readonly dark: "oklch(22% 0.015 260)";
|
|
90
|
+
};
|
|
91
|
+
readonly "color.bg.subtle-active": {
|
|
92
|
+
readonly cssVar: "--senui-color-bg-subtle-active";
|
|
93
|
+
readonly type: "color";
|
|
94
|
+
readonly value: "oklch(91% 0.008 260)";
|
|
95
|
+
readonly description: "bg.subtle while pressed.";
|
|
96
|
+
readonly dark: "oklch(30% 0.015 260)";
|
|
97
|
+
};
|
|
98
|
+
readonly "color.bg.subtle-hover": {
|
|
99
|
+
readonly cssVar: "--senui-color-bg-subtle-hover";
|
|
100
|
+
readonly type: "color";
|
|
101
|
+
readonly value: "oklch(94% 0.007 260)";
|
|
102
|
+
readonly description: "bg.subtle under the pointer.";
|
|
103
|
+
readonly dark: "oklch(26% 0.015 260)";
|
|
104
|
+
};
|
|
105
|
+
readonly "color.border.danger": {
|
|
106
|
+
readonly cssVar: "--senui-color-border-danger";
|
|
107
|
+
readonly type: "color";
|
|
108
|
+
readonly value: "oklch(53% 0.2 27)";
|
|
109
|
+
readonly description: "Outline of an invalid field (WCAG 1.4.11). Use with border.width.strong and an error message, never alone (1.4.1).";
|
|
110
|
+
readonly dark: "oklch(72% 0.16 25)";
|
|
111
|
+
};
|
|
112
|
+
readonly "color.border.default": {
|
|
113
|
+
readonly cssVar: "--senui-color-border-default";
|
|
114
|
+
readonly type: "color";
|
|
115
|
+
readonly value: "oklch(85% 0.01 260)";
|
|
116
|
+
readonly description: "Decorative dividers. Too faint to identify a control; use border.strong for that.";
|
|
117
|
+
readonly dark: "oklch(30% 0.015 260)";
|
|
118
|
+
};
|
|
119
|
+
readonly "color.border.disabled": {
|
|
120
|
+
readonly cssVar: "--senui-color-border-disabled";
|
|
121
|
+
readonly type: "color";
|
|
122
|
+
readonly value: "oklch(85% 0.01 260)";
|
|
123
|
+
readonly description: "Outline of a disabled control. Exempt from contrast (WCAG 1.4.11).";
|
|
124
|
+
readonly dark: "oklch(30% 0.015 260)";
|
|
125
|
+
};
|
|
126
|
+
readonly "color.border.strong": {
|
|
127
|
+
readonly cssVar: "--senui-color-border-strong";
|
|
128
|
+
readonly type: "color";
|
|
129
|
+
readonly value: "oklch(60% 0.015 260)";
|
|
130
|
+
readonly description: "Borders that identify a control, such as input outlines (WCAG 1.4.11).";
|
|
131
|
+
readonly dark: "oklch(60% 0.015 260)";
|
|
132
|
+
};
|
|
133
|
+
readonly "color.fg.accent": {
|
|
134
|
+
readonly cssVar: "--senui-color-fg-accent";
|
|
135
|
+
readonly type: "color";
|
|
136
|
+
readonly value: "oklch(52% 0.18 260)";
|
|
137
|
+
readonly description: "Links and accent text.";
|
|
138
|
+
readonly dark: "oklch(72% 0.14 255)";
|
|
139
|
+
};
|
|
140
|
+
readonly "color.fg.danger": {
|
|
141
|
+
readonly cssVar: "--senui-color-fg-danger";
|
|
142
|
+
readonly type: "color";
|
|
143
|
+
readonly value: "oklch(53% 0.2 27)";
|
|
144
|
+
readonly description: "Error messages. Colour alone must never carry an error (WCAG 1.4.1): pair it with text or an icon.";
|
|
145
|
+
readonly dark: "oklch(72% 0.16 25)";
|
|
146
|
+
};
|
|
147
|
+
readonly "color.fg.default": {
|
|
148
|
+
readonly cssVar: "--senui-color-fg-default";
|
|
149
|
+
readonly type: "color";
|
|
150
|
+
readonly value: "oklch(22% 0.015 260)";
|
|
151
|
+
readonly description: "Body text.";
|
|
152
|
+
readonly dark: "oklch(97% 0.005 260)";
|
|
153
|
+
};
|
|
154
|
+
readonly "color.fg.disabled": {
|
|
155
|
+
readonly cssVar: "--senui-color-fg-disabled";
|
|
156
|
+
readonly type: "color";
|
|
157
|
+
readonly value: "oklch(60% 0.015 260)";
|
|
158
|
+
readonly description: "Text of a disabled control. Exempt from contrast (WCAG 1.4.3).";
|
|
159
|
+
readonly dark: "oklch(50% 0.015 260)";
|
|
160
|
+
};
|
|
161
|
+
readonly "color.fg.muted": {
|
|
162
|
+
readonly cssVar: "--senui-color-fg-muted";
|
|
163
|
+
readonly type: "color";
|
|
164
|
+
readonly value: "oklch(50% 0.015 260)";
|
|
165
|
+
readonly description: "Secondary text: hints, captions, placeholders.";
|
|
166
|
+
readonly dark: "oklch(85% 0.01 260)";
|
|
167
|
+
};
|
|
168
|
+
readonly "color.fg.on-accent": {
|
|
169
|
+
readonly cssVar: "--senui-color-fg-on-accent";
|
|
170
|
+
readonly type: "color";
|
|
171
|
+
readonly value: "oklch(99% 0.003 260)";
|
|
172
|
+
readonly description: "Text and icons on the accent fills.";
|
|
173
|
+
readonly dark: "oklch(16% 0.012 260)";
|
|
174
|
+
};
|
|
175
|
+
readonly "color.fg.on-danger": {
|
|
176
|
+
readonly cssVar: "--senui-color-fg-on-danger";
|
|
177
|
+
readonly type: "color";
|
|
178
|
+
readonly value: "oklch(99% 0.003 260)";
|
|
179
|
+
readonly description: "Text and icons on the danger fills.";
|
|
180
|
+
readonly dark: "oklch(16% 0.012 260)";
|
|
181
|
+
};
|
|
182
|
+
readonly "color.focus.ring": {
|
|
183
|
+
readonly cssVar: "--senui-color-focus-ring";
|
|
184
|
+
readonly type: "color";
|
|
185
|
+
readonly value: "oklch(52% 0.18 260)";
|
|
186
|
+
readonly description: "Focus indicator (WCAG 1.4.11, 2.4.7). Drawn as an outline offset by focus.ring-offset, so it sits on the page background, never on a fill (ADR-0005).";
|
|
187
|
+
readonly dark: "oklch(72% 0.14 255)";
|
|
188
|
+
};
|
|
189
|
+
readonly "color.shadow": {
|
|
190
|
+
readonly cssVar: "--senui-color-shadow";
|
|
191
|
+
readonly type: "color";
|
|
192
|
+
readonly value: "rgb(0% 0% 0% / 0.12)";
|
|
193
|
+
readonly description: "Shadow colour used by the elevation tokens. Decorative.";
|
|
194
|
+
readonly dark: "rgb(0% 0% 0% / 0.5)";
|
|
195
|
+
};
|
|
196
|
+
readonly "elevation.1": {
|
|
197
|
+
readonly cssVar: "--senui-elevation-1";
|
|
198
|
+
readonly type: "shadow";
|
|
199
|
+
readonly value: "0px 1px 2px 0px var(--senui-color-shadow)";
|
|
200
|
+
};
|
|
201
|
+
readonly "elevation.2": {
|
|
202
|
+
readonly cssVar: "--senui-elevation-2";
|
|
203
|
+
readonly type: "shadow";
|
|
204
|
+
readonly value: "0px 4px 12px 0px var(--senui-color-shadow)";
|
|
205
|
+
};
|
|
206
|
+
readonly "focus.ring-offset": {
|
|
207
|
+
readonly cssVar: "--senui-focus-ring-offset";
|
|
208
|
+
readonly type: "dimension";
|
|
209
|
+
readonly value: "2px";
|
|
210
|
+
readonly description: "Gap between a control and its focus ring, so the ring sits on the page background (ADR-0005).";
|
|
211
|
+
};
|
|
212
|
+
readonly "focus.ring-width": {
|
|
213
|
+
readonly cssVar: "--senui-focus-ring-width";
|
|
214
|
+
readonly type: "dimension";
|
|
215
|
+
readonly value: "2px";
|
|
216
|
+
readonly description: "Outline width of the focus ring.";
|
|
217
|
+
};
|
|
218
|
+
readonly "font.family.mono": {
|
|
219
|
+
readonly cssVar: "--senui-font-family-mono";
|
|
220
|
+
readonly type: "fontFamily";
|
|
221
|
+
readonly value: "ui-monospace, 'SF Mono', Menlo, Consolas, 'Cascadia Mono', 'Liberation Mono', monospace";
|
|
222
|
+
};
|
|
223
|
+
readonly "font.family.sans": {
|
|
224
|
+
readonly cssVar: "--senui-font-family-sans";
|
|
225
|
+
readonly type: "fontFamily";
|
|
226
|
+
readonly value: "system-ui, sans-serif";
|
|
227
|
+
};
|
|
228
|
+
readonly "font.line-height.normal": {
|
|
229
|
+
readonly cssVar: "--senui-font-line-height-normal";
|
|
230
|
+
readonly type: "number";
|
|
231
|
+
readonly value: "1.5";
|
|
232
|
+
};
|
|
233
|
+
readonly "font.line-height.tight": {
|
|
234
|
+
readonly cssVar: "--senui-font-line-height-tight";
|
|
235
|
+
readonly type: "number";
|
|
236
|
+
readonly value: "1.25";
|
|
237
|
+
};
|
|
238
|
+
readonly "font.size.lg": {
|
|
239
|
+
readonly cssVar: "--senui-font-size-lg";
|
|
240
|
+
readonly type: "dimension";
|
|
241
|
+
readonly value: "1.25rem";
|
|
242
|
+
};
|
|
243
|
+
readonly "font.size.md": {
|
|
244
|
+
readonly cssVar: "--senui-font-size-md";
|
|
245
|
+
readonly type: "dimension";
|
|
246
|
+
readonly value: "1rem";
|
|
247
|
+
};
|
|
248
|
+
readonly "font.size.sm": {
|
|
249
|
+
readonly cssVar: "--senui-font-size-sm";
|
|
250
|
+
readonly type: "dimension";
|
|
251
|
+
readonly value: "0.875rem";
|
|
252
|
+
};
|
|
253
|
+
readonly "font.weight.bold": {
|
|
254
|
+
readonly cssVar: "--senui-font-weight-bold";
|
|
255
|
+
readonly type: "fontWeight";
|
|
256
|
+
readonly value: "700";
|
|
257
|
+
};
|
|
258
|
+
readonly "font.weight.medium": {
|
|
259
|
+
readonly cssVar: "--senui-font-weight-medium";
|
|
260
|
+
readonly type: "fontWeight";
|
|
261
|
+
readonly value: "500";
|
|
262
|
+
};
|
|
263
|
+
readonly "font.weight.regular": {
|
|
264
|
+
readonly cssVar: "--senui-font-weight-regular";
|
|
265
|
+
readonly type: "fontWeight";
|
|
266
|
+
readonly value: "400";
|
|
267
|
+
};
|
|
268
|
+
readonly "motion.distance.md": {
|
|
269
|
+
readonly cssVar: "--senui-motion-distance-md";
|
|
270
|
+
readonly type: "dimension";
|
|
271
|
+
readonly value: "8px";
|
|
272
|
+
readonly reducedMotion: "0px";
|
|
273
|
+
};
|
|
274
|
+
readonly "motion.distance.sm": {
|
|
275
|
+
readonly cssVar: "--senui-motion-distance-sm";
|
|
276
|
+
readonly type: "dimension";
|
|
277
|
+
readonly value: "4px";
|
|
278
|
+
readonly reducedMotion: "0px";
|
|
279
|
+
};
|
|
280
|
+
readonly "motion.duration.fast": {
|
|
281
|
+
readonly cssVar: "--senui-motion-duration-fast";
|
|
282
|
+
readonly type: "duration";
|
|
283
|
+
readonly value: "120ms";
|
|
284
|
+
};
|
|
285
|
+
readonly "motion.duration.moderate": {
|
|
286
|
+
readonly cssVar: "--senui-motion-duration-moderate";
|
|
287
|
+
readonly type: "duration";
|
|
288
|
+
readonly value: "200ms";
|
|
289
|
+
};
|
|
290
|
+
readonly "motion.duration.rotation": {
|
|
291
|
+
readonly cssVar: "--senui-motion-duration-rotation";
|
|
292
|
+
readonly type: "duration";
|
|
293
|
+
readonly value: "960ms";
|
|
294
|
+
readonly description: "One turn of essential continuous rotation (a progress spinner), and nothing else. Slow it by the factor rather than stopping it: × (4 − 3 × motion.reduce) (ADR-0017, ADR-0024).";
|
|
295
|
+
};
|
|
296
|
+
readonly "motion.duration.slow": {
|
|
297
|
+
readonly cssVar: "--senui-motion-duration-slow";
|
|
298
|
+
readonly type: "duration";
|
|
299
|
+
readonly value: "320ms";
|
|
300
|
+
};
|
|
301
|
+
readonly "motion.easing.enter": {
|
|
302
|
+
readonly cssVar: "--senui-motion-easing-enter";
|
|
303
|
+
readonly type: "cubicBezier";
|
|
304
|
+
readonly value: "cubic-bezier(0, 0, 0, 1)";
|
|
305
|
+
};
|
|
306
|
+
readonly "motion.easing.exit": {
|
|
307
|
+
readonly cssVar: "--senui-motion-easing-exit";
|
|
308
|
+
readonly type: "cubicBezier";
|
|
309
|
+
readonly value: "cubic-bezier(0.3, 0, 1, 1)";
|
|
310
|
+
};
|
|
311
|
+
readonly "motion.easing.linear": {
|
|
312
|
+
readonly cssVar: "--senui-motion-easing-linear";
|
|
313
|
+
readonly type: "cubicBezier";
|
|
314
|
+
readonly value: "cubic-bezier(0, 0, 1, 1)";
|
|
315
|
+
readonly description: "Constant speed, for continuous motion such as a loading spinner.";
|
|
316
|
+
};
|
|
317
|
+
readonly "motion.easing.standard": {
|
|
318
|
+
readonly cssVar: "--senui-motion-easing-standard";
|
|
319
|
+
readonly type: "cubicBezier";
|
|
320
|
+
readonly value: "cubic-bezier(0.2, 0, 0, 1)";
|
|
321
|
+
};
|
|
322
|
+
readonly "motion.reduce": {
|
|
323
|
+
readonly cssVar: "--senui-motion-reduce";
|
|
324
|
+
readonly type: "number";
|
|
325
|
+
readonly value: "1";
|
|
326
|
+
readonly description: "1 normally, 0 under prefers-reduced-motion. Multiply every movement by it, so an override of a distance can't bring motion back (ADR-0005).";
|
|
327
|
+
readonly reducedMotion: "0";
|
|
328
|
+
};
|
|
329
|
+
readonly "motion.scale.enter": {
|
|
330
|
+
readonly cssVar: "--senui-motion-scale-enter";
|
|
331
|
+
readonly type: "number";
|
|
332
|
+
readonly value: "0.96";
|
|
333
|
+
readonly description: "Starting scale for elements that grow in. 1 under reduced motion; apply as 1 - (1 - scale) × motion.reduce.";
|
|
334
|
+
readonly reducedMotion: "1";
|
|
335
|
+
};
|
|
336
|
+
readonly "radius.full": {
|
|
337
|
+
readonly cssVar: "--senui-radius-full";
|
|
338
|
+
readonly type: "dimension";
|
|
339
|
+
readonly value: "9999px";
|
|
340
|
+
};
|
|
341
|
+
readonly "radius.lg": {
|
|
342
|
+
readonly cssVar: "--senui-radius-lg";
|
|
343
|
+
readonly type: "dimension";
|
|
344
|
+
readonly value: "12px";
|
|
345
|
+
};
|
|
346
|
+
readonly "radius.md": {
|
|
347
|
+
readonly cssVar: "--senui-radius-md";
|
|
348
|
+
readonly type: "dimension";
|
|
349
|
+
readonly value: "8px";
|
|
350
|
+
};
|
|
351
|
+
readonly "radius.sm": {
|
|
352
|
+
readonly cssVar: "--senui-radius-sm";
|
|
353
|
+
readonly type: "dimension";
|
|
354
|
+
readonly value: "4px";
|
|
355
|
+
};
|
|
356
|
+
readonly "size.control.lg": {
|
|
357
|
+
readonly cssVar: "--senui-size-control-lg";
|
|
358
|
+
readonly type: "dimension";
|
|
359
|
+
readonly value: "2.5rem";
|
|
360
|
+
};
|
|
361
|
+
readonly "size.control.md": {
|
|
362
|
+
readonly cssVar: "--senui-size-control-md";
|
|
363
|
+
readonly type: "dimension";
|
|
364
|
+
readonly value: "2rem";
|
|
365
|
+
};
|
|
366
|
+
readonly "size.control.sm": {
|
|
367
|
+
readonly cssVar: "--senui-size-control-sm";
|
|
368
|
+
readonly type: "dimension";
|
|
369
|
+
readonly value: "1.5rem";
|
|
370
|
+
};
|
|
371
|
+
readonly "size.dialog.lg": {
|
|
372
|
+
readonly cssVar: "--senui-size-dialog-lg";
|
|
373
|
+
readonly type: "dimension";
|
|
374
|
+
readonly value: "48rem";
|
|
375
|
+
};
|
|
376
|
+
readonly "size.dialog.md": {
|
|
377
|
+
readonly cssVar: "--senui-size-dialog-md";
|
|
378
|
+
readonly type: "dimension";
|
|
379
|
+
readonly value: "32rem";
|
|
380
|
+
};
|
|
381
|
+
readonly "size.dialog.sm": {
|
|
382
|
+
readonly cssVar: "--senui-size-dialog-sm";
|
|
383
|
+
readonly type: "dimension";
|
|
384
|
+
readonly value: "24rem";
|
|
385
|
+
};
|
|
386
|
+
readonly "size.illustration.lg": {
|
|
387
|
+
readonly cssVar: "--senui-size-illustration-lg";
|
|
388
|
+
readonly type: "dimension";
|
|
389
|
+
readonly value: "5rem";
|
|
390
|
+
};
|
|
391
|
+
readonly "size.illustration.sm": {
|
|
392
|
+
readonly cssVar: "--senui-size-illustration-sm";
|
|
393
|
+
readonly type: "dimension";
|
|
394
|
+
readonly value: "2.5rem";
|
|
395
|
+
};
|
|
396
|
+
readonly "size.target.min": {
|
|
397
|
+
readonly cssVar: "--senui-size-target-min";
|
|
398
|
+
readonly type: "dimension";
|
|
399
|
+
readonly value: "24px";
|
|
400
|
+
readonly description: "Smallest allowed pointer target (WCAG 2.5.8). In px, because WCAG measures in CSS px.";
|
|
401
|
+
};
|
|
402
|
+
readonly "space.1": {
|
|
403
|
+
readonly cssVar: "--senui-space-1";
|
|
404
|
+
readonly type: "dimension";
|
|
405
|
+
readonly value: "0.25rem";
|
|
406
|
+
};
|
|
407
|
+
readonly "space.10": {
|
|
408
|
+
readonly cssVar: "--senui-space-10";
|
|
409
|
+
readonly type: "dimension";
|
|
410
|
+
readonly value: "2.5rem";
|
|
411
|
+
};
|
|
412
|
+
readonly "space.12": {
|
|
413
|
+
readonly cssVar: "--senui-space-12";
|
|
414
|
+
readonly type: "dimension";
|
|
415
|
+
readonly value: "3rem";
|
|
416
|
+
};
|
|
417
|
+
readonly "space.2": {
|
|
418
|
+
readonly cssVar: "--senui-space-2";
|
|
419
|
+
readonly type: "dimension";
|
|
420
|
+
readonly value: "0.5rem";
|
|
421
|
+
};
|
|
422
|
+
readonly "space.3": {
|
|
423
|
+
readonly cssVar: "--senui-space-3";
|
|
424
|
+
readonly type: "dimension";
|
|
425
|
+
readonly value: "0.75rem";
|
|
426
|
+
};
|
|
427
|
+
readonly "space.4": {
|
|
428
|
+
readonly cssVar: "--senui-space-4";
|
|
429
|
+
readonly type: "dimension";
|
|
430
|
+
readonly value: "1rem";
|
|
431
|
+
};
|
|
432
|
+
readonly "space.5": {
|
|
433
|
+
readonly cssVar: "--senui-space-5";
|
|
434
|
+
readonly type: "dimension";
|
|
435
|
+
readonly value: "1.25rem";
|
|
436
|
+
};
|
|
437
|
+
readonly "space.6": {
|
|
438
|
+
readonly cssVar: "--senui-space-6";
|
|
439
|
+
readonly type: "dimension";
|
|
440
|
+
readonly value: "1.5rem";
|
|
441
|
+
};
|
|
442
|
+
readonly "space.8": {
|
|
443
|
+
readonly cssVar: "--senui-space-8";
|
|
444
|
+
readonly type: "dimension";
|
|
445
|
+
readonly value: "2rem";
|
|
446
|
+
};
|
|
447
|
+
};
|
|
448
|
+
//#endregion
|
|
449
|
+
//#region src/types.d.ts
|
|
450
|
+
/** One public design token, as it appears in `tokens.css` (ADR-0004). */
|
|
451
|
+
interface Token {
|
|
452
|
+
/** The custom property to use in CSS, e.g. `--senui-color-fg-danger`. */
|
|
453
|
+
readonly cssVar: `--senui-${string}`;
|
|
454
|
+
/** The DTCG `$type`, e.g. `color`, `dimension`, `duration`. */
|
|
455
|
+
readonly type: string;
|
|
456
|
+
/** The CSS value; for colours, the light-theme value. */
|
|
457
|
+
readonly value: string;
|
|
458
|
+
/** The dark-theme value. Present on every colour token. */
|
|
459
|
+
readonly dark?: string;
|
|
460
|
+
/** The value under `prefers-reduced-motion: reduce`, where it differs. */
|
|
461
|
+
readonly reducedMotion?: string;
|
|
462
|
+
readonly description?: string;
|
|
463
|
+
}
|
|
464
|
+
//#endregion
|
|
465
|
+
//#region src/index.d.ts
|
|
466
|
+
/** The key of a public token, e.g. `'color.fg.danger'`. */
|
|
467
|
+
export type TokenKey = keyof typeof tokens;
|
|
468
|
+
//#endregion
|
|
469
|
+
export type { Token };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
//#region src/generated/tokens.ts
|
|
2
|
+
const tokens = {
|
|
3
|
+
"border.width.default": {
|
|
4
|
+
"cssVar": "--senui-border-width-default",
|
|
5
|
+
"type": "dimension",
|
|
6
|
+
"value": "1px"
|
|
7
|
+
},
|
|
8
|
+
"border.width.strong": {
|
|
9
|
+
"cssVar": "--senui-border-width-strong",
|
|
10
|
+
"type": "dimension",
|
|
11
|
+
"value": "2px",
|
|
12
|
+
"description": "Invalid and selected controls, so state is not shown by colour alone."
|
|
13
|
+
},
|
|
14
|
+
"color.bg.accent": {
|
|
15
|
+
"cssVar": "--senui-color-bg-accent",
|
|
16
|
+
"type": "color",
|
|
17
|
+
"value": "oklch(52% 0.18 260)",
|
|
18
|
+
"description": "Fill for primary actions.",
|
|
19
|
+
"dark": "oklch(72% 0.14 255)"
|
|
20
|
+
},
|
|
21
|
+
"color.bg.accent-active": {
|
|
22
|
+
"cssVar": "--senui-color-bg-accent-active",
|
|
23
|
+
"type": "color",
|
|
24
|
+
"value": "oklch(40% 0.15 260)",
|
|
25
|
+
"description": "bg.accent while pressed.",
|
|
26
|
+
"dark": "oklch(86% 0.07 255)"
|
|
27
|
+
},
|
|
28
|
+
"color.bg.accent-hover": {
|
|
29
|
+
"cssVar": "--senui-color-bg-accent-hover",
|
|
30
|
+
"type": "color",
|
|
31
|
+
"value": "oklch(46% 0.17 260)",
|
|
32
|
+
"description": "bg.accent under the pointer.",
|
|
33
|
+
"dark": "oklch(80% 0.11 255)"
|
|
34
|
+
},
|
|
35
|
+
"color.bg.backdrop": {
|
|
36
|
+
"cssVar": "--senui-color-bg-backdrop",
|
|
37
|
+
"type": "color",
|
|
38
|
+
"value": "rgb(0% 0% 0% / 0.5)",
|
|
39
|
+
"description": "The scrim behind a modal (the dialog's ::backdrop). Translucent, so the page stays visible but recedes. Darker in dark mode, where the page is already dark. Never a text background.",
|
|
40
|
+
"dark": "rgb(0% 0% 0% / 0.7)"
|
|
41
|
+
},
|
|
42
|
+
"color.bg.danger": {
|
|
43
|
+
"cssVar": "--senui-color-bg-danger",
|
|
44
|
+
"type": "color",
|
|
45
|
+
"value": "oklch(53% 0.2 27)",
|
|
46
|
+
"description": "Fill for destructive actions.",
|
|
47
|
+
"dark": "oklch(72% 0.16 25)"
|
|
48
|
+
},
|
|
49
|
+
"color.bg.danger-active": {
|
|
50
|
+
"cssVar": "--senui-color-bg-danger-active",
|
|
51
|
+
"type": "color",
|
|
52
|
+
"value": "oklch(41% 0.17 27)",
|
|
53
|
+
"description": "bg.danger while pressed.",
|
|
54
|
+
"dark": "oklch(86% 0.07 25)"
|
|
55
|
+
},
|
|
56
|
+
"color.bg.danger-hover": {
|
|
57
|
+
"cssVar": "--senui-color-bg-danger-hover",
|
|
58
|
+
"type": "color",
|
|
59
|
+
"value": "oklch(47% 0.19 27)",
|
|
60
|
+
"description": "bg.danger under the pointer.",
|
|
61
|
+
"dark": "oklch(80% 0.11 25)"
|
|
62
|
+
},
|
|
63
|
+
"color.bg.default": {
|
|
64
|
+
"cssVar": "--senui-color-bg-default",
|
|
65
|
+
"type": "color",
|
|
66
|
+
"value": "oklch(99% 0.003 260)",
|
|
67
|
+
"description": "Page and surface background.",
|
|
68
|
+
"dark": "oklch(16% 0.012 260)"
|
|
69
|
+
},
|
|
70
|
+
"color.bg.disabled": {
|
|
71
|
+
"cssVar": "--senui-color-bg-disabled",
|
|
72
|
+
"type": "color",
|
|
73
|
+
"value": "oklch(97% 0.005 260)",
|
|
74
|
+
"description": "Fill of a disabled control. Exempt from contrast (WCAG 1.4.3, 1.4.11).",
|
|
75
|
+
"dark": "oklch(22% 0.015 260)"
|
|
76
|
+
},
|
|
77
|
+
"color.bg.raised": {
|
|
78
|
+
"cssVar": "--senui-color-bg-raised",
|
|
79
|
+
"type": "color",
|
|
80
|
+
"value": "oklch(99% 0.003 260)",
|
|
81
|
+
"description": "Popovers, menus, dialogs. Lighter than bg.default in dark mode, because shadows barely show there. Pair with a border: forced-colours mode removes shadows.",
|
|
82
|
+
"dark": "oklch(19% 0.013 260)"
|
|
83
|
+
},
|
|
84
|
+
"color.bg.subtle": {
|
|
85
|
+
"cssVar": "--senui-color-bg-subtle",
|
|
86
|
+
"type": "color",
|
|
87
|
+
"value": "oklch(97% 0.005 260)",
|
|
88
|
+
"description": "Recessed areas: wells, table stripes, secondary buttons.",
|
|
89
|
+
"dark": "oklch(22% 0.015 260)"
|
|
90
|
+
},
|
|
91
|
+
"color.bg.subtle-active": {
|
|
92
|
+
"cssVar": "--senui-color-bg-subtle-active",
|
|
93
|
+
"type": "color",
|
|
94
|
+
"value": "oklch(91% 0.008 260)",
|
|
95
|
+
"description": "bg.subtle while pressed.",
|
|
96
|
+
"dark": "oklch(30% 0.015 260)"
|
|
97
|
+
},
|
|
98
|
+
"color.bg.subtle-hover": {
|
|
99
|
+
"cssVar": "--senui-color-bg-subtle-hover",
|
|
100
|
+
"type": "color",
|
|
101
|
+
"value": "oklch(94% 0.007 260)",
|
|
102
|
+
"description": "bg.subtle under the pointer.",
|
|
103
|
+
"dark": "oklch(26% 0.015 260)"
|
|
104
|
+
},
|
|
105
|
+
"color.border.danger": {
|
|
106
|
+
"cssVar": "--senui-color-border-danger",
|
|
107
|
+
"type": "color",
|
|
108
|
+
"value": "oklch(53% 0.2 27)",
|
|
109
|
+
"description": "Outline of an invalid field (WCAG 1.4.11). Use with border.width.strong and an error message, never alone (1.4.1).",
|
|
110
|
+
"dark": "oklch(72% 0.16 25)"
|
|
111
|
+
},
|
|
112
|
+
"color.border.default": {
|
|
113
|
+
"cssVar": "--senui-color-border-default",
|
|
114
|
+
"type": "color",
|
|
115
|
+
"value": "oklch(85% 0.01 260)",
|
|
116
|
+
"description": "Decorative dividers. Too faint to identify a control; use border.strong for that.",
|
|
117
|
+
"dark": "oklch(30% 0.015 260)"
|
|
118
|
+
},
|
|
119
|
+
"color.border.disabled": {
|
|
120
|
+
"cssVar": "--senui-color-border-disabled",
|
|
121
|
+
"type": "color",
|
|
122
|
+
"value": "oklch(85% 0.01 260)",
|
|
123
|
+
"description": "Outline of a disabled control. Exempt from contrast (WCAG 1.4.11).",
|
|
124
|
+
"dark": "oklch(30% 0.015 260)"
|
|
125
|
+
},
|
|
126
|
+
"color.border.strong": {
|
|
127
|
+
"cssVar": "--senui-color-border-strong",
|
|
128
|
+
"type": "color",
|
|
129
|
+
"value": "oklch(60% 0.015 260)",
|
|
130
|
+
"description": "Borders that identify a control, such as input outlines (WCAG 1.4.11).",
|
|
131
|
+
"dark": "oklch(60% 0.015 260)"
|
|
132
|
+
},
|
|
133
|
+
"color.fg.accent": {
|
|
134
|
+
"cssVar": "--senui-color-fg-accent",
|
|
135
|
+
"type": "color",
|
|
136
|
+
"value": "oklch(52% 0.18 260)",
|
|
137
|
+
"description": "Links and accent text.",
|
|
138
|
+
"dark": "oklch(72% 0.14 255)"
|
|
139
|
+
},
|
|
140
|
+
"color.fg.danger": {
|
|
141
|
+
"cssVar": "--senui-color-fg-danger",
|
|
142
|
+
"type": "color",
|
|
143
|
+
"value": "oklch(53% 0.2 27)",
|
|
144
|
+
"description": "Error messages. Colour alone must never carry an error (WCAG 1.4.1): pair it with text or an icon.",
|
|
145
|
+
"dark": "oklch(72% 0.16 25)"
|
|
146
|
+
},
|
|
147
|
+
"color.fg.default": {
|
|
148
|
+
"cssVar": "--senui-color-fg-default",
|
|
149
|
+
"type": "color",
|
|
150
|
+
"value": "oklch(22% 0.015 260)",
|
|
151
|
+
"description": "Body text.",
|
|
152
|
+
"dark": "oklch(97% 0.005 260)"
|
|
153
|
+
},
|
|
154
|
+
"color.fg.disabled": {
|
|
155
|
+
"cssVar": "--senui-color-fg-disabled",
|
|
156
|
+
"type": "color",
|
|
157
|
+
"value": "oklch(60% 0.015 260)",
|
|
158
|
+
"description": "Text of a disabled control. Exempt from contrast (WCAG 1.4.3).",
|
|
159
|
+
"dark": "oklch(50% 0.015 260)"
|
|
160
|
+
},
|
|
161
|
+
"color.fg.muted": {
|
|
162
|
+
"cssVar": "--senui-color-fg-muted",
|
|
163
|
+
"type": "color",
|
|
164
|
+
"value": "oklch(50% 0.015 260)",
|
|
165
|
+
"description": "Secondary text: hints, captions, placeholders.",
|
|
166
|
+
"dark": "oklch(85% 0.01 260)"
|
|
167
|
+
},
|
|
168
|
+
"color.fg.on-accent": {
|
|
169
|
+
"cssVar": "--senui-color-fg-on-accent",
|
|
170
|
+
"type": "color",
|
|
171
|
+
"value": "oklch(99% 0.003 260)",
|
|
172
|
+
"description": "Text and icons on the accent fills.",
|
|
173
|
+
"dark": "oklch(16% 0.012 260)"
|
|
174
|
+
},
|
|
175
|
+
"color.fg.on-danger": {
|
|
176
|
+
"cssVar": "--senui-color-fg-on-danger",
|
|
177
|
+
"type": "color",
|
|
178
|
+
"value": "oklch(99% 0.003 260)",
|
|
179
|
+
"description": "Text and icons on the danger fills.",
|
|
180
|
+
"dark": "oklch(16% 0.012 260)"
|
|
181
|
+
},
|
|
182
|
+
"color.focus.ring": {
|
|
183
|
+
"cssVar": "--senui-color-focus-ring",
|
|
184
|
+
"type": "color",
|
|
185
|
+
"value": "oklch(52% 0.18 260)",
|
|
186
|
+
"description": "Focus indicator (WCAG 1.4.11, 2.4.7). Drawn as an outline offset by focus.ring-offset, so it sits on the page background, never on a fill (ADR-0005).",
|
|
187
|
+
"dark": "oklch(72% 0.14 255)"
|
|
188
|
+
},
|
|
189
|
+
"color.shadow": {
|
|
190
|
+
"cssVar": "--senui-color-shadow",
|
|
191
|
+
"type": "color",
|
|
192
|
+
"value": "rgb(0% 0% 0% / 0.12)",
|
|
193
|
+
"description": "Shadow colour used by the elevation tokens. Decorative.",
|
|
194
|
+
"dark": "rgb(0% 0% 0% / 0.5)"
|
|
195
|
+
},
|
|
196
|
+
"elevation.1": {
|
|
197
|
+
"cssVar": "--senui-elevation-1",
|
|
198
|
+
"type": "shadow",
|
|
199
|
+
"value": "0px 1px 2px 0px var(--senui-color-shadow)"
|
|
200
|
+
},
|
|
201
|
+
"elevation.2": {
|
|
202
|
+
"cssVar": "--senui-elevation-2",
|
|
203
|
+
"type": "shadow",
|
|
204
|
+
"value": "0px 4px 12px 0px var(--senui-color-shadow)"
|
|
205
|
+
},
|
|
206
|
+
"focus.ring-offset": {
|
|
207
|
+
"cssVar": "--senui-focus-ring-offset",
|
|
208
|
+
"type": "dimension",
|
|
209
|
+
"value": "2px",
|
|
210
|
+
"description": "Gap between a control and its focus ring, so the ring sits on the page background (ADR-0005)."
|
|
211
|
+
},
|
|
212
|
+
"focus.ring-width": {
|
|
213
|
+
"cssVar": "--senui-focus-ring-width",
|
|
214
|
+
"type": "dimension",
|
|
215
|
+
"value": "2px",
|
|
216
|
+
"description": "Outline width of the focus ring."
|
|
217
|
+
},
|
|
218
|
+
"font.family.mono": {
|
|
219
|
+
"cssVar": "--senui-font-family-mono",
|
|
220
|
+
"type": "fontFamily",
|
|
221
|
+
"value": "ui-monospace, 'SF Mono', Menlo, Consolas, 'Cascadia Mono', 'Liberation Mono', monospace"
|
|
222
|
+
},
|
|
223
|
+
"font.family.sans": {
|
|
224
|
+
"cssVar": "--senui-font-family-sans",
|
|
225
|
+
"type": "fontFamily",
|
|
226
|
+
"value": "system-ui, sans-serif"
|
|
227
|
+
},
|
|
228
|
+
"font.line-height.normal": {
|
|
229
|
+
"cssVar": "--senui-font-line-height-normal",
|
|
230
|
+
"type": "number",
|
|
231
|
+
"value": "1.5"
|
|
232
|
+
},
|
|
233
|
+
"font.line-height.tight": {
|
|
234
|
+
"cssVar": "--senui-font-line-height-tight",
|
|
235
|
+
"type": "number",
|
|
236
|
+
"value": "1.25"
|
|
237
|
+
},
|
|
238
|
+
"font.size.lg": {
|
|
239
|
+
"cssVar": "--senui-font-size-lg",
|
|
240
|
+
"type": "dimension",
|
|
241
|
+
"value": "1.25rem"
|
|
242
|
+
},
|
|
243
|
+
"font.size.md": {
|
|
244
|
+
"cssVar": "--senui-font-size-md",
|
|
245
|
+
"type": "dimension",
|
|
246
|
+
"value": "1rem"
|
|
247
|
+
},
|
|
248
|
+
"font.size.sm": {
|
|
249
|
+
"cssVar": "--senui-font-size-sm",
|
|
250
|
+
"type": "dimension",
|
|
251
|
+
"value": "0.875rem"
|
|
252
|
+
},
|
|
253
|
+
"font.weight.bold": {
|
|
254
|
+
"cssVar": "--senui-font-weight-bold",
|
|
255
|
+
"type": "fontWeight",
|
|
256
|
+
"value": "700"
|
|
257
|
+
},
|
|
258
|
+
"font.weight.medium": {
|
|
259
|
+
"cssVar": "--senui-font-weight-medium",
|
|
260
|
+
"type": "fontWeight",
|
|
261
|
+
"value": "500"
|
|
262
|
+
},
|
|
263
|
+
"font.weight.regular": {
|
|
264
|
+
"cssVar": "--senui-font-weight-regular",
|
|
265
|
+
"type": "fontWeight",
|
|
266
|
+
"value": "400"
|
|
267
|
+
},
|
|
268
|
+
"motion.distance.md": {
|
|
269
|
+
"cssVar": "--senui-motion-distance-md",
|
|
270
|
+
"type": "dimension",
|
|
271
|
+
"value": "8px",
|
|
272
|
+
"reducedMotion": "0px"
|
|
273
|
+
},
|
|
274
|
+
"motion.distance.sm": {
|
|
275
|
+
"cssVar": "--senui-motion-distance-sm",
|
|
276
|
+
"type": "dimension",
|
|
277
|
+
"value": "4px",
|
|
278
|
+
"reducedMotion": "0px"
|
|
279
|
+
},
|
|
280
|
+
"motion.duration.fast": {
|
|
281
|
+
"cssVar": "--senui-motion-duration-fast",
|
|
282
|
+
"type": "duration",
|
|
283
|
+
"value": "120ms"
|
|
284
|
+
},
|
|
285
|
+
"motion.duration.moderate": {
|
|
286
|
+
"cssVar": "--senui-motion-duration-moderate",
|
|
287
|
+
"type": "duration",
|
|
288
|
+
"value": "200ms"
|
|
289
|
+
},
|
|
290
|
+
"motion.duration.rotation": {
|
|
291
|
+
"cssVar": "--senui-motion-duration-rotation",
|
|
292
|
+
"type": "duration",
|
|
293
|
+
"value": "960ms",
|
|
294
|
+
"description": "One turn of essential continuous rotation (a progress spinner), and nothing else. Slow it by the factor rather than stopping it: × (4 − 3 × motion.reduce) (ADR-0017, ADR-0024)."
|
|
295
|
+
},
|
|
296
|
+
"motion.duration.slow": {
|
|
297
|
+
"cssVar": "--senui-motion-duration-slow",
|
|
298
|
+
"type": "duration",
|
|
299
|
+
"value": "320ms"
|
|
300
|
+
},
|
|
301
|
+
"motion.easing.enter": {
|
|
302
|
+
"cssVar": "--senui-motion-easing-enter",
|
|
303
|
+
"type": "cubicBezier",
|
|
304
|
+
"value": "cubic-bezier(0, 0, 0, 1)"
|
|
305
|
+
},
|
|
306
|
+
"motion.easing.exit": {
|
|
307
|
+
"cssVar": "--senui-motion-easing-exit",
|
|
308
|
+
"type": "cubicBezier",
|
|
309
|
+
"value": "cubic-bezier(0.3, 0, 1, 1)"
|
|
310
|
+
},
|
|
311
|
+
"motion.easing.linear": {
|
|
312
|
+
"cssVar": "--senui-motion-easing-linear",
|
|
313
|
+
"type": "cubicBezier",
|
|
314
|
+
"value": "cubic-bezier(0, 0, 1, 1)",
|
|
315
|
+
"description": "Constant speed, for continuous motion such as a loading spinner."
|
|
316
|
+
},
|
|
317
|
+
"motion.easing.standard": {
|
|
318
|
+
"cssVar": "--senui-motion-easing-standard",
|
|
319
|
+
"type": "cubicBezier",
|
|
320
|
+
"value": "cubic-bezier(0.2, 0, 0, 1)"
|
|
321
|
+
},
|
|
322
|
+
"motion.reduce": {
|
|
323
|
+
"cssVar": "--senui-motion-reduce",
|
|
324
|
+
"type": "number",
|
|
325
|
+
"value": "1",
|
|
326
|
+
"description": "1 normally, 0 under prefers-reduced-motion. Multiply every movement by it, so an override of a distance can't bring motion back (ADR-0005).",
|
|
327
|
+
"reducedMotion": "0"
|
|
328
|
+
},
|
|
329
|
+
"motion.scale.enter": {
|
|
330
|
+
"cssVar": "--senui-motion-scale-enter",
|
|
331
|
+
"type": "number",
|
|
332
|
+
"value": "0.96",
|
|
333
|
+
"description": "Starting scale for elements that grow in. 1 under reduced motion; apply as 1 - (1 - scale) × motion.reduce.",
|
|
334
|
+
"reducedMotion": "1"
|
|
335
|
+
},
|
|
336
|
+
"radius.full": {
|
|
337
|
+
"cssVar": "--senui-radius-full",
|
|
338
|
+
"type": "dimension",
|
|
339
|
+
"value": "9999px"
|
|
340
|
+
},
|
|
341
|
+
"radius.lg": {
|
|
342
|
+
"cssVar": "--senui-radius-lg",
|
|
343
|
+
"type": "dimension",
|
|
344
|
+
"value": "12px"
|
|
345
|
+
},
|
|
346
|
+
"radius.md": {
|
|
347
|
+
"cssVar": "--senui-radius-md",
|
|
348
|
+
"type": "dimension",
|
|
349
|
+
"value": "8px"
|
|
350
|
+
},
|
|
351
|
+
"radius.sm": {
|
|
352
|
+
"cssVar": "--senui-radius-sm",
|
|
353
|
+
"type": "dimension",
|
|
354
|
+
"value": "4px"
|
|
355
|
+
},
|
|
356
|
+
"size.control.lg": {
|
|
357
|
+
"cssVar": "--senui-size-control-lg",
|
|
358
|
+
"type": "dimension",
|
|
359
|
+
"value": "2.5rem"
|
|
360
|
+
},
|
|
361
|
+
"size.control.md": {
|
|
362
|
+
"cssVar": "--senui-size-control-md",
|
|
363
|
+
"type": "dimension",
|
|
364
|
+
"value": "2rem"
|
|
365
|
+
},
|
|
366
|
+
"size.control.sm": {
|
|
367
|
+
"cssVar": "--senui-size-control-sm",
|
|
368
|
+
"type": "dimension",
|
|
369
|
+
"value": "1.5rem"
|
|
370
|
+
},
|
|
371
|
+
"size.dialog.lg": {
|
|
372
|
+
"cssVar": "--senui-size-dialog-lg",
|
|
373
|
+
"type": "dimension",
|
|
374
|
+
"value": "48rem"
|
|
375
|
+
},
|
|
376
|
+
"size.dialog.md": {
|
|
377
|
+
"cssVar": "--senui-size-dialog-md",
|
|
378
|
+
"type": "dimension",
|
|
379
|
+
"value": "32rem"
|
|
380
|
+
},
|
|
381
|
+
"size.dialog.sm": {
|
|
382
|
+
"cssVar": "--senui-size-dialog-sm",
|
|
383
|
+
"type": "dimension",
|
|
384
|
+
"value": "24rem"
|
|
385
|
+
},
|
|
386
|
+
"size.illustration.lg": {
|
|
387
|
+
"cssVar": "--senui-size-illustration-lg",
|
|
388
|
+
"type": "dimension",
|
|
389
|
+
"value": "5rem"
|
|
390
|
+
},
|
|
391
|
+
"size.illustration.sm": {
|
|
392
|
+
"cssVar": "--senui-size-illustration-sm",
|
|
393
|
+
"type": "dimension",
|
|
394
|
+
"value": "2.5rem"
|
|
395
|
+
},
|
|
396
|
+
"size.target.min": {
|
|
397
|
+
"cssVar": "--senui-size-target-min",
|
|
398
|
+
"type": "dimension",
|
|
399
|
+
"value": "24px",
|
|
400
|
+
"description": "Smallest allowed pointer target (WCAG 2.5.8). In px, because WCAG measures in CSS px."
|
|
401
|
+
},
|
|
402
|
+
"space.1": {
|
|
403
|
+
"cssVar": "--senui-space-1",
|
|
404
|
+
"type": "dimension",
|
|
405
|
+
"value": "0.25rem"
|
|
406
|
+
},
|
|
407
|
+
"space.10": {
|
|
408
|
+
"cssVar": "--senui-space-10",
|
|
409
|
+
"type": "dimension",
|
|
410
|
+
"value": "2.5rem"
|
|
411
|
+
},
|
|
412
|
+
"space.12": {
|
|
413
|
+
"cssVar": "--senui-space-12",
|
|
414
|
+
"type": "dimension",
|
|
415
|
+
"value": "3rem"
|
|
416
|
+
},
|
|
417
|
+
"space.2": {
|
|
418
|
+
"cssVar": "--senui-space-2",
|
|
419
|
+
"type": "dimension",
|
|
420
|
+
"value": "0.5rem"
|
|
421
|
+
},
|
|
422
|
+
"space.3": {
|
|
423
|
+
"cssVar": "--senui-space-3",
|
|
424
|
+
"type": "dimension",
|
|
425
|
+
"value": "0.75rem"
|
|
426
|
+
},
|
|
427
|
+
"space.4": {
|
|
428
|
+
"cssVar": "--senui-space-4",
|
|
429
|
+
"type": "dimension",
|
|
430
|
+
"value": "1rem"
|
|
431
|
+
},
|
|
432
|
+
"space.5": {
|
|
433
|
+
"cssVar": "--senui-space-5",
|
|
434
|
+
"type": "dimension",
|
|
435
|
+
"value": "1.25rem"
|
|
436
|
+
},
|
|
437
|
+
"space.6": {
|
|
438
|
+
"cssVar": "--senui-space-6",
|
|
439
|
+
"type": "dimension",
|
|
440
|
+
"value": "1.5rem"
|
|
441
|
+
},
|
|
442
|
+
"space.8": {
|
|
443
|
+
"cssVar": "--senui-space-8",
|
|
444
|
+
"type": "dimension",
|
|
445
|
+
"value": "2rem"
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
//#endregion
|
|
449
|
+
export { tokens };
|
package/dist/tokens.css
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/* Generated by @senakster/senui-tokens. Do not edit; change src/*.tokens.json instead. */
|
|
2
|
+
@layer senui.tokens, senui.base, senui.components;
|
|
3
|
+
|
|
4
|
+
@layer senui.tokens {
|
|
5
|
+
:where(:root) {
|
|
6
|
+
color-scheme: light dark;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
:where([data-theme="light"]) {
|
|
10
|
+
color-scheme: light;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
:where([data-theme="dark"]) {
|
|
14
|
+
color-scheme: dark;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
:where(:root, [data-theme]) {
|
|
18
|
+
--senui-border-width-default: 1px;
|
|
19
|
+
--senui-border-width-strong: 2px;
|
|
20
|
+
--senui-color-bg-accent: light-dark(oklch(52% 0.18 260), oklch(72% 0.14 255));
|
|
21
|
+
--senui-color-bg-accent-active: light-dark(oklch(40% 0.15 260), oklch(86% 0.07 255));
|
|
22
|
+
--senui-color-bg-accent-hover: light-dark(oklch(46% 0.17 260), oklch(80% 0.11 255));
|
|
23
|
+
--senui-color-bg-backdrop: light-dark(rgb(0% 0% 0% / 0.5), rgb(0% 0% 0% / 0.7));
|
|
24
|
+
--senui-color-bg-danger: light-dark(oklch(53% 0.2 27), oklch(72% 0.16 25));
|
|
25
|
+
--senui-color-bg-danger-active: light-dark(oklch(41% 0.17 27), oklch(86% 0.07 25));
|
|
26
|
+
--senui-color-bg-danger-hover: light-dark(oklch(47% 0.19 27), oklch(80% 0.11 25));
|
|
27
|
+
--senui-color-bg-default: light-dark(oklch(99% 0.003 260), oklch(16% 0.012 260));
|
|
28
|
+
--senui-color-bg-disabled: light-dark(oklch(97% 0.005 260), oklch(22% 0.015 260));
|
|
29
|
+
--senui-color-bg-raised: light-dark(oklch(99% 0.003 260), oklch(19% 0.013 260));
|
|
30
|
+
--senui-color-bg-subtle: light-dark(oklch(97% 0.005 260), oklch(22% 0.015 260));
|
|
31
|
+
--senui-color-bg-subtle-active: light-dark(oklch(91% 0.008 260), oklch(30% 0.015 260));
|
|
32
|
+
--senui-color-bg-subtle-hover: light-dark(oklch(94% 0.007 260), oklch(26% 0.015 260));
|
|
33
|
+
--senui-color-border-danger: light-dark(oklch(53% 0.2 27), oklch(72% 0.16 25));
|
|
34
|
+
--senui-color-border-default: light-dark(oklch(85% 0.01 260), oklch(30% 0.015 260));
|
|
35
|
+
--senui-color-border-disabled: light-dark(oklch(85% 0.01 260), oklch(30% 0.015 260));
|
|
36
|
+
--senui-color-border-strong: light-dark(oklch(60% 0.015 260), oklch(60% 0.015 260));
|
|
37
|
+
--senui-color-fg-accent: light-dark(oklch(52% 0.18 260), oklch(72% 0.14 255));
|
|
38
|
+
--senui-color-fg-danger: light-dark(oklch(53% 0.2 27), oklch(72% 0.16 25));
|
|
39
|
+
--senui-color-fg-default: light-dark(oklch(22% 0.015 260), oklch(97% 0.005 260));
|
|
40
|
+
--senui-color-fg-disabled: light-dark(oklch(60% 0.015 260), oklch(50% 0.015 260));
|
|
41
|
+
--senui-color-fg-muted: light-dark(oklch(50% 0.015 260), oklch(85% 0.01 260));
|
|
42
|
+
--senui-color-fg-on-accent: light-dark(oklch(99% 0.003 260), oklch(16% 0.012 260));
|
|
43
|
+
--senui-color-fg-on-danger: light-dark(oklch(99% 0.003 260), oklch(16% 0.012 260));
|
|
44
|
+
--senui-color-focus-ring: light-dark(oklch(52% 0.18 260), oklch(72% 0.14 255));
|
|
45
|
+
--senui-color-shadow: light-dark(rgb(0% 0% 0% / 0.12), rgb(0% 0% 0% / 0.5));
|
|
46
|
+
--senui-elevation-1: 0px 1px 2px 0px var(--senui-color-shadow);
|
|
47
|
+
--senui-elevation-2: 0px 4px 12px 0px var(--senui-color-shadow);
|
|
48
|
+
--senui-focus-ring-offset: 2px;
|
|
49
|
+
--senui-focus-ring-width: 2px;
|
|
50
|
+
--senui-font-family-mono: ui-monospace, 'SF Mono', Menlo, Consolas, 'Cascadia Mono', 'Liberation Mono', monospace;
|
|
51
|
+
--senui-font-family-sans: system-ui, sans-serif;
|
|
52
|
+
--senui-font-line-height-normal: 1.5;
|
|
53
|
+
--senui-font-line-height-tight: 1.25;
|
|
54
|
+
--senui-font-size-lg: 1.25rem;
|
|
55
|
+
--senui-font-size-md: 1rem;
|
|
56
|
+
--senui-font-size-sm: 0.875rem;
|
|
57
|
+
--senui-font-weight-bold: 700;
|
|
58
|
+
--senui-font-weight-medium: 500;
|
|
59
|
+
--senui-font-weight-regular: 400;
|
|
60
|
+
--senui-motion-distance-md: 8px;
|
|
61
|
+
--senui-motion-distance-sm: 4px;
|
|
62
|
+
--senui-motion-duration-fast: 120ms;
|
|
63
|
+
--senui-motion-duration-moderate: 200ms;
|
|
64
|
+
--senui-motion-duration-rotation: 960ms;
|
|
65
|
+
--senui-motion-duration-slow: 320ms;
|
|
66
|
+
--senui-motion-easing-enter: cubic-bezier(0, 0, 0, 1);
|
|
67
|
+
--senui-motion-easing-exit: cubic-bezier(0.3, 0, 1, 1);
|
|
68
|
+
--senui-motion-easing-linear: cubic-bezier(0, 0, 1, 1);
|
|
69
|
+
--senui-motion-easing-standard: cubic-bezier(0.2, 0, 0, 1);
|
|
70
|
+
--senui-motion-reduce: 1;
|
|
71
|
+
--senui-motion-scale-enter: 0.96;
|
|
72
|
+
--senui-radius-full: 9999px;
|
|
73
|
+
--senui-radius-lg: 12px;
|
|
74
|
+
--senui-radius-md: 8px;
|
|
75
|
+
--senui-radius-sm: 4px;
|
|
76
|
+
--senui-size-control-lg: 2.5rem;
|
|
77
|
+
--senui-size-control-md: 2rem;
|
|
78
|
+
--senui-size-control-sm: 1.5rem;
|
|
79
|
+
--senui-size-dialog-lg: 48rem;
|
|
80
|
+
--senui-size-dialog-md: 32rem;
|
|
81
|
+
--senui-size-dialog-sm: 24rem;
|
|
82
|
+
--senui-size-illustration-lg: 5rem;
|
|
83
|
+
--senui-size-illustration-sm: 2.5rem;
|
|
84
|
+
--senui-size-target-min: 24px;
|
|
85
|
+
--senui-space-1: 0.25rem;
|
|
86
|
+
--senui-space-10: 2.5rem;
|
|
87
|
+
--senui-space-12: 3rem;
|
|
88
|
+
--senui-space-2: 0.5rem;
|
|
89
|
+
--senui-space-3: 0.75rem;
|
|
90
|
+
--senui-space-4: 1rem;
|
|
91
|
+
--senui-space-5: 1.25rem;
|
|
92
|
+
--senui-space-6: 1.5rem;
|
|
93
|
+
--senui-space-8: 2rem;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
@media (prefers-reduced-motion: reduce) {
|
|
97
|
+
:where(:root, [data-theme]) {
|
|
98
|
+
--senui-motion-distance-md: 0px;
|
|
99
|
+
--senui-motion-distance-sm: 0px;
|
|
100
|
+
--senui-motion-reduce: 0;
|
|
101
|
+
--senui-motion-scale-enter: 1;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
@layer senui.base {
|
|
107
|
+
:where([data-theme]) {
|
|
108
|
+
background-color: var(--senui-color-bg-default);
|
|
109
|
+
color: var(--senui-color-fg-default);
|
|
110
|
+
accent-color: var(--senui-color-fg-accent);
|
|
111
|
+
}
|
|
112
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@senakster/senui-tokens",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Design tokens for senui: CSS custom properties and a typed JS map.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"homepage": "https://senakster.github.io/senui/",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/senakster/senui.git",
|
|
10
|
+
"directory": "packages/tokens"
|
|
11
|
+
},
|
|
12
|
+
"bugs": "https://github.com/senakster/senui/issues",
|
|
13
|
+
"type": "module",
|
|
14
|
+
"sideEffects": [
|
|
15
|
+
"**/*.css"
|
|
16
|
+
],
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"CHANGELOG.md"
|
|
20
|
+
],
|
|
21
|
+
"exports": {
|
|
22
|
+
".": "./dist/index.js",
|
|
23
|
+
"./tokens.css": "./dist/tokens.css",
|
|
24
|
+
"./package.json": "./package.json"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"colorjs.io": "0.5.2",
|
|
28
|
+
"publint": "0.3.25",
|
|
29
|
+
"style-dictionary": "5.6.1",
|
|
30
|
+
"tsdown": "0.23.1",
|
|
31
|
+
"typescript": "6.0.3",
|
|
32
|
+
"vite": "8.3.4",
|
|
33
|
+
"vitest": "5.0.4"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "node sd.config.mjs && tsdown",
|
|
37
|
+
"typecheck": "tsc --noEmit",
|
|
38
|
+
"test": "vitest run"
|
|
39
|
+
}
|
|
6
40
|
}
|