@codenhub/styles 0.7.0 → 0.8.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 (121) hide show
  1. package/README.es.md +8 -7
  2. package/README.md +7 -6
  3. package/README.pt-BR.md +8 -7
  4. package/dist/aesthetics/chunky-tile.css +1 -1
  5. package/dist/aesthetics/cyber.css +1 -1
  6. package/dist/aesthetics/glass.css +1 -1
  7. package/dist/aesthetics/index.css +2 -2
  8. package/dist/aesthetics/neobrutalism.css +1 -1
  9. package/dist/aesthetics/sketch.css +1 -1
  10. package/dist/cli.js +189 -0
  11. package/dist/components.css +2 -2
  12. package/dist/index.css +2 -2
  13. package/dist/index.d.ts +1 -0
  14. package/dist/native.css +2 -2
  15. package/dist/palette.css +1 -1
  16. package/dist/theme.css +2 -2
  17. package/docs/accessibility.md +46 -27
  18. package/docs/changelog/0.8.0.md +70 -0
  19. package/docs/changelog/index.md +1 -0
  20. package/docs/es/accessibility.md +47 -28
  21. package/docs/es/index.md +3 -2
  22. package/docs/es/integrating/index.md +38 -10
  23. package/docs/es/integrating/tailwind.md +78 -8
  24. package/docs/es/integrating/without-a-bundler.md +128 -5
  25. package/docs/es/setup.md +42 -34
  26. package/docs/es/usage/aesthetics.md +19 -13
  27. package/docs/es/usage/buttons.md +6 -2
  28. package/docs/es/usage/composing.md +6 -2
  29. package/docs/es/usage/content-and-layout.md +8 -4
  30. package/docs/es/usage/customizing.md +19 -13
  31. package/docs/es/usage/feedback.md +5 -1
  32. package/docs/es/usage/forms.md +29 -4
  33. package/docs/es/usage/index.md +6 -2
  34. package/docs/es/usage/presets.md +92 -0
  35. package/docs/es/usage/solo.md +4 -2
  36. package/docs/es/usage/theming.md +28 -15
  37. package/docs/index.md +2 -1
  38. package/docs/integrating/index.md +38 -10
  39. package/docs/integrating/tailwind.md +77 -7
  40. package/docs/integrating/without-a-bundler.md +127 -4
  41. package/docs/pt-BR/accessibility.md +47 -28
  42. package/docs/pt-BR/index.md +3 -2
  43. package/docs/pt-BR/integrating/index.md +38 -10
  44. package/docs/pt-BR/integrating/tailwind.md +78 -8
  45. package/docs/pt-BR/integrating/without-a-bundler.md +128 -5
  46. package/docs/pt-BR/setup.md +42 -34
  47. package/docs/pt-BR/usage/aesthetics.md +19 -13
  48. package/docs/pt-BR/usage/buttons.md +6 -2
  49. package/docs/pt-BR/usage/composing.md +6 -2
  50. package/docs/pt-BR/usage/content-and-layout.md +8 -4
  51. package/docs/pt-BR/usage/customizing.md +19 -13
  52. package/docs/pt-BR/usage/feedback.md +5 -1
  53. package/docs/pt-BR/usage/forms.md +29 -4
  54. package/docs/pt-BR/usage/index.md +6 -2
  55. package/docs/pt-BR/usage/presets.md +92 -0
  56. package/docs/pt-BR/usage/solo.md +4 -2
  57. package/docs/pt-BR/usage/theming.md +21 -8
  58. package/docs/setup.md +30 -22
  59. package/docs/usage/aesthetics.md +18 -12
  60. package/docs/usage/buttons.md +5 -1
  61. package/docs/usage/composing.md +5 -1
  62. package/docs/usage/content-and-layout.md +7 -3
  63. package/docs/usage/customizing.md +18 -12
  64. package/docs/usage/feedback.md +4 -0
  65. package/docs/usage/forms.md +28 -3
  66. package/docs/usage/index.md +5 -1
  67. package/docs/usage/presets.md +91 -0
  68. package/docs/usage/solo.md +3 -1
  69. package/docs/usage/theming.md +20 -7
  70. package/llms-full.txt +592 -115
  71. package/package.json +113 -63
  72. package/{dist/tw → tw}/aesthetics/chunky-tile.css +39 -19
  73. package/{dist/tw → tw}/aesthetics/cyber.css +15 -24
  74. package/{dist/tw → tw}/aesthetics/glass.css +105 -36
  75. package/{dist/tw → tw}/aesthetics/neobrutalism.css +37 -20
  76. package/{dist/tw → tw}/aesthetics/sketch.css +152 -133
  77. package/{dist/tw → tw}/box.css +89 -12
  78. package/tw/components/button.css +11 -0
  79. package/tw/components/button.rules.css +187 -0
  80. package/tw/components/feedback.css +11 -0
  81. package/{dist/tw/components/feedback.css → tw/components/feedback.rules.css} +134 -30
  82. package/tw/components/form.css +11 -0
  83. package/{dist/tw/components/form.css → tw/components/form.rules.css} +524 -111
  84. package/tw/components/index.css +16 -0
  85. package/tw/components/rules.css +41 -0
  86. package/tw/components/surface.css +11 -0
  87. package/tw/components/surface.rules.css +222 -0
  88. package/tw/components/tooltip.css +11 -0
  89. package/{dist/tw/components/tooltip.css → tw/components/tooltip.rules.css} +43 -27
  90. package/{dist/tw → tw}/corner.css +18 -12
  91. package/{dist/tw → tw}/elevation.css +23 -17
  92. package/{dist/tw → tw}/index.css +11 -9
  93. package/tw/index.d.ts +1 -0
  94. package/tw/intent.css +312 -0
  95. package/tw/modifiers.css +127 -0
  96. package/tw/native.css +320 -0
  97. package/tw/presentation.css +139 -0
  98. package/tw/reset.css +10 -0
  99. package/{dist/tw/reset.css → tw/reset.rules.css} +7 -8
  100. package/tw/size.css +34 -0
  101. package/tw/surface.css +9 -0
  102. package/tw/surface.rules.css +212 -0
  103. package/{dist/tw → tw}/theme.css +92 -28
  104. package/tw/typography.css +8 -0
  105. package/{dist/tw/typography.css → tw/typography.rules.css} +0 -3
  106. package/{dist/tw → tw}/utilities/content.css +183 -63
  107. package/tw/utilities/index.css +11 -0
  108. package/tw/utilities/layout.css +208 -0
  109. package/tw/utilities/rules.css +8 -0
  110. package/dist/tw/components/button.css +0 -139
  111. package/dist/tw/components/index.css +0 -35
  112. package/dist/tw/components/surface.css +0 -184
  113. package/dist/tw/intent.css +0 -229
  114. package/dist/tw/native.css +0 -203
  115. package/dist/tw/palette.css +0 -460
  116. package/dist/tw/presentation.css +0 -68
  117. package/dist/tw/surface.css +0 -61
  118. package/dist/tw/utilities/index.css +0 -6
  119. package/dist/tw/utilities/layout.css +0 -144
  120. /package/{dist/tw → tw}/aesthetics/index.css +0 -0
  121. /package/{dist/tw → tw}/aesthetics/pixel.css +0 -0
