@putdotio/design 3.8.0 → 3.9.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 CHANGED
@@ -126,7 +126,7 @@ Default radius `6px`; `4px` for tight controls, `8px` or `10px` for panels, pill
126
126
  ### Rows, fields, and panels
127
127
 
128
128
  - File rows are the core component: raw names, compact metadata, obvious hover and focus at the same row height.
129
- - Fields read `--field-bg`, `--field-border`, and `--field-ring` (focus). `aria-invalid="true"` turns border and text red; the fill stays.
129
+ - Fields read `--field-bg`, `--field-border`, and `--field-ring` (focus). They are filled: `--bg-secondary` on a `--line` border, so they read on the page as well as in panels. Hover steps the border to `--border-hover`; focus steps it to `--solid-hover` with a matching 1px ring, at least 3:1 against the fill, the page, and panels in both modes (WCAG 1.4.11). Disabled fields take `--component-bg`. `--bg-secondary` is the field fill, so fields never sit on it. `aria-invalid="true"` turns border and text red; the fill stays.
130
130
  - Raised panels read `--panel-*`.
131
131
  - Feedback uses `.form-callout`: `--alert-*` colours, `data-state` `info`, `success`, or `error`; `.inline` drops surface and border. It holds a message only. `.form-group` (`6px` gap) spaces a control and its feedback.
132
132
  - Every field and form error eases in through `.form-reveal`: `grid-template-rows` `0fr` to `1fr` plus opacity, over `--dur-reveal` (`180ms`) with `--ease-out`, so whatever sits below slides instead of jumping. A field error sits under its field inside `.form-group`, where the row absorbs the group gap; a form error sits above the submit button. `data-state="open"` shows it. Keep the `role="alert"` message mounted and rendered; empty it once a closed row has collapsed. An `aria-invalid` field or code fades its border red over the same `--dur-reveal`. Under `prefers-reduced-motion` nothing animates.
@@ -138,7 +138,7 @@ Default radius `6px`; `4px` for tight controls, `8px` or `10px` for panels, pill
138
138
  - One left-aligned column, up to `340px`, is centred horizontally and vertically.
139
139
  - A quiet centred footer links Terms of Service, Privacy Policy, and Help in muted `--fs-sm`.
140
140
  - One title per screen: `22px`, medium, `-0.01em` tracking. No subtitles, taglines, or marketing lines; copy stays short.
141
- - Fields are filled: the page points `--field-bg` at `--bg-secondary` and `--field-border` at `--line`. Fields and buttons in the column are `44px`.
141
+ - Fields are the standard filled field. Fields and buttons in the column are `44px`.
142
142
  - Labels are small, muted, and above the field.
143
143
  - The primary button is full-width yellow. Secondary actions sit under the form as muted text links: “Forgot password?”, “New to put.io? Sign up”, “Wrong account? Sign out”.
144
144
  - Tab order runs fields, submit, then secondary links; DOM order follows visual order, with no positive `tabindex`. Two-factor runs the code, Verify, then its links. The reveal-password toggle takes `tabindex="-1"` and keeps its accessible name: keyboard-only users can't toggle visibility, screen-reader users still can in browse mode. No link leaves the tab order.
@@ -25,21 +25,21 @@
25
25
  --button-ghost-fg: hsl(0, 0%, 43.5%);
26
26
  --button-ghost-fg-hover: hsl(0, 0%, 9.0%);
27
27
  --button-ghost-bg-hover: hsl(0, 0%, 93.0%);
28
- --input-bg: hsl(0, 0%, 100%); /* deprecated: use --field-bg */
29
- --input-border: hsl(0, 0%, 85.8%); /* deprecated: use --field-border */
28
+ --input-bg: hsl(0, 0%, 97.3%); /* deprecated: use --field-bg */
29
+ --input-border: hsl(0, 0%, 88.7%); /* deprecated: use --field-border */
30
30
  --input-border-hover: hsl(0, 0%, 78.0%); /* deprecated: use --field-border-hover */
31
- --input-border-focus: hsl(0, 0%, 78.0%); /* deprecated: use --field-border-focus */
32
- --input-ring: 0 0 0 1px hsl(0, 0%, 78.0%); /* deprecated: use --field-ring */
31
+ --input-border-focus: hsl(0, 0%, 52.3%); /* deprecated: use --field-border-focus */
32
+ --input-ring: 0 0 0 1px hsl(0, 0%, 52.3%); /* deprecated: use --field-ring */
33
33
  --input-text: hsl(0, 0%, 9.0%); /* deprecated: use --field-text */
34
34
  --input-placeholder: hsl(0, 0%, 43.5%); /* deprecated: use --field-placeholder */
35
- --field-bg: hsl(0, 0%, 100%);
36
- --field-bg-disabled: hsl(0, 0%, 97.3%);
37
- --field-border: hsl(0, 0%, 85.8%);
35
+ --field-bg: hsl(0, 0%, 97.3%);
36
+ --field-bg-disabled: hsl(0, 0%, 95.1%);
37
+ --field-border: hsl(0, 0%, 88.7%);
38
38
  --field-border-hover: hsl(0, 0%, 78.0%);
39
- --field-border-focus: hsl(0, 0%, 78.0%);
39
+ --field-border-focus: hsl(0, 0%, 52.3%);
40
40
  --field-text: hsl(0, 0%, 9.0%);
41
41
  --field-placeholder: hsl(0, 0%, 43.5%);
42
- --field-ring: 0 0 0 1px hsl(0, 0%, 78.0%);
42
+ --field-ring: 0 0 0 1px hsl(0, 0%, 52.3%);
43
43
  --panel-bg: hsl(0, 0%, 95.1%);
44
44
  --panel-border: hsl(0, 0%, 88.7%);
45
45
  --panel-shadow: 0 4px 12px hsla(0, 0%, 0%, 0.08);
@@ -58,7 +58,7 @@
58
58
  --card-foreground: hsl(0, 0%, 9.0%);
