@codenhub/styles 0.4.0 → 0.5.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 (53) hide show
  1. package/README.md +1 -1
  2. package/dist/aesthetics/chunky-tile.css +1 -1
  3. package/dist/aesthetics/cyber.css +1 -1
  4. package/dist/aesthetics/glass.css +1 -1
  5. package/dist/aesthetics/index.css +1 -1
  6. package/dist/aesthetics/neobrutalism.css +1 -1
  7. package/dist/aesthetics/pixel.css +1 -1
  8. package/dist/aesthetics/sketch.css +1 -0
  9. package/dist/components.css +1 -1
  10. package/dist/index.css +1 -1
  11. package/dist/native.css +1 -1
  12. package/dist/palette.css +1 -1
  13. package/dist/theme.css +1 -1
  14. package/dist/tw/aesthetics/chunky-tile.css +142 -126
  15. package/dist/tw/aesthetics/cyber.css +132 -95
  16. package/dist/tw/aesthetics/glass.css +97 -56
  17. package/dist/tw/aesthetics/index.css +1 -0
  18. package/dist/tw/aesthetics/neobrutalism.css +99 -52
  19. package/dist/tw/aesthetics/pixel.css +127 -87
  20. package/dist/tw/aesthetics/sketch.css +326 -0
  21. package/dist/tw/box.css +100 -35
  22. package/dist/tw/components/button.css +40 -22
  23. package/dist/tw/components/feedback.css +29 -14
  24. package/dist/tw/components/form.css +151 -155
  25. package/dist/tw/components/index.css +15 -3
  26. package/dist/tw/components/loader.css +34 -25
  27. package/dist/tw/components/surface.css +28 -71
  28. package/dist/tw/components/tooltip.css +20 -10
  29. package/dist/tw/corner.css +26 -0
  30. package/dist/tw/elevation.css +8 -9
  31. package/dist/tw/intent.css +17 -9
  32. package/dist/tw/native.css +45 -39
  33. package/dist/tw/palette.css +452 -446
  34. package/dist/tw/presentation.css +9 -4
  35. package/dist/tw/surface.css +62 -0
  36. package/dist/tw/theme.css +106 -75
  37. package/dist/tw/utilities/content.css +25 -16
  38. package/dist/tw/utilities/layout.css +2 -2
  39. package/docs/accessibility.md +16 -16
  40. package/docs/changelog/0.5.0.md +38 -0
  41. package/docs/changelog/index.md +1 -0
  42. package/docs/index.md +3 -3
  43. package/docs/setup.md +23 -3
  44. package/docs/usage/aesthetics.md +56 -13
  45. package/docs/usage/buttons.md +13 -13
  46. package/docs/usage/composing.md +11 -11
  47. package/docs/usage/content-and-layout.md +13 -13
  48. package/docs/usage/customizing.md +90 -52
  49. package/docs/usage/feedback.md +1 -1
  50. package/docs/usage/forms.md +11 -11
  51. package/docs/usage/theming.md +1 -1
  52. package/llms-full.txt +274 -136
  53. package/package.json +12 -2
@@ -1,39 +1,8 @@
1
1
  @reference "tailwindcss";
2
2
  @import "../theme.css";
3
+ @import "../surface.css";
3
4
  @reference "../box.css";
4
5
 
