@codenhub/styles 0.5.0 → 0.6.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 +7 -7
- package/dist/aesthetics/chunky-tile.css +1 -1
- package/dist/aesthetics/cyber.css +1 -1
- package/dist/aesthetics/glass.css +1 -1
- package/dist/aesthetics/index.css +1 -1
- package/dist/aesthetics/neobrutalism.css +1 -1
- package/dist/aesthetics/pixel.css +1 -1
- package/dist/aesthetics/sketch.css +1 -1
- package/dist/components.css +1 -1
- package/dist/index.css +1 -1
- package/dist/native.css +1 -1
- package/dist/palette.css +1 -1
- package/dist/theme.css +1 -1
- package/dist/tw/aesthetics/chunky-tile.css +39 -39
- package/dist/tw/aesthetics/cyber.css +16 -11
- package/dist/tw/aesthetics/glass.css +235 -10
- package/dist/tw/aesthetics/index.css +2 -1
- package/dist/tw/aesthetics/neobrutalism.css +23 -11
- package/dist/tw/aesthetics/pixel.css +18 -8
- package/dist/tw/aesthetics/sketch.css +14 -7
- package/dist/tw/box.css +49 -27
- package/dist/tw/components/button.css +35 -14
- package/dist/tw/components/feedback.css +59 -56
- package/dist/tw/components/form.css +200 -126
- package/dist/tw/components/index.css +3 -7
- package/dist/tw/components/loader.css +4 -5
- package/dist/tw/components/surface.css +71 -68
- package/dist/tw/components/tooltip.css +75 -41
- package/dist/tw/elevation.css +14 -22
- package/dist/tw/index.css +15 -19
- package/dist/tw/intent.css +31 -24
- package/dist/tw/native.css +15 -5
- package/dist/tw/palette.css +8 -5
- package/dist/tw/presentation.css +16 -30
- package/dist/tw/reset.css +21 -28
- package/dist/tw/surface.css +11 -12
- package/dist/tw/theme.css +58 -86
- package/dist/tw/utilities/content.css +268 -199
- package/dist/tw/utilities/layout.css +15 -25
- package/docs/accessibility.md +50 -33
- package/docs/changelog/0.6.0.md +52 -0
- package/docs/changelog/index.md +1 -0
- package/docs/concepts.md +6 -6
- package/docs/index.md +9 -0
- package/docs/integrating/nextjs.md +1 -1
- package/docs/integrating/tailwind.md +14 -6
- package/docs/setup.md +6 -6
- package/docs/usage/aesthetics.md +35 -8
- package/docs/usage/buttons.md +1 -1
- package/docs/usage/composing.md +1 -1
- package/docs/usage/content-and-layout.md +12 -11
- package/docs/usage/customizing.md +8 -9
- package/docs/usage/feedback.md +5 -3
- package/docs/usage/forms.md +51 -35
- package/docs/usage/theming.md +39 -40
- package/docs/usage/tooltips.md +37 -17
- package/llms-full.txt +331 -183
- package/llms.txt +6 -0
- package/package.json +5 -5
|
@@ -1,29 +1,53 @@
|
|
|
1
1
|
@reference "../box.css";
|
|
2
2
|
|
|
3
|
+
/* A scroll box clips whatever paints outside it, and `overflow-x` takes the
|
|
4
|
+
vertical overflow with it, so an aesthetic's halo around the table -- cyber's
|
|
5
|
+
glow -- would be cut flush on every side. The wrapper makes room for the halo
|
|
6
|
+
inside itself and gives the same room back outside, so the table sits where
|
|
7
|
+
it does and only the scroll box grows. Zero wherever no halo is drawn. The
|
|
8
|
+
cost, under a halo: the wrapper reaches that far past its parent, which shows
|
|
9
|
+
only where the parent is flush with the viewport. Vertical margins still add
|
|
10
|
+
up to the same gap when they collapse with a sibling's, since the negative
|
|
11
|
+
one is paid back by the padding.
|
|
12
|
+
|
|
13
|
+
It reads the halo from its own scope, so an aesthetic class on the table
|
|
14
|
+
alone gives it nothing to make room for: the class belongs on the wrapper or
|
|
15
|
+
an ancestor, as `content-and-layout.md` says. A parent cannot read a child's
|
|
16
|
+
tokens, and reaching down with `:has()` would name an aesthetic here. */
|
|
3
17
|
@utility table-wrap {
|
|
4
|
-
@apply
|
|
18
|
+
@apply overflow-x-auto;
|
|
19
|
+
|
|
20
|
+
--_table-wrap-bleed: calc(var(--ui-halo-blur, 0px) + var(--ui-halo-spread, 0px));
|
|
21
|
+
|
|
22
|
+
box-sizing: border-box;
|
|
23
|
+
width: calc(100% + var(--_table-wrap-bleed) * 2);
|
|
24
|
+
margin: calc(var(--_table-wrap-bleed) * -1);
|
|
25
|
+
padding: var(--_table-wrap-bleed);
|
|
5
26
|
}
|
|
6
27
|
|
|
7
28
|
/* The one component that takes the frame of `box` and not the whole of it. The
|
|
8
|
-
border
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
29
|
+
border and the plate come from the box, and the corner is a surface's,
|
|
30
|
+
because a table is a pane of content rather than a control; the head tone,
|
|
31
|
+
the cell rules and the row hover are private tokens, because none of the
|
|
32
|
+
three axes has a vocabulary for the inside of a table.
|
|
33
|
+
|
|
34
|
+
Nothing here clips the table. Chromium and WebKit lay a `<caption>` out
|
|
35
|
+
inside the table's own box while painting the plate and the frame around the
|
|
36
|
+
rows alone, so anything that acts on the whole box -- an `overflow` clip, a
|
|
37
|
+
`clip-path`, a backdrop filter, a positioned layer -- spans the caption: an
|
|
38
|
+
`overflow: hidden` would round the caption's corners instead of the head's
|
|
39
|
+
and cut the caption's first letter. The corner cells take the table's corners
|
|
40
|
+
instead (below), which every engine draws on the rows. Recorded in
|
|
41
|
+
`registry.json` beside the decision. */
|
|
16
42
|
@utility data-table {
|
|
17
|
-
@apply box text-body w-full border-separate text-
|
|
43
|
+
@apply box text-body w-full border-separate text-start;
|
|
18
44
|
|
|
19
45
|
--_d-fill: 12%;
|
|
20
46
|
--_d-fg-on-fill: 0%;
|
|
21
47
|
/* Edgeless, so the frame is asked for rather than inherited from a default
|
|
22
|
-
nobody can see in their own markup.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
`.edged` draws it now, and the two boundaries a table keeps whatever else it
|
|
26
|
-
draws mean a frameless one still reads as a table. */
|
|
48
|
+
nobody can see in their own markup. `.edged` draws it, and the two
|
|
49
|
+
boundaries a table keeps whatever else it draws mean a frameless one still
|
|
50
|
+
reads as a table. */
|
|
27
51
|
--_d-border: 0%;
|
|
28
52
|
--_d-elevation: 0;
|
|
29
53
|
|
|
@@ -31,30 +55,25 @@
|
|
|
31
55
|
other and a neutral table head is otherwise a slab of the page's ink with
|
|
32
56
|
ink printed on it. */
|
|
33
57
|
--table-fill: calc(min(var(--ui-fill, var(--_d-fill)), var(--intent-fill-max, 100%)) * var(--ui-bg-alpha, 1));
|
|
34
|
-
/* The head's plate is the tint, so a table carrying no fill has no head
|
|
35
|
-
`.ghost` means no tint here the way it means no fill everywhere
|
|
36
|
-
ghost table is boundaries and type and nothing else -- which is
|
|
37
|
-
is for on this component, since the published resting fill is
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
aesthetic's alpha left of it. A glass `.soft` table still wants its head
|
|
54
|
-
plate, and neutral's 20% cap has no bearing on whether there is one. Reading
|
|
55
|
-
the raw class value also keeps the expression a `calc()` over one `var()`
|
|
56
|
-
rather than over `--table-fill`'s own `calc()`/`min()` chain, which matters
|
|
57
|
-
for the reason `--table-rule-plated` below records. */
|
|
58
|
+
/* The head's plate is the tint, so a table carrying no fill has no head
|
|
59
|
+
plate. `.ghost` means no tint here the way it means no fill everywhere
|
|
60
|
+
else, and a ghost table is boundaries and type and nothing else -- which is
|
|
61
|
+
what `.ghost` is for on this component, since the published resting fill is
|
|
62
|
+
`soft`.
|
|
63
|
+
|
|
64
|
+
Zero stays zero, and nothing past it saturates: `* 5` keeps zero at zero,
|
|
65
|
+
lets `.solid`'s 100% clear the `min(100%, ...)` ceiling to a fully opaque
|
|
66
|
+
head, and stops `.soft`'s 12% short at 60%, a visibly lighter plate, so the
|
|
67
|
+
two presentations separate. A larger multiplier lands both on a fully
|
|
68
|
+
opaque plate, leaving only the small intent mix to tell them apart.
|
|
69
|
+
|
|
70
|
+
It reads `--ui-fill` rather than `--table-fill` because the question is
|
|
71
|
+
what the presentation wanted, not what the intent cap and an aesthetic's
|
|
72
|
+
alpha left of it: a glass `.soft` table still wants its head plate, and
|
|
73
|
+
neutral's 20% cap has no bearing on whether there is one. Reading the raw
|
|
74
|
+
class value also keeps the expression a `calc()` over one `var()` rather
|
|
75
|
+
than over `--table-fill`'s own `calc()`/`min()` chain, which matters for
|
|
76
|
+
the reason `--table-rule-plated` below records. */
|
|
58
77
|
--table-ground: min(100%, calc(var(--ui-fill, var(--_d-fill)) * 5));
|
|
59
78
|
--table-head-plate: color-mix(in oklab, var(--intent-subtle) var(--table-ground), transparent);
|
|
60
79
|
--table-head-bg: color-mix(in oklab, var(--intent-color) var(--table-fill), var(--table-head-plate));
|
|
@@ -62,147 +81,201 @@
|
|
|
62
81
|
|
|
63
82
|
/* Untinted rather than mixed, the same call `.card.soft` makes: 12% ink onto
|
|
64
83
|
`--intent-subtle` still reads as `.solid` on neutral, since neutral's ink
|
|
65
|
-
and ground are both on the same greyscale axis
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
the same
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
slot, unclaimed here until now -- both land on the table's own element,
|
|
82
|
-
same as `--table-fill`/`--table-head-plate` do, so nothing here fights
|
|
83
|
-
`.soft` for `--ui-fill` either. `.ghost` is left at box's default
|
|
84
|
-
(`--_d-ground: transparent`), so it stays the fully bare boundaries-only
|
|
85
|
-
table it already was -- `.soft` now differs from it by keeping an opaque,
|
|
86
|
-
untinted plate and a head label strip, not by how much ink is in either.
|
|
84
|
+
and ground are both on the same greyscale axis. A head has no hover or
|
|
85
|
+
interaction state to reveal a tint into the way a card does, so `.soft` is
|
|
86
|
+
`--color-foreground`, flat, always, for every intent. That mutes a coloured
|
|
87
|
+
`.success`/`.destructive` head at rest the way it mutes a non-interactive
|
|
88
|
+
`.card.soft`; accepted for the same reason.
|
|
89
|
+
|
|
90
|
+
The table's own base plate rests the same way: a `.soft` head at
|
|
91
|
+
`--color-foreground` (five units off the page) above a body carrying the
|
|
92
|
+
ordinary 12% tint (twenty-four units past the head) reads backwards, as
|
|
93
|
+
though the head belonged to the page and the body were the odd one out.
|
|
94
|
+
`--_fill-cap` is `box.css`'s override slot (the one `.card.soft` uses) and
|
|
95
|
+
`--_d-ground` is box's private ground slot; both land on the table's own
|
|
96
|
+
element, so nothing here fights `.soft` for `--ui-fill`. `.ghost` is left
|
|
97
|
+
at box's default (`--_d-ground: transparent`), so it stays the fully bare
|
|
98
|
+
boundaries-only table; `.soft` differs from it by keeping an opaque,
|
|
99
|
+
untinted plate and a head label strip.
|
|
87
100
|
|
|
88
101
|
`:not(.solid, .ghost)` rather than `.soft`: the published resting fill is
|
|
89
|
-
`soft`, so a bare `<table class="data-table">`
|
|
90
|
-
|
|
91
|
-
this has to reach, not the edge case. `.soft` alone would miss every table
|
|
92
|
-
that gets soft by doing nothing. */
|
|
102
|
+
`soft`, so a bare `<table class="data-table">` with no fill class at all is
|
|
103
|
+
the common case this has to reach. */
|
|
93
104
|
&:not(.solid, .ghost) {
|
|
94
105
|
--table-fill: 0%;
|
|
95
|
-
--table-head-plate: var(--
|
|
106
|
+
--table-head-plate: var(--table-ground-plate);
|
|
96
107
|
--_fill-cap: 0%;
|
|
97
|
-
--_d-ground: var(--
|
|
108
|
+
--_d-ground: var(--table-ground-plate);
|
|
109
|
+
|
|
110
|
+
/* A table is a pane of content, so under an aesthetic whose surfaces are
|
|
111
|
+
glass it is glass too: the plate is the aesthetic's surface ground when
|
|
112
|
+
one is named, and the blur behind it is the one surfaces take. Head and
|
|
113
|
+
body share the plate, as they do on the page. Only this arm reads them:
|
|
114
|
+
a `.solid` table is opaque, like every `.solid`, and a `.ghost` one is
|
|
115
|
+
boundaries and type with nothing behind them to blur. */
|
|
116
|
+
--table-ground-plate: var(--ui-surface-ground, var(--color-foreground));
|
|
117
|
+
|
|
118
|
+
-webkit-backdrop-filter: var(--ui-backdrop, none);
|
|
119
|
+
backdrop-filter: var(--ui-backdrop, none);
|
|
98
120
|
}
|
|
99
121
|
|
|
100
122
|
/* How much rule there is between body rows, and none unless asked for. Ruling
|
|
101
|
-
every row is a style choice rather than part of what a table is,
|
|
102
|
-
to the edge axis
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
`.ruled` is that ask and `.ruleless` is its opposite, with `--ui-rule` behind
|
|
108
|
-
both -- so a consumer who wants a whole region ruled, or a whole region bare,
|
|
109
|
-
sets the token on a container instead of classing every table.
|
|
123
|
+
every row is a style choice rather than part of what a table is, so it is
|
|
124
|
+
not tied to the edge axis: `.ruled` asks for it, `.ruleless` is its
|
|
125
|
+
opposite, and `--ui-rule` is behind both, so a consumer who wants a whole
|
|
126
|
+
region ruled, or a whole region bare, sets the token on a container instead
|
|
127
|
+
of classing every table.
|
|
110
128
|
|
|
111
129
|
One token covers three positions because the two places that read it take
|
|
112
130
|
different fallbacks. Unset, each site answers for itself: no rules between
|
|
113
131
|
rows, but the boundaries below still drawn. Set, the answer is the same at
|
|
114
|
-
both. So `.ruled` writes 100% and gets rules everywhere, `.ruleless` writes
|
|
115
|
-
and gets a table with no lines in it at all, and a table nobody classed
|
|
116
|
-
between them.
|
|
117
|
-
and would have let the two drift. */
|
|
132
|
+
both. So `.ruled` writes 100% and gets rules everywhere, `.ruleless` writes
|
|
133
|
+
0% and gets a table with no lines in it at all, and a table nobody classed
|
|
134
|
+
sits between them. */
|
|
118
135
|
--table-rule-amount: var(--ui-rule, 0%);
|
|
119
136
|
--table-boundary-amount: var(--ui-rule, 100%);
|
|
120
137
|
/* What the rule is drawn in, which is not the same tone at every fill.
|
|
121
|
-
`.ghost` and `.soft` keep `--intent-border` -- the slot an aesthetic
|
|
122
|
-
through `--ui-ink` -- because at those fills the plate has not
|
|
123
|
-
`.solid` is where it has: at a full fill `--intent-border`
|
|
124
|
-
every intent, and at neutral's capped fill it is a near
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
The filled case draws in `currentColor`
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
per-intent branch, and it lands *over* the plate because a translucent
|
|
132
|
-
composites onto the background the element already painted.
|
|
133
|
-
|
|
134
|
-
Naming the ink rather than composing it
|
|
135
|
-
|
|
136
|
-
`color-mix(--table-head-fg 20%, --_bg)`
|
|
137
|
-
of substitution, into a `color-mix()` over two more `color-mix()`es
|
|
138
|
-
`min()`/`max()`/`calc()` chain
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
`currentColor` and `transparent` are leaves the engine has resolved already,
|
|
145
|
-
which is what takes the expression back down to something every engine can
|
|
146
|
-
carry. `--table-row-hover` below is written the same way, for the same
|
|
147
|
-
reason. */
|
|
138
|
+
`.ghost` and `.soft` keep `--intent-border` -- the slot an aesthetic
|
|
139
|
+
restates through `--ui-ink` -- because at those fills the plate has not
|
|
140
|
+
swallowed it. `.solid` is where it has: at a full fill `--intent-border`
|
|
141
|
+
*is* the plate for every intent, and at neutral's capped fill it is a near
|
|
142
|
+
shade of the same grey, so the row rule disappears exactly where the plate
|
|
143
|
+
is busiest.
|
|
144
|
+
|
|
145
|
+
The filled case draws in `currentColor` at a fifth instead: the ink the
|
|
146
|
+
cell is already printing (`--table-head-fg` on a head, `box`'s own `--_fg`
|
|
147
|
+
in the body), so it reads on a light plate and a dark one without a
|
|
148
|
+
per-intent branch, and it lands *over* the plate because a translucent
|
|
149
|
+
border composites onto the background the element already painted.
|
|
150
|
+
|
|
151
|
+
Naming the ink rather than composing it also keeps this expression cheap,
|
|
152
|
+
which is a requirement: every `th` and `td` on a page resolves it, and
|
|
153
|
+
written as `color-mix(--table-head-fg 20%, --_bg)` it expands, through four
|
|
154
|
+
levels of substitution, into a `color-mix()` over two more `color-mix()`es
|
|
155
|
+
over a `min()`/`max()`/`calc()` chain, which crashes WebKit's renderer on
|
|
156
|
+
the routes that draw tables. `currentColor` and `transparent` are leaves
|
|
157
|
+
the engine has already resolved, which takes the expression back down to
|
|
158
|
+
something every engine can carry. `--table-row-hover` below is written the
|
|
159
|
+
same way, for the same reason. */
|
|
148
160
|
--table-rule-plated: color-mix(in oklab, currentColor 20%, transparent);
|
|
149
161
|
--table-rule-tone: color-mix(in oklab, var(--table-rule-plated) var(--ui-fill, var(--_d-fill)), var(--intent-border));
|
|
150
162
|
--table-rule: color-mix(in oklab, var(--table-rule-tone) var(--table-rule-amount), transparent);
|
|
151
163
|
--table-boundary: color-mix(in oklab, var(--table-rule-tone) var(--table-boundary-amount), transparent);
|
|
152
164
|
/* A hovered row is a step from the table it is in, not from a tone the page
|
|
153
|
-
happens to own.
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
1.008:1 -- the feedback was declared and invisible. A filled plate steps
|
|
168
|
-
toward `currentColor` instead, which is the ink that plate already carries
|
|
169
|
-
and therefore always contrasts with it.
|
|
165
|
+
happens to own. A translucent step is relative at every fill, the way
|
|
166
|
+
`box-hover` is: the row composites onto whatever plate the table drew, so a
|
|
167
|
+
filled table shifts within its own colour, a soft one deepens its tint, and
|
|
168
|
+
a ghost one picks up a faint wash of the page. (Mixed into
|
|
169
|
+
`--color-foreground`, a solid primary table in dark theme would hover to
|
|
170
|
+
near-black, a dark band across a light table.)
|
|
171
|
+
|
|
172
|
+
Which tone it steps toward moves with the fill. On a bare or tinted plate
|
|
173
|
+
that is `--intent-hover`, the deepening every other component gets. On a
|
|
174
|
+
filled one it cannot be: `--intent-hover` is `mix(--intent-color 82%,
|
|
175
|
+
--intent-strong)`, very nearly the colour the plate is already painted, so
|
|
176
|
+
a step toward it is no step (a solid success table moves 1.00:1 in light).
|
|
177
|
+
A filled plate steps toward `currentColor` instead, the ink that plate
|
|
178
|
+
already carries and therefore always contrasts with it.
|
|
170
179
|
|
|
171
180
|
Both ends are leaves, and the step lands on `transparent` rather than on
|
|
172
|
-
`--_bg`, for the reason `--table-rule-plated` above gives
|
|
173
|
-
what the browser does with a translucent background anyway, so naming `--_bg`
|
|
174
|
-
buys the same colour for two more levels of substitution. */
|
|
181
|
+
`--_bg`, for the reason `--table-rule-plated` above gives. */
|
|
175
182
|
--table-hover-tone: color-mix(in oklab, currentColor var(--ui-fill, var(--_d-fill)), var(--intent-hover));
|
|
176
183
|
--table-row-hover: color-mix(in oklab, var(--table-hover-tone) 12%, transparent);
|
|
177
184
|
|
|
178
185
|
border-spacing: 0;
|
|
179
|
-
|
|
186
|
+
|
|
187
|
+
/* A surface's corner, as `surface` computes it: a table sits beside cards and
|
|
188
|
+
panels as a pane, and under `.cyber` it took the controls' diagonal while
|
|
189
|
+
every pane around it cut the other one. */
|
|
190
|
+
--_corner-surface: calc(var(--ui-corner-surface, var(--radius-surface)) * var(--_scale));
|
|
191
|
+
border-radius: var(
|
|
192
|
+
--ui-radius-surface,
|
|
193
|
+
calc(var(--_corner-surface) * var(--ui-corner-tl, 1)) calc(var(--_corner-surface) * var(--ui-corner-tr, 1))
|
|
194
|
+
calc(var(--_corner-surface) * var(--ui-corner-br, 1)) calc(var(--_corner-surface) * var(--ui-corner-bl, 1))
|
|
195
|
+
);
|
|
196
|
+
/* No silhouette clip either, for the caption's sake: `.pixel`'s stepped clip
|
|
197
|
+
cut the caption's corners and left the head's square. A pixel table is
|
|
198
|
+
square, which is the chip answer that aesthetic already gives. */
|
|
199
|
+
clip-path: none;
|
|
200
|
+
|
|
201
|
+
/* The corners pass down to the cells that sit in them. Each section and row
|
|
202
|
+
inherits the table's four corners -- a radius does not apply to either, but
|
|
203
|
+
it still computes and inherits -- and each corner cell takes only its own
|
|
204
|
+
corner, as a longhand, so an elliptical or bevelled corner arrives whole.
|
|
205
|
+
The first row is the head's when there is one and the first body's when
|
|
206
|
+
not, and the last row likewise the foot's or the last body's; a caption
|
|
207
|
+
and a `colgroup` are skipped. A cell spanning rows into a corner is not
|
|
208
|
+
reached, and a percentage corner resolves against the cell. */
|
|
209
|
+
& > :is(thead, tbody, tfoot),
|
|
210
|
+
& > :is(thead, tbody, tfoot) > tr {
|
|
211
|
+
border-radius: inherit;
|
|
212
|
+
corner-shape: inherit;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
& > :is(thead, tbody, tfoot) > tr > * {
|
|
216
|
+
corner-shape: inherit;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
& > thead > tr:first-child,
|
|
220
|
+
&:not(:has(> thead)) > tbody:first-of-type > tr:first-child {
|
|
221
|
+
& > :first-child {
|
|
222
|
+
border-start-start-radius: inherit;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
& > :last-child {
|
|
226
|
+
border-start-end-radius: inherit;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
& > tfoot > tr:last-child,
|
|
231
|
+
&:not(:has(> tfoot)) > tbody:last-of-type > tr:last-child {
|
|
232
|
+
& > :first-child {
|
|
233
|
+
border-end-start-radius: inherit;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
& > :last-child {
|
|
237
|
+
border-end-end-radius: inherit;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
180
240
|
|
|
181
241
|
& caption {
|
|
182
|
-
@apply text-label text-text-secondary pb-2 text-
|
|
242
|
+
@apply text-label text-text-secondary pb-2 text-start;
|
|
183
243
|
}
|
|
184
244
|
|
|
245
|
+
/* The head's plate is painted on its cells rather than on the section, so the
|
|
246
|
+
corner cells round it: a section's background ignores the cells' corners. */
|
|
185
247
|
& thead,
|
|
186
248
|
& tfoot {
|
|
187
|
-
background-color: var(--table-head-bg);
|
|
188
249
|
color: var(--table-head-fg);
|
|
189
250
|
}
|
|
190
251
|
|
|
252
|
+
& :is(thead, tfoot) > tr > * {
|
|
253
|
+
background-color: var(--table-head-bg);
|
|
254
|
+
}
|
|
255
|
+
|
|
191
256
|
/* Every cell carries the hairline; what varies is whether it is painted. The
|
|
192
|
-
width tracks the aesthetic's own line weight
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
257
|
+
width tracks the aesthetic's own line weight rather than a fixed `1px`, so
|
|
258
|
+
a row rule reads as the same material as the boundary around it. It
|
|
259
|
+
survives a fill that would otherwise paint over it, because color and width
|
|
260
|
+
are independent here: `.ruleless` zeroes the color, not this.
|
|
261
|
+
|
|
262
|
+
The width is the aesthetic's, not `box`'s `--_width`: that one is capped by
|
|
263
|
+
`--ui-border-max`, which `.pixel` sets to zero because its frame is an
|
|
264
|
+
inset ring a clip cannot cut. A rule is not a frame and nothing clips a
|
|
265
|
+
table, so under pixel the capped width would draw no rule at all -- no line
|
|
266
|
+
under the head or above the foot, and `.ruled` would change nothing. A
|
|
267
|
+
divider reads the same uncapped width for the same reason.
|
|
268
|
+
|
|
269
|
+
Alignment is logical and stated on the cells, not only on the table: a
|
|
270
|
+
`th` centers unless its parent names an alignment, and `start` is the
|
|
271
|
+
initial value, which counts as naming none. */
|
|
272
|
+
--_table-rule-width: var(--ui-border-width, var(--border-width));
|
|
200
273
|
& th,
|
|
201
274
|
& td {
|
|
202
|
-
@apply px-4 py-3 align-top;
|
|
275
|
+
@apply px-4 py-3 text-start align-top;
|
|
203
276
|
|
|
204
277
|
border-bottom-style: var(--ui-rule-style, var(--ui-line-style, solid));
|
|
205
|
-
border-bottom-width: var(--
|
|
278
|
+
border-bottom-width: var(--_table-rule-width);
|
|
206
279
|
border-color: var(--table-rule);
|
|
207
280
|
}
|
|
208
281
|
|
|
@@ -221,7 +294,7 @@
|
|
|
221
294
|
|
|
222
295
|
& tfoot tr:first-child > * {
|
|
223
296
|
border-top-style: var(--ui-rule-style, var(--ui-line-style, solid));
|
|
224
|
-
border-top-width: var(--
|
|
297
|
+
border-top-width: var(--_table-rule-width);
|
|
225
298
|
border-top-color: var(--table-boundary);
|
|
226
299
|
}
|
|
227
300
|
|
|
@@ -243,57 +316,49 @@
|
|
|
243
316
|
/* Rows deliberately inherit the table's intent instead of resetting it, so a
|
|
244
317
|
`.data-table.success` tints its own rows. A `<tr class="warning">` still wins,
|
|
245
318
|
because an intent class on the element beats an inherited value. */
|
|
246
|
-
& tbody tr {
|
|
319
|
+
& tbody tr > * {
|
|
247
320
|
transition: background-color var(--motion-duration-fast) var(--motion-ease);
|
|
248
321
|
}
|
|
249
322
|
|
|
250
|
-
|
|
323
|
+
/* On the cells, for the reason the head's plate is: a hovered last row keeps
|
|
324
|
+
the table's bottom corners. */
|
|
325
|
+
& tbody tr:hover > * {
|
|
251
326
|
background-color: var(--table-row-hover);
|
|
252
327
|
}
|
|
253
328
|
|
|
254
329
|
/* The rule comes off the row that is visually last, which is not always the
|
|
255
|
-
last row of the body.
|
|
256
|
-
|
|
257
|
-
separates the two
|
|
258
|
-
|
|
259
|
-
inside the frame. A missing line where one belongs and a doubled one where it
|
|
260
|
-
does not, from the same declaration.
|
|
330
|
+
last row of the body. `tbody tr:last-child` would remove the body's last
|
|
331
|
+
row rule unconditionally, so a table with a footer would lose the one rule
|
|
332
|
+
that separates the two while the footer kept a bottom rule of its own,
|
|
333
|
+
drawing a hairline immediately inside the frame.
|
|
261
334
|
|
|
262
335
|
Both selectors are `:last-child` on the section, so whichever section the
|
|
263
|
-
markup puts last is the one that loses its rule. That covers a footer
|
|
264
|
-
before the body, which HTML
|
|
265
|
-
last one ends the table.
|
|
266
|
-
|
|
267
|
-
It went unseen because it was invisible until this release: `thead` and
|
|
268
|
-
`tfoot` shared an unconditional `--intent-subtle` plate, so the footer was a
|
|
269
|
-
band and the band did the separating. `.ghost` dropping that plate is what
|
|
270
|
-
left the rule doing the job alone. */
|
|
336
|
+
markup puts last is the one that loses its rule. That covers a footer
|
|
337
|
+
written before the body, which HTML allows, and multiple bodies, where only
|
|
338
|
+
the last one ends the table. `.ghost` drops the head and foot plate, which
|
|
339
|
+
leaves this rule doing the separating alone. */
|
|
271
340
|
& tbody:last-child tr:last-child > *,
|
|
272
341
|
& tfoot:last-child tr:last-child > * {
|
|
273
342
|
@apply border-b-0;
|
|
274
343
|
}
|
|
275
344
|
}
|
|
276
345
|
|
|
277
|
-
/* Three components rest on a ground rather than on nothing: a key cap, an
|
|
278
|
-
code chip and a code block are each a quiet tinted plate at rest, and
|
|
279
|
-
is `--intent-subtle` rather than a fill of the component's own
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
the ground
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
page
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
`--intent-color` -- the tone meant to sit *on* a page rather than on a tint of
|
|
294
|
-
itself, and amber-600 on amber-100 is a smudge. `box` now mixes toward
|
|
295
|
-
`--intent-strong`, which is what these three were reaching for, so the three
|
|
296
|
-
copies are gone and the ground is the only thing left to declare. */
|
|
346
|
+
/* Three components rest on a ground rather than on nothing: a key cap, an
|
|
347
|
+
inline code chip and a code block are each a quiet tinted plate at rest, and
|
|
348
|
+
that tone is `--intent-subtle` rather than a fill of the component's own
|
|
349
|
+
intent.
|
|
350
|
+
|
|
351
|
+
All three rest at `soft`, and `.ghost` is published as unsupported on them:
|
|
352
|
+
the ground draws the plate whatever the fill says, so `.ghost` would draw it
|
|
353
|
+
anyway and mean nothing, and at zero fill the plate is `--intent-subtle`
|
|
354
|
+
alone, a near-page tint that renders four intents as the same invisible chip
|
|
355
|
+
(`#e5e5e5` for neutral and primary on the light page). Resting at `soft` puts
|
|
356
|
+
a real 12% of the intent over the ground, so the plate is a step past the
|
|
357
|
+
page and the intents separate.
|
|
358
|
+
|
|
359
|
+
The foreground is `box`'s, which mixes toward `--intent-strong`, the tone
|
|
360
|
+
meant to sit on a page rather than on a tint of itself, so the ground is the
|
|
361
|
+
only thing left to declare. */
|
|
297
362
|
/* Neutral, for the same reason `.panel`'s own carve-out is: 12% of
|
|
298
363
|
`--color-text` mixed onto `--intent-subtle` (`--color-surface` for
|
|
299
364
|
neutral) reads as an assertive slab rather than a quiet chip -- measured,
|
|
@@ -376,7 +441,7 @@
|
|
|
376
441
|
|
|
377
442
|
The bar is twice the line width the aesthetic asks for, plus a pixel, which is
|
|
378
443
|
this component's own choice about what a quotation looks like rather than a
|
|
379
|
-
scale applied to an edge
|
|
444
|
+
scale applied to an edge. The constant is
|
|
380
445
|
what makes the bar read as a bar at the default hairline: doubling 1px gives
|
|
381
446
|
2px, and a quotation mark needs more presence than a table rule. */
|
|
382
447
|
@utility quote {
|
|
@@ -389,22 +454,27 @@
|
|
|
389
454
|
`--ui-bg-alpha` thins it. */
|
|
390
455
|
--quote-capped: min(var(--ui-fill, var(--_d-fill)), var(--intent-fill-max, 100%));
|
|
391
456
|
--quote-fill: calc(var(--quote-capped) * var(--ui-bg-alpha, 1));
|
|
392
|
-
|
|
457
|
+
/* `box`'s `--_plate`: a fill the intent's cap stopped short rests on the page
|
|
458
|
+
background, so a neutral `.solid` quotation is a plate rather than a tint
|
|
459
|
+
of whatever is behind it. */
|
|
460
|
+
--quote-plate: clamp(0%, calc((var(--ui-fill, var(--_d-fill)) - var(--quote-capped)) * 1000), 100%);
|
|
461
|
+
--quote-bg: color-mix(
|
|
462
|
+
in oklab,
|
|
463
|
+
var(--intent-color) var(--quote-fill),
|
|
464
|
+
color-mix(in oklab, var(--color-background) var(--quote-plate), transparent)
|
|
465
|
+
);
|
|
393
466
|
/* The same edge blend `box` draws, in the same order and for the same reason:
|
|
394
467
|
the blend is the line's colour, and how much line there is comes after it.
|
|
395
|
-
Written the other way round
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
That this had to be fixed three times is the cost of a quotation drawing
|
|
406
|
-
its own edge instead of taking `box`'s. Recorded in `registry.json` beside
|
|
407
|
-
the decision to compose none of `box`. */
|
|
468
|
+
Written the other way round, `.edgeless` lands on the fill colour rather
|
|
469
|
+
than on nothing, and the border box paints that over the fill it already
|
|
470
|
+
drew. It also fades toward `transparent` rather than toward the plate, as
|
|
471
|
+
`box`'s does: the plate runs under the bar, so a bar blended toward it
|
|
472
|
+
would paint a translucent plate twice and draw a darker stripe on a neutral
|
|
473
|
+
`.solid` quotation.
|
|
474
|
+
|
|
475
|
+
A quotation draws its own edge instead of taking `box`'s, so an edge change
|
|
476
|
+
is made in `box`, `.quote`, and `.progress`. Recorded in `registry.json`
|
|
477
|
+
beside the decision to compose none of `box`. */
|
|
408
478
|
--quote-line: color-mix(in oklab, transparent var(--ui-fill, var(--_d-fill)), var(--intent-border));
|
|
409
479
|
--quote-edge: color-mix(in oklab, var(--quote-line) var(--ui-border, var(--_d-border)), transparent);
|
|
410
480
|
--quote-width: calc(var(--ui-border-width, var(--border-width)) * 2 + 1px);
|
|
@@ -414,13 +484,12 @@
|
|
|
414
484
|
background-color: var(--quote-bg);
|
|
415
485
|
border-inline-start-color: var(--quote-edge);
|
|
416
486
|
border-inline-start-width: var(--quote-width);
|
|
417
|
-
/* The ink is gated by the plate, not tied to the fill: `--ui-fg-on-fill` is
|
|
418
|
-
ceiling, and the contrast tone only ramps in past a half fill, reaching
|
|
419
|
-
at a full fill. Below that the ink stays `--intent-strong`, the tone
|
|
420
|
-
to read on the page. This is `box`'s `--_on-fill` exactly
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
~11:1, and this renderer has to agree with `box`. */
|
|
487
|
+
/* The ink is gated by the plate, not tied to the fill: `--ui-fg-on-fill` is
|
|
488
|
+
the ceiling, and the contrast tone only ramps in past a half fill, reaching
|
|
489
|
+
full at a full fill. Below that the ink stays `--intent-strong`, the tone
|
|
490
|
+
chosen to read on the page. This is `box`'s `--_on-fill` exactly, and this
|
|
491
|
+
renderer has to agree with it: a fill-proportional ink prints a
|
|
492
|
+
capped-neutral `.solid` quote at ~6.6:1 where the ramp gives ~11:1. */
|
|
424
493
|
color: color-mix(
|
|
425
494
|
in oklab,
|
|
426
495
|
var(--intent-contrast)
|