59
59
  --popover: hsl(0, 0%, 95.1%);
60
60
  --popover-foreground: hsl(0, 0%, 9.0%);
61
- --input: hsl(0, 0%, 85.8%);
61
+ --input: hsl(0, 0%, 88.7%);
62
62
  --file-row-bg: hsla(0, 0%, 0%, 0);
63
63
  --file-row-bg-hover: hsl(0, 0%, 97.3%);
64
64
  --file-row-bg-active: hsl(0, 0%, 97.3%);
@@ -333,21 +333,21 @@
333
333
  --button-ghost-fg: hsl(0, 0%, 62.8%);
334
334
  --button-ghost-fg-hover: hsl(0, 0%, 93.0%);
335
335
  --button-ghost-bg-hover: hsl(0, 0%, 15.8%);
336
- --input-bg: hsl(0, 0%, 8.5%); /* deprecated: use --field-bg */
337
- --input-border: hsl(0, 0%, 24.3%); /* deprecated: use --field-border */
336
+ --input-bg: hsl(0, 0%, 11.0%); /* deprecated: use --field-bg */
337
+ --input-border: hsl(0, 0%, 20.5%); /* deprecated: use --field-border */
338
338
  --input-border-hover: hsl(0, 0%, 31.2%); /* deprecated: use --field-border-hover */
339
- --input-border-focus: hsl(0, 0%, 31.2%); /* deprecated: use --field-border-focus */
340
- --input-ring: 0 0 0 1px hsl(0, 0%, 31.2%); /* deprecated: use --field-ring */
339
+ --input-border-focus: hsl(0, 0%, 49.4%); /* deprecated: use --field-border-focus */
340
+ --input-ring: 0 0 0 1px hsl(0, 0%, 49.4%); /* deprecated: use --field-ring */
341
341
  --input-text: hsl(0, 0%, 93.0%); /* deprecated: use --field-text */
342
342
  --input-placeholder: hsl(0, 0%, 62.8%); /* deprecated: use --field-placeholder */
343
- --field-bg: hsl(0, 0%, 8.5%);
344
- --field-bg-disabled: hsl(0, 0%, 11.0%);
345
- --field-border: hsl(0, 0%, 24.3%);
343
+ --field-bg: hsl(0, 0%, 11.0%);
344
+ --field-bg-disabled: hsl(0, 0%, 13.6%);
345
+ --field-border: hsl(0, 0%, 20.5%);
346
346
  --field-border-hover: hsl(0, 0%, 31.2%);
347
- --field-border-focus: hsl(0, 0%, 31.2%);
347
+ --field-border-focus: hsl(0, 0%, 49.4%);
348
348
  --field-text: hsl(0, 0%, 93.0%);
349
349
  --field-placeholder: hsl(0, 0%, 62.8%);
350
- --field-ring: 0 0 0 1px hsl(0, 0%, 31.2%);
350
+ --field-ring: 0 0 0 1px hsl(0, 0%, 49.4%);
351
351
  --panel-bg: hsl(0, 0%, 13.6%);
352
352
  --panel-border: hsl(0, 0%, 20.5%);
353
353
  --panel-shadow: 0 4px 12px hsla(0, 0%, 0%, 0.5);
@@ -366,7 +366,7 @@
366
366
  --card-foreground: hsl(0, 0%, 93.0%);
367
367
  --popover: hsl(0, 0%, 13.6%);
368
368
  --popover-foreground: hsl(0, 0%, 93.0%);
369
- --input: hsl(0, 0%, 24.3%);
369
+ --input: hsl(0, 0%, 20.5%);
370
370
  --file-row-bg: hsla(0, 0%, 0%, 0);
371
371
  --file-row-bg-hover: hsl(0, 0%, 11.0%);
372
372
  --file-row-bg-active: hsl(0, 0%, 11.0%);