5
- /* What every surface shares. Two slots exist here and nowhere else, and that is
6
- how an aesthetic reaches surfaces without naming one: only a surface resolves
7
- `--ui-backdrop`, so glass blurs cards and panels while controls stay solid,
8
- and only a surface resolves `--ui-surface-shadow`, so a two-layer drop shadow
9
- does not land under every button on the page. */
10
- @utility surface {
11
- @apply box block;
12
-
13
- /* Bare and edged. `box` reads these three with no fallback, so `surface` --
14
- typeable on its own -- owes all three; `card` restates its own. No shadow
15
- geometry: depth is asked for (`.raised`/`.floating`, an aesthetic, the
16
- registry elevation) rather than carried, so a plain card is flat. */
17
- --_d-fill: 0%;
18
- --_d-fg-on-fill: 0%;
19
- --_d-border: 100%;
20
-
21
- --_d-ground: var(--ui-surface-ground, var(--color-background));
22
-
23
- /* The complete-shadow slot for a shadow that is not one layer (glass tucks two
24
- under with negative spread). Only `surface` reads it -- through `--ui-shadow`
25
- it would land an 18px drop under every button and chip -- like the backdrop. */
26
- --_shadow: var(--ui-surface-shadow, var(--_shadow-parts));
27
-
28
- border-radius: var(--ui-radius-surface, var(--radius-surface));
29
- /* Prefixed property first, deliberately: written second the minifier folds the
30
- pair into the prefixed one alone, and the standard property never reaches
31
- `dist/` -- which drops the blur in Firefox (the one engine with
32
- `backdrop-filter` and not the `-webkit-` alias). Measured on the built CSS. */
33
- -webkit-backdrop-filter: var(--ui-backdrop, none);
34
- backdrop-filter: var(--ui-backdrop, none);
35
- }
36
-
37
6
  /* A ghost, edged container that takes one unit when depth is supplied. */
