@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
@@ -0,0 +1,16 @@
1
+ /* The layer map, stated before any import uses a layer -- see `theme.css`.
2
+ Tailwind's utilities are imported into `utilities` the way
3
+ `tailwindcss/index.css` does it, so every component lands there on this
4
+ entrypoint and on `/native` too, exactly where `.` already puts them. Without
5
+ `layer(utilities)` the CLI emitted them unlayered here, and they beat every
6
+ consumer rule on these two entries alone. */
7
+ @layer theme, base, components, utilities;
8
+
9
+ /* The theme first, as `native.css` has it: Tailwind writes the theme's
10
+ variables at the first `@theme` it meets. See docs/internal/model.md
11
+ (Which files import the theme). */
12
+ @import "../theme.css";
13
+ @import "tailwindcss/utilities.css" layer(utilities);
14
+ /* Everything that is not `src/` -- see the note in `index.css`. Keeps a class
15
+ name in a docs code fence from shipping as a real rule in `dist/components.css`. */
16
+ @import "./rules.css";
@@ -0,0 +1,41 @@
1
+ /* Every component, with nothing they need to compile: the entry that imports
2
+ this file brings the theme and Tailwind once. `index.css` beside it is that
3
+ entry for `/components`; the complete stylesheet and `/native` are the
4
+ others. See docs/internal/model.md (One route to each utility). */
5
+ @import "../typography.rules.css";
6
+
7
+ /* `hidden` hides. The user agent says so at user-agent origin, which loses to
8
+ any author `display`, and every component sets one. The complete stylesheet
9
+ gets this rule from Tailwind's Preflight; this entry and `/native`, which
10
+ imports it, ship no Preflight, so a hidden `.btn` or `.card` stayed on the
11
+ page. Preflight's own rule, in the same layer, so the three entries agree. */
12
+ @layer base {
13
+ [hidden]:where(:not([hidden="until-found"])) {
14
+ display: none !important;
15
+ }
16
+ }
17
+
18
+ /* `box` and `surface` once each, then every component's rules: the focused
19
+ entries beside this file each bring their own reference to `box.css`, and
20
+ importing five of them stacked five copies of every `@apply box`. */
21
+ @import "../box.css";
22
+ @import "../surface.rules.css";
23
+ @import "./button.rules.css";
24
+ @import "./feedback.rules.css";
25
+ @import "./form.rules.css";
26
+ @import "./surface.rules.css";
27
+ @import "./tooltip.rules.css";
28
+
29
+ /* The composition utilities -- `box`, `box-hover`, `box-active`,
30
+ `text-control`, `surface`, `input-group` -- are `@utility` rules whose bodies
31
+ the content scan will not emit on its own. `box` and friends appear only as
32
+ `@utility` blocks and `@apply` targets; `text-control`, `surface` and
33
+ `input-group` appear only inside `:is()`/`:where()` argument lists in
34
+ `intent.css` and `form.css`, never as a selector of their own. Safelisting
35
+ all six makes the emission deliberate; the composition-body check in
36
+ `exports.test.ts` fails the build if one is dropped. `text-control` and
37
+ `surface` are also documented as consumer-usable on their own.
38
+
39
+ The list is for the compiled build only. `scripts/build-tw.mjs` strips it
40
+ from the `tw/` copy, so a `/tw` consumer's Tailwind emits just the classes
41
+ it finds in their files rather than every one named here. */
@@ -0,0 +1,11 @@
1
+ @reference "tailwindcss";
2
+ @import "../theme.css";
3
+ @import "../surface.css";
4
+
5
+ /* The focused entry: what the rules in `surface.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 "./surface.rules.css";
@@ -0,0 +1,222 @@
1
+ /* A ghost, edged container that takes one unit when depth is supplied. */
2
+ @utility card {
3
+ @layer families {
4
+ :where(&:not(.p-xs)) {
5
+ --_m-p-xs: initial;
6
+ }
7
+
8
+ :where(&:not(.p-sm)) {
9
+ --_m-p-sm: initial;
10
+ }
11
+
12
+ :where(&:not(.p-lg)) {
13
+ --_m-p-lg: initial;
14
+ }
15
+
16
+ :where(&:not(.flush)) {
17
+ --_m-flush: initial;
18
+ }
19
+ }
20
+
21
+ /* The hover flag, raised by `interactive` and `hoverable` below. */
22
+ @layer families {
23
+ :where(&:not(.interactive, .hoverable)) {
24
+ --_m-hover: initial;
25
+ }
26
+ }
27
+
28
+ @apply surface;
29
+
30
+ /* After the `@apply`, not before: `surface` inlines its own resting geometry
31
+ at that point, so defaults written above it would be overridden by the very
32
+ utility they are meant to specialise. */
33
+ --_d-fill: 0%;
34
+ --_d-fg-on-fill: 0%;
35
+ --_d-border: 100%;
36
+ --_d-elevation: 1;
37
+
38
+ /* The padding steps and `flush`. Each raises a flag (`modifiers.css`) and
39
+ the lines below compute only while theirs is up, so `@apply card p-xs`
40
+ carries the step. `--_scale-pad` is the step `box` scales the corner
41
+ and the depth by; `flush` leaves it alone. */
42
+ --_xs-pad: var(--_m-p-xs) 0.5rem;
43
+ --_sm-pad: var(--_m-p-sm) 0.75rem;
44
+ --_lg-pad: var(--_m-p-lg) 2rem;
45
+ --_flush-pad: var(--_m-flush) 0px;
46
+ --_xs-scale: var(--_m-p-xs) 0.5;
47
+ --_sm-scale: var(--_m-p-sm) 0.75;
48
+ --_lg-scale: var(--_m-p-lg) 1.25;
49
+ --_scale-pad: var(--_lg-scale, var(--_sm-scale, var(--_xs-scale)));
50
+
51
+ padding: var(--_flush-pad, var(--_lg-pad, var(--_sm-pad, var(--_xs-pad, 1.25rem))));
52
+
53
+ /* A quiet neutral tint -- `.soft`, on the card or on a container -- rests
54
+ untinted instead of mixing its 12%: 12% of `--color-text` onto any of
55
+ `--color-background`, `--color-foreground`, or `--color-surface` lands
56
+ within a few units of the others (a near-black ink dominates the result),
57
+ so swapping the ground token alone does not read as quieter. A resting
58
+ neutral `.card.soft` is `--color-foreground` with no ink mixed in -- a
59
+ plain step up from the page that marks a different container without
60
+ drawing attention to it.
61
+
62
+ A named intent keeps its ordinary 12% wash: 12% of an actual hue does not
63
+ read as a slab the way 12% of near-black ink does (`.card.soft.destructive`
64
+ is a gentle `249, 225, 225`), and untinting it would silence it rather than
65
+ quiet it. `.ghost` and `.solid` are not a tint and keep their own plates.
66
+
67
+ Which case applies is `surface`'s `--_quiet`, stepped from the resolved
68
+ fill and the intent's cap rather than keyed on classes on the card, so a
69
+ container's `.soft` renders the plate the card's own `.soft` does. Keyed
70
+ on the card's classes, `.soft > .card` drew the grey slab. `--_fill-cap`
71
+ (box.css's override slot, not `--ui-fill` directly -- see the comment
72
+ there) drops to 0% only when quiet, and the ground steps to the
73
+ foreground only then, through `--_d-surface-ground`, the default
74
+ `surface` reads beneath the public `--ui-surface-ground`, so a consumer's
75
+ override, or glass's ground, wins.
76
+
77
+ Composed with `box-hover`'s formula (`min(100%, resting + 14%)`), the
78
+ quiet rest reveals the intent on hover with no second fill declaration:
79
+ resting at 0% means hover lands at exactly the hover step, 14%, in
80
+ `--intent-hover`, and the ground steps to `--color-surface` at the same
81
+ moment. Scoped to `.interactive` and `.hoverable`, the two classes that
82
+ opt a card into `box-hover`. A named intent rests tinted, so the generic
83
+ formula deepens it on hover (12% to 26%). */
84
+ --_fill-cap: calc(100% - var(--_quiet));
85
+ --_d-surface-ground: color-mix(in oklab, var(--color-foreground) var(--_quiet), var(--color-background));
86
+
87
+ --_hover-ground: var(--_m-hover) color-mix(in oklab, var(--color-surface) var(--_quiet), var(--color-background));
88
+
89
+ &:hover {
90
+ --_d-surface-ground: var(
91
+ --_hover-ground,
92
+ color-mix(in oklab, var(--color-foreground) var(--_quiet), var(--color-background))
93
+ );
94
+ }
95
+
96
+ /* Opt-in, because a card is only sometimes a control. Applications still owe
97
+ it a real interactive element and an accessible name. Hover and press are
98
+ the derived ones every other pressable box gets; there is nothing
99
+ card-specific about either.
100
+
101
+ `.interactive` is the whole opt-in and stays that way; `.hoverable` and
102
+ `.pressable` are its halves, for a card that answers one gesture and not
103
+ the other. A card with its own nested controls takes `.hoverable` for the
104
+ hover warmth without the press-scale that reads as "you activated the
105
+ card" when the click really landed on a nested button. `.hoverable` alone
106
+ does not set the pointer cursor: that travels with being a click target,
107
+ i.e. with `.pressable` / `.interactive`. */
108
+ }
109
+
110
+ /* The opt-in itself: utilities, so `@apply card interactive` carries the
111
+ gestures. Each is `box-hover` or `box-active` under the name a card's
112
+ markup uses, and the hover half raises the flag the card's quiet ground
113
+ reads. The pointer is 0-1-0 here, below `box`'s disabled cursor, so a
114
+ disabled interactive card does not invite the click. */
115
+ @utility hoverable {
116
+ @layer families {
117
+ --_m-hover: ;
118
+ }
119
+
120
+ @apply box-hover;
121
+ }
122
+
123
+ @utility pressable {
124
+ @apply box-active cursor-pointer;
125
+ }
126
+
127
+ @utility interactive {
128
+ @layer families {
129
+ --_m-hover: ;
130
+ }
131
+
132
+ @apply box-hover box-active cursor-pointer;
133
+ }
134
+
135
+ /* A panel is the flush, unelevated sibling: sidebars, toolbars, and wells that
136
+ sit flat against the layout rather than floating above it. Soft and edgeless
137
+ is what makes it read as a well without drawing a line to say so. */
138
+ @utility panel {
139
+ @layer families {
140
+ :where(&:not(.p-xs)) {
141
+ --_m-p-xs: initial;
142
+ }
143
+
144
+ :where(&:not(.p-sm)) {
145
+ --_m-p-sm: initial;
146
+ }
147
+
148
+ :where(&:not(.p-lg)) {
149
+ --_m-p-lg: initial;
150
+ }
151
+
152
+ :where(&:not(.flush)) {
153
+ --_m-flush: initial;
154
+ }
155
+ }
156
+
157
+ @apply surface;
158
+
159
+ --_d-fill: 12%;
160
+ --_d-fg-on-fill: 0%;
161
+ --_d-border: 0%;
162
+ --_d-elevation: 0;
163
+
164
+ /* The padding steps and `flush`. Each raises a flag (`modifiers.css`) and
165
+ the lines below compute only while theirs is up, so `@apply card p-xs`
166
+ carries the step. `--_scale-pad` is the step `box` scales the corner
167
+ and the depth by; `flush` leaves it alone. */
168
+ --_xs-pad: var(--_m-p-xs) 0.25rem;
169
+ --_sm-pad: var(--_m-p-sm) 0.5rem;
170
+ --_lg-pad: var(--_m-p-lg) 1.5rem;
171
+ --_flush-pad: var(--_m-flush) 0px;
172
+ --_xs-scale: var(--_m-p-xs) 0.5;
173
+ --_sm-scale: var(--_m-p-sm) 0.75;
174
+ --_lg-scale: var(--_m-p-lg) 1.25;
175
+ --_scale-pad: var(--_lg-scale, var(--_sm-scale, var(--_xs-scale)));
176
+
177
+ padding: var(--_flush-pad, var(--_lg-pad, var(--_sm-pad, var(--_xs-pad, 1rem))));
178
+
179
+ /* Neutral panels are the common case -- layout wells, sidebars, toolbars with
180
+ no named intent -- and 12% of `--color-text` (near-black) mixed onto the
181
+ page is far more assertive than 12% of a hue (`217, 217, 217` against a
182
+ `250, 250, 250` page): the same "neutral ink reads louder" effect
183
+ `.card.soft` answers, and the reason `--intent-fill-max` stops neutral's
184
+ fill short everywhere else. So a quiet neutral tint rests untinted on
185
+ `--color-foreground`, through `--_d-surface-ground`, the default
186
+ `.card.soft` rests on, so a bare `.panel` rests at exactly the plate a
187
+ `.card.soft` does, and a consumer's `--ui-surface-ground` or glass's
188
+ translucent ground wins over it: a neutral panel under `.glass` is glass.
189
+
190
+ A named intent keeps its wash: a panel is edgeless by default, so the fill
191
+ is the only channel a `.primary` bulk-actions bar or a `.destructive`
192
+ danger-zone panel has to say what it is (a resting `.panel.destructive` is
193
+ a gentle `249, 225, 225` wash). `.ghost` and `.solid` keep their own
194
+ plates. Which case applies is `surface`'s `--_quiet`, stepped from the
195
+ resolved fill, so a container's `.ghost` or `.solid` renders the panel its
196
+ own would; keyed on the panel's classes, both landed on the quiet plate.
197
+ Permanent rather than hover-revealed: a panel has no interaction state to
198
+ reveal a tint into. */
199
+ --_fill-cap: calc(100% - var(--_quiet));
200
+ --_d-surface-ground: color-mix(in oklab, var(--color-foreground) var(--_quiet), var(--color-background));
201
+ }
202
+
203
+ /* A closed `<dialog>` is hidden, and an open one centred, by `surface` itself,
204
+ so every element that applies it -- these three, `.alert`, a consumer's
205
+ `@apply surface` -- gets both (see `surface.css`). That hide is in the
206
+ layer the surface is applied in. For the three containers a consumer
207
+ reaches for as a dialog, it is restated here unlayered: hiding a closed
208
+ dialog is behaviour, so it beats any layered rule whatever its specificity.
209
+ The centring stays a default in `utilities` at zero specificity, so a
210
+ consumer's own margin -- a utility, or unlayered CSS -- still places one.
211
+
212
+ Here rather than in the reset, so every entrypoint that ships `.card` ships
213
+ the fix, `/components` included. */
214
+ dialog:is(.card, .panel, .surface):not([open]) {
215
+ display: none;
216
+ }
217
+
218
+ /* The popover counterpart, unlayered for the same reason. `.alert` joins the
219
+ list: a toast is the surface most often given `popover`. */
220
+ :is(.card, .panel, .surface, .alert)[popover]:not(:popover-open) {
221
+ display: none;
222
+ }
@@ -0,0 +1,11 @@
1
+ @reference "tailwindcss";
2
+ @import "../theme.css";
3
+ @reference "../surface.css";
4
+
5
+ /* The focused entry: what the rules in `tooltip.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 "./tooltip.rules.css";
@@ -1,8 +1,3 @@
1
- @reference "tailwindcss";
2
- @import "../theme.css";
3
- @reference "../box.css";
4
- @reference "../surface.css";
5
-
6
1
  /* The host is a positioning wrapper and nothing else -- it paints no fill, no
7
2
  edge, no material of its own. The bubble is a real element beside the trigger
8
3
  rather than a pseudo-element, so intent, presentation, aesthetic, and
@@ -86,6 +81,10 @@
86
81
  --_d-elevation: 0;
87
82
  --_d-ground: var(--ui-surface-ground, var(--intent-subtle));
88
83
 
84
+ /* `surface` refuses the silhouette clip because it holds other things. The
85
+ bubble holds a line of text, so it takes the aesthetic's shape back. */
86
+ clip-path: var(--ui-clip, none);
87
+
89
88
  /* The bubble's line is a boundary against content nobody chose, so `box`'s
90
89
  edge blend is wrong here: at a full fill the line *is* the plate. Restate
91
90
  the colour only; how much line comes from `--_edge-amount`, floored below. */
