Skip to content

Commit c86ea23

Browse files
committed
feat(tokens): add form and panel design aliases
Add portable field, panel, and action token aliases with hsl brand output. Update form/auth previews, docs, smoke checks, and e2e expectations for the refreshed design-system contract.
1 parent 55b5a9d commit c86ea23

31 files changed

Lines changed: 3163 additions & 391 deletions

AGENTS.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ Use `pnpm tokens:build` after editing `tokens/**/*.tokens.json`.
2222

2323
- `tokens/**/*.tokens.json` is the source of truth.
2424
- Generated artifacts live in `dist/` and `system/tokens.css`.
25-
- Yellow `#FDCE45` is sacred.
25+
- Yellow `#FDCE45` is sacred; CSS emits it as `hsl(44.7, 97.9%, 63.1%)`.
26+
- Shared form and panel chrome lives in `--field-*` and `--panel-*` aliases.
2627
- Icons use Phosphor-style inline SVG. No emoji as UI icons.
2728
- TV surfaces are file browsers: list-first, focus-first, not poster grids.
2829
- Keep public docs generic. Private research, local paths, account data, team photos, and unreleased plans stay out.

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Use `pnpm verify:full` before large guide, token, package, or deploy changes.
2727
## Development Notes
2828

2929
- Edit token sources in `tokens/**/*.tokens.json`.
30-
- Run `pnpm tokens:build` after token changes.
30+
- Run `pnpm tokens:build` after token changes; run `pnpm tokens:check` when reviewing generated drift.
3131
- Keep examples public-safe and content-agnostic.
3232
- Use raw filename examples from [Agent guide](AGENTS.md).
3333
- Put deploy and package details in [Distribution](docs/DISTRIBUTION.md).

DESIGN.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@ version: "0.1.0"
33
name: "put.io Design System"
44
description: "Public token and guidance contract for put.io product surfaces."
55
colors:
6-
brand: "#FDCE45"
6+
brand: "hsl(44.7, 97.9%, 63.1%)"
77
dark:
88
app-bg: "hsl(0, 0%, 8.5%)"
9-
page-bg: "black"
9+
page-bg: "hsl(0, 0%, 0%)"
1010
text: "hsl(0, 0%, 93.0%)"
1111
text-muted: "hsl(0, 0%, 62.8%)"
1212
border: "hsl(0, 0%, 24.3%)"
1313
success: "hsl(151, 55.0%, 41.5%)"
1414
danger: "hsl(358, 75.0%, 59.0%)"
1515
light:
16-
app-bg: "white"
16+
app-bg: "hsl(0, 0%, 100%)"
1717
page-bg: "hsl(0, 0%, 97.3%)"
1818
text: "hsl(0, 0%, 9.0%)"
1919
text-muted: "hsl(0, 0%, 43.5%)"
@@ -96,6 +96,8 @@ The default radius is `6px`. Use `4px` for tight controls, `8px` or `10px` for l
9696

9797
Buttons use yellow only for primary commands. Secondary buttons should feel quiet and tokenized against the active surface. File rows are the core component: preserve raw names, keep metadata compact, and make hover/focus states obvious without inflating row height.
9898

99+
Form fields use the shared `--field-*` aliases: `--field-bg` for the fill, `--field-border` for the resting border, and `--field-ring` for focus. Invalid fields opt in with `aria-invalid="true"` and use red border/text only; do not add red fill. Raised panels use the shared `--panel-*` aliases instead of auth- or screen-specific panel variables.
100+
99101
TV components are list-first and focus-first. A TV app is still a file browser, not a poster wall. Roku, native Apple, Android, and web TV repos should consume the generic tokens and generate their own platform bindings.
100102

101103
## Do's and Don'ts

README.md

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ This repo owns the public contract behind it: DTCG token sources, generated
2222
CSS/JSON/TypeScript artifacts, brand assets, preview cards, and deployable
2323
static guidance.
2424

25-
## Use
25+
## Install
2626

