@putdotio/design 1.2.1 → 1.4.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/DESIGN.md +9 -5
- package/dist/css/tokens.css +57 -20
- package/dist/figma/putio.tokens.json +47 -10
- package/dist/tokens.d.ts +1 -1
- package/dist/tokens.dtcg.json +267 -54
- package/dist/tokens.flat.json +199 -60
- package/dist/tokens.js +199 -60
- package/package.json +3 -2
- package/system/README.md +93 -19
- package/tokens/components.tokens.json +112 -0
- package/tokens/foundation.css +29 -9
- package/tokens/primitives.tokens.json +127 -27
- package/tokens/semantic.tokens.json +28 -27
package/system/README.md
CHANGED
|
@@ -18,8 +18,18 @@ project root/
|
|
|
18
18
|
|
|
19
19
|
## Fonts
|
|
20
20
|
|
|
21
|
-
Preview pages load the public put.io font CSS from `static.put.io
|
|
22
|
-
|
|
21
|
+
Preview pages load the public put.io font CSS from `static.put.io` (the same
|
|
22
|
+
source as the product), so the design system always matches production. Do not
|
|
23
|
+
commit font files here. Each HTML file links three stylesheets in `<head>`:
|
|
24
|
+
|
|
25
|
+
```html
|
|
26
|
+
<link rel="stylesheet" href="https://static.put.io/fonts/gt-america/standard/font.css">
|
|
27
|
+
<link rel="stylesheet" href="https://static.put.io/fonts/gt-america/mono/font.css">
|
|
28
|
+
<link rel="stylesheet" href="https://static.put.io/fonts/berkeley-mono/variable/font.css">
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Canonical weight mapping (matches the brand font host):
|
|
32
|
+
`100 ultra-light · 200 thin · 300 light · 400 regular · 500 medium · 700 bold · 900 black`
|
|
23
33
|
|
|
24
34
|
## Using tokens
|
|
25
35
|
|
|
@@ -33,10 +43,17 @@ The canonical source is DTCG-compatible JSON in [`../tokens`](../tokens). This
|
|
|
33
43
|
site stylesheet (`system/tokens.css`) and the package stylesheet
|
|
34
44
|
(`dist/css/tokens.css`, exported as `@putdotio/design/css`) are generated from
|
|
35
45
|
the same source. Guide and component CSS should consume custom properties rather
|
|
36
|
-
than hard-coded palette values. Brand yellow is
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
`--
|
|
46
|
+
than hard-coded palette values. Brand yellow is `var(--yellow-solid)` —
|
|
47
|
+
canonical `#FDCE45`; the emitted hsl form is pinned in
|
|
48
|
+
[`../DESIGN.md`](../DESIGN.md) front-matter, and the `--yellow-solid-hover` →
|
|
49
|
+
`--button-primary-bg-hover` derivation is specified in the repo's
|
|
50
|
+
`docs/DISTRIBUTION.md`.
|
|
51
|
+
|
|
52
|
+
Stacking and breakpoints are tokenized (`--z-*`, `--bp-*`) and the root
|
|
53
|
+
font-size is responsive; the canonical values live in
|
|
54
|
+
[`../DESIGN.md`](../DESIGN.md) (Layout & Spacing, Typography). Guide-specific
|
|
55
|
+
rule: CSS media queries can't read custom properties, so write the literal px
|
|
56
|
+
in `@media` and keep it in sync with the `--bp-*` token.
|
|
40
57
|
|
|
41
58
|
Web package consumers import the package CSS export:
|
|
42
59
|
|
|
@@ -44,7 +61,7 @@ Web package consumers import the package CSS export:
|
|
|
44
61
|
@import "@putdotio/design/css";
|
|
45
62
|
```
|
|
46
63
|
|
|
47
|
-
For **TV preview cards**, also load `preview/tv-shell.css` — it adds the `.tv`, `.topnav`, `.scr`, glass tiers, and player chrome on top of the tokens. This is preview-only support CSS; platform repos implement TV components in their native UI stacks:
|
|
64
|
+
For **TV preview cards**, also load `preview/tv-shell.css` — it adds the `.tv`, `.topnav`, `.scr`, glass tiers, and player chrome on top of the tokens. Every component selector is scoped under `.tv`, so the file is safe to bundle globally without bleeding into web components. This is preview-only support CSS; platform repos implement TV components in their native UI stacks:
|
|
48
65
|
|
|
49
66
|
```html
|
|
50
67
|
<link rel="stylesheet" href="./tokens.css">
|
|
@@ -53,24 +70,81 @@ For **TV preview cards**, also load `preview/tv-shell.css` — it adds the `.tv`
|
|
|
53
70
|
|
|
54
71
|
## Core rules
|
|
55
72
|
|
|
56
|
-
- **Yellow `#FDCE45` is the brand
|
|
73
|
+
- **Yellow `#FDCE45` is the brand constant at rest** — full rule and approved uses in [`../DESIGN.md`](../DESIGN.md) (Colors). Guide specifics: `--yellow-solid-hover` (`#F3C435`) is the hover peer with its own canonical hex in both modes, and focus rings use the yellow at 35% alpha (`--shadow-focus-color`).
|
|
74
|
+
- **Yellow as text on light needs `--yellow-text-secondary`** (≈5:1, AA) — the brand `--yellow-solid` is fill-only on light backgrounds.
|
|
75
|
+
- **Labels on yellow** use `--primary-foreground` (`hsl(38, 65%, 10%)` — warm dark, never pure black). Passes AA on the yellow fill without feeling "hard."
|
|
57
76
|
- **Icons: Phosphor-style inline SVG.** No emoji, ever.
|
|
58
|
-
- **One design, two modes.** Light and dark are the same markup and components with different token values. Toggle `.dark` on `<html>`; do not fork the page or rebuild a light-specific copy.
|
|
59
|
-
- **Fields
|
|
60
|
-
- **Panels are shared.** Use `--panel-bg`, `--panel-border`, `--panel-radius`, and `--panel-shadow` for raised cards and auth-style shells instead of screen-specific variables.
|
|
77
|
+
- **One design, two modes.** Light and dark are the same markup and components with different token values. Toggle `.dark` on `<html>`; do not fork the page or rebuild a light-specific copy. Components must consume semantic tokens (`--bg`, `--text`, `--border`, `--accent`, …), not raw `#hex` or `hsl()`.
|
|
78
|
+
- **Fields and panels use the shared aliases** (`--field-*`, `--panel-*`) — full rules, including the `aria-invalid` red-border-only requirement, in [`../DESIGN.md`](../DESIGN.md) (Components).
|
|
61
79
|
- **Content-agnostic.** put.io doesn't know what the user's files are. Never parse `The.Wire.S03E04.1080p.mkv` into `The Wire`. Raw filenames only. See the root [`DESIGN.md`](../DESIGN.md) for the full principle.
|
|
62
80
|
|
|
63
81
|
## Theme System
|
|
64
82
|
|
|
65
|
-
The guide owns the theme toggle. It
|
|
66
|
-
updates `html.dark`, and broadcasts
|
|
67
|
-
|
|
68
|
-
|
|
83
|
+
The guide (`design-system.html`) owns the theme toggle. It writes
|
|
84
|
+
`putio-ds-theme` to `localStorage`, updates `html.dark`, and broadcasts
|
|
85
|
+
`{type:'__theme', theme}` to every embedded preview iframe via `postMessage`,
|
|
86
|
+
so embeds flip live without reloading. Each preview's inline bootstrap reads
|
|
87
|
+
the same storage key on standalone open, and `preview/_resize.js` listens for
|
|
88
|
+
the parent broadcast when embedded. A URL query (`?theme=light` or
|
|
89
|
+
`?theme=dark`) overrides both — useful for screenshots.
|
|
69
90
|
|
|
70
91
|
Fixed-mode previews opt out with `<html data-theme-lock="dark">`. This is only
|
|
71
|
-
for product mockups whose visual language is intrinsically one mode
|
|
72
|
-
|
|
73
|
-
|
|
92
|
+
for product mockups whose visual language is intrinsically one mode — TV's
|
|
93
|
+
translucent glass material and on-video player chrome can't render on a light
|
|
94
|
+
surface, so `tv-*.html`, `mobile-shell.html`, and `components-player-web.html`
|
|
95
|
+
are locked. Locked previews ignore both `localStorage` and parent broadcasts.
|
|
96
|
+
If you write a new component preview, you almost certainly don't want the
|
|
97
|
+
lock — let the tokens do the work and your specimen will render correctly in
|
|
98
|
+
both modes.
|
|
99
|
+
|
|
100
|
+
## shadcn / Base UI interop
|
|
101
|
+
|
|
102
|
+
The token layer ships a name-alias bridge so external component libraries that
|
|
103
|
+
read canonical shadcn token names theme correctly without renaming. Drop in a
|
|
104
|
+
shadcn/ui block, install a Base UI component, paste a Tailwind preset — they
|
|
105
|
+
resolve against our values via the aliases. Always alias, never duplicate, so
|
|
106
|
+
the two name systems can't drift.
|
|
107
|
+
|
|
108
|
+
| shadcn name | put.io target |
|
|
109
|
+
| --- | --- |
|
|
110
|
+
| `--primary` / `--primary-foreground` | `--yellow-solid` / `var(--primary-foreground)` (warm dark) |
|
|
111
|
+
| `--destructive` / `--destructive-foreground` | `--red-solid` / `var(--destructive-foreground)` (= `#fff`) |
|
|
112
|
+
| `--success` / `--success-foreground` | `--green-solid` / `var(--success-foreground)` (= `#fff`) |
|
|
113
|
+
| `--muted` / `--muted-foreground` | `--bg-secondary` / `--text-secondary` |
|
|
114
|
+
| `--accent` / `--accent-foreground` | `--component-bg` / `--text` |
|
|
115
|
+
| `--card` / `--card-foreground` | `--component-bg` / `--text` |
|
|
116
|
+
| `--popover` / `--popover-foreground` | `--component-bg` / `--text` |
|
|
117
|
+
| `--input` | `--border` |
|
|
118
|
+
| `--ring` | `--shadow-focus-color` |
|
|
119
|
+
| `--background` / `--foreground` | `--bg` / `--text` |
|
|
120
|
+
|
|
121
|
+
The foreground tokens (`--primary-foreground`, `--destructive-foreground`,
|
|
122
|
+
`--success-foreground`) encode the mode-safe inverse pair — always read these
|
|
123
|
+
instead of writing literal `#000` / `#fff` on a solid surface.
|
|
124
|
+
|
|
125
|
+
Use whichever name reads cleaner in context. Our own components prefer the long
|
|
126
|
+
descriptive names (`--component-bg-hover`, `--yellow-text-secondary`) because
|
|
127
|
+
they describe the role exactly. shadcn-imported code prefers the short names.
|
|
128
|
+
|
|
129
|
+
### State via `data-state`, not class flags
|
|
130
|
+
|
|
131
|
+
Base UI / headless primitives set
|
|
132
|
+
`data-state="open|closed|checked|unchecked|active|completed|pending|loading"`
|
|
133
|
+
on the DOM. Our components target those same attribute values in CSS — see the
|
|
134
|
+
wizard step bar in `components-form-layouts.html`
|
|
135
|
+
(`.step[data-state="completed"]`) and the menu/table cards. Prefer `data-state`
|
|
136
|
+
over inventing class flags (`.is-active`, `.on`, `.current`) so the same DOM
|
|
137
|
+
contract works whether the controlling code is React, Vue, vanilla JS, or
|
|
138
|
+
hand-written HTML, and so devtools can read the component's state at a glance.
|
|
139
|
+
|
|
140
|
+
### Compound parts via `data-slot`
|
|
141
|
+
|
|
142
|
+
shadcn marks parts of compound components with `data-slot="card-header"`,
|
|
143
|
+
`data-slot="card-title"`, etc. We do the same on the folder picker
|
|
144
|
+
(`data-slot="modal" / "modal-header" / "modal-body" / "modal-footer"`) and the
|
|
145
|
+
auth card in `components-form-layouts.html` (`data-slot="auth" / "auth-header"
|
|
146
|
+
/ "auth-body"`). This lets external CSS tweak one part without inventing
|
|
147
|
+
nested class chains.
|
|
74
148
|
|
|
75
149
|
## Design variants
|
|
76
150
|
|
|
@@ -85,4 +159,4 @@ Four documented type stacks — pick one per surface:
|
|
|
85
159
|
|
|
86
160
|
## Preview cards
|
|
87
161
|
|
|
88
|
-
Open `system/design-system.html` for the full index. Each card renders a single concept against the actual tokens
|
|
162
|
+
Open `system/design-system.html` for the full index. Each card renders a single concept against the actual tokens — read it like a spec.
|
|
@@ -215,6 +215,28 @@
|
|
|
215
215
|
}
|
|
216
216
|
},
|
|
217
217
|
"info": {
|
|
218
|
+
"background": {
|
|
219
|
+
"$type": "color",
|
|
220
|
+
"$value": "{color.neutral.light.solid}",
|
|
221
|
+
"$description": "Neutral solid command background in light mode.",
|
|
222
|
+
"$extensions": {
|
|
223
|
+
"putio": {
|
|
224
|
+
"cssName": "button-info-bg",
|
|
225
|
+
"mode": "light"
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
"backgroundDark": {
|
|
230
|
+
"$type": "color",
|
|
231
|
+
"$value": "{color.neutral.dark.solid}",
|
|
232
|
+
"$description": "Neutral solid command background in dark mode.",
|
|
233
|
+
"$extensions": {
|
|
234
|
+
"putio": {
|
|
235
|
+
"cssName": "button-info-bg",
|
|
236
|
+
"mode": "dark"
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
},
|
|
218
240
|
"backgroundHover": {
|
|
219
241
|
"$type": "color",
|
|
220
242
|
"$value": "{color.neutral.light.solidHover}",
|
|
@@ -236,6 +258,96 @@
|
|
|
236
258
|
"mode": "dark"
|
|
237
259
|
}
|
|
238
260
|
}
|
|
261
|
+
},
|
|
262
|
+
"foreground": {
|
|
263
|
+
"$type": "color",
|
|
264
|
+
"$value": "{component.alias.solidForeground}",
|
|
265
|
+
"$description": "Label on the neutral solid — mode-aware for AA contrast on the gray fill.",
|
|
266
|
+
"$extensions": {
|
|
267
|
+
"putio": {
|
|
268
|
+
"cssName": "button-info-fg",
|
|
269
|
+
"mode": "light"
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
"foregroundDark": {
|
|
274
|
+
"$type": "color",
|
|
275
|
+
"$value": "{component.alias.solidForegroundDark}",
|
|
276
|
+
"$description": "Label on the neutral solid in dark mode.",
|
|
277
|
+
"$extensions": {
|
|
278
|
+
"putio": {
|
|
279
|
+
"cssName": "button-info-fg",
|
|
280
|
+
"mode": "dark"
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
"default": {
|
|
286
|
+
"background": {
|
|
287
|
+
"$type": "color",
|
|
288
|
+
"$value": "{color.neutral.light.componentBg}",
|
|
289
|
+
"$description": "Quiet default button fill in light mode.",
|
|
290
|
+
"$extensions": {
|
|
291
|
+
"putio": {
|
|
292
|
+
"cssName": "button-default-bg",
|
|
293
|
+
"mode": "light"
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
"backgroundDark": {
|
|
298
|
+
"$type": "color",
|
|
299
|
+
"$value": "{color.neutral.dark.componentBg}",
|
|
300
|
+
"$description": "Quiet default button fill in dark mode.",
|
|
301
|
+
"$extensions": {
|
|
302
|
+
"putio": {
|
|
303
|
+
"cssName": "button-default-bg",
|
|
304
|
+
"mode": "dark"
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
},
|
|
308
|
+
"backgroundHover": {
|
|
309
|
+
"$type": "color",
|
|
310
|
+
"$value": "{color.neutral.light.componentBgHover}",
|
|
311
|
+
"$description": "Default button hover fill in light mode.",
|
|
312
|
+
"$extensions": {
|
|
313
|
+
"putio": {
|
|
314
|
+
"cssName": "button-default-bg-hover",
|
|
315
|
+
"mode": "light"
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
"backgroundHoverDark": {
|
|
320
|
+
"$type": "color",
|
|
321
|
+
"$value": "{color.neutral.dark.componentBgHover}",
|
|
322
|
+
"$description": "Default button hover fill in dark mode.",
|
|
323
|
+
"$extensions": {
|
|
324
|
+
"putio": {
|
|
325
|
+
"cssName": "button-default-bg-hover",
|
|
326
|
+
"mode": "dark"
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
"foreground": {
|
|
331
|
+
"$type": "color",
|
|
332
|
+
"$value": "{color.neutral.light.text}",
|
|
333
|
+
"$description": "Default button label in light mode.",
|
|
334
|
+
"$extensions": {
|
|
335
|
+
"putio": {
|
|
336
|
+
"cssName": "button-default-fg",
|
|
337
|
+
"mode": "light"
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
},
|
|
341
|
+
"foregroundDark": {
|
|
342
|
+
"$type": "color",
|
|
343
|
+
"$value": "{color.neutral.dark.text}",
|
|
344
|
+
"$description": "Default button label in dark mode.",
|
|
345
|
+
"$extensions": {
|
|
346
|
+
"putio": {
|
|
347
|
+
"cssName": "button-default-fg",
|
|
348
|
+
"mode": "dark"
|
|
349
|
+
}
|
|
350
|
+
}
|
|
239
351
|
}
|
|
240
352
|
}
|
|
241
353
|
},
|
package/tokens/foundation.css
CHANGED
|
@@ -3,7 +3,7 @@ html {
|
|
|
3
3
|
background: var(--html-bg);
|
|
4
4
|
color: var(--text);
|
|
5
5
|
font-family: var(--font-sans);
|
|
6
|
-
font-size:
|
|
6
|
+
font-size: 14px; /* app.put.io root: fontSize ["14px","14px","15px"] — 15px at ≥ --bp-lg (media query below) */
|
|
7
7
|
line-height: var(--lh-normal);
|
|
8
8
|
-webkit-font-smoothing: antialiased;
|
|
9
9
|
-moz-osx-font-smoothing: grayscale;
|
|
@@ -15,6 +15,13 @@ body {
|
|
|
15
15
|
margin: 0;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
/* Root steps up on desktop, matching app.put.io's responsive base.
|
|
19
|
+
14px/15px literals must stay in sync with --bp-lg (media queries
|
|
20
|
+
can't read custom properties). */
|
|
21
|
+
@media (min-width: 1280px) {
|
|
22
|
+
html { font-size: 15px; }
|
|
23
|
+
}
|
|
24
|
+
|
|
18
25
|
/* -- Semantic type ------------------------------------------------- */
|
|
19
26
|
|
|
20
27
|
.h-display, h1.display {
|
|
@@ -36,7 +43,7 @@ body {
|
|
|
36
43
|
|
|
37
44
|
h1, .h1 {
|
|
38
45
|
font-family: var(--font-sans);
|
|
39
|
-
font-size: var(--fs-
|
|
46
|
+
font-size: var(--fs-xl);
|
|
40
47
|
font-weight: var(--fw-bold);
|
|
41
48
|
line-height: var(--lh-tight);
|
|
42
49
|
letter-spacing: var(--tracking-tight);
|
|
@@ -45,7 +52,7 @@ h1, .h1 {
|
|
|
45
52
|
|
|
46
53
|
h2, .h2 {
|
|
47
54
|
font-family: var(--font-sans);
|
|
48
|
-
font-size: var(--fs-
|
|
55
|
+
font-size: var(--fs-lg);
|
|
49
56
|
font-weight: var(--fw-bold);
|
|
50
57
|
line-height: var(--lh-tight);
|
|
51
58
|
margin: 0 0 var(--space-3);
|
|
@@ -53,7 +60,7 @@ h2, .h2 {
|
|
|
53
60
|
|
|
54
61
|
h3, .h3 {
|
|
55
62
|
font-family: var(--font-sans);
|
|
56
|
-
font-size: var(--fs-
|
|
63
|
+
font-size: var(--fs-md);
|
|
57
64
|
font-weight: var(--fw-medium);
|
|
58
65
|
line-height: var(--lh-snug);
|
|
59
66
|
margin: 0 0 var(--space-2);
|
|
@@ -61,7 +68,7 @@ h3, .h3 {
|
|
|
61
68
|
|
|
62
69
|
h4, .h4 {
|
|
63
70
|
font-family: var(--font-sans);
|
|
64
|
-
font-size: var(--fs-
|
|
71
|
+
font-size: var(--fs-base);
|
|
65
72
|
font-weight: var(--fw-medium);
|
|
66
73
|
line-height: var(--lh-snug);
|
|
67
74
|
margin: 0 0 var(--space-2);
|
|
@@ -82,26 +89,26 @@ p, .body {
|
|
|
82
89
|
}
|
|
83
90
|
|
|
84
91
|
.lead {
|
|
85
|
-
font-size: var(--fs-
|
|
92
|
+
font-size: var(--fs-md);
|
|
86
93
|
font-weight: var(--fw-regular);
|
|
87
94
|
line-height: var(--lh-normal);
|
|
88
95
|
color: var(--text-secondary);
|
|
89
96
|
}
|
|
90
97
|
|
|
91
98
|
small, .caption {
|
|
92
|
-
font-size: var(--fs-
|
|
99
|
+
font-size: var(--fs-sm); /* production caption = fontSize 0 */
|
|
93
100
|
color: var(--text-secondary);
|
|
94
101
|
}
|
|
95
102
|
|
|
96
103
|
.label {
|
|
97
|
-
font-size: var(--fs-
|
|
104
|
+
font-size: var(--fs-base); /* production label = fontSize 1, medium */
|
|
98
105
|
font-weight: var(--fw-medium);
|
|
99
106
|
color: var(--text);
|
|
100
107
|
}
|
|
101
108
|
|
|
102
109
|
.button-text {
|
|
103
110
|
font-weight: var(--fw-medium);
|
|
104
|
-
font-size: var(--fs-
|
|
111
|
+
font-size: var(--fs-sm); /* production button = fontSize 0 */
|
|
105
112
|
letter-spacing: 0;
|
|
106
113
|
}
|
|
107
114
|
|
|
@@ -131,3 +138,16 @@ a:hover { text-decoration-color: currentColor; }
|
|
|
131
138
|
.bg-2 { background: var(--bg-secondary); }
|
|
132
139
|
.bg-component { background: var(--component-bg); }
|
|
133
140
|
.bg-yellow { background: var(--yellow-solid); color: var(--primary-foreground); }
|
|
141
|
+
|
|
142
|
+
/* -- Reduced motion ------------------------------------------------ */
|
|
143
|
+
/* Honor the OS "reduce motion" setting: collapse transitions/animations
|
|
144
|
+
to near-instant and stop looping/auto-scrolling effects. Components
|
|
145
|
+
should not rely on motion to convey state. */
|
|
146
|
+
@media (prefers-reduced-motion: reduce) {
|
|
147
|
+
*, *::before, *::after {
|
|
148
|
+
animation-duration: 0.01ms !important;
|
|
149
|
+
animation-iteration-count: 1 !important;
|
|
150
|
+
transition-duration: 0.01ms !important;
|
|
151
|
+
scroll-behavior: auto !important;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
},
|
|
31
31
|
"color": {
|
|
32
32
|
"$type": "color",
|
|
33
|
-
"$value": "
|
|
33
|
+
"$value": "{elevation.shadowColor}",
|
|
34
|
+
"$description": "Compat name kept for existing web consumers — alias of elevation.shadowColor so the two can never drift.",
|
|
34
35
|
"$extensions": {
|
|
35
36
|
"putio": {
|
|
36
37
|
"cssName": "shadow",
|
|
@@ -85,24 +86,11 @@
|
|
|
85
86
|
},
|
|
86
87
|
"focus": {
|
|
87
88
|
"$type": "string",
|
|
88
|
-
"$value": "0 0 0
|
|
89
|
-
"$description": "Focus ring: brand-yellow inner band + high-contrast text-color outer edge so the indicator clears WCAG 1.4.11 (3:1) on any surface. Light-mode edge.",
|
|
89
|
+
"$value": "0 0 0 3px {elevation.focusColor}",
|
|
90
90
|
"$extensions": {
|
|
91
91
|
"putio": {
|
|
92
92
|
"cssName": "shadow-focus",
|
|
93
|
-
"mode": "
|
|
94
|
-
"figma": false
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
},
|
|
98
|
-
"focusDark": {
|
|
99
|
-
"$type": "string",
|
|
100
|
-
"$value": "0 0 0 2px {elevation.focusColor}, 0 0 0 3.5px hsl(0, 0%, 93.0%)",
|
|
101
|
-
"$description": "Dark-mode focus ring: brand-yellow inner band + high-contrast text-color outer edge (WCAG 1.4.11).",
|
|
102
|
-
"$extensions": {
|
|
103
|
-
"putio": {
|
|
104
|
-
"cssName": "shadow-focus",
|
|
105
|
-
"mode": "dark",
|
|
93
|
+
"mode": "global",
|
|
106
94
|
"figma": false
|
|
107
95
|
}
|
|
108
96
|
}
|
|
@@ -123,7 +111,7 @@
|
|
|
123
111
|
},
|
|
124
112
|
"display": {
|
|
125
113
|
"$type": "fontFamily",
|
|
126
|
-
"$value": "
|
|
114
|
+
"$value": "{typography.fontFamily.sans}",
|
|
127
115
|
"$extensions": {
|
|
128
116
|
"putio": {
|
|
129
117
|
"cssName": "font-display",
|
|
@@ -145,7 +133,7 @@
|
|
|
145
133
|
},
|
|
146
134
|
"mono": {
|
|
147
135
|
"$type": "fontFamily",
|
|
148
|
-
"$value": "\"Berkeley Mono\",
|
|
136
|
+
"$value": "\"Berkeley Mono\", {typography.fontFamily.uiMono}",
|
|
149
137
|
"$extensions": {
|
|
150
138
|
"putio": {
|
|
151
139
|
"cssName": "font-mono",
|
|
@@ -169,7 +157,8 @@
|
|
|
169
157
|
},
|
|
170
158
|
"sm": {
|
|
171
159
|
"$type": "dimension",
|
|
172
|
-
"$value": "0.
|
|
160
|
+
"$value": "0.875rem",
|
|
161
|
+
"$description": "Caption and button labels — production fontSize 0.",
|
|
173
162
|
"$extensions": {
|
|
174
163
|
"putio": {
|
|
175
164
|
"cssName": "fs-sm",
|
|
@@ -180,7 +169,8 @@
|
|
|
180
169
|
},
|
|
181
170
|
"base": {
|
|
182
171
|
"$type": "dimension",
|
|
183
|
-
"$value": "
|
|
172
|
+
"$value": "1rem",
|
|
173
|
+
"$description": "Body, labels, inputs — production fontSize 1; equals the responsive root (14px, 15px at >= breakpoint.lg).",
|
|
184
174
|
"$extensions": {
|
|
185
175
|
"putio": {
|
|
186
176
|
"cssName": "fs-base",
|
|
@@ -191,7 +181,8 @@
|
|
|
191
181
|
},
|
|
192
182
|
"md": {
|
|
193
183
|
"$type": "dimension",
|
|
194
|
-
"$value": "
|
|
184
|
+
"$value": "1.125rem",
|
|
185
|
+
"$description": "Subheading.",
|
|
195
186
|
"$extensions": {
|
|
196
187
|
"putio": {
|
|
197
188
|
"cssName": "fs-md",
|
|
@@ -202,7 +193,8 @@
|
|
|
202
193
|
},
|
|
203
194
|
"lg": {
|
|
204
195
|
"$type": "dimension",
|
|
205
|
-
"$value": "1.
|
|
196
|
+
"$value": "1.5rem",
|
|
197
|
+
"$description": "Heading.",
|
|
206
198
|
"$extensions": {
|
|
207
199
|
"putio": {
|
|
208
200
|
"cssName": "fs-lg",
|
|
@@ -213,7 +205,8 @@
|
|
|
213
205
|
},
|
|
214
206
|
"xl": {
|
|
215
207
|
"$type": "dimension",
|
|
216
|
-
"$value": "
|
|
208
|
+
"$value": "2rem",
|
|
209
|
+
"$description": "Page title.",
|
|
217
210
|
"$extensions": {
|
|
218
211
|
"putio": {
|
|
219
212
|
"cssName": "fs-xl",
|
|
@@ -224,7 +217,8 @@
|
|
|
224
217
|
},
|
|
225
218
|
"2xl": {
|
|
226
219
|
"$type": "dimension",
|
|
227
|
-
"$value": "
|
|
220
|
+
"$value": "48px",
|
|
221
|
+
"$description": "Fixed display tier — does not scale with the responsive root.",
|
|
228
222
|
"$extensions": {
|
|
229
223
|
"putio": {
|
|
230
224
|
"cssName": "fs-2xl",
|
|
@@ -235,7 +229,8 @@
|
|
|
235
229
|
},
|
|
236
230
|
"3xl": {
|
|
237
231
|
"$type": "dimension",
|
|
238
|
-
"$value": "
|
|
232
|
+
"$value": "64px",
|
|
233
|
+
"$description": "Fixed display tier — does not scale with the responsive root.",
|
|
239
234
|
"$extensions": {
|
|
240
235
|
"putio": {
|
|
241
236
|
"cssName": "fs-3xl",
|
|
@@ -246,7 +241,8 @@
|
|
|
246
241
|
},
|
|
247
242
|
"4xl": {
|
|
248
243
|
"$type": "dimension",
|
|
249
|
-
"$value": "
|
|
244
|
+
"$value": "{typography.fontSize.3xl}",
|
|
245
|
+
"$description": "Compatibility alias for the former 4xl tier; new surfaces should use fontSize.3xl or fontSize.display.",
|
|
250
246
|
"$extensions": {
|
|
251
247
|
"putio": {
|
|
252
248
|
"cssName": "fs-4xl",
|
|
@@ -257,7 +253,8 @@
|
|
|
257
253
|
},
|
|
258
254
|
"display": {
|
|
259
255
|
"$type": "dimension",
|
|
260
|
-
"$value": "
|
|
256
|
+
"$value": "96px",
|
|
257
|
+
"$description": "Fixed display tier for brand display moments.",
|
|
261
258
|
"$extensions": {
|
|
262
259
|
"putio": {
|
|
263
260
|
"cssName": "fs-display",
|
|
@@ -637,5 +634,108 @@
|
|
|
637
634
|
}
|
|
638
635
|
}
|
|
639
636
|
}
|
|
637
|
+
},
|
|
638
|
+
"z": {
|
|
639
|
+
"$description": "Stacking scale. Gapped for platform chrome — never invent z-index numbers in apps.",
|
|
640
|
+
"dropdown": {
|
|
641
|
+
"$type": "number",
|
|
642
|
+
"$value": 1000,
|
|
643
|
+
"$extensions": {
|
|
644
|
+
"putio": {
|
|
645
|
+
"cssName": "z-dropdown",
|
|
646
|
+
"mode": "global",
|
|
647
|
+
"category": "other",
|
|
648
|
+
"figma": false
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
},
|
|
652
|
+
"sticky": {
|
|
653
|
+
"$type": "number",
|
|
654
|
+
"$value": 1100,
|
|
655
|
+
"$extensions": {
|
|
656
|
+
"putio": {
|
|
657
|
+
"cssName": "z-sticky",
|
|
658
|
+
"mode": "global",
|
|
659
|
+
"category": "other",
|
|
660
|
+
"figma": false
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
},
|
|
664
|
+
"modal": {
|
|
665
|
+
"$type": "number",
|
|
666
|
+
"$value": 1300,
|
|
667
|
+
"$extensions": {
|
|
668
|
+
"putio": {
|
|
669
|
+
"cssName": "z-modal",
|
|
670
|
+
"mode": "global",
|
|
671
|
+
"category": "other",
|
|
672
|
+
"figma": false
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
},
|
|
676
|
+
"notification": {
|
|
677
|
+
"$type": "number",
|
|
678
|
+
"$value": 1400,
|
|
679
|
+
"$extensions": {
|
|
680
|
+
"putio": {
|
|
681
|
+
"cssName": "z-notification",
|
|
682
|
+
"mode": "global",
|
|
683
|
+
"category": "other",
|
|
684
|
+
"figma": false
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
},
|
|
688
|
+
"tooltip": {
|
|
689
|
+
"$type": "number",
|
|
690
|
+
"$value": 1500,
|
|
691
|
+
"$extensions": {
|
|
692
|
+
"putio": {
|
|
693
|
+
"cssName": "z-tooltip",
|
|
694
|
+
"mode": "global",
|
|
695
|
+
"category": "other",
|
|
696
|
+
"figma": false
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
},
|
|
701
|
+
"breakpoint": {
|
|
702
|
+
"$description": "Responsive breakpoints, lifted from app.put.io's BREAKPOINTS. Generator-facing: CSS media queries cannot read custom properties, so emitters bind these as Tailwind screens, StyleX consts, or documented literals.",
|
|
703
|
+
"sm": {
|
|
704
|
+
"$type": "dimension",
|
|
705
|
+
"$value": "640px",
|
|
706
|
+
"$extensions": {
|
|
707
|
+
"putio": {
|
|
708
|
+
"cssName": "bp-sm",
|
|
709
|
+
"mode": "global",
|
|
710
|
+
"category": "other",
|
|
711
|
+
"figma": false
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
},
|
|
715
|
+
"md": {
|
|
716
|
+
"$type": "dimension",
|
|
717
|
+
"$value": "768px",
|
|
718
|
+
"$extensions": {
|
|
719
|
+
"putio": {
|
|
720
|
+
"cssName": "bp-md",
|
|
721
|
+
"mode": "global",
|
|
722
|
+
"category": "other",
|
|
723
|
+
"figma": false
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
},
|
|
727
|
+
"lg": {
|
|
728
|
+
"$type": "dimension",
|
|
729
|
+
"$value": "1280px",
|
|
730
|
+
"$description": "The root font-size steps from 14px to 15px at this width.",
|
|
731
|
+
"$extensions": {
|
|
732
|
+
"putio": {
|
|
733
|
+
"cssName": "bp-lg",
|
|
734
|
+
"mode": "global",
|
|
735
|
+
"category": "other",
|
|
736
|
+
"figma": false
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
}
|
|
640
740
|
}
|
|
641
741
|
}
|