38
7
  @utility card {
39
8
  @apply surface p-(--surface-padding,1.25rem);
@@ -46,21 +15,19 @@
46
15
  --_d-border: 100%;
47
16
  --_d-elevation: 1;
48
17
 
49
- /* `.p-xs`/`.p-sm`/`.p-lg` are the canonical names; `.dense`/`.compact`/`.spacious`
50
- are first-class aliases -- see the identical note in `button.css`. */
51
- &.p-xs,
52
- &.dense {
18
+ &.p-xs {
53
19
  --surface-padding: 0.5rem;
20
+ --_scale-pad: 0.5;
54
21
  }
55
22
 
56
- &.p-sm,
57
- &.compact {
23
+ &.p-sm {
58
24
  --surface-padding: 0.75rem;
25
+ --_scale-pad: 0.75;
59
26
  }
60
27
 
61
- &.p-lg,
62
- &.spacious {
28
+ &.p-lg {
63
29
  --surface-padding: 2rem;
30
+ --_scale-pad: 1.25;
64
31
  }
65
32
 
66
33
  &.flush {
@@ -96,21 +63,21 @@
96
63
  a second fill declaration, for the no-intent case: resting at 0% means
97
64
  hover lands at exactly the hover step, 14%, in `--intent-hover` as
98
65
  always. The ground steps to `--color-surface` at the same moment,
99
- through the public `--ui-surface-ground` escape hatch rather than the
100
- private `--_d-ground`, so a consumer's own override still wins over both
101
- states the way it always has. Scoped to `.interactive` and `.hoverable`,
66
+ through `--_d-surface-ground`, the default `surface` reads beneath the
67
+ public `--ui-surface-ground` -- so a consumer's own override, or glass's
68
+ ground, still wins over both states. Scoped to `.interactive` and `.hoverable`,
102
69
  the two classes that already opt a card into `box-hover` -- a plain
103
70
  `.card.soft` with neither has no hover state to reveal into and stays at
104
71
  the quiet, untinted rest. A named intent needs neither special case: it
105
72
  already rests tinted, so the same generic `box-hover` formula deepens it
106
73
  on hover (12% to 26%) with no ground shift required. */
107
- &.soft:not(.primary, .secondary, .success, .warning, .destructive, .danger, .error, .info) {
74
+ &.soft:not(.primary, .secondary, .success, .warning, .destructive, .info) {
108
75
  --_fill-cap: 0%;
109
- --ui-surface-ground: var(--color-foreground);
76
+ --_d-surface-ground: var(--color-foreground);
110
77
 
111
78
  &.interactive:hover,
112
79
  &.hoverable:hover {
113
- --ui-surface-ground: var(--color-surface);
80
+ --_d-surface-ground: var(--color-surface);
114
81
  }
115
82
  }
116
83
 
@@ -148,19 +115,19 @@
148
115
  --_d-border: 0%;
149
116
  --_d-elevation: 0;
150
117
 
151
- &.p-xs,
152
- &.dense {
118
+ &.p-xs {
153
119
  --surface-padding: 0.25rem;
120
+ --_scale-pad: 0.5;
154
121
  }
155
122
 
156
- &.p-sm,
157
- &.compact {
123
+ &.p-sm {
158
124
  --surface-padding: 0.5rem;
125
+ --_scale-pad: 0.75;
159
126
  }
160
127
 
161
- &.p-lg,
162
- &.spacious {
128
+ &.p-lg {
163
129
  --surface-padding: 1.5rem;
130
+ --_scale-pad: 1.25;
164
131
  }
165
132
 
166
133
  &.flush {
@@ -190,26 +157,16 @@
190
157
  not ask for -- the same guard `data-table`'s own `:not(.solid, .ghost)`
191
158
  uses.
192
159
 
193
- Grounds on `--color-foreground` through the public `--ui-surface-ground`
194
- escape hatch, not the private `--_d-ground`, the same token `.card.soft`
195
- steps to -- so a consumer's own override still wins, and a bare `.panel`
196
- rests at exactly the plate a `.card.soft` does (measured: `245, 245, 245`
197
- light, `23, 23, 23` dark, identical both ways). Permanent rather than
160
+ Grounds on `--color-foreground` through `--_d-surface-ground`, the same
161
+ default `.card.soft` rests on -- so a bare `.panel` rests at exactly the
162
+ plate a `.card.soft` does (measured: `245, 245, 245` light, `23, 23, 23`
163
+ dark, identical both ways), and a consumer's `--ui-surface-ground` or
164
+ glass's translucent ground still wins over it: a neutral panel under
165
+ `.glass` is glass, like every other surface there. Permanent rather than
198
166
  hover-revealed: neither a panel nor `data-table` has an interaction
199
- state to reveal a tint into, so both rest quiet rather than reveal.
200
-
201
- The one cost, inherited rather than new: an own declaration always beats
202
- an inherited one, so this also beats `.glass` setting the same token on
203
- an ancestor for its translucent ground -- a neutral panel under `.glass`
204
- is quiet but opaque rather than blurred. `.card.soft` has carried this
205
- exact trade-off since it shipped; nothing exercised it there because
206
- `tests/browser/aesthetics.spec.ts`'s glass coverage tests a default
207
- (ghost) card, never a soft one. Accepted rather than solved differently:
208
- there is no way to ask "did an ancestor already set this token" in CSS,
209
- only which declaration wins, and the quiet neutral rest is the more
210
- common case a panel needs to get right. */
211
- &:not(.primary, .secondary, .success, .warning, .destructive, .danger, .error, .info, .solid, .ghost) {
167
+ state to reveal a tint into, so both rest quiet rather than reveal. */
168
+ &:not(.primary, .secondary, .success, .warning, .destructive, .info, .solid, .ghost) {
212
169
  --_fill-cap: 0%;
213
- --ui-surface-ground: var(--color-foreground);
170
+ --_d-surface-ground: var(--color-foreground);
214
171
  }
215
172
  }
@@ -1,7 +1,7 @@
1
1
  @reference "tailwindcss";
2
2
  @import "../theme.css";
3
3
  @reference "../box.css";
4
- @reference "./surface.css";
4
+ @reference "../surface.css";
5
5
 
6
6
  /* The host is a positioning wrapper and nothing else -- it paints no fill, no
7
7
  edge, no material of its own. The bubble is a real element beside the
@@ -88,8 +88,13 @@
88
88
  --_edge-floor: 100%;
89
89
 
90
90
  /* A bubble is a small transient popover, not a modal, so it takes the
91
- control radius rather than the surface one `surface` hands it. */
92
- border-radius: var(--ui-radius, var(--radius-control));
91
+ control corner `box` computes rather than the surface one `surface` hands
92
+ it, with the same pattern. */
93
+ border-radius: var(
94
+ --ui-radius,
95
+ calc(var(--_corner) * var(--ui-corner-tl, 1)) calc(var(--_corner) * var(--ui-corner-tr, 1))
96
+ calc(var(--_corner) * var(--ui-corner-br, 1)) calc(var(--_corner) * var(--ui-corner-bl, 1))
97
+ );
93
98
  left: var(--tooltip-left);
94
99
  right: var(--tooltip-right);
95
100
  top: var(--tooltip-top);
@@ -108,12 +113,17 @@
108
113
  identical reason: the bubble is a sibling, not a pseudo-element, of the
109
114
  trigger, so nothing but the shared ancestor can see both at once. The cost
110
115
  is the one `.input-group` already accepts -- the bubble also shows on a
111
- mouse click, which the old `:focus-visible`-only version did not. */
112
- .tooltip:hover .tooltip-bubble,
113
- .tooltip:focus-within .tooltip-bubble,
114
- .tooltip[data-state="open"] .tooltip-bubble {
115
- opacity: 1;
116
- transform: var(--tooltip-transform) scale(1);
116
+ mouse click, which the old `:focus-visible`-only version did not.
117
+
118
+ In `utilities`, where the bubble's own `@utility` is, winning on
119
+ specificity -- see the seams note in `form.css`. */
120
+ @layer utilities {
121
+ .tooltip:hover .tooltip-bubble,
122
+ .tooltip:focus-within .tooltip-bubble,
123
+ .tooltip[data-state="open"] .tooltip-bubble {
124
+ opacity: 1;
125
+ transform: var(--tooltip-transform) scale(1);
126
+ }
117
127
  }
118
128
 
119
129
  /* The trigger badge, for a message with no other element to hang it on. Quiet
@@ -138,6 +148,6 @@
138
148
  --_d-elevation: 0;
139
149
  --_d-ground: var(--intent-subtle);
140
150
 
141
- border-radius: var(--ui-radius-pill, var(--ui-radius, calc(infinity * 1px)));
151
+ border-radius: var(--ui-radius-pill, var(--ui-radius, var(--ui-corner, calc(infinity * 1px))));
142
152
  clip-path: none;
143
153
  }
@@ -0,0 +1,26 @@
1
+ /* Imported into the `components` layer by `theme.css`, below every utility, so
2
+ a consumer's own utility or unlayered CSS beats these classes. See
3
+ docs/internal/model.md#cascade-layers.
4
+
5
+ The corner pattern: which corners take the corner the aesthetic draws. `box`
6
+ and `surface` multiply their computed corner by `--ui-corner-tl`, `-tr`,
7
+ `-br`, and `-bl`, each 0 or 1, so a class that sets the four draws two
8
+ corners and leaves two square under every aesthetic -- a two-corner leaf
9
+ under the default look, two cuts under `.cyber`. An explicit `--ui-radius`
10
+ is taken as written and ignores the pattern. See docs/internal/model.md#material-tokens. */
11
+
12
+ /* Top-left and bottom-right. */
13
+ .cut-diagonal {
14
+ --ui-corner-tl: 1;
15
+ --ui-corner-tr: 0;
16
+ --ui-corner-br: 1;
17
+ --ui-corner-bl: 0;
18
+ }
19
+
20
+ /* Top-right and bottom-left. */
21
+ .cut-diagonal-reverse {
22
+ --ui-corner-tl: 0;
23
+ --ui-corner-tr: 1;
24
+ --ui-corner-br: 0;
25
+ --ui-corner-bl: 1;
26
+ }
@@ -1,3 +1,7 @@
1
+ /* Imported into the `components` layer by `theme.css`, below every utility, so
2
+ a consumer's own utility or unlayered CSS beats these classes. See
3
+ docs/internal/model.md#cascade-layers. */
4
+
1
5
  /* Elevation is a modifier, not an axis: depth is a per-element decision (raised
2
6
  tiles beside a flat panel in one aesthetic), so one unitless number multiplies
3
7
  the aesthetic's shadow geometry where the component composes it. `.flat`
@@ -20,10 +24,10 @@
20
24
  component uniformly the way it always did. Registering these three is what
21
25
  scopes the change to the elevation modifier alone.
22
26
 
23
- `.flat`/`.raised`/`.floating` and `.elevation-none`/`-sm`/`-md` are
24
- interchangeable aliases, the second borrowing the raw `--elevation-*` scale's
25
- naming. Bare `sm`/`md`/`lg` would collide with the size modifier;
26
- `.elevation-lg` is reserved, not shipped. */
27
+ `.flat`/`.raised`/`.floating` name what they do rather than a scale step:
28
+ bare `sm`/`md`/`lg` would collide with the size modifier, and the
29
+ `.elevation-*` spellings, which borrowed the raw `--elevation-*` shadows'
30
+ names for a different mechanism, were removed in `0.5.0`. */
27
31
 
28
32
  /* `syntax: "*"` with no `initial-value` is deliberate: a numeric syntax would
29
33
  require one (CSS Properties and Values API), and any initial-value at all
@@ -51,7 +55,6 @@
51
55
 
52
56
  /* No part-based depth. Complete surface shadow values, such as glass, are not
53
57
  reached by the elevation multiplier. */
54
- .elevation-none,
55
58
  .flat {
56
59
  --ui-elevation: 0;
57
60
  }
@@ -61,22 +64,18 @@
61
64
  that declares its own shadow parts overrides it, and the elevation multiplier
62
65
  scales whichever one lands. `.floating` takes its extra depth from the
63
66
  multiplier below, not a second copy of these parts. */
64
- .elevation-sm,
65
67
  .raised,
66
- .elevation-md,
67
68
  .floating {
68
69
  --elevation-y: 1px;
69
70
  --elevation-blur: 3px;
70
71
  }
71
72
 
72
73
  /* The aesthetic's depth as authored, said explicitly. */
73
- .elevation-sm,
74
74
  .raised {
75
75
  --ui-elevation: 1;
76
76
  }
77
77
 
78
78
  /* Twice it, for menus and popovers. */
79
- .elevation-md,
80
79
  .floating {
81
80
  --ui-elevation: 2;
82
81
  }
@@ -1,3 +1,7 @@
1
+ /* Imported into the `components` layer by `theme.css`, below every utility, so
2
+ a consumer's own utility or unlayered CSS beats these classes. See
3
+ docs/internal/model.md#cascade-layers. */
4
+
1
5
  /* An intent maps one colour family onto seven shared slots and nothing else.
2
6
  It does not cascade: the reset at the bottom redeclares the neutral defaults
3
7
  at every component's own root, so a `.success` container cannot recolour a
@@ -85,9 +89,7 @@
85
89
  --intent-fill-max: 100%;
86
90
  }
87
91
 
88
- .destructive,
89
- .danger,
90
- .error {
92
+ .destructive {
91
93
  --intent-color: var(--color-destructive);
92
94
  --intent-contrast: var(--color-destructive-contrast);
93
95
  --intent-hover: var(--color-destructive-hover);
@@ -159,13 +161,19 @@
159
161
  border for 3:1. `--color-border` gives it 1.42:1.
160
162
 
161
163
  Declared here at zero specificity for the same reason the indicators below
162
- are: written inside `@utility text-control` it would land in the utilities
163
- layer, the reset above lands in no layer at all, and unlayered beats layered
164
- at any specificity. Written as a plain class list it would carry 0-1-0 and,
165
- being later in the stylesheet, beat `.primary` -- which would make every
166
- colored control draw a grey line. `:where()` keeps it under both. */
164
+ are: written inside `@utility text-control` it would land in `utilities`,
165
+ above every intent class in `components`, and overrule `.primary` on the
166
+ element. Written as a plain class list it would carry 0-1-0 and, being later
167
+ in the stylesheet, beat `.primary` the same way. Either would make every
168
+ colored control draw a grey line; `:where()` keeps it under both.
169
+
170
+ An aesthetic reaches this line through `--ui-control-ink` first, then its
171
+ `--ui-ink`: the theme keeps a control border apart from a surface border, and
172
+ an aesthetic whose neutral line suits a pane but not a control's boundary --
173
+ `.glass`'s white hairline, `.chunky-tile`'s tile grey -- names a control line
174
+ of its own. See docs/internal/model.md#presentation. */
167
175
  :where(.text-control, .ipt, .textarea, .select, .input-group, .checkbox, .radio, .switch) {
168
- --intent-border: var(--ui-ink, var(--color-control-border));
176
+ --intent-border: var(--ui-control-ink, var(--ui-ink, var(--color-control-border)));
169
177
  }
170
178
 
171
179
  /* The bubble a tooltip draws is the one plate in the package that is chosen
@@ -1,3 +1,6 @@
1
+ /* The layer map, stated before any import uses a layer -- see `theme.css`. */
2
+ @layer theme, base, components, utilities;
3
+
1
4
  @import "./theme.css";
2
5
  @reference "tailwindcss";
3
6
  /* Everything that is not `src/` -- see the note in `index.css`. Without the
@@ -8,45 +11,48 @@
8
11
  @import "./components/index.css";
9
12
  @import "./reset.css";
10
13
 
11
- /* `intent.css`'s reset keys on class names; these bare elements need the same,
12
- or a `color-mix()` reading an undefined `--intent-*` drops silently. Zero
13
- specificity like the class reset, values matching it slot for slot -- a bare
14
- `<code>` and a `.code` chip are one component reached two ways. */
15
- :where(table, kbd, code, pre, blockquote, hr, input, textarea, select, button) {
16
- --intent-color: var(--color-text);
17
- --intent-contrast: var(--color-text-contrast);
18
- --intent-hover: var(--color-text-hover);
19
- --intent-strong: var(--color-text-strong);
20
- --intent-subtle: var(--color-surface);
21
- --intent-border: var(--ui-ink, var(--color-border));
22
- --intent-fill-max: 20%;
23
- }
24
-
25
- /* Native text controls need the same stronger neutral boundary as their classed
26
- counterparts, without changing buttons, checkboxes, radios, or other inputs. */
27
- :where(
28
- input:not([type]),
29
- input[type="text"],
30
- input[type="number"],
31
- input[type="email"],
32
- input[type="password"],
33
- input[type="url"],
34
- input[type="tel"],
35
- input[type="search"],
36
- input[type="month"],
37
- input[type="week"],
38
- input[type="time"],
39
- input[type="date"],
40
- input[type="datetime-local"],
41
- textarea,
42
- select
43
- ) {
44
- --intent-border: var(--ui-ink, var(--color-control-border));
45
- }
46
-
47
- :where(hr) {
48
- --intent-color: currentColor;
49
- --intent-border: currentColor;
14
+ @layer components {
15
+ /* `intent.css`'s reset keys on class names; these bare elements need the same,
16
+ or a `color-mix()` reading an undefined `--intent-*` drops silently. Zero
17
+ specificity like the class reset, values matching it slot for slot -- a bare
18
+ `<code>` and a `.code` chip are one component reached two ways. */
19
+ :where(table, kbd, code, pre, blockquote, hr, input, textarea, select, button) {
20
+ --intent-color: var(--color-text);
21
+ --intent-contrast: var(--color-text-contrast);
22
+ --intent-hover: var(--color-text-hover);
23
+ --intent-strong: var(--color-text-strong);
24
+ --intent-subtle: var(--color-surface);
25
+ --intent-border: var(--ui-ink, var(--color-border));
26
+ --intent-fill-max: 20%;
27
+ }
28
+
29
+ /* Native text controls need the same stronger neutral boundary as their classed
30
+ counterparts, without changing buttons, checkboxes, radios, or other inputs --
31
+ control ink included, as `intent.css`'s class reset reads it. */
32
+ :where(
33
+ input:not([type]),
34
+ input[type="text"],
35
+ input[type="number"],
36
+ input[type="email"],
37
+ input[type="password"],
38
+ input[type="url"],
39
+ input[type="tel"],
40
+ input[type="search"],
41
+ input[type="month"],
42
+ input[type="week"],
43
+ input[type="time"],
44
+ input[type="date"],
45
+ input[type="datetime-local"],
46
+ textarea,
47
+ select
48
+ ) {
49
+ --intent-border: var(--ui-control-ink, var(--ui-ink, var(--color-control-border)));
50
+ }
51
+
52
+ :where(hr) {
53
+ --intent-color: currentColor;
54
+ --intent-border: currentColor;
55
+ }
50
56
  }
51
57
 
52
58
  @layer base {