@radicool/throughline 0.23.0 → 0.24.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.
Files changed (47) hide show
  1. package/README.md +5 -5
  2. package/adapters/codex/prompts/component-builder.md +8 -4
  3. package/adapters/cursor/.cursor/rules/component-builder.mdc +8 -4
  4. package/adapters/generic/skills/component-builder/SKILL.md +8 -4
  5. package/package.json +1 -1
  6. package/references/figma-checks.md +357 -28
  7. package/references/figma-component-standards.md +8 -0
  8. package/references/proof-bundle.md +1 -0
  9. package/scripts/README.md +4 -4
  10. package/scripts/build-figma-checks.mjs +25 -12
  11. package/scripts/lib/contrast.mjs +5 -2
  12. package/scripts/lib/figma-checks-read.figma.js +59 -5
  13. package/scripts/lib/figma-checks.mjs +160 -15
  14. package/scripts/lib/fixtures/figma-checks/avatar-not-in-table.json +2 -1
  15. package/scripts/lib/fixtures/figma-checks/button-ios-swift-skipped.json +2 -1
  16. package/scripts/lib/fixtures/figma-checks/button-missing-default.json +2 -1
  17. package/scripts/lib/fixtures/figma-checks/button-mui-ring.json +2 -1
  18. package/scripts/lib/fixtures/figma-checks/button-no-focus-variant.json +2 -1
  19. package/scripts/lib/fixtures/figma-checks/button-plain-frames.json +2 -1
  20. package/scripts/lib/fixtures/figma-checks/button-ring-child-not-absolute.json +2 -1
  21. package/scripts/lib/fixtures/figma-checks/button-ring-hidden.json +2 -1
  22. package/scripts/lib/fixtures/figma-checks/button-ring-unbound-colour.json +4 -3
  23. package/scripts/lib/fixtures/figma-checks/button-shadcn-filled.json +2 -1
  24. package/scripts/lib/fixtures/figma-checks/button-sparse.json +2 -1
  25. package/scripts/lib/fixtures/figma-checks/button-spread-zero.json +2 -1
  26. package/scripts/lib/fixtures/figma-checks/button-transparent-ring-child.json +2 -1
  27. package/scripts/lib/fixtures/figma-checks/button-vanilla-inside.json +2 -1
  28. package/scripts/lib/fixtures/figma-checks/button-vanilla-outside.json +2 -1
  29. package/scripts/lib/fixtures/figma-checks/button-wrong-combination.json +2 -1
  30. package/scripts/lib/fixtures/figma-checks/checkbox-checked-axis.real.json +2 -1
  31. package/scripts/lib/fixtures/figma-checks/checkbox-checked-synonym.json +2 -1
  32. package/scripts/lib/fixtures/figma-checks/checkbox-missing-selected.json +2 -1
  33. package/scripts/lib/fixtures/figma-checks/indicator-failed.json +106 -0
  34. package/scripts/lib/fixtures/figma-checks/input-control-layer-missing.json +2 -1
  35. package/scripts/lib/fixtures/figma-checks/input-control-layer-ring-on-wrapper.json +2 -1
  36. package/scripts/lib/fixtures/figma-checks/input-control-layer.json +2 -1
  37. package/scripts/lib/fixtures/figma-checks/input-mui-weight-unbound.json +2 -1
  38. package/scripts/lib/fixtures/figma-checks/input-mui.json +2 -1
  39. package/scripts/lib/fixtures/figma-checks/ring-single-mode.json +112 -0
  40. package/scripts/lib/fixtures/figma-checks/ring-translucent.json +111 -0
  41. package/scripts/lib/fixtures/figma-checks/sample-button.real.json +2 -1
  42. package/scripts/lib/fixtures/figma-checks/sample-ring-on-muted-raw.json +113 -0
  43. package/scripts/lib/fixtures/figma-checks/sample-ring-passes.json +169 -0
  44. package/scripts/lib/fixtures/figma-checks/surface-missing.json +108 -0
  45. package/scripts/lib/fixtures/figma-checks/surface-single-mode.json +112 -0
  46. package/scripts/lib/fixtures/figma-checks/surface-translucent.json +112 -0
  47. package/scripts/lib/fixtures/figma-checks/zygarden-ring-light-fails.json +113 -0
