@codenhub/styles 0.1.0 → 0.2.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.
- package/README.md +8 -69
- package/dist/aesthetics/chunky-tile.css +1 -1
- package/dist/aesthetics/index.css +1 -1
- package/dist/components.css +1 -1
- package/dist/index.css +1 -1
- package/dist/native.css +1 -1
- package/dist/theme.css +1 -1
- package/dist/tw/aesthetics/chunky-tile.css +20 -2
- package/dist/tw/box.css +45 -2
- package/dist/tw/components/button.css +38 -29
- package/dist/tw/components/feedback.css +58 -41
- package/dist/tw/components/form.css +139 -47
- package/dist/tw/components/index.css +16 -6
- package/dist/tw/components/loader.css +2 -16
- package/dist/tw/components/surface.css +122 -5
- package/dist/tw/components/tooltip.css +102 -91
- package/dist/tw/elevation.css +57 -14
- package/dist/tw/index.css +23 -5
- package/dist/tw/intent.css +36 -12
- package/dist/tw/native.css +4 -20
- package/dist/tw/reset.css +40 -32
- package/dist/tw/theme.css +46 -8
- package/dist/tw/utilities/content.css +104 -18
- package/dist/tw/utilities/index.css +1 -1
- package/dist/tw/utilities/layout.css +33 -0
- package/docs/accessibility.md +68 -48
- package/docs/changelog/0.1.0.md +37 -0
- package/docs/changelog/0.1.1.md +10 -0
- package/docs/changelog/0.2.0.md +41 -0
- package/docs/changelog/index.md +11 -0
- package/docs/concepts.md +21 -46
- package/docs/index.md +18 -45
- package/docs/integrating/astro.md +13 -7
- package/docs/integrating/index.md +25 -16
- package/docs/integrating/nextjs.md +31 -8
- package/docs/integrating/svelte.md +14 -8
- package/docs/integrating/tailwind.md +31 -15
- package/docs/integrating/vue.md +13 -7
- package/docs/setup.md +31 -32
- package/docs/usage/aesthetics.md +31 -107
- package/docs/usage/buttons.md +24 -36
- package/docs/usage/composing.md +31 -102
- package/docs/usage/content-and-layout.md +65 -83
- package/docs/usage/customizing.md +25 -90
- package/docs/usage/feedback.md +25 -56
- package/docs/usage/forms.md +48 -80
- package/docs/usage/index.md +9 -17
- package/docs/usage/theming.md +25 -81
- package/docs/usage/tooltips.md +55 -35
- package/llms-full.txt +1193 -1510
- package/package.json +121 -44
|
@@ -3,16 +3,20 @@
|
|
|
3
3
|
@reference "../box.css";
|
|
4
4
|
@reference "./surface.css";
|
|
5
5
|
|
|
6
|
-
/* The host is a positioning wrapper and nothing else
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
6
|
+
/* The host is a positioning wrapper and nothing else -- it paints no fill, no
|
|
7
|
+
edge, no material of its own. The bubble is a real element beside the
|
|
8
|
+
trigger rather than a pseudo-element attached to it, so intent,
|
|
9
|
+
presentation, aesthetic, and elevation classes go on `.tooltip-bubble`, the
|
|
10
|
+
thing actually shown, not on the wrapper -- the same rule every other
|
|
11
|
+
component in this package follows (theming.md: "Intent does not cascade").
|
|
12
|
+
|
|
13
|
+
Composing the bubble as a real element fixes a real gap, not just a styling
|
|
14
|
+
one: `content: attr(data-tooltip)` text is not reliably exposed to
|
|
15
|
+
assistive tech and cannot be the target of an `aria-describedby`, since that
|
|
16
|
+
needs a real element with a real `id`. A real bubble can carry
|
|
17
|
+
`role="tooltip"` and be referenced by the trigger's own `aria-describedby`;
|
|
18
|
+
wiring that association is the consumer's, this package only styles the
|
|
19
|
+
bubble. See docs/usage/tooltips.md. */
|
|
16
20
|
@utility tooltip {
|
|
17
21
|
--tooltip-gap: 0.5rem;
|
|
18
22
|
--tooltip-top: calc(var(--tooltip-gap) * -1);
|
|
@@ -22,34 +26,7 @@
|
|
|
22
26
|
--tooltip-origin: bottom;
|
|
23
27
|
--tooltip-transform: translate(-50%, -100%);
|
|
24
28
|
|
|
25
|
-
@apply relative;
|
|
26
|
-
|
|
27
|
-
/* The trigger badge, for a page with no element to hang the message on. Quiet
|
|
28
|
-
-- ghost, edged, on `--intent-subtle`, a key cap's resting shape -- because
|
|
29
|
-
it marks that there is a message, it is not one. The line earns its keep:
|
|
30
|
-
`--intent-subtle` is a near-page tint that reads the same across families,
|
|
31
|
-
so a plate alone left three of eight intents indistinguishable;
|
|
32
|
-
`--intent-border` is the slot that differs. Painting the host is right only
|
|
33
|
-
here -- everywhere else the bubble is outside the host's box, so painting it
|
|
34
|
-
boxes the trigger. `.tooltip-icon` is the opt-in that says the host *is* the
|
|
35
|
-
badge. */
|
|
36
|
-
&.tooltip-icon {
|
|
37
|
-
@apply box inline-flex size-5 cursor-default items-center justify-center text-sm font-bold;
|
|
38
|
-
|
|
39
|
-
--_d-fill: 0%;
|
|
40
|
-
--_d-fg-on-fill: 0%;
|
|
41
|
-
--_d-border: 100%;
|
|
42
|
-
--_d-elevation: 0;
|
|
43
|
-
--_d-ground: var(--intent-subtle);
|
|
44
|
-
|
|
45
|
-
border-radius: var(--ui-radius, calc(infinity * 1px));
|
|
46
|
-
/* The one thing `box` hands it that it must refuse. An aesthetic's `clip-path`
|
|
47
|
-
clips a host's pseudo-elements along with the host, and this host's
|
|
48
|
-
pseudo-element is the bubble, positioned outside its box -- so a stepped
|
|
49
|
-
badge under `.pixel` would clip the message away entirely. The bubble
|
|
50
|
-
carries the stepped shape itself; the badge stays round. */
|
|
51
|
-
clip-path: none;
|
|
52
|
-
}
|
|
29
|
+
@apply relative inline-block;
|
|
53
30
|
|
|
54
31
|
&[data-tooltip-position="bottom"] {
|
|
55
32
|
--tooltip-top: auto;
|
|
@@ -72,61 +49,95 @@
|
|
|
72
49
|
--tooltip-origin: left;
|
|
73
50
|
--tooltip-transform: translate(100%, -50%);
|
|
74
51
|
}
|
|
52
|
+
}
|
|
75
53
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
&.edgeless
|
|
54
|
+
/* The bubble. It is a surface, so an aesthetic that blurs surfaces blurs it
|
|
55
|
+
too, and it rests on a ground of its own, edged, and flat -- depth is
|
|
56
|
+
opt-in through its own `.raised`/`.floating`, like any other component, now
|
|
57
|
+
that it is one. No proxy inheritance is needed to carry elevation across a
|
|
58
|
+
host-to-pseudo-element gap: there is no gap, `.tooltip-bubble.raised` reads
|
|
59
|
+
`--ui-elevation` the ordinary way every other component does. See
|
|
60
|
+
model.md#elevation. */
|
|
61
|
+
@utility tooltip-bubble {
|
|
62
|
+
@apply surface pointer-events-none absolute z-(--z-popover) w-max max-w-72 px-2.5 py-2 text-sm font-normal whitespace-normal opacity-0 transition-[opacity,transform] duration-(--motion-duration-normal) ease-(--motion-ease);
|
|
63
|
+
|
|
64
|
+
/* Filled, over a ground of its own. An intent floods the fill
|
|
65
|
+
(`.tooltip-bubble.primary` is the primary colour); with no intent
|
|
66
|
+
`intent.css` resolves the bubble onto `--color-tooltip` and lifts the
|
|
67
|
+
neutral cap, a plate stated per theme because the derived version was a
|
|
68
|
+
mid-grey slab in light and lifted in dark. The ground stays the surface
|
|
69
|
+
tone, not the plate -- pointed at both, the fill axis went inert and
|
|
70
|
+
`axes.spec.ts` caught it. An opaque ground is also what keeps a cascaded
|
|
71
|
+
`.ghost` from leaving the bubble boundaryless. `--ui-surface-ground` is
|
|
72
|
+
read first so a glass tooltip stays glass. */
|
|
73
|
+
--_d-fill: 100%;
|
|
74
|
+
--_d-fg-on-fill: 100%;
|
|
75
|
+
--_d-border: 100%;
|
|
76
|
+
--_d-elevation: 0;
|
|
77
|
+
--_d-ground: var(--ui-surface-ground, var(--intent-subtle));
|
|
78
|
+
|
|
79
|
+
/* The bubble's line is a boundary against content nobody chose, so `box`'s
|
|
80
|
+
edge blend is wrong here: at a full fill the line *is* the plate. Restate
|
|
81
|
+
the colour only; how much line comes from `--_edge-amount`, floored below. */
|
|
82
|
+
--_line: var(--intent-border);
|
|
83
|
+
|
|
84
|
+
/* Floored, for the same reason the ground is opaque: a cascade must not take
|
|
85
|
+
the boundary from a bubble nobody classed (worst in light, where the plate
|
|
86
|
+
is near-white). The element's own `.edgeless` lowers it -- same
|
|
87
|
+
element-vs-cascade idiom `text-control` uses. */
|
|
88
|
+
--_edge-floor: 100%;
|
|
89
|
+
|
|
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));
|
|
93
|
+
left: var(--tooltip-left);
|
|
94
|
+
right: var(--tooltip-right);
|
|
95
|
+
top: var(--tooltip-top);
|
|
96
|
+
bottom: var(--tooltip-bottom);
|
|
97
|
+
transform: var(--tooltip-transform) scale(0);
|
|
98
|
+
transform-origin: var(--tooltip-origin);
|
|
99
|
+
|
|
100
|
+
&.edgeless {
|
|
123
101
|
--_edge-floor: 0%;
|
|
124
102
|
}
|
|
103
|
+
}
|
|
125
104
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
105
|
+
/* Shown on hover or focus anywhere in the host, or pinned open with
|
|
106
|
+
`data-state="open"`. `:focus-within` rather than the trigger's own
|
|
107
|
+
`:focus-visible`, the same substitution `.input-group` makes for the
|
|
108
|
+
identical reason: the bubble is a sibling, not a pseudo-element, of the
|
|
109
|
+
trigger, so nothing but the shared ancestor can see both at once. The cost
|
|
110
|
+
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);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/* The trigger badge, for a message with no other element to hang it on. Quiet
|
|
120
|
+
-- ghost, edged, on `--intent-subtle`, a key cap's resting shape -- because
|
|
121
|
+
it marks that there is a message, it is not one. The line earns its keep:
|
|
122
|
+
`--intent-subtle` is a near-page tint that reads the same across families,
|
|
123
|
+
so a plate alone left three of eight intents indistinguishable;
|
|
124
|
+
`--intent-border` is the slot that differs.
|
|
125
|
+
|
|
126
|
+
`clip-path: none` used to exist to protect the bubble, a pseudo-element of
|
|
127
|
+
this same host, from being clipped away along with it under an aesthetic
|
|
128
|
+
like `.pixel`. The bubble is independent now, so that reason is gone, but
|
|
129
|
+
the declaration stays: the docs call this a circular fixed identity, not a
|
|
130
|
+
shape a container's aesthetic reaches, the same way `.radio` keeps its own
|
|
131
|
+
circle instead of taking `.pixel`'s stepped silhouette. */
|
|
132
|
+
@utility tooltip-icon {
|
|
133
|
+
@apply box inline-flex size-5 cursor-default items-center justify-center text-sm font-bold;
|
|
134
|
+
|
|
135
|
+
--_d-fill: 0%;
|
|
136
|
+
--_d-fg-on-fill: 0%;
|
|
137
|
+
--_d-border: 100%;
|
|
138
|
+
--_d-elevation: 0;
|
|
139
|
+
--_d-ground: var(--intent-subtle);
|
|
140
|
+
|
|
141
|
+
border-radius: var(--ui-radius, calc(infinity * 1px));
|
|
142
|
+
clip-path: none;
|
|
132
143
|
}
|
package/dist/tw/elevation.css
CHANGED
|
@@ -1,18 +1,54 @@
|
|
|
1
1
|
/* Elevation is a modifier, not an axis: depth is a per-element decision (raised
|
|
2
2
|
tiles beside a flat panel in one aesthetic), so one unitless number multiplies
|
|
3
|
-
the aesthetic's shadow geometry where the component composes it.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
the aesthetic's shadow geometry where the component composes it. `.flat`
|
|
4
|
+
removes a part-based slab or blur without a conditional (complete surface
|
|
5
|
+
shadows like glass remain). See model.md#elevation.
|
|
6
|
+
|
|
7
|
+
`--ui-elevation`, and the plain-page fallback geometry (`--elevation-y`,
|
|
8
|
+
`--elevation-blur`) below, are registered non-inheriting: a class sets them
|
|
9
|
+
on the element it is written on and nothing else picks them up. They used to
|
|
10
|
+
be ordinary inherited custom properties, on the reasoning that a container
|
|
11
|
+
could flatten or lift a whole region in one class and any element inside
|
|
12
|
+
could opt back out -- but the same mechanism let a `.floating` dialog's
|
|
13
|
+
ambient ×2 reach its own unclassed "Cancel"/"Remove" buttons, doubling their
|
|
14
|
+
shadow with nothing in the markup asking for that. Depth is not the same
|
|
15
|
+
kind of thing as color or material: a button inside a raised card is not
|
|
16
|
+
itself more raised, it is just resting normally inside an already-raised
|
|
17
|
+
surface. `--ui-shadow-*` -- what an aesthetic supplies -- is unaffected and
|
|
18
|
+
still cascades normally; that is a different mechanism (the material tokens
|
|
19
|
+
in `src/aesthetics/*.css`), and an aesthetic still has to reach every nested
|
|
20
|
+
component uniformly the way it always did. Registering these three is what
|
|
21
|
+
scopes the change to the elevation modifier alone.
|
|
10
22
|
|
|
11
23
|
`.flat`/`.raised`/`.floating` and `.elevation-none`/`-sm`/`-md` are
|
|
12
24
|
interchangeable aliases, the second borrowing the raw `--elevation-*` scale's
|
|
13
25
|
naming. Bare `sm`/`md`/`lg` would collide with the size modifier;
|
|
14
26
|
`.elevation-lg` is reserved, not shipped. */
|
|
15
27
|
|
|
28
|
+
/* `syntax: "*"` with no `initial-value` is deliberate: a numeric syntax would
|
|
29
|
+
require one (CSS Properties and Values API), and any initial-value at all
|
|
30
|
+
would mean the property is never actually unset on an element that does not
|
|
31
|
+
write it -- which is exactly the state `var(--ui-elevation, var(--_d-elevation,
|
|
32
|
+
1))` in `box.css` needs to fall through to a component's own default. With
|
|
33
|
+
no initial-value and `inherits: false`, an element that does not set the
|
|
34
|
+
property directly computes it as guaranteed-invalid, the same as if it had
|
|
35
|
+
never been registered at all -- `var()` takes its fallback precisely where
|
|
36
|
+
inheritance used to hand it an ambient value instead. */
|
|
37
|
+
@property --ui-elevation {
|
|
38
|
+
syntax: "*";
|
|
39
|
+
inherits: false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@property --elevation-y {
|
|
43
|
+
syntax: "*";
|
|
44
|
+
inherits: false;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@property --elevation-blur {
|
|
48
|
+
syntax: "*";
|
|
49
|
+
inherits: false;
|
|
50
|
+
}
|
|
51
|
+
|
|
16
52
|
/* No part-based depth. Complete surface shadow values, such as glass, are not
|
|
17
53
|
reached by the elevation multiplier. */
|
|
18
54
|
.elevation-none,
|
|
@@ -20,20 +56,27 @@
|
|
|
20
56
|
--ui-elevation: 0;
|
|
21
57
|
}
|
|
22
58
|
|
|
23
|
-
/* The
|
|
24
|
-
fallback for a page with no aesthetic in scope; an aesthetic
|
|
25
|
-
own overrides it, and the elevation
|
|
59
|
+
/* The plain-step geometry both rungs multiply, declared once so the two cannot
|
|
60
|
+
drift. It is the fallback for a page with no aesthetic in scope; an aesthetic
|
|
61
|
+
that declares its own shadow parts overrides it, and the elevation multiplier
|
|
62
|
+
scales whichever one lands. `.floating` takes its extra depth from the
|
|
63
|
+
multiplier below, not a second copy of these parts. */
|
|
26
64
|
.elevation-sm,
|
|
27
|
-
.raised
|
|
28
|
-
|
|
65
|
+
.raised,
|
|
66
|
+
.elevation-md,
|
|
67
|
+
.floating {
|
|
29
68
|
--elevation-y: 1px;
|
|
30
69
|
--elevation-blur: 3px;
|
|
31
70
|
}
|
|
32
71
|
|
|
72
|
+
/* The aesthetic's depth as authored, said explicitly. */
|
|
73
|
+
.elevation-sm,
|
|
74
|
+
.raised {
|
|
75
|
+
--ui-elevation: 1;
|
|
76
|
+
}
|
|
77
|
+
|
|
33
78
|
/* Twice it, for menus and popovers. */
|
|
34
79
|
.elevation-md,
|
|
35
80
|
.floating {
|
|
36
81
|
--ui-elevation: 2;
|
|
37
|
-
--elevation-y: 1px;
|
|
38
|
-
--elevation-blur: 3px;
|
|
39
82
|
}
|
package/dist/tw/index.css
CHANGED
|
@@ -1,9 +1,27 @@
|
|
|
1
1
|
@import "tailwindcss";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
|
5
|
+
how the composition utilities (`box`, `surface`, `text-control`,
|
|
6
|
+
`input-group`, `loader-mask`) get emitted as standalone rules, since nothing
|
|
7
|
+
`@source inline`s them -- so `source(none)` is not an option. A handful of
|
|
8
|
+
Tailwind utility names also collide with a CSS property or a word this
|
|
9
|
+
file's own comments use (`backdrop-filter`, `filter`, `transition`,
|
|
10
|
+
`transform`, `container`), which reads like a risk of the same scan --
|
|
11
|
+
verified against Tailwind 4.3.2, none of them emit.
|
|
12
|
+
`tests/integration/exports.test.ts` guards it, so a scanner change that
|
|
13
|
+
starts emitting one is caught rather than shipping silently.
|
|
14
|
+
|
|
15
|
+
The `@source not` lines below keep everything that is not `src/` out of that
|
|
16
|
+
scan: the sibling app and fixture directories, the `docs/` tree, the build
|
|
17
|
+
scripts, and the root prose and data files (`README.md`, `llms*.txt`,
|
|
18
|
+
`registry*.json`, `package.json`). Without them a class name or `--color-*`
|
|
19
|
+
reference that appears only in a documentation example ships as real CSS --
|
|
20
|
+
the violet ramp in `docs/usage/theming.md`'s custom-intent example was
|
|
21
|
+
compiling into `dist/index.css` and `dist/native.css`, and any utility in a
|
|
22
|
+
docs code fence did the same. `tests/integration/exports.test.ts` guards it.
|
|
23
|
+
`scripts/build-tw.mjs` strips these lines from the `dist/tw/` copy, where they
|
|
24
|
+
resolve to nothing and the `/tw` consumer scans their own tree anyway. */
|
|
7
25
|
|
|
8
26
|
@import "./theme.css";
|
|
9
27
|
@import "./typography.css";
|
package/dist/tw/intent.css
CHANGED
|
@@ -8,6 +8,26 @@
|
|
|
8
8
|
tooltips, key caps, code and table heads sit on) and `--intent-border` to
|
|
9
9
|
`--ui-ink` (how an aesthetic restates the neutral line without naming one). */
|
|
10
10
|
|
|
11
|
+
/* The same neutral values, at the root. This is the floor: an element that
|
|
12
|
+
carries no intent class and matches none of the resets below -- a component
|
|
13
|
+
`@apply`-ed onto a selector the package does not name, a bare `<code>` with
|
|
14
|
+
no native stylesheet loaded -- still composes against a real colour instead
|
|
15
|
+
of an undefined one that collapses its `color-mix()` to nothing. It is not
|
|
16
|
+
the barrier. `.neutral` and both resets below still write these slots on the
|
|
17
|
+
element itself, which is a matching rule and so beats this inherited value --
|
|
18
|
+
that is what stops a `.success` container's intent reaching a component
|
|
19
|
+
nested under it. An intent class on the element beats both. Values track
|
|
20
|
+
`.neutral` slot for slot; `registry.test.ts` fails the build on drift. */
|
|
21
|
+
:root {
|
|
22
|
+
--intent-color: var(--color-text);
|
|
23
|
+
--intent-contrast: var(--color-text-contrast);
|
|
24
|
+
--intent-hover: var(--color-text-hover);
|
|
25
|
+
--intent-strong: var(--color-text-strong);
|
|
26
|
+
--intent-subtle: var(--color-surface);
|
|
27
|
+
--intent-border: var(--ui-ink, var(--color-border));
|
|
28
|
+
--intent-fill-max: 20%;
|
|
29
|
+
}
|
|
30
|
+
|
|
11
31
|
/* Neutral stops its fill short: its colour is the page's ink, so a full fill is
|
|
12
32
|
a slab and `.neutral.solid` was pixel-for-pixel `.primary.solid`. 20% is
|
|
13
33
|
chosen against `.soft`'s 12% -- a step past the tint, not a repeat.
|
|
@@ -113,7 +133,8 @@
|
|
|
113
133
|
.data-table,
|
|
114
134
|
.pre,
|
|
115
135
|
.quote,
|
|
116
|
-
.tooltip,
|
|
136
|
+
.tooltip-bubble,
|
|
137
|
+
.tooltip-icon,
|
|
117
138
|
.badge,
|
|
118
139
|
.kbd,
|
|
119
140
|
.code,
|
|
@@ -148,8 +169,8 @@
|
|
|
148
169
|
}
|
|
149
170
|
|
|
150
171
|
/* The bubble a tooltip draws is the one plate in the package that is chosen
|
|
151
|
-
rather than composed, so
|
|
152
|
-
|
|
172
|
+
rather than composed, so it resolves the no-intent case onto its own pair
|
|
173
|
+
instead of onto the shared neutral. Composed, it was 20% of the page's
|
|
153
174
|
ink over `--color-surface`, which lifts off a dark page and sinks into a light
|
|
154
175
|
one -- see `--color-tooltip` in `theme.css` for the measurements.
|
|
155
176
|
|
|
@@ -158,17 +179,20 @@
|
|
|
158
179
|
rather than an ink, so a full fill of it is the plate and there is nothing to
|
|
159
180
|
stop short of.
|
|
160
181
|
|
|
161
|
-
`--intent-subtle` stays the surface token
|
|
162
|
-
|
|
163
|
-
|
|
182
|
+
`--intent-subtle` stays the surface token, the same tone every other
|
|
183
|
+
unclassed component sits on. `.tooltip-icon`, the trigger badge, is a
|
|
184
|
+
separate element now and does not read this block at all -- it never fills
|
|
185
|
+
past `0%`, so the generic neutral reset above it is enough, and it keeps its
|
|
186
|
+
own resting ground and line independent of whatever intent the bubble shows.
|
|
164
187
|
|
|
165
188
|
Two selectors, because `none` and `neutral` have to agree here. `:where()`
|
|
166
|
-
loses to any intent class, so `.tooltip.primary` still floods with
|
|
167
|
-
`.tooltip.neutral` carries 0-2-0 and beats `.neutral`, so
|
|
168
|
-
out gives the same bubble as writing nothing. Without the
|
|
169
|
-
two would differ on a component where they mean the
|
|
170
|
-
|
|
171
|
-
.tooltip
|
|
189
|
+
loses to any intent class, so `.tooltip-bubble.primary` still floods with
|
|
190
|
+
primary; `.tooltip-bubble.neutral` carries 0-2-0 and beats `.neutral`, so
|
|
191
|
+
writing the intent out gives the same bubble as writing nothing. Without the
|
|
192
|
+
second selector the two would differ on a component where they mean the
|
|
193
|
+
same thing. */
|
|
194
|
+
:where(.tooltip-bubble),
|
|
195
|
+
.tooltip-bubble.neutral {
|
|
172
196
|
--intent-color: var(--color-tooltip);
|
|
173
197
|
--intent-contrast: var(--color-tooltip-contrast);
|
|
174
198
|
--intent-hover: var(--color-tooltip);
|
package/dist/tw/native.css
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
@import "./theme.css";
|
|
2
2
|
@reference "tailwindcss";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
@source not "../debug";
|
|
7
|
-
@source not "../playground";
|
|
3
|
+
/* Everything that is not `src/` -- see the note in `index.css`. Without the
|
|
4
|
+
docs and root-file excludes a utility used only in a documentation example
|
|
5
|
+
compiles into `dist/native.css`. */
|
|
8
6
|
@import "./typography.css";
|
|
9
7
|
@import "./utilities/index.css";
|
|
10
8
|
@import "./components/index.css";
|
|
@@ -52,21 +50,7 @@
|
|
|
52
50
|
}
|
|
53
51
|
|
|
54
52
|
@layer base {
|
|
55
|
-
h1
|
|
56
|
-
h2,
|
|
57
|
-
h3,
|
|
58
|
-
h4,
|
|
59
|
-
h5,
|
|
60
|
-
h6,
|
|
61
|
-
p,
|
|
62
|
-
figure,
|
|
63
|
-
blockquote,
|
|
64
|
-
dl,
|
|
65
|
-
dd,
|
|
66
|
-
ul,
|
|
67
|
-
ol {
|
|
68
|
-
margin: 0;
|
|
69
|
-
}
|
|
53
|
+
/* The `h1`-`ol` margin reset lives in `reset.css`, imported above. */
|
|
70
54
|
|
|
71
55
|
/* Headings */
|
|
72
56
|
h1 {
|
package/dist/tw/reset.css
CHANGED
|
@@ -3,16 +3,13 @@
|
|
|
3
3
|
@import "./typography.css";
|
|
4
4
|
|
|
5
5
|
@layer base {
|
|
6
|
-
/*
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
pipeline of its own — `apps/demo` imports this compiled stylesheet
|
|
14
|
-
directly — got the content-box default instead, inflating every sized
|
|
15
|
-
control by its own padding and border. */
|
|
6
|
+
/* The package's own components no longer lean on this: `@utility box` sets
|
|
7
|
+
`box-sizing: border-box` on itself, so a sized control is right in every
|
|
8
|
+
entrypoint including the reset-less `/components` and granular `/tw/*`
|
|
9
|
+
ones. What is left for the universal rule is the consumer's own markup --
|
|
10
|
+
a plain `<div>` laid out beside our components under the full reset -- so
|
|
11
|
+
it stays part of the opinionated baseline the reset already is, rather
|
|
12
|
+
than a correctness prop the components need. */
|
|
16
13
|
*,
|
|
17
14
|
*::before,
|
|
18
15
|
*::after {
|
|
@@ -36,7 +33,7 @@
|
|
|
36
33
|
|
|
37
34
|
html,
|
|
38
35
|
body {
|
|
39
|
-
@apply bg-background text-text font-default
|
|
36
|
+
@apply bg-background text-text font-default;
|
|
40
37
|
}
|
|
41
38
|
|
|
42
39
|
h1,
|
|
@@ -55,10 +52,6 @@
|
|
|
55
52
|
margin: 0;
|
|
56
53
|
}
|
|
57
54
|
|
|
58
|
-
body {
|
|
59
|
-
@apply flex flex-col;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
55
|
button,
|
|
63
56
|
input,
|
|
64
57
|
optgroup,
|
|
@@ -74,10 +67,6 @@
|
|
|
74
67
|
@apply enabled:cursor-pointer;
|
|
75
68
|
}
|
|
76
69
|
|
|
77
|
-
img {
|
|
78
|
-
@apply select-none;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
70
|
::selection {
|
|
82
71
|
background: var(--color-primary);
|
|
83
72
|
color: var(--color-primary-contrast);
|
|
@@ -124,19 +113,38 @@
|
|
|
124
113
|
}
|
|
125
114
|
}
|
|
126
115
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
116
|
+
/* Unlayered on purpose, matching the `forced-colors` blocks in `native.css` and
|
|
117
|
+
`form.css`. An accessibility override has to win over any layered rule
|
|
118
|
+
whatever the specificity, and a `@layer components` wrapper here would let the
|
|
119
|
+
component utilities that draw a border overrule it. */
|
|
120
|
+
@media (forced-colors: active) {
|
|
121
|
+
.btn,
|
|
122
|
+
.ipt,
|
|
123
|
+
.textarea,
|
|
124
|
+
.select,
|
|
125
|
+
.alert,
|
|
126
|
+
.badge {
|
|
127
|
+
border-color: CanvasText;
|
|
130
128
|
}
|
|
129
|
+
}
|
|
131
130
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
131
|
+
/* The user agent already promises both of these for a native `<dialog>` --
|
|
132
|
+
`dialog:not([open]) { display: none }` and a centered `margin: auto` on the
|
|
133
|
+
open box -- but both are user-agent origin, which loses to any author rule
|
|
134
|
+
at all. `.card`'s own `display: block` (`surface`'s `@apply box block`)
|
|
135
|
+
beats the first outright, so a `<dialog class="card">` renders open with no
|
|
136
|
+
`open` attribute and no `.showModal()` call -- the registry has no
|
|
137
|
+
dialog/modal component of its own, and `.card` is the closest primitive a
|
|
138
|
+
consumer reaches for. A margin reset on every element -- Tailwind's own
|
|
139
|
+
Preflight on the entries that carry it -- beats the second, so an opened
|
|
140
|
+
dialog pins to the top-left instead of centering. Restated here, unlayered like
|
|
141
|
+
the block above, for the same reason: a behavior override has to win over
|
|
142
|
+
any layered rule whatever the specificity, and `.card` is layered in the
|
|
143
|
+
utilities layer regardless of how it composes `box`. */
|
|
144
|
+
dialog:not([open]) {
|
|
145
|
+
display: none;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
dialog[open] {
|
|
149
|
+
margin: auto;
|
|
142
150
|
}
|