@uniflowed/stylex 0.1.0 → 0.3.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/index.js +22 -10
- package/package.json +2 -2
- package/preset.js +33 -13
- package/theme.js +34 -38
- package/tokens.stylex.js +109 -33
package/index.js
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
//
|
|
22
22
|
// 1. **A token set that already exists.** `@uniflowed/stylex/tokens.stylex.js`
|
|
23
23
|
// is a real `stylex.defineVars` module — colour roles, a type scale,
|
|
24
|
-
// spacing, radii
|
|
24
|
+
// spacing, radii and motion — so a project has a coherent palette
|
|
25
25
|
// without authoring one, and gets it as `:root` custom properties the build
|
|
26
26
|
// inlined rather than as anything computed in a browser.
|
|
27
27
|
// 2. **A base layer over those tokens.** `@uniflowed/stylex/preset` is
|
|
@@ -67,14 +67,17 @@
|
|
|
67
67
|
//
|
|
68
68
|
// # Where the token values come from
|
|
69
69
|
//
|
|
70
|
-
// `@uniflowed/brand` owns uf's visual identity — the
|
|
71
|
-
//
|
|
72
|
-
//
|
|
73
|
-
//
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
-
//
|
|
70
|
+
// `@uniflowed/brand` owns uf's visual identity — the logo, its spectrum, the
|
|
71
|
+
// type and spacing scales — and it stays there. The interface borrows brand's
|
|
72
|
+
// type and spacing, and chooses its own colours and corners: a UI dressed in
|
|
73
|
+
// the logo's cyan-to-magenta spectrum and round corners looks generated, so
|
|
74
|
+
// `./tokens.stylex.js` holds a neutral-first palette of its own
|
|
75
|
+
// (`docs/ui-visual-language.md` says why). Brand could not own the token
|
|
76
|
+
// module anyway: a StyleX token's name is computed by the compiler from the
|
|
77
|
+
// binding and key it was declared under, and `defineVars` accepts only
|
|
78
|
+
// literals. So `./tokens.stylex.js` is where the semantic roles — `accent`,
|
|
79
|
+
// `ink`, `canvas` — get their values, which is the layer a design system needs
|
|
80
|
+
// and an identity does not have.
|
|
78
81
|
//
|
|
79
82
|
// # Readiness
|
|
80
83
|
//
|
|
@@ -129,13 +132,22 @@ export type ThemeOverrides<Tokens extends { readonly [string]: ThemeValue }> = P
|
|
|
129
132
|
/**
|
|
130
133
|
* Declare a set of style namespaces.
|
|
131
134
|
*
|
|
135
|
+
* Typed as what the compiler hands back, not what was written: every key of
|
|
136
|
+
* `styles` becomes a {@link CompiledStyle}, a map of property to class name
|
|
137
|
+
* marked with `$$css`. Typing the result as the input (`T`) said a namespace
|
|
138
|
+
* held `{ color: "black" }` when at run time it holds `{ $$css: true, color:
|
|
139
|
+
* "x1e2nbdu" }`, so code reading the compiled marker, and `props`'s own
|
|
140
|
+
* tests, were type errors against the truth.
|
|
141
|
+
*
|
|
132
142
|
* Never runs. `uf transform` replaces the whole call with the object it
|
|
133
143
|
* computed, so reaching this means the module was loaded without going through
|
|
134
144
|
* uf — a bundler configured by hand, a plain `node` invocation — and the styles
|
|
135
145
|
* it declares are in no stylesheet. Throwing says so; returning the input would
|
|
136
146
|
* render an application with no styles and no explanation.
|
|
137
147
|
*/
|
|
138
|
-
export function create<T extends { readonly [string]: mixed }>(
|
|
148
|
+
export function create<T extends { readonly [string]: mixed }>(
|
|
149
|
+
styles: T,
|
|
150
|
+
): { readonly [Key in keyof T]: CompiledStyle } {
|
|
139
151
|
return nativeRuntimeRequired(MODULE, "stylex.create");
|
|
140
152
|
}
|
|
141
153
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uniflowed/stylex",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Flow declarations for @uniflowed/stylex, part of the Unified Toolchain for Flow.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"!*.test.js"
|
|
24
24
|
],
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@uniflowed/core": "0.
|
|
26
|
+
"@uniflowed/core": "0.3.0"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
29
|
"react-native": ">=0.86.0"
|
package/preset.js
CHANGED
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
//
|
|
21
21
|
// It is the only module in the package that has opinions. `props` is a merge,
|
|
22
22
|
// the tokens are names, the themes are values; this is where uf says a card has
|
|
23
|
-
// a
|
|
24
|
-
// everything else, and a bundler drops
|
|
25
|
-
// references them.
|
|
23
|
+
// a 6px radius and a 1px border rather than a shadow. A project that wants its
|
|
24
|
+
// own look drops this import and keeps everything else, and a bundler drops
|
|
25
|
+
// the rules with it because nothing else references them.
|
|
26
26
|
//
|
|
27
27
|
// # Why functions rather than exported namespaces
|
|
28
28
|
//
|
|
@@ -84,13 +84,14 @@ const surfaces = stylex.create({
|
|
|
84
84
|
borderColor: ufTokens.border,
|
|
85
85
|
borderRadius: ufTokens.radiusLg,
|
|
86
86
|
padding: ufTokens.space6,
|
|
87
|
-
boxShadow: ufTokens.shadowCard,
|
|
88
87
|
},
|
|
89
88
|
panel: {
|
|
90
89
|
backgroundColor: ufTokens.surface,
|
|
91
|
-
|
|
90
|
+
borderWidth: "1px",
|
|
91
|
+
borderStyle: "solid",
|
|
92
|
+
borderColor: ufTokens.border,
|
|
93
|
+
borderRadius: ufTokens.radiusLg,
|
|
92
94
|
padding: ufTokens.space6,
|
|
93
|
-
boxShadow: ufTokens.shadowPanel,
|
|
94
95
|
},
|
|
95
96
|
sunken: {
|
|
96
97
|
backgroundColor: ufTokens.sunken,
|
|
@@ -131,7 +132,20 @@ const buttons = stylex.create({
|
|
|
131
132
|
borderStyle: "solid",
|
|
132
133
|
borderColor: "transparent",
|
|
133
134
|
cursor: "pointer",
|
|
134
|
-
|
|
135
|
+
// Press: the button gives a little under the pointer, to 97% of its size
|
|
136
|
+
// in `durationFast`, and comes back on release without passing 1. Under
|
|
137
|
+
// reduced motion it does not move; only the colours still change.
|
|
138
|
+
transform: {
|
|
139
|
+
default: "none",
|
|
140
|
+
":active": "scale(0.97)",
|
|
141
|
+
"@media (prefers-reduced-motion: reduce)": "none",
|
|
142
|
+
},
|
|
143
|
+
// The focus ring draws itself outward from the edge (`outline-width`
|
|
144
|
+
// 0 → 2px) rather than blinking on, in `durationFast`.
|
|
145
|
+
transitionProperty: {
|
|
146
|
+
default: "background-color, border-color, color, outline-width, transform",
|
|
147
|
+
"@media (prefers-reduced-motion: reduce)": "background-color, border-color, color",
|
|
148
|
+
},
|
|
135
149
|
transitionDuration: ufTokens.durationFast,
|
|
136
150
|
transitionTimingFunction: ufTokens.easing,
|
|
137
151
|
// The ring is drawn only for a keyboard focus, which is the whole reason
|
|
@@ -191,7 +205,7 @@ const fields = stylex.create({
|
|
|
191
205
|
borderWidth: "1px",
|
|
192
206
|
borderStyle: "solid",
|
|
193
207
|
borderColor: ufTokens.border,
|
|
194
|
-
borderRadius: ufTokens.
|
|
208
|
+
borderRadius: ufTokens.radiusMd,
|
|
195
209
|
paddingBlock: ufTokens.space2,
|
|
196
210
|
paddingInline: ufTokens.space3,
|
|
197
211
|
outlineWidth: { default: "0", ":focus-visible": "2px" },
|
|
@@ -226,9 +240,11 @@ const overlays = stylex.create({
|
|
|
226
240
|
backgroundColor: ufTokens.surface,
|
|
227
241
|
color: ufTokens.ink,
|
|
228
242
|
fontFamily: ufTokens.fontSans,
|
|
229
|
-
|
|
243
|
+
borderWidth: "1px",
|
|
244
|
+
borderStyle: "solid",
|
|
245
|
+
borderColor: ufTokens.border,
|
|
246
|
+
borderRadius: ufTokens.radiusLg,
|
|
230
247
|
padding: ufTokens.space6,
|
|
231
|
-
boxShadow: ufTokens.shadowPanel,
|
|
232
248
|
},
|
|
233
249
|
});
|
|
234
250
|
|
|
@@ -243,7 +259,6 @@ const menus = stylex.create({
|
|
|
243
259
|
borderStyle: "solid",
|
|
244
260
|
borderColor: ufTokens.border,
|
|
245
261
|
borderRadius: ufTokens.radiusMd,
|
|
246
|
-
boxShadow: ufTokens.shadowPanel,
|
|
247
262
|
},
|
|
248
263
|
item: {
|
|
249
264
|
display: "flex",
|
|
@@ -314,7 +329,12 @@ const controls = stylex.create({
|
|
|
314
329
|
backgroundColor: ufTokens.surface,
|
|
315
330
|
color: ufTokens.accentInk,
|
|
316
331
|
cursor: "pointer",
|
|
317
|
-
|
|
332
|
+
// Colours, and the focus ring drawing outward; only the colours stay
|
|
333
|
+
// under reduced motion.
|
|
334
|
+
transitionProperty: {
|
|
335
|
+
default: "background-color, border-color, outline-width",
|
|
336
|
+
"@media (prefers-reduced-motion: reduce)": "background-color, border-color",
|
|
337
|
+
},
|
|
318
338
|
transitionDuration: ufTokens.durationFast,
|
|
319
339
|
transitionTimingFunction: ufTokens.easing,
|
|
320
340
|
outlineWidth: { default: "0", ":focus-visible": "2px" },
|
|
@@ -325,7 +345,7 @@ const controls = stylex.create({
|
|
|
325
345
|
box: {
|
|
326
346
|
width: ufTokens.sizeControl,
|
|
327
347
|
height: ufTokens.sizeControl,
|
|
328
|
-
borderRadius:
|
|
348
|
+
borderRadius: ufTokens.radiusSm,
|
|
329
349
|
},
|
|
330
350
|
// A switch's track is the one piece of geometry here that is not a token:
|
|
331
351
|
// nothing but a switch reads it, and a theme that changed it would leave the
|
package/theme.js
CHANGED
|
@@ -62,25 +62,23 @@ import { ufTokens } from "./tokens.stylex.js";
|
|
|
62
62
|
* exactly one `@media (prefers-color-scheme: dark)` block.
|
|
63
63
|
*/
|
|
64
64
|
export const ufAutoTheme = stylex.createTheme(ufTokens, {
|
|
65
|
-
canvas: { "@media (prefers-color-scheme: dark)": "#
|
|
66
|
-
sunken: { "@media (prefers-color-scheme: dark)": "#
|
|
67
|
-
surface: { "@media (prefers-color-scheme: dark)": "#
|
|
68
|
-
surfaceHover: { "@media (prefers-color-scheme: dark)": "#
|
|
69
|
-
border: { "@media (prefers-color-scheme: dark)": "#
|
|
70
|
-
ink: { "@media (prefers-color-scheme: dark)": "#
|
|
71
|
-
muted: { "@media (prefers-color-scheme: dark)": "#
|
|
72
|
-
accent: { "@media (prefers-color-scheme: dark)": "#
|
|
73
|
-
accentHover: { "@media (prefers-color-scheme: dark)": "#
|
|
74
|
-
accentInk: { "@media (prefers-color-scheme: dark)": "#
|
|
75
|
-
accentSoft: { "@media (prefers-color-scheme: dark)": "#
|
|
76
|
-
danger: { "@media (prefers-color-scheme: dark)": "#
|
|
77
|
-
dangerHover: { "@media (prefers-color-scheme: dark)": "#
|
|
78
|
-
dangerInk: { "@media (prefers-color-scheme: dark)": "#
|
|
79
|
-
dangerSoft: { "@media (prefers-color-scheme: dark)": "#
|
|
80
|
-
focus: { "@media (prefers-color-scheme: dark)": "#
|
|
81
|
-
scrim: { "@media (prefers-color-scheme: dark)": "rgba(
|
|
82
|
-
shadowCard: { "@media (prefers-color-scheme: dark)": "0 1px 2px rgba(0, 0, 0, 0.40)" },
|
|
83
|
-
shadowPanel: { "@media (prefers-color-scheme: dark)": "0 16px 48px rgba(0, 0, 0, 0.55)" },
|
|
65
|
+
canvas: { "@media (prefers-color-scheme: dark)": "#141413" },
|
|
66
|
+
sunken: { "@media (prefers-color-scheme: dark)": "#0f0f0e" },
|
|
67
|
+
surface: { "@media (prefers-color-scheme: dark)": "#1c1c1a" },
|
|
68
|
+
surfaceHover: { "@media (prefers-color-scheme: dark)": "#262623" },
|
|
69
|
+
border: { "@media (prefers-color-scheme: dark)": "#363632" },
|
|
70
|
+
ink: { "@media (prefers-color-scheme: dark)": "#ecece7" },
|
|
71
|
+
muted: { "@media (prefers-color-scheme: dark)": "#a5a59e" },
|
|
72
|
+
accent: { "@media (prefers-color-scheme: dark)": "#8eaee8" },
|
|
73
|
+
accentHover: { "@media (prefers-color-scheme: dark)": "#a8c1ee" },
|
|
74
|
+
accentInk: { "@media (prefers-color-scheme: dark)": "#101318" },
|
|
75
|
+
accentSoft: { "@media (prefers-color-scheme: dark)": "#1f2838" },
|
|
76
|
+
danger: { "@media (prefers-color-scheme: dark)": "#ee8a80" },
|
|
77
|
+
dangerHover: { "@media (prefers-color-scheme: dark)": "#f3a49c" },
|
|
78
|
+
dangerInk: { "@media (prefers-color-scheme: dark)": "#1d0f0d" },
|
|
79
|
+
dangerSoft: { "@media (prefers-color-scheme: dark)": "#35201d" },
|
|
80
|
+
focus: { "@media (prefers-color-scheme: dark)": "#8eaee8" },
|
|
81
|
+
scrim: { "@media (prefers-color-scheme: dark)": "rgba(0, 0, 0, 0.6)" },
|
|
84
82
|
});
|
|
85
83
|
|
|
86
84
|
/**
|
|
@@ -90,23 +88,21 @@ export const ufAutoTheme = stylex.createTheme(ufTokens, {
|
|
|
90
88
|
* preference a reader chose.
|
|
91
89
|
*/
|
|
92
90
|
export const ufDarkTheme = stylex.createTheme(ufTokens, {
|
|
93
|
-
canvas: "#
|
|
94
|
-
sunken: "#
|
|
95
|
-
surface: "#
|
|
96
|
-
surfaceHover: "#
|
|
97
|
-
border: "#
|
|
98
|
-
ink: "#
|
|
99
|
-
muted: "#
|
|
100
|
-
accent: "#
|
|
101
|
-
accentHover: "#
|
|
102
|
-
accentInk: "#
|
|
103
|
-
accentSoft: "#
|
|
104
|
-
danger: "#
|
|
105
|
-
dangerHover: "#
|
|
106
|
-
dangerInk: "#
|
|
107
|
-
dangerSoft: "#
|
|
108
|
-
focus: "#
|
|
109
|
-
scrim: "rgba(
|
|
110
|
-
shadowCard: "0 1px 2px rgba(0, 0, 0, 0.40)",
|
|
111
|
-
shadowPanel: "0 16px 48px rgba(0, 0, 0, 0.55)",
|
|
91
|
+
canvas: "#141413",
|
|
92
|
+
sunken: "#0f0f0e",
|
|
93
|
+
surface: "#1c1c1a",
|
|
94
|
+
surfaceHover: "#262623",
|
|
95
|
+
border: "#363632",
|
|
96
|
+
ink: "#ecece7",
|
|
97
|
+
muted: "#a5a59e",
|
|
98
|
+
accent: "#8eaee8",
|
|
99
|
+
accentHover: "#a8c1ee",
|
|
100
|
+
accentInk: "#101318",
|
|
101
|
+
accentSoft: "#1f2838",
|
|
102
|
+
danger: "#ee8a80",
|
|
103
|
+
dangerHover: "#f3a49c",
|
|
104
|
+
dangerInk: "#1d0f0d",
|
|
105
|
+
dangerSoft: "#35201d",
|
|
106
|
+
focus: "#8eaee8",
|
|
107
|
+
scrim: "rgba(0, 0, 0, 0.6)",
|
|
112
108
|
});
|
package/tokens.stylex.js
CHANGED
|
@@ -11,18 +11,37 @@
|
|
|
11
11
|
// # Roles, not colours
|
|
12
12
|
//
|
|
13
13
|
// The names are what a token is *for*, never what it looks like. `accent` is
|
|
14
|
-
// the colour a primary action wears; it is
|
|
15
|
-
// anything, and no rule in `preset.js` has to change when it does.
|
|
16
|
-
// named `
|
|
17
|
-
// wanted a green product.
|
|
14
|
+
// the colour a primary action wears; it is a quiet cobalt today and a theme
|
|
15
|
+
// can make it anything, and no rule in `preset.js` has to change when it does.
|
|
16
|
+
// A token named `blue600` would have made the preset unthemeable the moment
|
|
17
|
+
// someone wanted a green product.
|
|
18
18
|
//
|
|
19
|
-
// The
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
19
|
+
// # The palette
|
|
20
|
+
//
|
|
21
|
+
// `docs/ui-visual-language.md` explains it; in short: the interface is
|
|
22
|
+
// neutral first — warm greys with no blue cast, near-black ink on off-white
|
|
23
|
+
// paper — and colour is spent in one place, a single accent for what is
|
|
24
|
+
// selected, current or primary. Danger is a brick red rather than a signal
|
|
25
|
+
// red. Dark is designed as its own palette (charcoal, not navy; a lighter,
|
|
26
|
+
// desaturated accent that does not glow), not the light one inverted.
|
|
27
|
+
//
|
|
28
|
+
// The type and spacing steps are `@uniflowed/brand`'s scales. The colours and
|
|
29
|
+
// the corners are not: brand's cyan-to-magenta spectrum and its round corners
|
|
30
|
+
// are uf's logo and marketing identity, and an interface built from them looks
|
|
31
|
+
// like every other generated one, so this module's values are its own. Brand
|
|
32
|
+
// cannot hold the token module itself anyway — a StyleX token's name is
|
|
33
|
+
// computed by the compiler, and `defineVars` takes literals, not an imported
|
|
34
|
+
// array.
|
|
35
|
+
//
|
|
36
|
+
// # No shadows, no gradients
|
|
37
|
+
//
|
|
38
|
+
// The defaults draw depth with a rule and a change of surface, and nothing
|
|
39
|
+
// else. A shadow is the first thing a theme has to fight when the product's
|
|
40
|
+
// look is flat, and a gradient is a decision about a brand this module does
|
|
41
|
+
// not have, so neither is a token and neither appears in a default style.
|
|
42
|
+
// `crates/uf_stylex/src/tests/defaults.rs` compiles every default style —
|
|
43
|
+
// this module, `preset.js`, `theme.js` and every file in `registry/ui/` — and
|
|
44
|
+
// fails on a `box-shadow`, a `text-shadow`, a `drop-shadow()` or a gradient.
|
|
26
45
|
//
|
|
27
46
|
// # What is not a token
|
|
28
47
|
//
|
|
@@ -45,31 +64,31 @@ import { stylex } from "@uniflowed/stylex";
|
|
|
45
64
|
// `ThemeOverrides<typeof ufTokens>` reject a token this module does not declare.
|
|
46
65
|
export const ufTokens = stylex.defineVars({
|
|
47
66
|
// Surfaces, from furthest back to nearest front.
|
|
48
|
-
canvas: "#
|
|
49
|
-
sunken: "#
|
|
67
|
+
canvas: "#f6f6f4",
|
|
68
|
+
sunken: "#eeeeeb",
|
|
50
69
|
surface: "#ffffff",
|
|
51
|
-
surfaceHover: "#
|
|
52
|
-
border: "#
|
|
70
|
+
surfaceHover: "#f1f1ee",
|
|
71
|
+
border: "#d9d9d4",
|
|
53
72
|
|
|
54
73
|
// Text.
|
|
55
|
-
ink: "#
|
|
56
|
-
muted: "#
|
|
74
|
+
ink: "#1b1b19",
|
|
75
|
+
muted: "#5c5c57",
|
|
57
76
|
|
|
58
77
|
// The colour a primary action wears, and what is legible on it.
|
|
59
|
-
accent: "#
|
|
60
|
-
accentHover: "#
|
|
78
|
+
accent: "#2b58b5",
|
|
79
|
+
accentHover: "#234996",
|
|
61
80
|
accentInk: "#ffffff",
|
|
62
|
-
accentSoft: "#
|
|
81
|
+
accentSoft: "#e8eef9",
|
|
63
82
|
|
|
64
83
|
// The colour a destructive action wears.
|
|
65
|
-
danger: "#
|
|
66
|
-
dangerHover: "#
|
|
84
|
+
danger: "#b1271d",
|
|
85
|
+
dangerHover: "#931f17",
|
|
67
86
|
dangerInk: "#ffffff",
|
|
68
|
-
dangerSoft: "#
|
|
87
|
+
dangerSoft: "#fbedeb",
|
|
69
88
|
|
|
70
89
|
// Focus ring, and the wash behind a modal surface.
|
|
71
|
-
focus: "#
|
|
72
|
-
scrim: "rgba(
|
|
90
|
+
focus: "#2b58b5",
|
|
91
|
+
scrim: "rgba(27, 27, 25, 0.45)",
|
|
73
92
|
|
|
74
93
|
// Type.
|
|
75
94
|
fontSans: "ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif",
|
|
@@ -95,20 +114,77 @@ export const ufTokens = stylex.defineVars({
|
|
|
95
114
|
space8: "32px",
|
|
96
115
|
space12: "48px",
|
|
97
116
|
|
|
98
|
-
// Shape.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
117
|
+
// Shape. Three small steps and a pill, and nothing rounder: a control is
|
|
118
|
+
// 2px, a button, field group or popover 4px, and the largest surface — a
|
|
119
|
+
// card, a dialog — 6px. `radiusPill` is for the few things that are round
|
|
120
|
+
// by what they are, such as a switch's track or a radio's dot, and not a
|
|
121
|
+
// way to soften a rectangle.
|
|
122
|
+
radiusSm: "2px",
|
|
123
|
+
radiusMd: "4px",
|
|
124
|
+
radiusLg: "6px",
|
|
103
125
|
radiusPill: "999px",
|
|
104
126
|
|
|
105
127
|
// The size of a control a finger or a pointer aims at.
|
|
106
128
|
sizeControl: "18px",
|
|
107
129
|
|
|
108
|
-
//
|
|
109
|
-
|
|
110
|
-
|
|
130
|
+
// There is no elevation: a surface in front of another is told apart by a
|
|
131
|
+
// 1px `border` and its own background, never by a shadow.
|
|
132
|
+
|
|
133
|
+
// # Motion
|
|
134
|
+
//
|
|
135
|
+
// Three durations and three easings, and every default transition is one of
|
|
136
|
+
// each. `docs/ui-visual-language.md` has the table of what moves how; the
|
|
137
|
+
// values are argued here, where a theme that wants to change them will look.
|
|
138
|
+
//
|
|
139
|
+
// **Durations, by how far the eye has to follow.**
|
|
140
|
+
//
|
|
141
|
+
// * `durationFast`, 120ms: a change *in place* — a colour, a pressed
|
|
142
|
+
// button giving way, a focus ring drawing itself, a chevron turning.
|
|
143
|
+
// Nothing travels, so anything longer reads as lag between the press
|
|
144
|
+
// and the answer; anything under ~100ms is not seen at all, which is
|
|
145
|
+
// how #1414's defaults came to look like they had no motion.
|
|
146
|
+
// * `durationBase`, 200ms: something small *arriving* or *travelling* — a
|
|
147
|
+
// popover, menu or listbox leaving its trigger, a switch's thumb, a
|
|
148
|
+
// check being drawn. Long enough to see where it came from, short enough
|
|
149
|
+
// that a reader who opens a menu to act in it is never waiting for it.
|
|
150
|
+
// * `durationSlow`, 280ms: something *large* — a dialog, a sheet, a
|
|
151
|
+
// drawer, a toast, a progress bar's fill. A surface that covers a third
|
|
152
|
+
// of the screen and moves as fast as a menu looks thrown. It stops short
|
|
153
|
+
// of the ~300ms where an interface starts to feel like it is performing.
|
|
154
|
+
//
|
|
155
|
+
// **Easings, by where the motion starts and ends.** All three are
|
|
156
|
+
// cubic-béziers with both y values inside 0..1, so nothing overshoots its
|
|
157
|
+
// destination and nothing bounces; `defaults.rs` holds them to that.
|
|
158
|
+
//
|
|
159
|
+
// * `easing`, `cubic-bezier(0.2, 0, 0, 1)`: the standard curve, for
|
|
160
|
+
// something moving between two places it rests at — a switch's thumb, a
|
|
161
|
+
// progress fill, a drawer between snap points, a colour. It eases out of
|
|
162
|
+
// rest a little and settles for a long time, so it never stops abruptly.
|
|
163
|
+
// * `easingEnter`, `cubic-bezier(0, 0, 0.2, 1)`: a decelerate, for
|
|
164
|
+
// something *arriving*. It leaves at full speed and spends its second
|
|
165
|
+
// half settling: half the distance is covered by a fifth of the time,
|
|
166
|
+
// so the content is legible almost at once, while the settle is long
|
|
167
|
+
// enough to be seen. A stronger curve (Material's emphasised
|
|
168
|
+
// `0.05, 0.7, 0.1, 1`) was tried and rejected: it is 78% there by a
|
|
169
|
+
// fifth of the time, which on a 200ms popover is the "almost no motion"
|
|
170
|
+
// this replaces.
|
|
171
|
+
// * `easingExit`, `cubic-bezier(0.4, 0, 1, 1)`: an accelerate, for
|
|
172
|
+
// something *leaving*. It starts slowly, so the eye registers that it is
|
|
173
|
+
// going, then gets out of the way at full speed. Exits pair it with a
|
|
174
|
+
// shorter duration than the matching enter, because nobody watches a
|
|
175
|
+
// thing leave. (Exit transitions need the behaviour layer to keep a
|
|
176
|
+
// closing part mounted until they finish; until it does, this token is
|
|
177
|
+
// declared and not yet read — see `docs/ui-visual-language.md`.)
|
|
178
|
+
//
|
|
179
|
+
// A transition names the properties it moves, never `all`. Under
|
|
180
|
+
// `prefers-reduced-motion: reduce` nothing travels, grows or is drawn:
|
|
181
|
+
// either the duration is `0s`, or only opacity and colour still transition,
|
|
182
|
+
// so an overlay still fades rather than cutting. `defaults.rs` checks every
|
|
183
|
+
// default style for each of these.
|
|
111
184
|
durationFast: "120ms",
|
|
112
185
|
durationBase: "200ms",
|
|
186
|
+
durationSlow: "280ms",
|
|
113
187
|
easing: "cubic-bezier(0.2, 0, 0, 1)",
|
|
188
|
+
easingEnter: "cubic-bezier(0, 0, 0.2, 1)",
|
|
189
|
+
easingExit: "cubic-bezier(0.4, 0, 1, 1)",
|
|
114
190
|
});
|