2727
Token sources live in [`tokens`](tokens). Generated package artifacts live in
2828
[`dist`](dist). Package-safe brand assets live in [`system/assets`](system/assets).
@@ -31,7 +31,19 @@ Token sources live in [`tokens`](tokens). Generated package artifacts live in
3131
npm install @putdotio/design
3232
```
3333

34-
Common entrypoints:
34+
## Use
35+
36+
Import the generated CSS when a web surface needs put.io custom properties:
37+
38+
```css
39+
@import "@putdotio/design/css";
40+
```
41+
42+
Component recipes should consume semantic aliases such as `--field-*`,
43+
`--panel-*`, `--primary`, `--success`, and `--destructive` instead of reaching
44+
into palette tokens directly.
45+
46+
Package entrypoints:
3547

3648
- CSS custom properties: [`dist/css/tokens.css`](dist/css/tokens.css)
3749
- DTCG token tree: [`dist/tokens.dtcg.json`](dist/tokens.dtcg.json)
@@ -60,6 +72,11 @@ Use `pnpm tokens:build` after token edits.
6072
- [Security](SECURITY.md)
6173
- [Agent guide](AGENTS.md)
6274

75+
## Contributing
76+
77+
See [Contributing](CONTRIBUTING.md) for local setup, validation, and pull
78+
request expectations.
79+
6380
## License
6481

6582
[MIT](LICENSE)

dist/css/tokens.css

Lines changed: 73 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,33 @@
1010
:root {
1111
--button-secondary-bg: hsl(0, 0%, 95.1%);
1212
--button-secondary-fg: hsl(0, 0%, 9.0%);
13-
--input-bg: white;
13+
--input-bg: hsl(0, 0%, 100%);
1414
--input-border: hsl(0, 0%, 85.8%);
15+
--field-bg: hsl(0, 0%, 100%);
16+
--field-bg-disabled: hsl(0, 0%, 97.3%);
17+
--field-border: hsl(0, 0%, 85.8%);
18+
--field-border-hover: hsl(0, 0%, 78.0%);
19+
--field-border-focus: hsl(0, 0%, 78.0%);
20+
--field-text: hsl(0, 0%, 9.0%);
21+
--field-placeholder: hsl(0, 0%, 43.5%);
22+
--field-ring: 0 0 0 1px hsl(0, 0%, 78.0%);
23+
--panel-bg: hsl(0, 0%, 95.1%);
24+
--panel-border: hsl(0, 0%, 88.7%);
25+
--panel-shadow: 0 4px 12px hsla(0, 0%, 0%, 0.08);
26+
--background: hsl(0, 0%, 99.0%);
27+
--foreground: hsl(0, 0%, 9.0%);
28+
--foreground-muted: hsl(0, 0%, 43.5%);
29+
--success: hsl(153, 67.0%, 28.5%);
30+
--destructive: hsl(358, 65.0%, 48.7%);
31+
--muted: hsl(0, 0%, 97.3%);
32+
--muted-foreground: hsl(0, 0%, 43.5%);
33+
--accent: hsl(0, 0%, 95.1%);
34+
--accent-foreground: hsl(0, 0%, 9.0%);
35+
--card: hsl(0, 0%, 95.1%);
36+
--card-foreground: hsl(0, 0%, 9.0%);
37+
--popover: hsl(0, 0%, 95.1%);
38+
--popover-foreground: hsl(0, 0%, 9.0%);
39+
--input: hsl(0, 0%, 85.8%);
1540
--file-row-bg: transparent;
1641
--file-row-bg-hover: hsl(0, 0%, 97.3%);
1742
--notification-info-bg: hsl(0, 0%, 97.3%);
@@ -60,13 +85,13 @@
6085
--yellow-line: hsl(50, 89.4%, 76.1%);
6186
--yellow-border: hsl(47, 80.4%, 68.0%);
6287
--yellow-border-hover: hsl(48, 100%, 46.1%);
63-
--yellow-solid-hover: #FDCE45;
88+
--yellow-solid-hover: hsl(44.7, 97.9%, 63.1%);
6489
--yellow-text-secondary: hsl(42, 100%, 29.0%);
6590
--yellow-text: hsl(40, 55.0%, 13.5%);
6691
--lime-3: hsl(85, 76.0%, 92.3%);
6792
--html-bg: hsl(0, 0%, 97.3%);
68-
--app-bg: white;
69-
--nav-bg: white;
93+
--app-bg: hsl(0, 0%, 100%);
94+
--nav-bg: hsl(0, 0%, 100%);
7095
--nav-item-bg: transparent;
7196
--nav-item-bg-hover: hsl(0, 0%, 95.1%);
7297
--nav-item-bg-active: hsl(0, 0%, 95.1%);
@@ -75,7 +100,7 @@
75100
--list-item-bg-active: hsl(0, 0%, 97.3%);
76101
--list-item-border: hsl(0, 0%, 90.9%);
77102
--segmented-control-bg: hsl(0, 0%, 95.1%);
78-
--segmented-control-bg-active: white;
103+
--segmented-control-bg-active: hsl(0, 0%, 100%);
79104
--transfer-list-item-completing-bg: hsl(85, 76.0%, 92.3%);
80105
--transfer-list-item-downloading-bg: hsl(85, 76.0%, 92.3%);
81106
--transfer-list-item-finished-bg: hsl(0, 0%, 97.3%);
@@ -85,19 +110,26 @@
85110
--transparent: transparent;
86111
--overlay-inline: hsla(0, 0%, 0%, 0.047);
87112
--overlay-full: hsla(0, 0%, 0%, 0.439);
88-
--button-primary-bg: #FDCE45;
89-
--button-primary-fg: #0A0A0A;
113+
--button-primary-bg: hsl(44.7, 97.9%, 63.1%);
114+
--button-primary-fg: hsl(0, 0%, 4.0%);
90115
--button-radius: 6px;
91116
--input-radius: 6px;
92-
--file-row-icon: #FDCE45;
93-
--yellow-solid: #FDCE45;
117+
--panel-radius: 10px;
118+
--primary: hsl(44.7, 97.9%, 63.1%);
119+
--primary-foreground: hsl(0, 0%, 0%);
120+
--success-foreground: hsl(0, 0%, 100%);
121+
--destructive-foreground: hsl(0, 0%, 100%);
122+
--solid-foreground: hsl(0, 0%, 100%);
123+
--ring: hsla(47, 100%, 65%, 0.35);
124+
--file-row-icon: hsl(44.7, 97.9%, 63.1%);
125+
--yellow-solid: hsl(44.7, 97.9%, 63.1%);
94126
--shadow-color: hsl(0, 0%, 78.0%);
95127
--shadow: hsl(0, 0%, 78.0%);
96128
--shadow-sm: 0 1px 2px hsla(0, 0%, 0%, 0.05);
97129
--shadow-md: 0 4px 12px hsla(0, 0%, 0%, 0.08);
98130
--shadow-lg: 0 16px 40px hsla(0, 0%, 0%, 0.12);
99131
--shadow-focus-color: hsla(47, 100%, 65%, 0.35);
100-
--shadow-focus: 0 0 0 3px var(--shadow-focus-color);
132+
--shadow-focus: 0 0 0 3px hsla(47, 100%, 65%, 0.35);
101133
--font-sans: "GT America", sans-serif;
102134
--font-display: "GT America", sans-serif;
103135
--font-ui-mono: "GT America Mono", monospace;
@@ -150,8 +182,33 @@
150182
.dark {
151183
--button-secondary-bg: hsl(0, 0%, 13.6%);
152184
--button-secondary-fg: hsl(0, 0%, 93.0%);
153-
--input-bg: hsl(0, 0%, 13.6%);
185+
--input-bg: hsl(0, 0%, 8.5%);
154186
--input-border: hsl(0, 0%, 24.3%);
187+
--field-bg: hsl(0, 0%, 8.5%);
188+
--field-bg-disabled: hsl(0, 0%, 11.0%);
189+
--field-border: hsl(0, 0%, 24.3%);
190+
--field-border-hover: hsl(0, 0%, 31.2%);
191+
--field-border-focus: hsl(0, 0%, 31.2%);
192+
--field-text: hsl(0, 0%, 93.0%);
193+
--field-placeholder: hsl(0, 0%, 62.8%);
194+
--field-ring: 0 0 0 1px hsl(0, 0%, 31.2%);
195+
--panel-bg: hsl(0, 0%, 13.6%);
196+
--panel-border: hsl(0, 0%, 20.5%);
197+
--panel-shadow: 0 4px 12px hsla(0, 0%, 0%, 0.5);
198+
--background: hsl(0, 0%, 8.5%);
199+
--foreground: hsl(0, 0%, 93.0%);
200+
--foreground-muted: hsl(0, 0%, 62.8%);
201+
--success: hsl(151, 51.7%, 28.4%);
202+
--destructive: hsl(358, 65.0%, 40.4%);
203+
--muted: hsl(0, 0%, 11.0%);
204+
--muted-foreground: hsl(0, 0%, 62.8%);
205+
--accent: hsl(0, 0%, 13.6%);
206+
--accent-foreground: hsl(0, 0%, 93.0%);
207+
--card: hsl(0, 0%, 13.6%);
208+
--card-foreground: hsl(0, 0%, 93.0%);
209+
--popover: hsl(0, 0%, 13.6%);
210+
--popover-foreground: hsl(0, 0%, 93.0%);
211+
--input: hsl(0, 0%, 24.3%);
155212
--file-row-bg: transparent;
156213
--file-row-bg-hover: hsl(0, 0%, 11.0%);
157214
--notification-info-bg: hsl(0, 0%, 13.6%);
@@ -200,11 +257,11 @@
200257
--yellow-line: hsl(49, 100%, 14.3%);
201258
--yellow-border: hsl(49, 90.3%, 18.4%);
202259
--yellow-border-hover: hsl(50, 100%, 22.0%);
203-
--yellow-solid-hover: #FDCE45;
260+
--yellow-solid-hover: hsl(44.7, 97.9%, 63.1%);
204261
--yellow-text-secondary: hsl(48, 100%, 47.0%);
205262
--yellow-text: hsl(53, 100%, 91.0%);
206263
--lime-3: hsl(85, 45%, 12%);
207-
--html-bg: black;
264+
--html-bg: hsl(0, 0%, 0%);
208265
--app-bg: hsl(0, 0%, 8.5%);
209266
--nav-bg: hsl(0, 0%, 8.5%);
210267
--nav-item-bg: transparent;
@@ -224,8 +281,8 @@
224281
--lo-contrast: hsl(0, 0%, 8.5%);
225282
--overlay-inline: hsla(0, 0%, 0%, 0.439);
226283
--overlay-full: hsla(0, 0%, 0%, 0.565);
227-
--shadow-color: black;
228-
--shadow: black;
284+
--shadow-color: hsl(0, 0%, 0%);
285+
--shadow: hsl(0, 0%, 0%);
229286
--shadow-sm: 0 1px 2px hsla(0, 0%, 0%, 0.4);
230287
--shadow-md: 0 4px 12px hsla(0, 0%, 0%, 0.5);
231288
--shadow-lg: 0 16px 40px hsla(0, 0%, 0%, 0.6);
@@ -363,4 +420,4 @@ a:hover { text-decoration-color: currentColor; }
363420
.bg-1 { background: var(--bg); }
364421
.bg-2 { background: var(--bg-secondary); }
365422
.bg-component { background: var(--component-bg); }
366-
.bg-yellow { background: var(--yellow-solid); color: #000; }
423+
.bg-yellow { background: var(--yellow-solid); color: var(--primary-foreground); }

dist/figma/putio.tokens.json

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44
"primary": {
55
"background": {
66
"$type": "color",
7-
"$value": "#FDCE45",
7+
"$value": "hsl(44.7, 97.9%, 63.1%)",
88
"$description": "Primary command background."
99
},
1010
"foreground": {
1111
"$type": "color",
12-
"$value": "#0A0A0A",
12+
"$value": "hsl(0, 0%, 4.0%)",
1313
"$description": "Text or icon color on the yellow primary button."
1414
},
1515
"radius": {
@@ -31,7 +31,7 @@
3131
"input": {
3232
"background": {
3333
"$type": "color",
34-
"$value": "white"
34+
"$value": "hsl(0, 0%, 100%)"
3535
},
3636
"border": {
3737
"$type": "color",
@@ -53,7 +53,7 @@
5353
},
5454
"icon": {
5555
"$type": "color",
56-
"$value": "#FDCE45"
56+
"$value": "hsl(44.7, 97.9%, 63.1%)"
5757
}
5858
},
5959
"notification": {
@@ -71,8 +71,8 @@
7171
"brand": {
7272
"yellow": {
7373
"$type": "color",
74-
"$value": "#FDCE45",
75-
"$description": "Sacred put.io brand yellow. Do not change or tint."
74+
"$value": "hsl(44.7, 97.9%, 63.1%)",
75+
"$description": "Sacred put.io brand yellow (canonical hex #FDCE45). Do not change or tint."
7676
}
7777
},
7878
"neutral": {
@@ -267,7 +267,7 @@
267267
},
268268
"solidHover": {
269269
"$type": "color",
270-
"$value": "#FDCE45"
270+
"$value": "hsl(44.7, 97.9%, 63.1%)"
271271
},
272272
"textSecondary": {
273273
"$type": "color",
@@ -508,11 +508,11 @@
508508
},
509509
"appBg": {
510510
"$type": "color",
511-
"$value": "white"
511+
"$value": "hsl(0, 0%, 100%)"
512512
},
513513
"navBg": {
514514
"$type": "color",
515-
"$value": "white"
515+
"$value": "hsl(0, 0%, 100%)"
516516
},
517517
"navItemBg": {
518518
"$type": "color",
@@ -548,7 +548,7 @@
548548
},
549549
"segmentedControlBgActive": {
550550
"$type": "color",
551-
"$value": "white"
551+
"$value": "hsl(0, 0%, 100%)"
552552
},
553553
"transferListItemCompletingBg": {
554554
"$type": "color",

dist/tokens.d.ts

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)