@@ -129,6 +129,7 @@
129
129
  "expected": {
130
130
  "structural-read-back": "fail",
131
131
  "state-baseline": "pass",
132
- "focus-indicator": "pass"
132
+ "focus-indicator": "pass",
133
+ "focus-contrast": "skip"
133
134
  }
134
135
  }
@@ -87,6 +87,7 @@
87
87
  "expected": {
88
88
  "structural-read-back": "pass",
89
89
  "state-baseline": "pass",
90
- "focus-indicator": "fail"
90
+ "focus-indicator": "fail",
91
+ "focus-contrast": "skip"
91
92
  }
92
93
  }
@@ -89,6 +89,7 @@
89
89
  "expected": {
90
90
  "structural-read-back": "pass",
91
91
  "state-baseline": "pass",
92
- "focus-indicator": "pass"
92
+ "focus-indicator": "pass",
93
+ "focus-contrast": "skip"
93
94
  }
94
95
  }
@@ -82,6 +82,7 @@
82
82
  "expected": {
83
83
  "structural-read-back": "pass",
84
84
  "state-baseline": "pass",
85
- "focus-indicator": "fail"
85
+ "focus-indicator": "fail",
86
+ "focus-contrast": "skip"
86
87
  }
87
88
  }
@@ -82,6 +82,7 @@
82
82
  "expected": {
83
83
  "structural-read-back": "pass",
84
84
  "state-baseline": "pass",
85
- "focus-indicator": "pass"
85
+ "focus-indicator": "pass",
86
+ "focus-contrast": "skip"
86
87
  }
87
88
  }
@@ -87,6 +87,7 @@
87
87
  "expected": {
88
88
  "structural-read-back": "fail",
89
89
  "state-baseline": "fail",
90
- "focus-indicator": "pass"
90
+ "focus-indicator": "pass",
91
+ "focus-contrast": "skip"
91
92
  }
92
93
  }
@@ -22,7 +22,8 @@
22
22
  "expected": {
23
23
  "structural-read-back": "pass",
24
24
  "state-baseline": "pass",
25
- "focus-indicator": "pass"
25
+ "focus-indicator": "pass",
26
+ "focus-contrast": "skip"
26
27
  },
27
28
  "snapshot": {
28
29
  "type": "COMPONENT_SET",
@@ -82,6 +82,7 @@
82
82
  "expected": {
83
83
  "structural-read-back": "pass",
84
84
  "state-baseline": "pass",
85
- "focus-indicator": "pass"
85
+ "focus-indicator": "pass",
86
+ "focus-contrast": "skip"
86
87
  }
87
88
  }
@@ -74,6 +74,7 @@
74
74
  "expected": {
75
75
  "structural-read-back": "pass",
76
76
  "state-baseline": "fail",
77
- "focus-indicator": "pass"
77
+ "focus-indicator": "pass",
78
+ "focus-contrast": "skip"
78
79
  }
79
80
  }