@@ -73,12 +73,6 @@
73
73
  font-family: var(--font-sketch, cursive);
74
74
  }
75
75
 
76
- @media (prefers-reduced-motion: reduce) {
77
- .sketch {
78
- --ui-active-transform: none;
79
- }
80
- }
81
-
82
76
  /* Rounded variant: bounded elliptical corners, so the top and bottom edges of
83
77
  a wide element stay straight instead of bulging into an egg. On the region
84
78
  with `.sketch`, or on one component inside it. Knobs follow R8.
@@ -97,188 +91,213 @@
97
91
 
98
92
  /* One region token gives every element the same outline, so the rotation and
99
93
  the dashed accents are written on components, which the registry records.
100
- The root is a component carrying either class, or one inside either region
101
- and not inside another aesthetic nested there, which keeps its own
102
- material. The list below is the one place other aesthetics are named, and
103
- `registry.test.ts` fails when one is missing from it.
94
+
95
+ The nearest region decides. A component in another aesthetic nested inside
96
+ a sketch region keeps that aesthetic's material, and one in a sketch region
97
+ nested again inside that rotates. A `:not(.sketch :is(...) *)` exclusion
98
+ cannot tell those two apart, since the re-entered component also sits below
99
+ the other aesthetic, so each region writes private flags instead and
100
+ inheritance hands a component the nearest one's -- the way neobrutalism
101
+ rests its alert:
102
+
103
+ - `--_sketch-on`, `--_sketch-pointed`, `--_sketch-rounded` are space
104
+ toggles: empty is on, and `initial` makes a value reading one invalid at
105
+ computed-value time, which is off. `.sketch` turns on the pointed
106
+ outlines and `.sketch-rounded` the rounded ones; rounded wins where both
107
+ are on, as the modifier does. Another aesthetic turns all three off.
108
+ - `--_sketch-pass-*` is what that other aesthetic declared for each token
109
+ the rotation writes, so a component under it takes the region's value
110
+ back rather than a rotation's -- cyber's whole surface shape included.
111
+ Off, a value is the pass, then the rounded one, then the pointed one; the
112
+ first that is valid wins, and with none the token is unset, as every
113
+ other aesthetic declares it.
114
+
115
+ The other aesthetics are named below and in the flags, and
116
+ `registry.test.ts` fails when one is missing. A region's own element is
117
+ not rotated: it declares the pass from its own tokens, which a rotation
118
+ would then declare from the pass.
104
119
 
105
120
  Rotation is by sibling position, and a field's control takes its field's
106
121
  position instead of its own, so stacked rows alternate. It is stable for a
107
122
  given DOM order. A knob, when set, is one outline for every position. */
