@codenhub/styles 0.6.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 (151) hide show
  1. package/NOTICE +18 -16
  2. package/README.es.md +62 -0
  3. package/README.md +28 -22
  4. package/README.pt-BR.md +62 -0
  5. package/dist/aesthetics/chunky-tile.css +1 -1
  6. package/dist/aesthetics/cyber.css +1 -1
  7. package/dist/aesthetics/glass.css +1 -1
  8. package/dist/aesthetics/index.css +2 -2
  9. package/dist/aesthetics/neobrutalism.css +1 -1
  10. package/dist/aesthetics/pixel.css +1 -1
  11. package/dist/aesthetics/sketch.css +1 -1
  12. package/dist/cli.js +189 -0
  13. package/dist/components.css +2 -2
  14. package/dist/index.css +2 -2
  15. package/dist/index.d.ts +1 -0
  16. package/dist/native.css +2 -2
  17. package/dist/palette.css +1 -1
  18. package/dist/theme.css +2 -2
  19. package/docs/accessibility.md +108 -60
  20. package/docs/changelog/0.1.1.md +1 -0
  21. package/docs/changelog/0.2.0.md +1 -0
  22. package/docs/changelog/0.3.0.md +1 -0
  23. package/docs/changelog/0.4.0.md +1 -0
  24. package/docs/changelog/0.5.0.md +8 -3
  25. package/docs/changelog/0.6.0.md +2 -1
  26. package/docs/changelog/0.7.0.md +50 -0
  27. package/docs/changelog/0.8.0.md +70 -0
  28. package/docs/changelog/index.md +2 -0
  29. package/docs/concepts.md +188 -46
  30. package/docs/es/accessibility.md +169 -0
  31. package/docs/es/concepts.md +212 -0
  32. package/docs/es/index.md +105 -0
  33. package/docs/es/integrating/astro.md +35 -0
  34. package/docs/es/integrating/index.md +75 -0
  35. package/docs/es/integrating/nextjs.md +67 -0
  36. package/docs/es/integrating/svelte.md +45 -0
  37. package/docs/es/integrating/tailwind.md +148 -0
  38. package/docs/es/integrating/vue.md +31 -0
  39. package/docs/es/integrating/without-a-bundler.md +238 -0
  40. package/docs/es/setup.md +188 -0
  41. package/docs/es/usage/aesthetics.md +282 -0
  42. package/docs/es/usage/buttons.md +135 -0
  43. package/docs/es/usage/composing.md +168 -0
  44. package/docs/es/usage/content-and-layout.md +219 -0
  45. package/docs/es/usage/customizing.md +304 -0
  46. package/docs/es/usage/feedback.md +157 -0
  47. package/docs/es/usage/forms.md +256 -0
  48. package/docs/es/usage/index.md +33 -0
  49. package/docs/es/usage/presets.md +92 -0
  50. package/docs/es/usage/solo.md +86 -0
  51. package/docs/es/usage/theming.md +309 -0
  52. package/docs/es/usage/tooltips.md +127 -0
  53. package/docs/index.md +86 -26
  54. package/docs/integrating/astro.md +3 -4
  55. package/docs/integrating/index.md +46 -13
  56. package/docs/integrating/nextjs.md +3 -4
  57. package/docs/integrating/svelte.md +5 -4
  58. package/docs/integrating/tailwind.md +89 -6
  59. package/docs/integrating/vue.md +3 -4
  60. package/docs/integrating/without-a-bundler.md +237 -0
  61. package/docs/pt-BR/accessibility.md +169 -0
  62. package/docs/pt-BR/concepts.md +212 -0
  63. package/docs/pt-BR/index.md +105 -0
  64. package/docs/pt-BR/integrating/astro.md +35 -0
  65. package/docs/pt-BR/integrating/index.md +75 -0
  66. package/docs/pt-BR/integrating/nextjs.md +67 -0
  67. package/docs/pt-BR/integrating/svelte.md +45 -0
  68. package/docs/pt-BR/integrating/tailwind.md +148 -0
  69. package/docs/pt-BR/integrating/vue.md +31 -0
  70. package/docs/pt-BR/integrating/without-a-bundler.md +238 -0
  71. package/docs/pt-BR/setup.md +188 -0
  72. package/docs/pt-BR/usage/aesthetics.md +282 -0
  73. package/docs/pt-BR/usage/buttons.md +135 -0
  74. package/docs/pt-BR/usage/composing.md +168 -0
  75. package/docs/pt-BR/usage/content-and-layout.md +219 -0
  76. package/docs/pt-BR/usage/customizing.md +304 -0
  77. package/docs/pt-BR/usage/feedback.md +157 -0
  78. package/docs/pt-BR/usage/forms.md +256 -0
  79. package/docs/pt-BR/usage/index.md +33 -0
  80. package/docs/pt-BR/usage/presets.md +92 -0
  81. package/docs/pt-BR/usage/solo.md +86 -0
  82. package/docs/pt-BR/usage/theming.md +309 -0
  83. package/docs/pt-BR/usage/tooltips.md +127 -0
  84. package/docs/setup.md +142 -91
  85. package/docs/usage/aesthetics.md +89 -73
  86. package/docs/usage/buttons.md +112 -40
  87. package/docs/usage/composing.md +109 -92
  88. package/docs/usage/content-and-layout.md +160 -125
  89. package/docs/usage/customizing.md +117 -41
  90. package/docs/usage/feedback.md +138 -71
  91. package/docs/usage/forms.md +201 -107
  92. package/docs/usage/index.md +22 -14
  93. package/docs/usage/presets.md +91 -0
  94. package/docs/usage/solo.md +85 -0
  95. package/docs/usage/theming.md +273 -118
  96. package/docs/usage/tooltips.md +90 -49
  97. package/llms-full.txt +2820 -1298
  98. package/llms.txt +24 -22
  99. package/package.json +134 -91
  100. package/{dist/tw → tw}/aesthetics/chunky-tile.css +107 -29
  101. package/{dist/tw → tw}/aesthetics/cyber.css +88 -40
  102. package/{dist/tw → tw}/aesthetics/glass.css +257 -61
  103. package/{dist/tw → tw}/aesthetics/neobrutalism.css +113 -20
  104. package/{dist/tw → tw}/aesthetics/pixel.css +93 -8
  105. package/tw/aesthetics/sketch.css +417 -0
  106. package/{dist/tw → tw}/box.css +105 -9
  107. package/tw/components/button.css +11 -0
  108. package/tw/components/button.rules.css +187 -0
  109. package/tw/components/feedback.css +11 -0
  110. package/{dist/tw/components/feedback.css → tw/components/feedback.rules.css} +136 -32
  111. package/tw/components/form.css +11 -0
  112. package/{dist/tw/components/form.css → tw/components/form.rules.css} +577 -125
  113. package/tw/components/index.css +16 -0
  114. package/tw/components/rules.css +41 -0
  115. package/tw/components/surface.css +11 -0
  116. package/tw/components/surface.rules.css +222 -0
  117. package/tw/components/tooltip.css +11 -0
  118. package/{dist/tw/components/tooltip.css → tw/components/tooltip.rules.css} +43 -27
  119. package/{dist/tw → tw}/corner.css +18 -12
  120. package/{dist/tw → tw}/elevation.css +23 -17
  121. package/{dist/tw → tw}/index.css +12 -10
  122. package/tw/index.d.ts +1 -0
  123. package/tw/intent.css +312 -0
  124. package/tw/modifiers.css +127 -0
  125. package/tw/native.css +320 -0
  126. package/tw/presentation.css +139 -0
  127. package/tw/reset.css +10 -0
  128. package/{dist/tw/reset.css → tw/reset.rules.css} +21 -22
  129. package/tw/size.css +34 -0
  130. package/tw/surface.css +9 -0
  131. package/tw/surface.rules.css +212 -0
  132. package/{dist/tw → tw}/theme.css +121 -45
  133. package/tw/typography.css +8 -0
  134. package/{dist/tw/typography.css → tw/typography.rules.css} +0 -3
  135. package/{dist/tw → tw}/utilities/content.css +212 -50
  136. package/tw/utilities/index.css +11 -0
  137. package/tw/utilities/layout.css +208 -0
  138. package/tw/utilities/rules.css +8 -0
  139. package/dist/tw/aesthetics/sketch.css +0 -333
  140. package/dist/tw/components/button.css +0 -139
  141. package/dist/tw/components/index.css +0 -36
  142. package/dist/tw/components/loader.css +0 -116
  143. package/dist/tw/components/surface.css +0 -175
  144. package/dist/tw/intent.css +0 -228
  145. package/dist/tw/native.css +0 -203
  146. package/dist/tw/palette.css +0 -460
  147. package/dist/tw/presentation.css +0 -68
  148. package/dist/tw/surface.css +0 -61
  149. package/dist/tw/utilities/index.css +0 -6
  150. package/dist/tw/utilities/layout.css +0 -130
  151. /package/{dist/tw → tw}/aesthetics/index.css +0 -0