@@ -0,0 +1,106 @@
1
+ {
2
+ "covers": "no ring on the focus variant: focus-indicator fails, so focus-contrast skips",
3
+ "expect": {
4
+ "name": "Button",
5
+ "matrix": {
6
+ "variant": [
7
+ "primary"
8
+ ],
9
+ "state": [
10
+ "default",
11
+ "hover",
12
+ "focus",
13
+ "active",
14
+ "disabled"
15
+ ]
16
+ },
17
+ "uiFramework": "shadcn",
18
+ "surfaces": [
19
+ "color/bg/canvas"
20
+ ]
21
+ },
22
+ "snapshot": {
23
+ "type": "COMPONENT_SET",
24
+ "variantGroupProperties": {
25
+ "Variant": {
26
+ "values": [
27
+ "Primary"
28
+ ]
29
+ },
30
+ "State": {
31
+ "values": [
32
+ "Default",
33
+ "Hover",
34
+ "Focus",
35
+ "Active",
36
+ "Disabled"
37
+ ]
38
+ }
39
+ },
40
+ "children": [
41
+ {
42
+ "type": "COMPONENT",
43
+ "variantProperties": {
44
+ "Variant": "Primary",
45
+ "State": "Default"
46
+ }
47
+ },
48
+ {
49
+ "type": "COMPONENT",
50
+ "variantProperties": {
51
+ "Variant": "Primary",
52
+ "State": "Hover"
53
+ }
54
+ },
55
+ {
56
+ "type": "COMPONENT",
57
+ "variantProperties": {
58
+ "Variant": "Primary",
59
+ "State": "Focus"
60
+ },
61
+ "effects": [
62
+ {
63
+ "type": "DROP_SHADOW",
64
+ "visible": true,
65
+ "spread": 3,
66
+ "colorVariable": null
67
+ }
68
+ ],
69
+ "strokeAlign": "INSIDE",
70
+ "strokeVariables": [],
71
+ "strokeWeightBound": false,
72
+ "children": []
73
+ },
74
+ {
75
+ "type": "COMPONENT",
76
+ "variantProperties": {
77
+ "Variant": "Primary",
78
+ "State": "Active"
79
+ }
80
+ },
81
+ {
82
+ "type": "COMPONENT",
83
+ "variantProperties": {
84
+ "Variant": "Primary",
85
+ "State": "Disabled"
86
+ }
87
+ }
88
+ ],
89
+ "colors": {
90
+ "color/bg/canvas": {
91
+ "modes": {
92
+ "Light": "#ffffff",
93
+ "Dark": "#181818"
94
+ },
95
+ "defaultMode": "Light"
96
+ }
97
+ },
98
+ "missingSurfaces": []
99
+ },
100
+ "expected": {
101
+ "structural-read-back": "pass",
102
+ "state-baseline": "pass",
103
+ "focus-indicator": "fail",
104
+ "focus-contrast": "skip"
105
+ }
106
+ }
@@ -61,6 +61,7 @@
61
61
  "expected": {
62
62
  "structural-read-back": "pass",
63
63
  "state-baseline": "pass",
64
- "focus-indicator": "fail"
64
+ "focus-indicator": "fail",
65
+ "focus-contrast": "skip"
65
66
  }
66
67
  }
@@ -74,6 +74,7 @@
74
74
  "expected": {
75
75
  "structural-read-back": "pass",
76
76
  "state-baseline": "pass",
77
- "focus-indicator": "fail"
77
+ "focus-indicator": "fail",
78
+ "focus-contrast": "skip"
78
79
  }
79
80
  }
@@ -74,6 +74,7 @@
74
74
  "expected": {
75
75
  "structural-read-back": "pass",
76
76
  "state-baseline": "pass",
77
- "focus-indicator": "pass"
77
+ "focus-indicator": "pass",
78
+ "focus-contrast": "skip"
78
79
  }
79
80
  }
@@ -61,6 +61,7 @@
61
61
  "expected": {
62
62
  "structural-read-back": "pass",
63
63
  "state-baseline": "pass",
64
- "focus-indicator": "fail"
64
+ "focus-indicator": "fail",
65
+ "focus-contrast": "skip"
65
66
  }
66
67
  }
@@ -61,6 +61,7 @@
61
61
  "expected": {
62
62
  "structural-read-back": "pass",
63
63
  "state-baseline": "pass",
64
- "focus-indicator": "pass"
64
+ "focus-indicator": "pass",
65
+ "focus-contrast": "skip"
65
66
  }
66
67
  }