108
- :is(
109
- .sketch,
110
- .sketch-rounded:not(.sketch-solo),
111
- :is(.sketch, .sketch-rounded:not(.sketch-solo))
112
- :not(
113
- :is(.sketch, .sketch-rounded:not(.sketch-solo)) :is(.neobrutalism, .glass, .pixel, .chunky-tile, .cyber),
114
- :is(.sketch, .sketch-rounded:not(.sketch-solo)) :is(.neobrutalism, .glass, .pixel, .chunky-tile, .cyber) *
115
- )
116
- ) {
117
- /* The pointed outlines: controls, fields, surfaces, and chips. */
118
- &:is(.sketch, .sketch *):not(.sketch-rounded:not(.sketch-solo), .sketch-rounded:not(.sketch-solo) *) {
119
- &:is(.btn, .ipt, .textarea, .select, .input-group, .pre, .tooltip-bubble) {
120
- &:nth-child(4n + 2) {
121
- --ui-radius: var(--sketch-radius, 18px 240px 15px 255px / 240px 15px 255px 18px);
122
- }
123
-
124
- &:nth-child(4n + 3) {
125
- --ui-radius: var(--sketch-radius, 245px 220px 15px 18px / 18px 15px 245px 235px);
126
- }
127
-
128
- &:nth-child(4n) {
129
- --ui-radius: var(--sketch-radius, 18px 250px 225px 15px / 245px 15px 18px 235px);
130
- }
131
- }
123
+ .sketch,
124
+ .sketch-rounded:not(.sketch-solo) {
125
+ --_sketch-on: ;
126
+ --_sketch-pass-radius: initial;
127
+ --_sketch-pass-radius-surface: initial;
128
+ --_sketch-pass-radius-tight: initial;
129
+ --_sketch-pass-radius-pill: initial;
130
+ --_sketch-pass-line-style: initial;
131
+ --_sketch-pass-rule-style: initial;
132
+ }
132
133
 
133
- &:is(.ipt, .textarea, .select, .input-group) {
134
- .field:nth-child(4n + 1) & {
135
- --ui-radius: var(--sketch-radius, 255px 15px 225px 15px / 15px 225px 15px 255px);
136
- }
134
+ .sketch {
135
+ --_sketch-pointed: ;
136
+ }
137
137
 
138
- .field:nth-child(4n + 2) & {
139
- --ui-radius: var(--sketch-radius, 18px 240px 15px 255px / 240px 15px 255px 18px);
140
- }
138
+ .sketch-rounded:not(.sketch-solo) {
139
+ --_sketch-rounded: ;
140
+ }
141
141
 
142
- .field:nth-child(4n + 3) & {
143
- --ui-radius: var(--sketch-radius, 245px 220px 15px 18px / 18px 15px 245px 235px);
144
- }
142
+ :is(.neobrutalism, .glass, .pixel, .chunky-tile, .cyber) {
143
+ --_sketch-on: initial;
144
+ --_sketch-pointed: initial;
145
+ --_sketch-rounded: initial;
146
+ --_sketch-pass-radius: var(--ui-radius);
147
+ --_sketch-pass-radius-surface: var(--ui-radius-surface);
148
+ --_sketch-pass-radius-tight: var(--ui-radius-tight);
149
+ --_sketch-pass-radius-pill: var(--ui-radius-pill);
150
+ --_sketch-pass-line-style: var(--ui-line-style);
151
+ --_sketch-pass-rule-style: var(--ui-rule-style);
152
+ }
145
153
 
146
- .field:nth-child(4n) & {
147
- --ui-radius: var(--sketch-radius, 18px 250px 225px 15px / 245px 15px 18px 235px);
148
- }
154
+ :is(.sketch, .sketch-rounded:not(.sketch-solo), :is(.sketch, .sketch-rounded:not(.sketch-solo)) *):not(
155
+ :is(.neobrutalism, .glass, .pixel, .chunky-tile, .cyber)
156
+ ) {
157
+ /* Controls, fields, surfaces, and chips. Each position names its pointed
158
+ outline in `--_sketch-p` and its rounded one in `--_sketch-r`, declared
159
+ with the token, so a position never reads a value inherited from an
160
+ ancestor's. */
161
+ &:is(.btn, .ipt, .textarea, .select, .input-group, .pre, .tooltip-bubble) {
162
+ &:nth-child(4n + 2) {
163
+ --_sketch-p: var(--_sketch-pointed) var(--sketch-radius, 18px 240px 15px 255px / 240px 15px 255px 18px);
164
+ --_sketch-r: var(--_sketch-rounded) var(--sketch-radius-rounded, 11px 25px 12px 24px / 23px 11px 22px 12px);
165
+ --ui-radius: var(--_sketch-pass-radius, var(--_sketch-r, var(--_sketch-p)));
149
166
  }
150
167
 
151
- &:is(.card, .panel, .alert, .data-table) {
152
- &:nth-child(4n + 2) {
153
- --ui-radius-surface: var(--sketch-radius-surface, 4px 75px 5px 80px / 75px 3px 80px 4px);
154
- }
155
-
156
- &:nth-child(4n + 3) {
157
- --ui-radius-surface: var(--sketch-radius-surface, 75px 70px 4px 5px / 4px 3px 75px 70px);
158
- }
159
-
160
- &:nth-child(4n) {
161
- --ui-radius-surface: var(--sketch-radius-surface, 5px 80px 75px 4px / 75px 4px 5px 70px);
162
- }
168
+ &:nth-child(4n + 3) {
169
+ --_sketch-p: var(--_sketch-pointed) var(--sketch-radius, 245px 220px 15px 18px / 18px 15px 245px 235px);
170
+ --_sketch-r: var(--_sketch-rounded) var(--sketch-radius-rounded, 24px 12px 26px 10px / 11px 23px 12px 22px);
171
+ --ui-radius: var(--_sketch-pass-radius, var(--_sketch-r, var(--_sketch-p)));
163
172
  }
164
173
 
165
- &:is(.badge, .kbd, .code, .checkbox, .switch, .progress) {
166
- &:nth-child(4n + 2) {
167
- --ui-radius-tight: 2px 8px 1px 10px / 8px 2px 10px 1px;
168
- }
169
-
170
- &:nth-child(4n + 3) {
171
- --ui-radius-tight: 8px 2px 10px 1px / 1px 9px 2px 8px;
172
- }
173
-
174
- &:nth-child(4n) {
175
- --ui-radius-tight: 1px 10px 2px 7px / 9px 1px 8px 2px;
176
- }
174
+ &:nth-child(4n) {
175
+ --_sketch-p: var(--_sketch-pointed) var(--sketch-radius, 18px 250px 225px 15px / 245px 15px 18px 235px);
176
+ --_sketch-r: var(--_sketch-rounded) var(--sketch-radius-rounded, 12px 24px 10px 25px / 22px 12px 23px 11px);
177
+ --ui-radius: var(--_sketch-pass-radius, var(--_sketch-r, var(--_sketch-p)));
177
178
  }
178
179
  }
179
180
 
180
- /* The rounded outlines, in the same four places. */
181
- &:is(.sketch-rounded:not(.sketch-solo), .sketch-rounded:not(.sketch-solo) *) {
182
- &:is(.btn, .ipt, .textarea, .select, .input-group, .pre, .tooltip-bubble) {
183
- &:nth-child(4n + 2) {
184
- --ui-radius: var(--sketch-radius-rounded, 11px 25px 12px 24px / 23px 11px 22px 12px);
185
- }
186
-
187
- &:nth-child(4n + 3) {
188
- --ui-radius: var(--sketch-radius-rounded, 24px 12px 26px 10px / 11px 23px 12px 22px);
189
- }
190
-
191
- &:nth-child(4n) {
192
- --ui-radius: var(--sketch-radius-rounded, 12px 24px 10px 25px / 22px 12px 23px 11px);
193
- }
181
+ &:is(.ipt, .textarea, .select, .input-group) {
182
+ .field:nth-child(4n + 1) & {
183
+ --_sketch-p: var(--_sketch-pointed) var(--sketch-radius, 255px 15px 225px 15px / 15px 225px 15px 255px);
184
+ --_sketch-r: var(--_sketch-rounded) var(--sketch-radius-rounded, 26px 10px 24px 11px / 12px 23px 11px 20px);
185
+ --ui-radius: var(--_sketch-pass-radius, var(--_sketch-r, var(--_sketch-p)));
194
186
  }
195
187
 
196
- &:is(.ipt, .textarea, .select, .input-group) {
197
- .field:nth-child(4n + 1) & {
198
- --ui-radius: var(--sketch-radius-rounded, 26px 10px 24px 11px / 12px 23px 11px 20px);
199
- }
200
-
201
- .field:nth-child(4n + 2) & {
202
- --ui-radius: var(--sketch-radius-rounded, 11px 25px 12px 24px / 23px 11px 22px 12px);
203
- }
188
+ .field:nth-child(4n + 2) & {
189
+ --_sketch-p: var(--_sketch-pointed) var(--sketch-radius, 18px 240px 15px 255px / 240px 15px 255px 18px);
190
+ --_sketch-r: var(--_sketch-rounded) var(--sketch-radius-rounded, 11px 25px 12px 24px / 23px 11px 22px 12px);
191
+ --ui-radius: var(--_sketch-pass-radius, var(--_sketch-r, var(--_sketch-p)));
192
+ }
204
193
 
205
- .field:nth-child(4n + 3) & {
206
- --ui-radius: var(--sketch-radius-rounded, 24px 12px 26px 10px / 11px 23px 12px 22px);
207
- }
194
+ .field:nth-child(4n + 3) & {
195
+ --_sketch-p: var(--_sketch-pointed) var(--sketch-radius, 245px 220px 15px 18px / 18px 15px 245px 235px);
196
+ --_sketch-r: var(--_sketch-rounded) var(--sketch-radius-rounded, 24px 12px 26px 10px / 11px 23px 12px 22px);
197
+ --ui-radius: var(--_sketch-pass-radius, var(--_sketch-r, var(--_sketch-p)));
198
+ }
208
199
 
209
- .field:nth-child(4n) & {
210
- --ui-radius: var(--sketch-radius-rounded, 12px 24px 10px 25px / 22px 12px 23px 11px);
211
- }
200
+ .field:nth-child(4n) & {
201
+ --_sketch-p: var(--_sketch-pointed) var(--sketch-radius, 18px 250px 225px 15px / 245px 15px 18px 235px);
202
+ --_sketch-r: var(--_sketch-rounded) var(--sketch-radius-rounded, 12px 24px 10px 25px / 22px 12px 23px 11px);
203
+ --ui-radius: var(--_sketch-pass-radius, var(--_sketch-r, var(--_sketch-p)));
212
204
  }
205
+ }
213
206
 
214
- &:is(.card, .panel, .alert, .data-table) {
215
- &:nth-child(4n + 2) {
216
- --ui-radius-surface: var(--sketch-radius-surface-rounded, 17px 36px 18px 34px / 33px 16px 32px 17px);
217
- }
207
+ &:is(.card, .panel, .alert, .data-table) {
208
+ &:nth-child(4n + 2) {
209
+ --_sketch-p: var(--_sketch-pointed) var(--sketch-radius-surface, 4px 75px 5px 80px / 75px 3px 80px 4px);
210
+ --_sketch-r: var(--_sketch-rounded)
211
+ var(--sketch-radius-surface-rounded, 17px 36px 18px 34px / 33px 16px 32px 17px);
212
+ --ui-radius-surface: var(--_sketch-pass-radius-surface, var(--_sketch-r, var(--_sketch-p)));
213
+ }
218
214
 
219
- &:nth-child(4n + 3) {
220
- --ui-radius-surface: var(--sketch-radius-surface-rounded, 35px 18px 38px 15px / 17px 32px 16px 34px);
221
- }
215
+ &:nth-child(4n + 3) {
216
+ --_sketch-p: var(--_sketch-pointed) var(--sketch-radius-surface, 75px 70px 4px 5px / 4px 3px 75px 70px);
217
+ --_sketch-r: var(--_sketch-rounded)
218
+ var(--sketch-radius-surface-rounded, 35px 18px 38px 15px / 17px 32px 16px 34px);
219
+ --ui-radius-surface: var(--_sketch-pass-radius-surface, var(--_sketch-r, var(--_sketch-p)));
220
+ }
222
221
 
223
- &:nth-child(4n) {
224
- --ui-radius-surface: var(--sketch-radius-surface-rounded, 18px 35px 16px 37px / 31px 17px 34px 16px);
225
- }
222
+ &:nth-child(4n) {
223
+ --_sketch-p: var(--_sketch-pointed) var(--sketch-radius-surface, 5px 80px 75px 4px / 75px 4px 5px 70px);
224
+ --_sketch-r: var(--_sketch-rounded)
225
+ var(--sketch-radius-surface-rounded, 18px 35px 16px 37px / 31px 17px 34px 16px);
226
+ --ui-radius-surface: var(--_sketch-pass-radius-surface, var(--_sketch-r, var(--_sketch-p)));
226
227
  }
228
+ }
227
229
 
228
- &:is(.badge, .kbd, .code, .checkbox, .switch, .progress) {
229
- &:nth-child(4n + 2) {
230
- --ui-radius-tight: 4px 8px 3px 9px / 8px 3px 8px 4px;
231
- }
230
+ &:is(.badge, .kbd, .code, .checkbox, .switch, .progress) {
231
+ &:nth-child(4n + 2) {
232
+ --_sketch-p: var(--_sketch-pointed) 2px 8px 1px 10px / 8px 2px 10px 1px;
233
+ --_sketch-r: var(--_sketch-rounded) 4px 8px 3px 9px / 8px 3px 8px 4px;
234
+ --ui-radius-tight: var(--_sketch-pass-radius-tight, var(--_sketch-r, var(--_sketch-p)));
235
+ }
232
236
 
233
- &:nth-child(4n + 3) {
234
- --ui-radius-tight: 8px 4px 9px 3px / 3px 9px 4px 8px;
235
- }
237
+ &:nth-child(4n + 3) {
238
+ --_sketch-p: var(--_sketch-pointed) 8px 2px 10px 1px / 1px 9px 2px 8px;
239
+ --_sketch-r: var(--_sketch-rounded) 8px 4px 9px 3px / 3px 9px 4px 8px;
240
+ --ui-radius-tight: var(--_sketch-pass-radius-tight, var(--_sketch-r, var(--_sketch-p)));
241
+ }
236
242
 
237
- &:nth-child(4n) {
238
- --ui-radius-tight: 3px 9px 4px 8px / 9px 4px 8px 3px;
239
- }
243
+ &:nth-child(4n) {
244
+ --_sketch-p: var(--_sketch-pointed) 1px 10px 2px 7px / 9px 1px 8px 2px;
245
+ --_sketch-r: var(--_sketch-rounded) 3px 9px 4px 8px / 9px 4px 8px 3px;
246
+ --ui-radius-tight: var(--_sketch-pass-radius-tight, var(--_sketch-r, var(--_sketch-p)));
240
247
  }
241
248
  }
242
249
 
243
250
  /* A pill button keeps a rounded pill in either variant, bounded to the
244
251
  button's half-height so a wide one keeps flat top and bottom edges. */
245
252
  &.btn.pill {
246
- --ui-radius-pill: var(--sketch-radius-pill, 24px 16px 23px 17px / 17px 21px 16px 20px);
253
+ --ui-radius-pill: var(
254
+ --_sketch-pass-radius-pill,
255
+ var(--_sketch-on) var(--sketch-radius-pill, 24px 16px 23px 17px / 17px 21px 16px 20px)
256
+ );
247
257
 
248
258
  &:nth-child(4n + 2) {
249
- --ui-radius-pill: var(--sketch-radius-pill, 17px 23px 16px 24px / 21px 16px 20px 17px);
259
+ --ui-radius-pill: var(
260
+ --_sketch-pass-radius-pill,
261
+ var(--_sketch-on) var(--sketch-radius-pill, 17px 23px 16px 24px / 21px 16px 20px 17px)
262
+ );
250
263
  }
251
264
 
252
265
  &:nth-child(4n + 3) {
253
- --ui-radius-pill: var(--sketch-radius-pill, 23px 17px 24px 16px / 16px 20px 17px 21px);
266
+ --ui-radius-pill: var(
267
+ --_sketch-pass-radius-pill,
268
+ var(--_sketch-on) var(--sketch-radius-pill, 23px 17px 24px 16px / 16px 20px 17px 21px)
269
+ );
254
270
  }
255
271
 
256
272
  &:nth-child(4n) {
257
- --ui-radius-pill: var(--sketch-radius-pill, 16px 24px 17px 23px / 20px 17px 21px 16px);
273
+ --ui-radius-pill: var(
274
+ --_sketch-pass-radius-pill,
275
+ var(--_sketch-on) var(--sketch-radius-pill, 16px 24px 17px 23px / 20px 17px 21px 16px)
276
+ );
258
277
  }
259
278
  }
260
279
 
261
280
  /* Badges, progress bars, and switches take their chip outline where they
262
281
  would be fully round. */
263
282
  &:is(.badge, .progress, .switch) {
264
- --ui-radius-pill: var(--ui-radius-tight);
283
+ --ui-radius-pill: var(--_sketch-pass-radius-pill, var(--_sketch-on) var(--ui-radius-tight));
265
284
  }
266
285
 
267
286
  /* Radios and the tooltip trigger stay circles, slightly uneven, so a radio
268
287
  is never mistaken for a checkbox. */
269
288
  &:is(.radio, .tooltip-icon) {
270
- --ui-radius-pill: 48% 52% 46% 54% / 53% 46% 54% 47%;
289
+ --ui-radius-pill: var(--_sketch-pass-radius-pill, var(--_sketch-on) 48% 52% 46% 54% / 53% 46% 54% 47%);
271
290
  }
272
291
 
273
- /* The dashed accents; every other line stays solid. */
274
- &:is(.sketch, .sketch *) {
275
- &.checkbox {
276
- --ui-line-style: dashed;
277
- }
292
+ /* The dashed accents, under `.sketch`; every other line stays solid. The
293
+ bare elements `/native` styles as these components are named beside
294
+ them, in `:where()` so the selector's weight stays the class's. */
295
+ &:is(.checkbox, :where(input[type="checkbox"]:not(.switch, .radio))) {
296
+ --ui-line-style: var(--_sketch-pass-line-style, var(--_sketch-pointed) dashed);
297
+ }
278
298
 
279
- &:is(.divider, .data-table) {
280
- --ui-rule-style: dashed;
281
- }
299
+ &:is(.divider, .data-table, :where(hr, table)) {
300
+ --ui-rule-style: var(--_sketch-pass-rule-style, var(--_sketch-pointed) dashed);
282
301
  }
283
302
  }
284
303
  }
@@ -34,6 +34,23 @@
34
34
  specificity, so restating it here is what keeps a nested box reading its
35
35
  own presentation instead of the container's reinterpretation of one. */
36
36
  --_fill-cap: 100%;
37
+ /* What a box rests as when nothing above `@apply box` says otherwise: no
38
+ fill, no line, the ordinary depth. Stated on the element, not left to
39
+ the `var()` fallbacks: `--_d-*` inherit like any custom property, so a
40
+ bare `box` inside a `.btn` rested as the button does -- a full fill and
41
+ the button's line. A component writes its own after `@apply box`, where
42
+ the later declaration wins. See docs/internal/model.md#resting-defaults. */
43
+ --_d-fill: 0%;
44
+ --_d-fg-on-fill: 0%;
45
+ --_d-border: 0%;
46
+ --_d-elevation: 1;
47
+ --_d-holds-ink: none;
48
+
49
+ /* Printed as drawn. A browser leaves backgrounds off paper by default, and
50
+ a filled box prints its label in the contrast colour: white on nothing.
51
+ Inherited, so everything inside keeps its paint too. */
52
+ print-color-adjust: exact;
53
+
37
54
  --_capped: min(var(--ui-fill, var(--_d-fill)), var(--_fill-cap, 100%), var(--intent-fill-max, 100%));
38
55
  /* Whether the intent's cap stopped the fill short, as 0% or 100%. A capped
39
56
  fill is a plate the presentation asked to be full, so it rests on the page
@@ -85,7 +102,26 @@
85
102
  `--intent-contrast` keeps its own meaning -- `--_on-fill` reconciles it with
86
103
  a capped intent -- rather than being bent so neutral's contrast is the ink,
87
104
  which renders a checked neutral checkbox black-on-black. */
88
- --_fg: color-mix(in oklab, var(--intent-contrast) var(--_on-fill), var(--intent-strong));
105
+ --_fg-own: color-mix(in oklab, var(--intent-contrast) var(--_on-fill), var(--intent-strong));
106
+ /* The ink of the plate beneath. Intent does not cascade, so a component with
107
+ none prints the page's ink, and on a filled parent that ink sat on the
108
+ parent's fill: a badge in a primary button read at 1.11:1. A box whose
109
+ fill is a plate hands its own ink down; one with no plate declares these
110
+ invalid, which for a registered property means it inherits them, so the
111
+ ink passes through an input group to the field inside it. `--_through`
112
+ is 100% for a neutral box (its cap is below 100%) that was handed an ink
113
+ and holds none: an intent keeps its own ink, as it keeps its own colour.
114
+ A component that rests on a ground of its own restates all three after
115
+ `@apply box`. See docs/internal/model.md#the-ink-of-the-plate-beneath. */
116
+ --_held-ink: var(--_holds-ink, var(--_d-holds-ink)) var(--_fg-own);
117
+ --_held-on: var(--_holds-ink, var(--_d-holds-ink)) 100%;
118
+ --_own-hold: var(--_holds-ink, var(--_d-holds-ink)) 100%;
119
+ --_through: min(
120
+ var(--_held-on),
121
+ calc(100% - var(--_own-hold)),
122
+ clamp(0%, calc((100% - var(--intent-fill-max, 100%)) * 1000), 100%)
123
+ );
124
+ --_fg: color-mix(in oklab, var(--_held-ink) var(--_through), var(--_fg-own));
89
125
  /* P3: the line fades out as the fill fills in, so a filled box has a seamless
90
126
  edge. It fades toward `transparent`, not toward the plate: the plate
91
127
  already runs under the border (nothing clips the background to the padding
@@ -98,7 +134,29 @@
98
134
  `.edgeless` on the fill colour, which the border box paints as a second
99
135
  coat -- a ring around an element that asked for no edge. See
100
136
  docs/internal/model.md#presentation. */
101
- --_line: color-mix(in oklab, transparent var(--ui-fill, var(--_d-fill)), var(--intent-border));
137
+ /* The neutral line of a box with no fill, where an aesthetic's line cannot
138
+ be seen without one: glass's hairline is a highlight on a plate, and on a
139
+ `.ghost.edged` button there is no plate (1.01:1 on a light page). A
140
+ component that wants the swap names the ink after `@apply box`; cleared
141
+ here so a box nested in one does not inherit it. `--_bare` is 100% for a
142
+ neutral intent (its cap is below 100%) resolving to no fill, stepped from
143
+ the resolved values as `surface`'s `--_quiet` is, so a container's
144
+ `.ghost` counts and an intent's own line is never swapped. */
145
+ --_bare-ink: initial;
146
+ --_bare: min(
147
+ clamp(0%, calc((100% - var(--intent-fill-max, 100%)) * 1000), 100%),
148
+ clamp(0%, calc(100% - var(--ui-fill, var(--_d-fill)) * 1000), 100%)
149
+ );
150
+ --_line-ink: color-mix(
151
+ in oklab,
152
+ var(--_held-ink) var(--_through),
153
+ color-mix(
154
+ in oklab,
155
+ var(--_bare-ink, var(--intent-border, var(--ui-ink, var(--color-border)))) var(--_bare),
156
+ var(--intent-border, var(--ui-ink, var(--color-border)))
157
+ )
158
+ );
159
+ --_line: color-mix(in oklab, transparent var(--ui-fill, var(--_d-fill)), var(--_line-ink));
102
160
  /* How much line there is, as an input rather than a result. A component that
103
161
  must keep its line whatever the edge class says raises `--_edge-floor`
104
162
  instead of rewriting `--_edge`, and the composition above still runs.
@@ -134,10 +192,6 @@
134
192
  public override, undeclared by the package. See docs/internal/model.md#material-tokens. */
135
193
  --_scale-size: initial;
136
194
  --_scale-pad: initial;
137
- /* The padding the same modifiers set on a `.card` or `.panel`, restated for
138
- the same reason: a `.card.p-xs` or `.flush` would otherwise pad every
139
- surface nested inside it to its own value. */
140
- --surface-padding: initial;
141
195
  --_scale: var(--ui-scale, min(var(--_scale-size, var(--_scale-pad, 1)), var(--_scale-pad, var(--_scale-size, 1))));
142
196
  /* Depth follows the step down and not up: a 4px slab under a 20px button
143
197
  swallows it, while a press that travels the aesthetic's whole depth has to
@@ -161,7 +215,11 @@
161
215
  mixes where the intent lives). An intent-coloured shadow at full opacity is
162
216
  a smear of the component's hue, not depth; neobrutalism's slab, which *is*
163
217
  ink, asks for it by name. */
164
- --_depth-color: color-mix(in oklab, var(--intent-border) var(--ui-shadow-ink, 0%), var(--elevation-color));
218
+ --_depth-color: color-mix(
219
+ in oklab,
220
+ var(--intent-border, var(--ui-ink, var(--color-border))) var(--ui-shadow-ink, 0%),
221
+ var(--elevation-color)
222
+ );
165
223
  /* Or the shadow *is* the edge. An aesthetic that draws its line as an inset
166
224
  ring (`.pixel`) puts the border where `clip-path` cannot cut it, so that
167
225
  ring must answer the edge axis like a real border -- `--_edge` already does,
@@ -187,7 +245,7 @@
187
245
  --_halo-layer:
188
246
  ,
189
247
  0 0 var(--ui-halo-blur, 0px) var(--ui-halo-spread, 0px)
190
- color-mix(in oklab, var(--intent-border) var(--ui-halo-ink), transparent);
248
+ color-mix(in oklab, var(--intent-border, var(--ui-ink, var(--color-border))) var(--ui-halo-ink), transparent);
191
249
  /* Indirection so a component can substitute a complete value of its own
192
250
  without restating the parts -- `surface` does, for the multi-layer case.
193
251
  There is deliberately no `--ui-shadow` wrapper: a complete value has nothing
@@ -202,8 +260,21 @@
202
260
  differs from the fill, whatever the fill is. Shadows paint first-on-top,
203
261
  so the line is listed last and is the two pixels the ring leaves showing. */
204
262
  --_focus-stack:
205
- var(--_shadow), inset 0 0 0 var(--ui-focus-inset) var(--focus-ring),
263
+ var(--_shadow),
264
+ inset 0 0 0 var(--ui-focus-inset) var(--focus-ring, color-mix(in srgb, var(--color-primary) 64%, transparent)),
206
265
  inset 0 0 0 calc(var(--ui-focus-inset) + 2px) var(--color-background);
266
+ /* The same line of the page colour under the outline `reset.css` draws,
267
+ for the same reason: the outline sits over the box's own edge, and on a
268
+ box filled with the ring's colour that part of it was invisible. Under a
269
+ two-pixel line that left one pixel of ring, which neobrutalism's slab
270
+ covered on two sides. Stepped from the capped fill, so only a box filled
271
+ past half takes it: on an unfilled one the ring already reads against the
272
+ page, and a line of the page colour inside a soft field is a stray mark. */
273
+ --_focus-gap: color-mix(
274
+ in oklab,
275
+ var(--color-background) clamp(0%, calc((var(--_capped) - 50%) * 1000), 100%),
276
+ transparent
277
+ );
207
278
 
208
279
  /* Every box sizes itself as `min-height`/`min-width: var(--control-height)`
209
280
  plus its own padding and the border shorthand above, so its geometry is
@@ -274,7 +345,7 @@
274
345
  non-inherited property is `initial`, that is `none`. Every focused box would
275
346
  lose its shadow rather than keep it. */
276
347
  &:focus-visible {
277
- box-shadow: var(--_focus-stack, var(--_shadow));
348
+ box-shadow: var(--_focus-stack, var(--_shadow), inset 0 0 0 2px var(--_focus-gap));
278
349
  }
279
350
 
280
351
  &:disabled,
@@ -314,7 +385,9 @@
314
385
  component opts in. `btn` and `.card.interactive` both do. The gesture is the
315
386
  aesthetic's -- neobrutalism travels into its offset shadow, chunky-tile drops
316
387
  onto its bar -- and with no aesthetic it is the base `scale(0.97)` from
317
- `theme.css`, dropped under reduced motion. The `--ui-active-shadow-*` slots
388
+ `theme.css`. Reduced motion keeps every press and drops its motion, in
389
+ `box`, since a press is the feedback that a click landed. The
390
+ `--ui-active-shadow-*` slots
318
391
  stay no-ops until an aesthetic sets them.
319
392
 
320
393
  A press that travels into the element's own depth is a translation, given as
@@ -331,7 +404,11 @@
331
404
  @utility box-active {
332
405
  &:active:not(:disabled, .disabled, [aria-disabled="true"], [data-disabled]) {
333
406
  --_sx: calc(var(--ui-active-shadow-x, var(--ui-shadow-x, var(--_d-shadow-x, 0px))) * var(--_depth));
334
- --_sy: calc(var(--ui-active-shadow-y, var(--ui-shadow-y, var(--_d-shadow-y, 0px))) * var(--_depth));
407
+ /* The same three slots as the resting offset, `.raised`'s plain step last,
408
+ so with no aesthetic a pressed button keeps the depth it rests on. */
409
+ --_sy: calc(
410
+ var(--ui-active-shadow-y, var(--ui-shadow-y, var(--_d-shadow-y, var(--elevation-y, 0px)))) * var(--_depth)
411
+ );
335
412
 
336
413
  --_press: calc(var(--ui-active-translate-x, 0px) * var(--_depth))
337
414
  calc(var(--ui-active-translate-y, 0px) * var(--_depth));
@@ -0,0 +1,11 @@
1
+ @reference "tailwindcss";
2
+ @import "../theme.css";
3
+ @reference "../box.css";
4
+
5
+ /* The focused entry: what the rules in `button.rules.css` need to compile on their
6
+ own, then the rules. An aggregate entry imports the rules file directly and
7
+ supplies those needs once -- Tailwind stacks a `@utility` each time a file
8
+ that defines it is imported or referenced, so a second route to `box.css`
9
+ doubles every `@apply box`. See docs/internal/model.md (One route to each
10
+ utility). */
11
+ @import "./button.rules.css";