@@ -218,12 +218,12 @@
218
218
  "input": {
219
219
  "background": {
220
220
  "$type": "color",
221
- "$value": "hsl(0, 0%, 100%)",
221
+ "$value": "hsl(0, 0%, 97.3%)",
222
222
  "$description": "Deprecated alias. Use --field-bg (component.field.background)."
223
223
  },
224
224
  "border": {
225
225
  "$type": "color",
226
- "$value": "hsl(0, 0%, 85.8%)",
226
+ "$value": "hsl(0, 0%, 88.7%)",
227
227
  "$description": "Deprecated alias. Use --field-border (component.field.border)."
228
228
  },
229
229
  "radius": {
@@ -238,7 +238,7 @@
238
238
  },
239
239
  "borderFocus": {
240
240
  "$type": "color",
241
- "$value": "hsl(0, 0%, 78.0%)",
241
+ "$value": "hsl(0, 0%, 52.3%)",
242
242
  "$description": "Deprecated alias. Use --field-border-focus (component.field.borderFocus)."
243
243
  },
244
244
  "text": {
@@ -828,8 +828,8 @@
828
828
  "field": {
829
829
  "background": {
830
830
  "$type": "color",
831
- "$value": "{surface.light.appBg}",
832
- "$description": "Form-control fill. Fields stay on the app background surface, even inside a raised panel.",
831
+ "$value": "{color.neutral.light.bgSecondary}",
832
+ "$description": "Form-control fill. Fields are filled so they read on the page background as well as inside panels.",
833
833
  "$extensions": {
834
834
  "putio": {
835
835
  "cssName": "field-bg",
@@ -840,7 +840,7 @@
840
840
  },
841
841
  "backgroundDark": {
842
842
  "$type": "color",
843
- "$value": "{surface.dark.appBg}",
843
+ "$value": "{color.neutral.dark.bgSecondary}",
844
844
  "$description": "Dark-mode form-control fill.",
845
845
  "$extensions": {
846
846
  "putio": {
@@ -852,8 +852,8 @@
852
852
  },
853
853
  "backgroundDisabled": {
854
854
  "$type": "color",
855
- "$value": "{color.neutral.light.bgSecondary}",
856
- "$description": "Disabled form-control fill.",
855
+ "$value": "{color.neutral.light.componentBg}",
856
+ "$description": "Disabled form-control fill, a step off the resting fill.",
857
857
  "$extensions": {
858
858
  "putio": {
859
859
  "cssName": "field-bg-disabled",
@@ -864,7 +864,7 @@
864
864
  },
865
865
  "backgroundDisabledDark": {
866
866
  "$type": "color",
867
- "$value": "{color.neutral.dark.bgSecondary}",
867
+ "$value": "{color.neutral.dark.componentBg}",
868
868
  "$description": "Dark-mode disabled form-control fill.",
869
869
  "$extensions": {
870
870
  "putio": {
@@ -876,7 +876,7 @@
876
876
  },
877
877
  "border": {
878
878
  "$type": "color",
879
- "$value": "{color.neutral.light.border}",
879
+ "$value": "{color.neutral.light.line}",
880
880
  "$description": "Resting form-control border.",
881
881
  "$extensions": {
882
882
  "putio": {
@@ -888,7 +888,7 @@
888
888
  },
889
889
  "borderDark": {
890
890
  "$type": "color",
891
- "$value": "{color.neutral.dark.border}",
891
+ "$value": "{color.neutral.dark.line}",
892
892
  "$description": "Dark-mode resting form-control border.",
893
893
  "$extensions": {
894
894
  "putio": {
@@ -924,8 +924,8 @@
924
924
  },
925
925
  "borderFocus": {
926
926
  "$type": "color",
927
- "$value": "{color.neutral.light.borderHover}",
928
- "$description": "Focused form-control border. Focus matches hover and does not use the yellow focus shadow.",
927
+ "$value": "{color.neutral.light.solidHover}",
928
+ "$description": "Focused form-control border, a step past hover; at least 3:1 against the fill, the page, and panels. Does not use the yellow focus shadow.",
929
929
  "$extensions": {
930
930
  "putio": {
931
931
  "cssName": "field-border-focus",
@@ -936,8 +936,8 @@
936
936
  },
937
937
  "borderFocusDark": {
938
938
  "$type": "color",
939
- "$value": "{color.neutral.dark.borderHover}",
940
- "$description": "Dark-mode focused form-control border. Focus matches hover and does not use the yellow focus shadow.",
939
+ "$value": "{color.neutral.dark.solidHover}",
940
+ "$description": "Dark-mode focused form-control border, a step past hover; at least 3:1 against the fill, the page, and panels.",
941
941
  "$extensions": {
942
942
  "putio": {
943
943
  "cssName": "field-border-focus",
@@ -1008,8 +1008,8 @@
1008
1008
  },
1009
1009
  "ring": {
1010
1010
  "$type": "string",
1011
- "$value": "0 0 0 1px {color.neutral.light.borderHover}",
1012
- "$description": "Quiet field focus ring. Brand-yellow shadow focus is reserved for buttons, links, nav, and TV focus.",
1011
+ "$value": "0 0 0 1px {color.neutral.light.solidHover}",
1012
+ "$description": "Quiet field focus ring in the focus border colour. Buttons, links, and nav focus with --shadow-focus instead.",
1013
1013
  "$extensions": {
1014
1014
  "putio": {
1015
1015
  "cssName": "field-ring",
@@ -1020,8 +1020,8 @@
1020
1020
  },
1021
1021
  "ringDark": {
1022
1022
  "$type": "string",
1023
- "$value": "0 0 0 1px {color.neutral.dark.borderHover}",
1024
- "$description": "Dark-mode quiet field focus ring. Brand-yellow shadow focus is reserved for buttons, links, nav, and TV focus.",
1023
+ "$value": "0 0 0 1px {color.neutral.dark.solidHover}",
1024
+ "$description": "Dark-mode quiet field focus ring. Buttons, links, and nav focus with --shadow-focus instead.",
1025
1025
  "$extensions": {
1026
1026
  "putio": {
1027
1027
  "cssName": "field-ring",
@@ -1500,7 +1500,7 @@
1500
1500
  },
1501
1501
  "input": {
1502
1502
  "$type": "color",
1503
- "$value": "{color.neutral.light.border}",
1503
+ "$value": "{component.field.border}",
1504
1504
  "$extensions": {
1505
1505
  "putio": {
1506
1506
  "cssName": "input",
@@ -1511,7 +1511,7 @@
1511
1511
  },
1512
1512
  "inputDark": {
1513
1513
  "$type": "color",
1514
- "$value": "{color.neutral.dark.border}",
1514
+ "$value": "{component.field.borderDark}",
1515
1515
  "$extensions": {
1516
1516
  "putio": {
1517
1517
  "cssName": "input",
@@ -454,7 +454,7 @@
454
454
  "cssName": "--input-bg",
455
455
  "type": "color",
456
456
  "mode": "light",
457
- "value": "hsl(0, 0%, 100%)",
457
+ "value": "hsl(0, 0%, 97.3%)",
458
458
  "originalValue": "{component.field.background}",
459
459
  "description": "Deprecated alias. Use --field-bg (component.field.background).",
460
460
  "deprecated": true
@@ -463,7 +463,7 @@
463
463
  "cssName": "--input-bg",
464
464
  "type": "color",
465
465
  "mode": "dark",
466
- "value": "hsl(0, 0%, 8.5%)",
466
+ "value": "hsl(0, 0%, 11.0%)",
467
467
  "originalValue": "{component.field.backgroundDark}",
468
468
  "description": "Deprecated alias. Use --field-bg (component.field.backgroundDark).",
469
469
  "deprecated": true
@@ -472,7 +472,7 @@
472
472
  "cssName": "--input-border",
473
473
  "type": "color",
474
474
  "mode": "light",
475
- "value": "hsl(0, 0%, 85.8%)",
475
+ "value": "hsl(0, 0%, 88.7%)",
476
476
  "originalValue": "{component.field.border}",
477
477
  "description": "Deprecated alias. Use --field-border (component.field.border).",
478
478
  "deprecated": true
@@ -481,7 +481,7 @@
481
481
  "cssName": "--input-border",
482
482
  "type": "color",
483
483
  "mode": "dark",
484
- "value": "hsl(0, 0%, 24.3%)",
484
+ "value": "hsl(0, 0%, 20.5%)",
485
485
  "originalValue": "{component.field.borderDark}",
486
486
  "description": "Deprecated alias. Use --field-border (component.field.borderDark).",
487
487
  "deprecated": true
@@ -517,7 +517,7 @@
517
517
  "cssName": "--input-border-focus",
518
518
  "type": "color",
519
519
  "mode": "light",
520
- "value": "hsl(0, 0%, 78.0%)",
520
+ "value": "hsl(0, 0%, 52.3%)",
521
521
  "originalValue": "{component.field.borderFocus}",
522
522
  "description": "Deprecated alias. Use --field-border-focus (component.field.borderFocus).",
523
523
  "deprecated": true
@@ -526,7 +526,7 @@
526
526
  "cssName": "--input-border-focus",
527
527
  "type": "color",
528
528
  "mode": "dark",
529
- "value": "hsl(0, 0%, 31.2%)",
529
+ "value": "hsl(0, 0%, 49.4%)",
530
530
  "originalValue": "{component.field.borderFocusDark}",
531
531
  "description": "Deprecated alias. Use --field-border-focus (component.field.borderFocusDark).",
532
532
  "deprecated": true
@@ -535,7 +535,7 @@
535
535
  "cssName": "--input-ring",
536
536
  "type": "string",
537
537
  "mode": "light",
538
- "value": "0 0 0 1px hsl(0, 0%, 78.0%)",
538
+ "value": "0 0 0 1px hsl(0, 0%, 52.3%)",
539
539
  "originalValue": "{component.field.ring}",
540
540
  "description": "Deprecated alias. Use --field-ring (component.field.ring).",
541
541
  "deprecated": true
@@ -544,7 +544,7 @@
544
544
  "cssName": "--input-ring",
545
545
  "type": "string",
546
546
  "mode": "dark",
547
- "value": "0 0 0 1px hsl(0, 0%, 31.2%)",
547
+ "value": "0 0 0 1px hsl(0, 0%, 49.4%)",
548
548
  "originalValue": "{component.field.ringDark}",
549
549
  "description": "Deprecated alias. Use --field-ring (component.field.ringDark).",
550
550
  "deprecated": true
@@ -589,48 +589,48 @@
589
589
  "cssName": "--field-bg",
590
590
  "type": "color",
591
591
  "mode": "light",
592
- "value": "hsl(0, 0%, 100%)",
593
- "originalValue": "{surface.light.appBg}",
594
- "description": "Form-control fill. Fields stay on the app background surface, even inside a raised panel."
592
+ "value": "hsl(0, 0%, 97.3%)",
593
+ "originalValue": "{color.neutral.light.bgSecondary}",
594
+ "description": "Form-control fill. Fields are filled so they read on the page background as well as inside panels."
595
595
  },
596
596
  "component.field.backgroundDark": {
597
597
  "cssName": "--field-bg",
598
598
  "type": "color",
599
599
  "mode": "dark",
600
- "value": "hsl(0, 0%, 8.5%)",
601
- "originalValue": "{surface.dark.appBg}",
600
+ "value": "hsl(0, 0%, 11.0%)",
601
+ "originalValue": "{color.neutral.dark.bgSecondary}",
602
602
  "description": "Dark-mode form-control fill."
603
603
  },
604
604
  "component.field.backgroundDisabled": {
605
605
  "cssName": "--field-bg-disabled",
606
606
  "type": "color",
607
607
  "mode": "light",
608
- "value": "hsl(0, 0%, 97.3%)",
609
- "originalValue": "{color.neutral.light.bgSecondary}",
610
- "description": "Disabled form-control fill."
608
+ "value": "hsl(0, 0%, 95.1%)",
609
+ "originalValue": "{color.neutral.light.componentBg}",
610
+ "description": "Disabled form-control fill, a step off the resting fill."
611
611
  },
612
612
  "component.field.backgroundDisabledDark": {
613
613
  "cssName": "--field-bg-disabled",
614
614
  "type": "color",
615
615
  "mode": "dark",
616
- "value": "hsl(0, 0%, 11.0%)",
617
- "originalValue": "{color.neutral.dark.bgSecondary}",
616
+ "value": "hsl(0, 0%, 13.6%)",
617
+ "originalValue": "{color.neutral.dark.componentBg}",
618
618
  "description": "Dark-mode disabled form-control fill."
619
619
  },
620
620
  "component.field.border": {
621
621
  "cssName": "--field-border",
622
622
  "type": "color",
623
623
  "mode": "light",
624
- "value": "hsl(0, 0%, 85.8%)",
625
- "originalValue": "{color.neutral.light.border}",
624
+ "value": "hsl(0, 0%, 88.7%)",
625
+ "originalValue": "{color.neutral.light.line}",
626
626
  "description": "Resting form-control border."
627
627
  },
628
628
  "component.field.borderDark": {
629
629
  "cssName": "--field-border",
630
630
  "type": "color",
631
631
  "mode": "dark",
632
- "value": "hsl(0, 0%, 24.3%)",
633
- "originalValue": "{color.neutral.dark.border}",
632
+ "value": "hsl(0, 0%, 20.5%)",
633
+ "originalValue": "{color.neutral.dark.line}",
634
634
  "description": "Dark-mode resting form-control border."
635
635
  },
636
636
  "component.field.borderHover": {
@@ -653,17 +653,17 @@
653
653
  "cssName": "--field-border-focus",
654
654
  "type": "color",
655
655
  "mode": "light",
656
- "value": "hsl(0, 0%, 78.0%)",
657
- "originalValue": "{color.neutral.light.borderHover}",
658
- "description": "Focused form-control border. Focus matches hover and does not use the yellow focus shadow."
656
+ "value": "hsl(0, 0%, 52.3%)",
657
+ "originalValue": "{color.neutral.light.solidHover}",
658
+ "description": "Focused form-control border, a step past hover; at least 3:1 against the fill, the page, and panels. Does not use the yellow focus shadow."
659
659
  },
660
660
  "component.field.borderFocusDark": {
661
661
  "cssName": "--field-border-focus",
662
662
  "type": "color",
663
663
  "mode": "dark",
664
- "value": "hsl(0, 0%, 31.2%)",
665
- "originalValue": "{color.neutral.dark.borderHover}",
666
- "description": "Dark-mode focused form-control border. Focus matches hover and does not use the yellow focus shadow."
664
+ "value": "hsl(0, 0%, 49.4%)",
665
+ "originalValue": "{color.neutral.dark.solidHover}",
666
+ "description": "Dark-mode focused form-control border, a step past hover; at least 3:1 against the fill, the page, and panels."
667
667
  },
668
668
  "component.field.text": {
669
669
  "cssName": "--field-text",
@@ -709,17 +709,17 @@
709
709
  "cssName": "--field-ring",
710
710
  "type": "string",
711
711
  "mode": "light",
712
- "value": "0 0 0 1px hsl(0, 0%, 78.0%)",
713
- "originalValue": "0 0 0 1px {color.neutral.light.borderHover}",
714
- "description": "Quiet field focus ring. Brand-yellow shadow focus is reserved for buttons, links, nav, and TV focus."
712
+ "value": "0 0 0 1px hsl(0, 0%, 52.3%)",
713
+ "originalValue": "0 0 0 1px {color.neutral.light.solidHover}",
714
+ "description": "Quiet field focus ring in the focus border colour. Buttons, links, and nav focus with --shadow-focus instead."
715
715
  },
716
716
  "component.field.ringDark": {
717
717
  "cssName": "--field-ring",
718
718
  "type": "string",
719
719
  "mode": "dark",
720
- "value": "0 0 0 1px hsl(0, 0%, 31.2%)",
721
- "originalValue": "0 0 0 1px {color.neutral.dark.borderHover}",
722
- "description": "Dark-mode quiet field focus ring. Brand-yellow shadow focus is reserved for buttons, links, nav, and TV focus."
720
+ "value": "0 0 0 1px hsl(0, 0%, 49.4%)",
721
+ "originalValue": "0 0 0 1px {color.neutral.dark.solidHover}",
722
+ "description": "Dark-mode quiet field focus ring. Buttons, links, and nav focus with --shadow-focus instead."
723
723
  },
724
724
  "component.panel.background": {
725
725
  "cssName": "--panel-bg",
@@ -1025,15 +1025,15 @@
1025
1025
  "cssName": "--input",
1026
1026
  "type": "color",
1027
1027
  "mode": "light",
1028
- "value": "hsl(0, 0%, 85.8%)",
1029
- "originalValue": "{color.neutral.light.border}"
1028
+ "value": "hsl(0, 0%, 88.7%)",
1029
+ "originalValue": "{component.field.border}"
1030
1030
  },
1031
1031
  "component.alias.inputDark": {
1032
1032
  "cssName": "--input",
1033
1033
  "type": "color",
1034
1034
  "mode": "dark",
1035
- "value": "hsl(0, 0%, 24.3%)",
1036
- "originalValue": "{color.neutral.dark.border}"
1035
+ "value": "hsl(0, 0%, 20.5%)",
1036
+ "originalValue": "{component.field.borderDark}"
1037
1037
  },
1038
1038
  "component.alias.ring": {
1039
1039
  "cssName": "--ring",
package/dist/tokens.js CHANGED
@@ -456,7 +456,7 @@ export const tokens = {
456
456
  "cssName": "--input-bg",
457
457
  "type": "color",
458
458
  "mode": "light",
459
- "value": "hsl(0, 0%, 100%)",
459
+ "value": "hsl(0, 0%, 97.3%)",
460
460
  "originalValue": "{component.field.background}",
461
461
  "description": "Deprecated alias. Use --field-bg (component.field.background).",
462
462
  "deprecated": true
@@ -465,7 +465,7 @@ export const tokens = {
465
465
  "cssName": "--input-bg",
466
466
  "type": "color",
467
467
  "mode": "dark",
468
- "value": "hsl(0, 0%, 8.5%)",
468
+ "value": "hsl(0, 0%, 11.0%)",
469
469
  "originalValue": "{component.field.backgroundDark}",
470
470
  "description": "Deprecated alias. Use --field-bg (component.field.backgroundDark).",
471
471
  "deprecated": true
@@ -474,7 +474,7 @@ export const tokens = {
474
474
  "cssName": "--input-border",
475
475
  "type": "color",
476
476
  "mode": "light",
477
- "value": "hsl(0, 0%, 85.8%)",
477
+ "value": "hsl(0, 0%, 88.7%)",
478
478
  "originalValue": "{component.field.border}",
479
479
  "description": "Deprecated alias. Use --field-border (component.field.border).",
480
480
  "deprecated": true
@@ -483,7 +483,7 @@ export const tokens = {
483
483
  "cssName": "--input-border",
484
484
  "type": "color",
485
485
  "mode": "dark",
486
- "value": "hsl(0, 0%, 24.3%)",
486
+ "value": "hsl(0, 0%, 20.5%)",
487
487
  "originalValue": "{component.field.borderDark}",
488
488
  "description": "Deprecated alias. Use --field-border (component.field.borderDark).",
489
489
  "deprecated": true
@@ -519,7 +519,7 @@ export const tokens = {
519
519
  "cssName": "--input-border-focus",
520
520
  "type": "color",
521
521
  "mode": "light",
522
- "value": "hsl(0, 0%, 78.0%)",
522
+ "value": "hsl(0, 0%, 52.3%)",
523
523
  "originalValue": "{component.field.borderFocus}",
524
524
  "description": "Deprecated alias. Use --field-border-focus (component.field.borderFocus).",
525
525
  "deprecated": true
@@ -528,7 +528,7 @@ export const tokens = {
528
528
  "cssName": "--input-border-focus",
529
529
  "type": "color",
530
530
  "mode": "dark",
531
- "value": "hsl(0, 0%, 31.2%)",
531
+ "value": "hsl(0, 0%, 49.4%)",
532
532
  "originalValue": "{component.field.borderFocusDark}",
533
533
  "description": "Deprecated alias. Use --field-border-focus (component.field.borderFocusDark).",
534
534
  "deprecated": true
@@ -537,7 +537,7 @@ export const tokens = {
537
537
  "cssName": "--input-ring",
538
538
  "type": "string",
539
539
  "mode": "light",
540
- "value": "0 0 0 1px hsl(0, 0%, 78.0%)",
540
+ "value": "0 0 0 1px hsl(0, 0%, 52.3%)",
541
541
  "originalValue": "{component.field.ring}",
542
542
  "description": "Deprecated alias. Use --field-ring (component.field.ring).",
543
543
  "deprecated": true
@@ -546,7 +546,7 @@ export const tokens = {
546
546
  "cssName": "--input-ring",
547
547
  "type": "string",
548
548
  "mode": "dark",
549
- "value": "0 0 0 1px hsl(0, 0%, 31.2%)",
549
+ "value": "0 0 0 1px hsl(0, 0%, 49.4%)",
550
550
  "originalValue": "{component.field.ringDark}",
551
551
  "description": "Deprecated alias. Use --field-ring (component.field.ringDark).",
552
552
  "deprecated": true
@@ -591,48 +591,48 @@ export const tokens = {
591
591
  "cssName": "--field-bg",
592
592
  "type": "color",
593
593
  "mode": "light",
594
- "value": "hsl(0, 0%, 100%)",
595
- "originalValue": "{surface.light.appBg}",
596
- "description": "Form-control fill. Fields stay on the app background surface, even inside a raised panel."
594
+ "value": "hsl(0, 0%, 97.3%)",
595
+ "originalValue": "{color.neutral.light.bgSecondary}",
596
+ "description": "Form-control fill. Fields are filled so they read on the page background as well as inside panels."
597
597
  },
598
598
  "component.field.backgroundDark": {
599
599
  "cssName": "--field-bg",
600
600
  "type": "color",
601
601
  "mode": "dark",
602
- "value": "hsl(0, 0%, 8.5%)",
603
- "originalValue": "{surface.dark.appBg}",
602
+ "value": "hsl(0, 0%, 11.0%)",
603
+ "originalValue": "{color.neutral.dark.bgSecondary}",
604
604
  "description": "Dark-mode form-control fill."
605
605
  },
606
606
  "component.field.backgroundDisabled": {
607
607
  "cssName": "--field-bg-disabled",
608
608
  "type": "color",
609
609
  "mode": "light",
610
- "value": "hsl(0, 0%, 97.3%)",
611
- "originalValue": "{color.neutral.light.bgSecondary}",
612
- "description": "Disabled form-control fill."
610
+ "value": "hsl(0, 0%, 95.1%)",
611
+ "originalValue": "{color.neutral.light.componentBg}",
612
+ "description": "Disabled form-control fill, a step off the resting fill."
613
613
  },
614
614
  "component.field.backgroundDisabledDark": {
615
615
  "cssName": "--field-bg-disabled",
616
616
  "type": "color",
617
617
  "mode": "dark",
618
- "value": "hsl(0, 0%, 11.0%)",
619
- "originalValue": "{color.neutral.dark.bgSecondary}",
618
+ "value": "hsl(0, 0%, 13.6%)",
619
+ "originalValue": "{color.neutral.dark.componentBg}",
620
620
  "description": "Dark-mode disabled form-control fill."
621
621
  },
622
622
  "component.field.border": {
623
623
  "cssName": "--field-border",
624
624
  "type": "color",
625
625
  "mode": "light",
626
- "value": "hsl(0, 0%, 85.8%)",
627
- "originalValue": "{color.neutral.light.border}",
626
+ "value": "hsl(0, 0%, 88.7%)",
627
+ "originalValue": "{color.neutral.light.line}",
628
628
  "description": "Resting form-control border."
629
629
  },
630
630
  "component.field.borderDark": {
631
631
  "cssName": "--field-border",
632
632
  "type": "color",
633
633
  "mode": "dark",
634
- "value": "hsl(0, 0%, 24.3%)",
635
- "originalValue": "{color.neutral.dark.border}",
634
+ "value": "hsl(0, 0%, 20.5%)",
635
+ "originalValue": "{color.neutral.dark.line}",
636
636
  "description": "Dark-mode resting form-control border."
637
637
  },
638
638
  "component.field.borderHover": {
@@ -655,17 +655,17 @@ export const tokens = {
655
655
  "cssName": "--field-border-focus",
656
656
  "type": "color",
657
657
  "mode": "light",
658
- "value": "hsl(0, 0%, 78.0%)",
659
- "originalValue": "{color.neutral.light.borderHover}",
660
- "description": "Focused form-control border. Focus matches hover and does not use the yellow focus shadow."
658
+ "value": "hsl(0, 0%, 52.3%)",
659
+ "originalValue": "{color.neutral.light.solidHover}",
660
+ "description": "Focused form-control border, a step past hover; at least 3:1 against the fill, the page, and panels. Does not use the yellow focus shadow."
661
661
  },
662
662
  "component.field.borderFocusDark": {
663
663
  "cssName": "--field-border-focus",
664
664
  "type": "color",
665
665
  "mode": "dark",
666
- "value": "hsl(0, 0%, 31.2%)",
667
- "originalValue": "{color.neutral.dark.borderHover}",
668
- "description": "Dark-mode focused form-control border. Focus matches hover and does not use the yellow focus shadow."
666
+ "value": "hsl(0, 0%, 49.4%)",
667
+ "originalValue": "{color.neutral.dark.solidHover}",
668
+ "description": "Dark-mode focused form-control border, a step past hover; at least 3:1 against the fill, the page, and panels."
669
669
  },
670
670
  "component.field.text": {
671
671
  "cssName": "--field-text",
@@ -711,17 +711,17 @@ export const tokens = {
711
711
  "cssName": "--field-ring",
712
712
  "type": "string",
713
713
  "mode": "light",
714
- "value": "0 0 0 1px hsl(0, 0%, 78.0%)",
715
- "originalValue": "0 0 0 1px {color.neutral.light.borderHover}",
716
- "description": "Quiet field focus ring. Brand-yellow shadow focus is reserved for buttons, links, nav, and TV focus."
714
+ "value": "0 0 0 1px hsl(0, 0%, 52.3%)",
715
+ "originalValue": "0 0 0 1px {color.neutral.light.solidHover}",
716
+ "description": "Quiet field focus ring in the focus border colour. Buttons, links, and nav focus with --shadow-focus instead."
717
717
  },
718
718
  "component.field.ringDark": {
719
719
  "cssName": "--field-ring",
720
720
  "type": "string",
721
721
  "mode": "dark",
722
- "value": "0 0 0 1px hsl(0, 0%, 31.2%)",
723
- "originalValue": "0 0 0 1px {color.neutral.dark.borderHover}",
724
- "description": "Dark-mode quiet field focus ring. Brand-yellow shadow focus is reserved for buttons, links, nav, and TV focus."
722
+ "value": "0 0 0 1px hsl(0, 0%, 49.4%)",
723
+ "originalValue": "0 0 0 1px {color.neutral.dark.solidHover}",
724
+ "description": "Dark-mode quiet field focus ring. Buttons, links, and nav focus with --shadow-focus instead."
725
725
  },
726
726
  "component.panel.background": {
727
727
  "cssName": "--panel-bg",
@@ -1027,15 +1027,15 @@ export const tokens = {
1027
1027
  "cssName": "--input",
1028
1028
  "type": "color",
1029
1029
  "mode": "light",
1030
- "value": "hsl(0, 0%, 85.8%)",
1031
- "originalValue": "{color.neutral.light.border}"
1030
+ "value": "hsl(0, 0%, 88.7%)",
1031
+ "originalValue": "{component.field.border}"
1032
1032
  },
1033
1033
  "component.alias.inputDark": {
1034
1034
  "cssName": "--input",
1035
1035
  "type": "color",
1036
1036
  "mode": "dark",
1037
- "value": "hsl(0, 0%, 24.3%)",
1038
- "originalValue": "{color.neutral.dark.border}"
1037
+ "value": "hsl(0, 0%, 20.5%)",
1038
+ "originalValue": "{component.field.borderDark}"
1039
1039
  },
1040
1040
  "component.alias.ring": {
1041
1041
  "cssName": "--ring",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@putdotio/design",
3
- "version": "3.8.0",
3
+ "version": "3.9.0",
4
4
  "description": "Public put.io design tokens, brand assets, and design-system guidance.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/system/README.md CHANGED
@@ -139,7 +139,7 @@ own, so the two name systems cannot drift.
139
139
  | `--accent` / `--accent-foreground` | `--component-bg` / `--text` |
140
140
  | `--card` / `--card-foreground` | `--component-bg` / `--text` |
141
141
  | `--popover` / `--popover-foreground` | `--component-bg` / `--text` |
142
- | `--input` | `--border` |
142
+ | `--input` | `--field-border` |
143
143
  | `--ring` | `--shadow-focus-color` |
144
144
  | `--background` / `--foreground` | `--bg` / `--text` |
145
145
 
@@ -265,11 +265,12 @@ input, textarea, select { text-transform: none; letter-spacing: normal; }
265
265
  now they all inherit from here. To override per-screen, change
266
266
  geometry (height/padding) — not the surface tokens.
267
267
 
268
- Surface contract:
269
- bg → --field-bg (= --app-bg)
270
- border → --field-border (= --border)
271
- border:hover → --field-border-hover
272
- focus ring → --field-ring (1px border-hover, NOT yellow)
268
+ Surface contract (filled, so a field reads on any surface):
269
+ bg → --field-bg (= --bg-secondary)
270
+ border → --field-border (= --line)
271
+ border:hover → --field-border-hover (= --border-hover)
272
+ border:focus → --field-border-focus (= --solid-hover, ≥3:1 on fill, page, panel)
273
+ focus ring → --field-ring (1px in the focus colour, NOT yellow)
273
274
  placeholder → --field-placeholder
274
275
  disabled bg → --field-bg-disabled
275
276
 
@@ -567,18 +568,11 @@ input, textarea, select { text-transform: none; letter-spacing: normal; }
567
568
 
568
569
  Card-less: the form sits on the page background. Logo top-left
569
570
  in .auth-header, one left-aligned 340px column centred in
570
- .auth-main, a quiet link row in .auth-footer. The page re-points
571
- --field-bg / --field-border, so .field and .otp-slot render filled
572
- without a variant. Controls are 44px; the title is the only
573
- heading. Under 640px the gutters drop to 24px so the logo lines
571
+ .auth-main, a quiet link row in .auth-footer. Controls are 44px;
572
+ the title is the only heading. Under 640px the gutters drop to 24px so the logo lines
574
573
  up with the column.
575
574
  =========================================================== */
576
575
  .auth-page {
577
- --field-bg: var(--bg-secondary);
578
- --field-border: var(--line);
579
- /* Focus a step past hover, so it holds 3:1 against the filled field. */
580
- --field-border-focus: var(--solid-hover);
581
- --field-ring: 0 0 0 1px var(--solid-hover);
582
576
  box-sizing: border-box;
583
577
  min-height: 100dvh;
584
578
  display: flex;
@@ -828,8 +828,8 @@
828
828
  "field": {
829
829
  "background": {
830
830
  "$type": "color",
831
- "$value": "{surface.light.appBg}",
832
- "$description": "Form-control fill. Fields stay on the app background surface, even inside a raised panel.",
831
+ "$value": "{color.neutral.light.bgSecondary}",
832
+ "$description": "Form-control fill. Fields are filled so they read on the page background as well as inside panels.",
833
833
  "$extensions": {
834
834
  "putio": {
835
835
  "cssName": "field-bg",
@@ -840,7 +840,7 @@
840
840
  },
841
841
  "backgroundDark": {
842
842
  "$type": "color",
843
- "$value": "{surface.dark.appBg}",
843
+ "$value": "{color.neutral.dark.bgSecondary}",
844
844
  "$description": "Dark-mode form-control fill.",
845
845
  "$extensions": {
846
846
  "putio": {
@@ -852,8 +852,8 @@
852
852
  },
853
853
  "backgroundDisabled": {
854
854
  "$type": "color",
855
- "$value": "{color.neutral.light.bgSecondary}",
856
- "$description": "Disabled form-control fill.",
855
+ "$value": "{color.neutral.light.componentBg}",
856
+ "$description": "Disabled form-control fill, a step off the resting fill.",
857
857
  "$extensions": {
858
858
  "putio": {
859
859
  "cssName": "field-bg-disabled",
@@ -864,7 +864,7 @@
864
864
  },
865
865
  "backgroundDisabledDark": {
866
866
  "$type": "color",
867
- "$value": "{color.neutral.dark.bgSecondary}",
867
+ "$value": "{color.neutral.dark.componentBg}",
868
868
  "$description": "Dark-mode disabled form-control fill.",
869
869
  "$extensions": {
870
870
  "putio": {
@@ -876,7 +876,7 @@
876
876
  },
877
877
  "border": {
878
878
  "$type": "color",
879
- "$value": "{color.neutral.light.border}",
879
+ "$value": "{color.neutral.light.line}",
880
880
  "$description": "Resting form-control border.",
881
881
  "$extensions": {
882
882
  "putio": {
@@ -888,7 +888,7 @@
888
888
  },
889
889
  "borderDark": {
890
890
  "$type": "color",
891
- "$value": "{color.neutral.dark.border}",
891
+ "$value": "{color.neutral.dark.line}",
892
892
  "$description": "Dark-mode resting form-control border.",
893
893
  "$extensions": {
894
894
  "putio": {
@@ -924,8 +924,8 @@
924
924
  },
925
925
  "borderFocus": {
926
926
  "$type": "color",
927
- "$value": "{color.neutral.light.borderHover}",
928
- "$description": "Focused form-control border. Focus matches hover and does not use the yellow focus shadow.",
927
+ "$value": "{color.neutral.light.solidHover}",
928
+ "$description": "Focused form-control border, a step past hover; at least 3:1 against the fill, the page, and panels. Does not use the yellow focus shadow.",
929
929
  "$extensions": {
930
930
  "putio": {
931
931
  "cssName": "field-border-focus",
@@ -936,8 +936,8 @@
936
936
  },
937
937
  "borderFocusDark": {
938
938
  "$type": "color",
939
- "$value": "{color.neutral.dark.borderHover}",
940
- "$description": "Dark-mode focused form-control border. Focus matches hover and does not use the yellow focus shadow.",
939
+ "$value": "{color.neutral.dark.solidHover}",
940
+ "$description": "Dark-mode focused form-control border, a step past hover; at least 3:1 against the fill, the page, and panels.",
941
941
  "$extensions": {
942
942
  "putio": {
943
943
  "cssName": "field-border-focus",
@@ -1008,8 +1008,8 @@
1008
1008
  },
1009
1009
  "ring": {
1010
1010
  "$type": "string",
1011
- "$value": "0 0 0 1px {color.neutral.light.borderHover}",
1012
- "$description": "Quiet field focus ring. Brand-yellow shadow focus is reserved for buttons, links, nav, and TV focus.",
1011
+ "$value": "0 0 0 1px {color.neutral.light.solidHover}",
1012
+ "$description": "Quiet field focus ring in the focus border colour. Buttons, links, and nav focus with --shadow-focus instead.",
1013
1013
  "$extensions": {
1014
1014
  "putio": {
1015
1015
  "cssName": "field-ring",
@@ -1020,8 +1020,8 @@
1020
1020
  },
1021
1021
  "ringDark": {
1022
1022
  "$type": "string",
1023
- "$value": "0 0 0 1px {color.neutral.dark.borderHover}",
1024
- "$description": "Dark-mode quiet field focus ring. Brand-yellow shadow focus is reserved for buttons, links, nav, and TV focus.",
1023
+ "$value": "0 0 0 1px {color.neutral.dark.solidHover}",
1024
+ "$description": "Dark-mode quiet field focus ring. Buttons, links, and nav focus with --shadow-focus instead.",
1025
1025
  "$extensions": {
1026
1026
  "putio": {
1027
1027
  "cssName": "field-ring",
@@ -1500,7 +1500,7 @@
1500
1500
  },
1501
1501
  "input": {
1502
1502
  "$type": "color",
1503
- "$value": "{color.neutral.light.border}",
1503
+ "$value": "{component.field.border}",
1504
1504
  "$extensions": {
1505
1505
  "putio": {
1506
1506
  "cssName": "input",
@@ -1511,7 +1511,7 @@
1511
1511
  },
1512
1512
  "inputDark": {
1513
1513
  "$type": "color",
1514
- "$value": "{color.neutral.dark.border}",
1514
+ "$value": "{component.field.borderDark}",
1515
1515
  "$extensions": {
1516
1516
  "putio": {
1517
1517
  "cssName": "input",