@@ -0,0 +1,112 @@
1
+ {
2
+ "covers": "a single-mode ring is compared in both surface modes, matched after the fold",
3
+ "expect": {
4
+ "name": "Button",
5
+ "matrix": {
6
+ "variant": [
7
+ "primary"
8
+ ],
9
+ "state": [
10
+ "default",
11
+ "hover",
12
+ "focus",
13
+ "active",
14
+ "disabled"
15
+ ]
16
+ },
17
+ "uiFramework": "shadcn",
18
+ "surfaces": [
19
+ "color/bg/canvas"
20
+ ]
21
+ },
22
+ "snapshot": {
23
+ "type": "COMPONENT_SET",
24
+ "variantGroupProperties": {
25
+ "Variant": {
26
+ "values": [
27
+ "Primary"
28
+ ]
29
+ },
30
+ "State": {
31
+ "values": [
32
+ "Default",
33
+ "Hover",
34
+ "Focus",
35
+ "Active",
36
+ "Disabled"
37
+ ]
38
+ }
39
+ },
40
+ "children": [
41
+ {
42
+ "type": "COMPONENT",
43
+ "variantProperties": {
44
+ "Variant": "Primary",
45
+ "State": "Default"
46
+ }
47
+ },
48
+ {
49
+ "type": "COMPONENT",
50
+ "variantProperties": {
51
+ "Variant": "Primary",
52
+ "State": "Hover"
53
+ }
54
+ },
55
+ {
56
+ "type": "COMPONENT",
57
+ "variantProperties": {
58
+ "Variant": "Primary",
59
+ "State": "Focus"
60
+ },
61
+ "effects": [
62
+ {
63
+ "type": "DROP_SHADOW",
64
+ "visible": true,
65
+ "spread": 3,
66
+ "colorVariable": "color/focus/ring"
67
+ }
68
+ ],
69
+ "strokeAlign": "INSIDE",
70
+ "strokeVariables": [],
71
+ "strokeWeightBound": false,
72
+ "children": []
73
+ },
74
+ {
75
+ "type": "COMPONENT",
76
+ "variantProperties": {
77
+ "Variant": "Primary",
78
+ "State": "Active"
79
+ }
80
+ },
81
+ {
82
+ "type": "COMPONENT",
83
+ "variantProperties": {
84
+ "Variant": "Primary",
85
+ "State": "Disabled"
86
+ }
87
+ }
88
+ ],
89
+ "colors": {
90
+ "color/focus/ring": {
91
+ "modes": {
92
+ "Default": "#169c46"
93
+ },
94
+ "defaultMode": "Default"
95
+ },
96
+ "color/bg/canvas": {
97
+ "modes": {
98
+ "light": "#ffffff",
99
+ "dark": "#181818"
100
+ },
101
+ "defaultMode": "light"
102
+ }
103
+ },
104
+ "missingSurfaces": []
105
+ },
106
+ "expected": {
107
+ "structural-read-back": "pass",
108
+ "state-baseline": "pass",
109
+ "focus-indicator": "pass",
110
+ "focus-contrast": "pass"
111
+ }
112
+ }
@@ -0,0 +1,111 @@
1
+ {
2
+ "covers": "a translucent ring is composited first: #00000033 over white is #cccccc, 1.6:1",
3
+ "expect": {
4
+ "name": "Button",
5
+ "matrix": {
6
+ "variant": [
7
+ "primary"
8
+ ],
9
+ "state": [
10
+ "default",
11
+ "hover",
12
+ "focus",
13
+ "active",
14
+ "disabled"
15
+ ]
16
+ },
17
+ "uiFramework": "shadcn",
18
+ "surfaces": [
19
+ "color/bg/canvas"
20
+ ]
21
+ },
22
+ "snapshot": {
23
+ "type": "COMPONENT_SET",
24
+ "variantGroupProperties": {
25
+ "Variant": {
26
+ "values": [
27
+ "Primary"
28
+ ]
29
+ },
30
+ "State": {
31
+ "values": [
32
+ "Default",
33
+ "Hover",
34
+ "Focus",
35
+ "Active",
36
+ "Disabled"
37
+ ]
38
+ }
39
+ },
40
+ "children": [
41
+ {
42
+ "type": "COMPONENT",
43
+ "variantProperties": {
44
+ "Variant": "Primary",
45
+ "State": "Default"
46
+ }
47
+ },
48
+ {
49
+ "type": "COMPONENT",
50
+ "variantProperties": {
51
+ "Variant": "Primary",
52
+ "State": "Hover"
53
+ }
54
+ },
55
+ {
56
+ "type": "COMPONENT",
57
+ "variantProperties": {
58
+ "Variant": "Primary",
59
+ "State": "Focus"
60
+ },
61
+ "effects": [
62
+ {
63
+ "type": "DROP_SHADOW",
64
+ "visible": true,
65
+ "spread": 3,
66
+ "colorVariable": "color/focus/ring"
67
+ }
68
+ ],
69
+ "strokeAlign": "INSIDE",
70
+ "strokeVariables": [],
71
+ "strokeWeightBound": false,
72
+ "children": []
73
+ },
74
+ {
75
+ "type": "COMPONENT",
76
+ "variantProperties": {
77
+ "Variant": "Primary",
78
+ "State": "Active"
79
+ }
80
+ },
81
+ {
82
+ "type": "COMPONENT",
83
+ "variantProperties": {
84
+ "Variant": "Primary",
85
+ "State": "Disabled"
86
+ }
87
+ }
88
+ ],
89
+ "colors": {
90
+ "color/focus/ring": {
91
+ "modes": {
92
+ "Default": "#00000033"
93
+ },
94
+ "defaultMode": "Default"
95
+ },
96
+ "color/bg/canvas": {
97
+ "modes": {
98
+ "Default": "#ffffff"
99
+ },
100
+ "defaultMode": "Default"
101
+ }
102
+ },
103
+ "missingSurfaces": []
104
+ },
105
+ "expected": {
106
+ "structural-read-back": "pass",
107
+ "state-baseline": "pass",
108
+ "focus-indicator": "pass",
109
+ "focus-contrast": "fail"
110
+ }
111
+ }
@@ -30,7 +30,8 @@
30
30
  "expected": {
31
31
  "structural-read-back": "pass",
32
32
  "state-baseline": "pass",
33
- "focus-indicator": "pass"
33
+ "focus-indicator": "pass",
34
+ "focus-contrast": "skip"
34
35
  },