package/tw/native.css ADDED
@@ -0,0 +1,320 @@
1
+ /* The layer map, stated before any import uses a layer -- see `theme.css`. */
2
+ @layer theme, base, components, utilities;
3
+
4
+ @import "./theme.css";
5
+ /* Tailwind's utilities into `utilities`, as `components/index.css` does it
6
+ and for its reason. */
7
+ @import "tailwindcss/utilities.css" layer(utilities);
8
+ /* Everything that is not `src/` -- see the note in `index.css`. Without the
9
+ docs and root-file excludes a utility used only in a documentation example
10
+ compiles into `dist/native.css`. */
11
+ /* No `typography.css` here: `components/rules.css` brings its rules, and a
12
+ second route to a `@utility` stacks its body. */
13
+ @import "./utilities/rules.css";
14
+ @import "./components/rules.css";
15
+ @import "./reset.rules.css";
16
+
17
+ @layer components {
18
+ /* `intent.css`'s reset keys on class names; these bare elements need the same,
19
+ or a `color-mix()` reading an undefined `--intent-*` drops silently. Zero
20
+ specificity like the class reset, values matching it slot for slot -- a bare
21
+ `<code>` and a `.code` chip are one component reached two ways. */
22
+ :where(table, kbd, code, pre, blockquote, hr, input, textarea, select, button, progress) {
23
+ --intent-color: var(--color-text);
24
+ --intent-contrast: var(--color-text-contrast);
25
+ --intent-hover: var(--color-text-hover);
26
+ --intent-strong: var(--color-text-strong);
27
+ --intent-subtle: var(--color-surface);
28
+ --intent-border: var(--ui-ink, var(--color-border));
29
+ --intent-fill-max: 20%;
30
+ }
31
+
32
+ /* Native text controls and toggles take the same stronger neutral boundary as
33
+ their classed counterparts, without changing buttons or other inputs --
34
+ control ink included, as `intent.css`'s class reset reads it. */
35
+ :where(
36
+ input:not([type]),
37
+ input[type="checkbox"],
38
+ input[type="radio"],
39
+ input[type="text"],
40
+ input[type="number"],
41
+ input[type="email"],
42
+ input[type="password"],
43
+ input[type="url"],
44
+ input[type="tel"],
45
+ input[type="search"],
46
+ input[type="month"],
47
+ input[type="week"],
48
+ input[type="time"],
49
+ input[type="date"],
50
+ input[type="datetime-local"],
51
+ textarea,
52
+ select
53
+ ) {
54
+ --intent-border: var(--ui-control-ink, var(--ui-ink, var(--color-control-border)));
55
+ }
56
+
57
+ /* A bare table's lines take the rule line, as `.data-table`'s do in
58
+ `intent.css`. */
59
+ :where(table) {
60
+ --intent-border: var(--ui-rule-ink, var(--ui-ink, var(--color-border)));
61
+ }
62
+
63
+ :where(hr) {
64
+ --intent-color: currentColor;
65
+ --intent-border: currentColor;
66
+ }
67
+ }
68
+
69
+ @layer base {
70
+ /* The `h1`-`ol` margin reset lives in `reset.css`, imported above. */
71
+
72
+ /* Headings */
73
+ h1 {
74
+ @apply text-title-lg;
75
+ }
76
+
77
+ h2 {
78
+ @apply text-title;
79
+ }
80
+
81
+ h3 {
82
+ @apply text-title-sm;
83
+ }
84
+
85
+ h4 {
86
+ @apply text-label-lg;
87
+ }
88
+
89
+ h5,
90
+ h6 {
91
+ @apply text-label;
92
+ }
93
+
94
+ /* Body copy is the page's text, set once on `body` and inherited, so a
95
+ container can resize or embolden the Markdown inside it. Pinned on `p` and
96
+ `li` instead, a bold 20px container printed its paragraphs at 14px regular,
97
+ and their tracking reached the controls inside one. The controls keep
98
+ their own tracking all the same: `.btn`, `.badge`, and `text-control` set
99
+ `normal`, so this body's wider tracking stops at them. Links take the text
100
+ they sit in, so one inside a heading stays heading-sized. */
101
+ body {
102
+ @apply text-body;
103
+ }
104
+
105
+ /* Content */
106
+ table {
107
+ @apply data-table;
108
+ }
109
+
110
+ kbd {
111
+ @apply kbd;
112
+ }
113
+
114
+ blockquote {
115
+ @apply quote;
116
+ }
117
+
118
+ q {
119
+ @apply quote-inline;
120
+ }
121
+
122
+ code {
123
+ @apply code;
124
+ }
125
+
126
+ pre {
127
+ @apply pre;
128
+ }
129
+
130
+ /* The block is the chip; the code inside it is text. Clearing only the fill
131
+ and padding left the rest of the chip an aesthetic draws: `.cyber`'s glow
132
+ boxed the text, neobrutalism's 2px transparent border indented the first
133
+ line, and `.pixel`'s inset ring outlined it. The halo token goes too, so
134
+ nothing that reads it inside a block draws one, and so does the clip a
135
+ cutting aesthetic gives the chip, which would trim the block's text. */
136
+ pre code {
137
+ @apply bg-transparent p-0;
138
+
139
+ --ui-halo-ink: initial;
140
+ border: 0;
141
+ box-shadow: none;
142
+ clip-path: none;
143
+ }
144
+
145
+ hr {
146
+ @apply divider;
147
+ }
148
+
149
+ /* Form controls. Every text-like type maps onto `.ipt` for the shared chrome
150
+ and nothing else -- an icon is a wrapper composition (`.input-group`), not a
151
+ property of the type, so no type paints one. */
152
+ input:not([type]),
153
+ input[type="text"],
154
+ input[type="number"],
155
+ input[type="email"],
156
+ input[type="password"],
157
+ input[type="url"],
158
+ input[type="tel"],
159
+ input[type="search"],
160
+ input[type="month"],
161
+ input[type="week"],
162
+ input[type="time"],
163
+ input[type="date"],
164
+ input[type="datetime-local"] {
165
+ @apply ipt;
166
+ }
167
+
168
+ textarea {
169
+ @apply textarea;
170
+ }
171
+
172
+ select {
173
+ @apply select;
174
+ }
175
+
176
+ input[type="checkbox"] {
177
+ @apply checkbox;
178
+ }
179
+
180
+ input[type="radio"] {
181
+ @apply radio;
182
+ }
183
+
184
+ /* Buttons */
185
+ button,
186
+ input[type="button"],
187
+ input[type="submit"],
188
+ input[type="reset"] {
189
+ @apply btn;
190
+ }
191
+
192
+ /* A dialog is the one surface with an element of its own, and it sits above
193
+ the page, so it is a floating card. `surface` carries the closed-dialog
194
+ hide and the centring. */
195
+ dialog {
196
+ @apply card floating;
197
+ }
198
+
199
+ /* The track is `.progress`'s. Its value is not: `.progress` draws the fill
200
+ as an `::after` sized by `--progress-value`, and a `<progress>` states its
201
+ value in an attribute and paints it in a pseudo-element of the engine's
202
+ own, so the fill is restated on each. One rule per engine: a selector
203
+ list with a pseudo-element an engine does not know drops the whole rule. */
204
+ progress {
205
+ @apply progress;
206
+
207
+ display: block;
208
+ appearance: none;
209
+ }
210
+
211
+ progress::-webkit-progress-bar {
212
+ background-color: transparent;
213
+ }
214
+
215
+ progress::-webkit-progress-value {
216
+ border-radius: var(--ui-radius-pill, var(--ui-radius, var(--ui-corner, calc(infinity * 1px))));
217
+ background-color: var(--progress-color, var(--intent-color));
218
+ }
219
+
220
+ progress::-moz-progress-bar {
221
+ border-radius: var(--ui-radius-pill, var(--ui-radius, var(--ui-corner, calc(infinity * 1px))));
222
+ background-color: var(--progress-color, var(--intent-color));
223
+ }
224
+
225
+ /* No `value` attribute is the indeterminate bar, `.progress.indeterminate`'s
226
+ sweep. Drawn on the track's own background: with no value an engine
227
+ paints its pseudo-element empty or full, and neither can be moved. */
228
+ progress:indeterminate {
229
+ background-image: linear-gradient(
230
+ var(--progress-color, var(--intent-color)),
231
+ var(--progress-color, var(--intent-color))
232
+ );
233
+ background-repeat: no-repeat;
234
+ background-size: 33% 100%;
235
+ animation: anim-progress-sweep 1.5s infinite ease-in-out;
236
+ }
237
+
238
+ /* The keyframes move a physical background position, so right-to-left text
239
+ runs them backwards: the sweep starts on the start side, as
240
+ `.progress.indeterminate`'s does. */
241
+ progress:indeterminate:dir(rtl) {
242
+ animation-direction: reverse;
243
+ }
244
+
245
+ progress:indeterminate::-webkit-progress-value {
246
+ background-color: transparent;
247
+ }
248
+
249
+ progress:indeterminate::-moz-progress-bar {
250
+ background-color: transparent;
251
+ }
252
+
253
+ /* The sweep rests at the start, as `.progress.indeterminate`'s does. */
254
+ @media (prefers-reduced-motion: reduce) {
255
+ progress:indeterminate {
256
+ animation: none;
257
+ }
258
+ }
259
+ }
260
+
261
+ /* The indeterminate `<progress>`'s sweep: a third of the track, from just off
262
+ one end to just off the other. */
263
+ @keyframes anim-progress-sweep {
264
+ from {
265
+ background-position: -50% 0;
266
+ }
267
+
268
+ to {
269
+ background-position: 150% 0;
270
+ }
271
+ }
272
+
273
+ @media (forced-colors: active) {
274
+ /* The bar in system colours, as `.progress` is in `feedback.css`. */
275
+ progress {
276
+ forced-color-adjust: none;
277
+ background-color: Canvas;
278
+ border-color: CanvasText;
279
+ }
280
+
281
+ progress::-webkit-progress-value {
282
+ background-color: CanvasText;
283
+ }
284
+
285
+ progress::-moz-progress-bar {
286
+ background-color: CanvasText;
287
+ }
288
+
289
+ progress:indeterminate {
290
+ background-image: linear-gradient(CanvasText, CanvasText);
291
+ }
292
+
293
+ input[type="checkbox"],
294
+ input[type="radio"] {
295
+ /* Keep these explicit system colors from being forced back to transparent. */
296
+ forced-color-adjust: none;
297
+ background-color: Canvas;
298
+ border-color: CanvasText;
299
+ transition: none;
300
+ }
301
+
302
+ /* A checked radio is the filled disc and dot it draws with forced colours
303
+ off, as `.radio` is in `form.css`: one look on both entrypoints. */
304
+ input[type="checkbox"]:checked,
305
+ input[type="checkbox"]:indeterminate,
306
+ input[type="radio"]:checked {
307
+ background-color: Highlight;
308
+ border-color: Highlight;
309
+
310
+ &::after {
311
+ background-color: HighlightText;
312
+ }
313
+ }
314
+
315
+ /* The platform's arrow, for the reason `.select` takes it back in
316
+ `form.css`: forced colours drop the gradient chevron. */
317
+ select:not([multiple], [size]:not([size="1"])) {
318
+ appearance: auto;
319
+ }
320
+ }
@@ -0,0 +1,139 @@
1
+ /* Each class here is a `@utility` whose body sits in `utilities.families`: a
2
+ utility, so `@apply` and Tailwind's variants reach it, and in a sublayer, so
3
+ it still loses to every rule written straight into `utilities` -- a
4
+ component's, or a consumer's own utility. See
5
+ docs/internal/model.md#cascade-layers. */
6
+
7
+ /* Presentation answers two independent questions, and each is its own closed
8
+ set: how much of the intent color fills the box, and whether the box draws a
9
+ line at its boundary. Exactly one value from each set applies, so the six
10
+ combinations are the whole vocabulary.
11
+
12
+ A fill class never decides an edge and an edge class never decides a fill, so
13
+ each half means only what it says. The line fades toward `transparent` as the
14
+ fill fills in (`box.css`; docs/internal/model.md#presentation), so
15
+ `.solid.edged` and `.solid.edgeless` render one box without either class
16
+ deciding the other's question.
17
+
18
+ Presentation declares only unitless numbers and percentages, and the
19
+ `--_holds-ink` toggle, whose values are a keyword and an empty value: neither
20
+ carries an intent either, so it inherits as safely. A custom
21
+ property's value is resolved on the element that declares it, so anything
22
+ referencing an intent token here would resolve against the container's intent
23
+ and inherit down already-resolved. Numbers carry no intent, so they inherit
24
+ safely and each component mixes them against its own palette.
25
+
26
+ A declaration on the element beats an inherited one, which is what lets a
27
+ container set the look for its subtree while any element still opts out.
28
+
29
+ Hover is derived from these values rather than declared beside them:
30
+ `min(100%, resting fill + --hover-step)`, always in `--intent-hover`. There
31
+ is no hover token and no per-presentation branch. */
32
+
33
+ /* The ink of the plate an element sits on, handed down by the nearest filled
34
+ box above it. Registered, so that an unfilled box -- whose declaration of
35
+ these is deliberately invalid -- inherits them instead of clearing them:
36
+ that is what lets the ink pass through a box with no plate of its own.
37
+ `--_own-hold` does not inherit, so the same invalid declaration reads 0%
38
+ and a box can tell an ink it was handed from one it holds. See
39
+ docs/internal/model.md#the-ink-of-the-plate-beneath. */
40
+ @property --_held-ink {
41
+ syntax: "<color>";
42
+ inherits: true;
43
+ initial-value: transparent;
44
+ }
45
+
46
+ @property --_held-on {
47
+ syntax: "<percentage>";
48
+ inherits: true;
49
+ initial-value: 0%;
50
+ }
51
+
52
+ @property --_own-hold {
53
+ syntax: "<percentage>";
54
+ inherits: false;
55
+ initial-value: 0%;
56
+ }
57
+
58
+ /* Filled with the intent color. Text is the contrast tone. `--_holds-ink` is
59
+ the same answer as a toggle `box` can read: empty where the fill is a
60
+ plate, `none` where it is not. A percentage cannot make a declaration
61
+ invalid, and an invalid one is how an unfilled box passes the ink on. */
62
+ /* What the element itself asked for, as against what reached it from a
63
+ container: the fill and the edge its own presentation class names. Neither
64
+ inherits, so a field reads its own `.soft` here and a toolbar's `.soft`
65
+ only through `--ui-fill`. A class on the element is a request and a class
66
+ on a container is a cascade, and a component that bounds the cascade --
67
+ `text-control`'s 6% wash, its edge floor, the tooltip bubble's -- lifts the
68
+ bound by these. Written by the utilities, so `@apply ipt soft` carries the
69
+ request as the class on the element does; a selector keyed on `.soft` saw
70
+ only the class. See docs/internal/model.md#what-apply-carries. */
71
+ @property --_own-fill {
72
+ syntax: "<percentage>";
73
+ inherits: false;
74
+ initial-value: 0%;
75
+ }
76
+
77
+ @property --_own-edge {
78
+ syntax: "<percentage>";
79
+ inherits: false;
80
+ initial-value: 100%;
81
+ }
82
+
83
+ @utility solid {
84
+ @layer families {
85
+ --ui-fill: 100%;
86
+ --ui-fg-on-fill: 100%;
87
+ --_own-fill: 100%;
88
+ --_holds-ink: ;
89
+ }
90
+ }
91
+
92
+ /* Tinted with the intent color. Text is the intent color. */
93
+ @utility soft {
94
+ @layer families {
95
+ --ui-fill: 12%;
96
+ --ui-fg-on-fill: 0%;
97
+ --_own-fill: 12%;
98
+ --_holds-ink: none;
99
+ }
100
+ }
101
+
102
+ /* No fill at rest; the derived hover gives it one. Text is the intent color. It
103
+ names a fill and only a fill: `.bare` and `.edgeless` both read as "less of
104
+ something", so an author wanting no border would reach for the wrong one.
105
+
106
+ A component that rests on a ground rather than on nothing keeps that ground
107
+ here: `.ghost` is zero fill, not zero paint. `.data-table` is the exception
108
+ that proves it -- its head plate *is* the tint, so a ghost table drops it. */
109
+ @utility ghost {
110
+ @layer families {
111
+ --ui-fill: 0%;
112
+ --ui-fg-on-fill: 0%;
113
+ --_own-fill: 0%;
114
+ --_holds-ink: none;
115
+ }
116
+ }
117
+
118
+ /* A line in the intent color, at the aesthetic's material width. The width
119
+ comes from the aesthetic and nothing else: there is no presentation scale on
120
+ it, so small components need no ceilings to survive a thick one.
121
+
122
+ The edge is the silhouette and nothing else. Rules *inside* a component that
123
+ has an inside are a separate decision with their own class --
124
+ `.data-table.ruled` -- so a consumer's own markup says whether they asked for
125
+ them. */
126
+ @utility edged {
127
+ @layer families {
128
+ --ui-border: 100%;
129
+ --_own-edge: 100%;
130
+ }
131
+ }
132
+
133
+ /* No line. */
134
+ @utility edgeless {
135
+ @layer families {
136
+ --ui-border: 0%;
137
+ --_own-edge: 0%;
138
+ }
139
+ }
package/tw/reset.css ADDED
@@ -0,0 +1,10 @@
1
+ @reference "tailwindcss";
2
+ @import "./theme.css";
3
+ @import "./typography.css";
4
+
5
+ /* The focused entry: what the rules in `reset.rules.css` need to compile on
6
+ their own, then the rules. `index.css` and `native.css` import the rules
7
+ file directly, since they already hold the typography utilities it applies
8
+ and a second route would stack them. See docs/internal/model.md (One route
9
+ to each utility). */
10
+ @import "./reset.rules.css";
@@ -1,7 +1,3 @@
1
- @reference "tailwindcss";
2
- @import "./theme.css";
3
- @import "./typography.css";
4
-
5
1
  @layer base {
6
2
  /* The package's own components do not lean on this: `@utility box` sets
7
3
  `box-sizing: border-box` on itself, so a sized control is right in every
@@ -87,29 +83,32 @@
87
83
  A component drawing no line at rest loses nothing: the outline moves inward
88
84
  over its own fill by a hairline, which is not a visible change. */
89
85
  :focus-visible {
90
- outline: var(--focus-ring-width) solid var(--focus-ring);
86
+ outline: var(--focus-ring-width) solid var(--focus-ring, color-mix(in srgb, var(--color-primary) 64%, transparent));
91
87
  outline-offset: var(--focus-ring-offset, calc(-1 * var(--ui-border-width, var(--border-width))));
92
88
  }
93
89
 
90
+ /* Not on a control inside an `.input-group`, which draws the field's ring
91
+ for it: an important declaration in `base` beats any later one, so the
92
+ group could not suppress this one and a focused field drew two rings. */
94
93
  @media (forced-colors: active) {
95
94
  input:is(
96
- [type="text"],
97
- [type="email"],
98
- [type="password"],
99
- [type="url"],
100
- [type="tel"],
101
- [type="number"],
102
- [type="search"],
103
- [type="date"],
104
- [type="datetime-local"],
105
- [type="month"],
106
- [type="week"],
107
- [type="time"],
108
- [type="checkbox"],
109
- [type="radio"]
110
- ):focus-visible,
111
- textarea:focus-visible,
112
- select:focus-visible {
95
+ [type="text"],
96
+ [type="email"],
97
+ [type="password"],
98
+ [type="url"],
99
+ [type="tel"],
100
+ [type="number"],
101
+ [type="search"],
102
+ [type="date"],
103
+ [type="datetime-local"],
104
+ [type="month"],
105
+ [type="week"],
106
+ [type="time"],
107
+ [type="checkbox"],
108
+ [type="radio"]
109
+ ):focus-visible:not(.input-group > *),
110
+ textarea:focus-visible:not(.input-group > *),
111
+ select:focus-visible:not(.input-group > *) {
113
112
  outline: 2px solid Highlight !important;
114
113
  outline-offset: 2px;
115
114
  }
package/tw/size.css ADDED
@@ -0,0 +1,34 @@
1
+ /* The size modifier: `sm` and `lg`. A utility in `utilities.families`, as the
2
+ classes in `presentation.css` are, so `@apply btn sm` and `md:lg` work.
3
+
4
+ A size cannot say what it changes, because each component has its own
5
+ steps, so it raises a flag and the component reads it. The flag is a space
6
+ toggle: unset it is guaranteed-invalid, so `--_sm-h: var(--_size-sm) 2rem`
7
+ is invalid too and the `var(--_sm-h, ...)` that reads it takes its
8
+ fallback; set, it is empty, and the same line computes to `2rem`.
9
+
10
+ Registered non-inheriting, as `--ui-elevation` is and for its reason: a
11
+ size is a choice about one element, and inherited, a `.sm` form would
12
+ shrink every control inside it. No `initial-value`, so an element that
13
+ does not set it computes guaranteed-invalid. See docs/internal/model.md#size. */
14
+ @property --_size-sm {
15
+ syntax: "*";
16
+ inherits: false;
17
+ }
18
+
19
+ @property --_size-lg {
20
+ syntax: "*";
21
+ inherits: false;
22
+ }
23
+
24
+ @utility sm {
25
+ @layer families {
26
+ --_size-sm: ;
27
+ }
28
+ }
29
+
30
+ @utility lg {
31
+ @layer families {
32
+ --_size-lg: ;
33
+ }
34
+ }
package/tw/surface.css ADDED
@@ -0,0 +1,9 @@
1
+ @reference "./box.css";
2
+
3
+ /* The focused entry: what the rules in `surface.rules.css` need to compile on their
4
+ own, then the rules. An aggregate entry imports the rules file directly and
5
+ supplies those needs once -- Tailwind stacks a `@utility` each time a file
6
+ that defines it is imported or referenced, so a second route to `box.css`
7
+ doubles every `@apply box`. See docs/internal/model.md (One route to each
8
+ utility). */
9
+ @import "./surface.rules.css";