@@ -93,9 +92,9 @@
93
92
 
94
93
  /* Floored, for the same reason the ground is opaque: a cascade must not take
95
94
  the boundary from a bubble nobody classed (worst in light, where the plate
96
- is near-white). The element's own `.edgeless` lowers it -- same
97
- element-vs-cascade idiom `text-control` uses. */
98
- --_edge-floor: 100%;
95
+ is near-white). The element's own `.edgeless` lowers it -- the same
96
+ `--_own-edge` `text-control` reads. */
97
+ --_edge-floor: var(--_own-edge);
99
98
 
100
99
  /* A bubble is a small transient popover, not a modal, so it takes the
101
100
  control corner `box` computes rather than the surface one `surface` hands
@@ -112,30 +111,43 @@
112
111
  transform: var(--tooltip-transform) scale(0);
113
112
  transform-origin: var(--tooltip-origin);
114
113
 
115
- &.edgeless {
116
- --_edge-floor: 0%;
117
- }
118
-
119
114
  /* The bubble appears without growing under reduced motion, for the entries
120
115
  without the reset; see `box.css`. */
121
116
  @media (prefers-reduced-motion: reduce) {
122
117
  transition-duration: 0.01ms;
123
118
  }
124
- }
125
119
 
126
- /* Shown on hover or focus anywhere in the host, or pinned open with
127
- `data-state="open"`. `:focus-within` rather than the trigger's own
128
- `:focus-visible`, the same substitution `.input-group` makes: the bubble is a
129
- sibling of the trigger, so only the shared ancestor can see both at once. The
130
- cost is the one `.input-group` accepts -- the bubble also shows on a mouse
131
- click.
132
-
133
- In `utilities`, where the bubble's own `@utility` is, winning on specificity
134
- -- see the seams note in `form.css`. */
135
- @layer utilities {
136
- .tooltip:hover .tooltip-bubble,
137
- .tooltip:focus-within .tooltip-bubble,
138
- .tooltip[data-state="open"] .tooltip-bubble {
120
+ /* The no-intent plate, carried so `@apply tooltip-bubble` gets it: the rule
121
+ in `intent.css` names `.tooltip-bubble`, which a consumer's `.my-tip` is
122
+ not, so an applied bubble took `surface`'s neutral reset and drew the
123
+ page's ink at a fifth. In `families` after that reset, which `surface`
124
+ carries at the same zero specificity, so this one wins and an intent
125
+ applied with it still beats both. Never on `.tooltip-bubble` itself,
126
+ which keeps the rule in `components`. */
127
+ @layer families {
128
+ :where(&:not(.tooltip-bubble, .primary, .secondary, .success, .warning, .destructive, .info)) {
129
+ --intent-color: var(--color-tooltip);
130
+ --intent-contrast: var(--color-tooltip-contrast);
131
+ --intent-hover: var(--color-tooltip);
132
+ --intent-strong: var(--color-tooltip-contrast);
133
+ --intent-subtle: var(--color-surface);
134
+ --intent-border: var(--ui-ink, var(--color-border));
135
+ --intent-fill-max: 100%;
136
+ }
137
+ }
138
+
139
+ /* Shown on hover or focus anywhere in the host, or pinned open with
140
+ `data-state="open"`. `:focus-within` rather than the trigger's own
141
+ `:focus-visible`, the same substitution `.input-group` makes: the bubble
142
+ is a sibling of the trigger, so only the shared ancestor can see both at
143
+ once. The cost is the one `.input-group` accepts -- the bubble also shows
144
+ on a mouse click.
145
+
146
+ In the body, so an applied bubble opens in a `.tooltip` as the class
147
+ does; they win over the resting values above on specificity. */
148
+ .tooltip:hover &,
149
+ .tooltip:focus-within &,
150
+ .tooltip[data-state="open"] & {
139
151
  opacity: 1;
140
152
  transform: var(--tooltip-transform) scale(1);
141
153
  visibility: visible;
@@ -147,7 +159,7 @@
147
159
  writes `data-state="closed"` and clears it when the pointer and focus
148
160
  leave. Later and as specific as the rule above, so it wins over hover and
149
161
  focus alike. */
150
- .tooltip[data-state="closed"] .tooltip-bubble {
162
+ .tooltip[data-state="closed"] & {
151
163
  opacity: 0;
152
164
  transform: var(--tooltip-transform) scale(0);
153
165
  visibility: hidden;
@@ -176,6 +188,10 @@
176
188
  --_d-elevation: 0;
177
189
  --_d-ground: var(--intent-subtle);
178
190
 
191
+ /* A ground of its own, so no ink from above passes through, as on `surface`. */
192
+ --_held-ink: var(--_fg-own);
193
+ --_held-on: var(--_own-hold);
194
+
179
195
  /* The trigger is best a real `<button>`, which is a `.btn` under `/native`
180
196
  and carries the user agent's padding under `/components`; either would
181
197
  stretch the chip past its own size. */
@@ -1,5 +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
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
3
5
  docs/internal/model.md#cascade-layers.
4
6
 
5
7
  The corner pattern: which corners take the corner the aesthetic draws. `box`
@@ -10,17 +12,21 @@
10
12
  is taken as written and ignores the pattern. See docs/internal/model.md#material-tokens. */
11
13
 
12
14
  /* 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;
15
+ @utility cut-diagonal {
16
+ @layer families {
17
+ --ui-corner-tl: 1;
18
+ --ui-corner-tr: 0;
19
+ --ui-corner-br: 1;
20
+ --ui-corner-bl: 0;
21
+ }
18
22
  }
19
23
 
20
24
  /* 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;
25
+ @utility cut-diagonal-reverse {
26
+ @layer families {
27
+ --ui-corner-tl: 0;
28
+ --ui-corner-tr: 1;
29
+ --ui-corner-br: 0;
30
+ --ui-corner-bl: 1;
31
+ }
26
32
  }
@@ -1,5 +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
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
3
5
  docs/internal/model.md#cascade-layers. */
4
6
 
5
7
  /* Elevation is a modifier, not an axis: depth is a per-element decision (raised
@@ -47,27 +49,31 @@
47
49
 
48
50
  /* No part-based depth. Complete surface shadow values, such as glass, are not
49
51
  reached by the elevation multiplier. */
50
- .flat {
51
- --ui-elevation: 0;
52
+ @utility flat {
53
+ @layer families {
54
+ --ui-elevation: 0;
55
+ }
52
56
  }
53
57
 
54
- /* The plain-step geometry both rungs multiply, declared once so the two cannot
55
- drift. It is the fallback for a page with no aesthetic in scope; an aesthetic
58
+ /* The plain-step geometry both rungs multiply. Each utility restates it so
59
+ `@apply raised` carries it, so the two copies must stay identical. It is the fallback for a page with no aesthetic in scope; an aesthetic
56
60
  that declares its own shadow parts overrides it, and the elevation multiplier
57
61
  scales whichever one lands. `.floating` takes its extra depth from the
58
- multiplier below, not a second copy of these parts. */
59
- .raised,
60
- .floating {
61
- --elevation-y: 1px;
62
- --elevation-blur: 3px;
63
- }
64
-
62
+ multiplier, not from different parts. */
65
63
  /* The aesthetic's depth as authored, said explicitly. */
66
- .raised {
67
- --ui-elevation: 1;
64
+ @utility raised {
65
+ @layer families {
66
+ --elevation-y: 1px;
67
+ --elevation-blur: 3px;
68
+ --ui-elevation: 1;
69
+ }
68
70
  }
69
71
 
70
72
  /* Twice it, for menus and popovers. */
71
- .floating {
72
- --ui-elevation: 2;
73
+ @utility floating {
74
+ @layer families {
75
+ --elevation-y: 1px;
76
+ --elevation-blur: 3px;
77
+ --ui-elevation: 2;
78
+ }
73
79
  }
@@ -1,7 +1,7 @@
1
1
  @import "tailwindcss";
2
2
 
3
- /* The build has no markup to scan, so Tailwind's automatic content detection
4
- sees only this package's own files. The `src/` scan is load-bearing: it is
3
+ /* The compiled build has no markup to scan, so Tailwind's automatic content
4
+ detection sees only this package's own files. The `src/` scan is load-bearing: it is
5
5
  how the composition utilities (`box`, `surface`, `text-control`,
6
6
  `input-group`) are emitted as standalone rules, so
7
7
  `source(none)` is not an option. Tailwind utility names that collide with a
@@ -9,18 +9,20 @@
9
9
  `transition`, `transform`, `container`) do not emit, verified against
10
10
  Tailwind 4.3.2; `tests/integration/exports.test.ts` guards it.
11
11
 
12
- The `@source not` lines keep everything that is not `src/` out of the scan:
12
+ The `@source not` lines keep the build command's TypeScript in `src/cli/`, whose
13
+ prose once shipped as `.relative`, and everything that is not `src/` out of the scan:
13
14
  the sibling app and fixture directories, the `docs/` tree, the build scripts,
14
15
  and the root prose, data, config, and license files. Without them a class
15
16
  name or `--color-*` reference that appears only in a documentation example
16
17
  ships as real CSS -- the license's "contents" once shipped as
17
18
  `.contents{display:contents}`.
18
19
  `exports.test.ts` guards it. `scripts/build-tw.mjs` strips these lines from
19
- the `dist/tw/` copy, where they resolve to nothing and the `/tw` consumer
20
- scans their own tree. */
20
+ the `tw/` copy, where they have no job: the `/tw` consumer scans their own
21
+ tree. */
21
22
 
22
23
  @import "./theme.css";
23
- @import "./typography.css";
24
- @import "./utilities/index.css";
25
- @import "./components/index.css";
26
- @import "./reset.css";
24
+ /* No `typography.css` here: `components/rules.css` brings its rules, and a
25
+ second route to a `@utility` stacks its body. */
26
+ @import "./utilities/rules.css";
27
+ @import "./components/rules.css";
28
+ @import "./reset.rules.css";
package/tw/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ export {};