35
36
  "snapshot": {
36
37
  "type": "COMPONENT_SET",
@@ -0,0 +1,113 @@
1
+ {
2
+ "covers": "sample 2026-10-13: color/focus/ring on color/bg/muted is 2.997 in Light: fails raw, prints 2.99",
3
+ "expect": {
4
+ "name": "Button",
5
+ "matrix": {
6
+ "variant": [
7
+ "primary"
8
+ ],
9
+ "state": [
10
+ "default",
11
+ "hover",
12
+ "focus",
13
+ "active",
14
+ "disabled"
15
+ ]
16
+ },
17
+ "uiFramework": "shadcn",
18
+ "surfaces": [
19
+ "color/bg/muted"
20
+ ]
21
+ },
22
+ "snapshot": {
23
+ "type": "COMPONENT_SET",
24
+ "variantGroupProperties": {
25
+ "Variant": {
26
+ "values": [
27
+ "Primary"
28
+ ]
29
+ },
30
+ "State": {
31
+ "values": [
32
+ "Default",
33
+ "Hover",
34
+ "Focus",
35
+ "Active",
36
+ "Disabled"
37
+ ]
38
+ }
39
+ },
40
+ "children": [
41
+ {
42
+ "type": "COMPONENT",
43
+ "variantProperties": {
44
+ "Variant": "Primary",
45
+ "State": "Default"
46
+ }
47
+ },
48
+ {
49
+ "type": "COMPONENT",
50
+ "variantProperties": {
51
+ "Variant": "Primary",
52
+ "State": "Hover"
53
+ }
54
+ },
55
+ {
56
+ "type": "COMPONENT",
57
+ "variantProperties": {
58
+ "Variant": "Primary",
59
+ "State": "Focus"
60
+ },
61
+ "effects": [
62
+ {
63
+ "type": "DROP_SHADOW",
64
+ "visible": true,
65
+ "spread": 3,
66
+ "colorVariable": "color/focus/ring"
67
+ }
68
+ ],
69
+ "strokeAlign": "INSIDE",
70
+ "strokeVariables": [],
71
+ "strokeWeightBound": false,
72
+ "children": []
73
+ },
74
+ {
75
+ "type": "COMPONENT",
76
+ "variantProperties": {
77
+ "Variant": "Primary",
78
+ "State": "Active"
79
+ }
80
+ },
81
+ {
82
+ "type": "COMPONENT",
83
+ "variantProperties": {
84
+ "Variant": "Primary",
85
+ "State": "Disabled"
86
+ }
87
+ }
88
+ ],
89
+ "colors": {
90
+ "color/focus/ring": {
91
+ "modes": {
92
+ "Light": "#169c46",
93
+ "Dark": "#1db954"
94
+ },
95
+ "defaultMode": "Light"
96
+ },
97
+ "color/bg/muted": {
98
+ "modes": {
99
+ "Light": "#ebebeb",
100
+ "Dark": "#353535"
101
+ },
102
+ "defaultMode": "Light"
103
+ }
104
+ },
105
+ "missingSurfaces": []
106
+ },
107
+ "expected": {
108
+ "structural-read-back": "pass",
109
+ "state-baseline": "pass",
110
+ "focus-indicator": "pass",
111
+ "focus-contrast": "fail"
112
+ }
113
+ }