@gridkitjs/theme-css 0.0.0-dev-20261108090704
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/LICENSE +21 -0
- package/README.md +55 -0
- package/package.json +35 -0
- package/src/styles.css +2226 -0
package/src/styles.css
ADDED
|
@@ -0,0 +1,2226 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* GridKit plain-CSS theme.
|
|
3
|
+
*
|
|
4
|
+
* Generated from packages/theme-tailwind/src/styles.css in the GridKit
|
|
5
|
+
* repository by this package's scripts/write-stylesheet.mjs. Don't edit it
|
|
6
|
+
* by hand: change the source and run the package's build.
|
|
7
|
+
*
|
|
8
|
+
* The theme tokens are the `--gridkit-*` custom properties declared on
|
|
9
|
+
* `:root` below. A theme overrides them on `:root`, in a stylesheet loaded
|
|
10
|
+
* after this one.
|
|
11
|
+
*
|
|
12
|
+
* Each colour is a raw `-light`/`-dark` pair and a live name the rules
|
|
13
|
+
* read, pointed at one pair by whichever of these applies:
|
|
14
|
+
*
|
|
15
|
+
* - `:root`, by default: light.
|
|
16
|
+
* - The `prefers-color-scheme: dark` query: dark, following the OS.
|
|
17
|
+
* - `.gridkit-light` / `.gridkit-dark`: one palette, whatever the OS
|
|
18
|
+
* prefers, for an app with its own theme toggle. Put either on `<html>`
|
|
19
|
+
* or on any ancestor of a grid.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
:root {
|
|
23
|
+
/*
|
|
24
|
+
* A default of `inherit` is the CSS-wide keyword even here: it leaves the
|
|
25
|
+
* token with no value, so a declaration reading it falls back to `unset`,
|
|
26
|
+
* and the property, being one that inherits, takes the page's value.
|
|
27
|
+
*/
|
|
28
|
+
--gridkit-font-family: inherit;
|
|
29
|
+
--gridkit-font-size: 1em;
|
|
30
|
+
--gridkit-menu-font-size: 0.875rem;
|
|
31
|
+
--gridkit-bar-font-size: 0.8125rem;
|
|
32
|
+
--gridkit-hint-font-size: 0.75rem;
|
|
33
|
+
--gridkit-header-font-weight: 700;
|
|
34
|
+
--gridkit-header-text-transform: inherit;
|
|
35
|
+
--gridkit-header-letter-spacing: inherit;
|
|
36
|
+
--gridkit-group-font-weight: 600;
|
|
37
|
+
--gridkit-font-variant-numeric: inherit;
|
|
38
|
+
|
|
39
|
+
/*
|
|
40
|
+
* Every padding, gap and control height in the rules is a multiple of the
|
|
41
|
+
* spacing unit, unless a token below sets it for one part.
|
|
42
|
+
*/
|
|
43
|
+
--gridkit-spacing: 0.25rem;
|
|
44
|
+
--gridkit-cell-padding-x: calc(var(--gridkit-spacing) * 2);
|
|
45
|
+
--gridkit-cell-padding-y: calc(var(--gridkit-spacing) * 2);
|
|
46
|
+
--gridkit-header-padding-x: var(--gridkit-cell-padding-x);
|
|
47
|
+
--gridkit-header-padding-y: var(--gridkit-cell-padding-y);
|
|
48
|
+
--gridkit-toolbar-padding: calc(var(--gridkit-spacing) * 2);
|
|
49
|
+
--gridkit-group-by-bar-padding: calc(var(--gridkit-spacing) * 2);
|
|
50
|
+
--gridkit-pager-padding: calc(var(--gridkit-spacing) * 2);
|
|
51
|
+
--gridkit-menu-item-padding-x: calc(var(--gridkit-spacing) * 3);
|
|
52
|
+
--gridkit-menu-item-padding-y: calc(var(--gridkit-spacing) * 1.5);
|
|
53
|
+
|
|
54
|
+
/* A line width of 0 turns that kind of line off. */
|
|
55
|
+
--gridkit-border-width: 1px;
|
|
56
|
+
--gridkit-border-style: solid;
|
|
57
|
+
--gridkit-row-line-width: var(--gridkit-border-width);
|
|
58
|
+
--gridkit-column-line-width: var(--gridkit-border-width);
|
|
59
|
+
--gridkit-outer-border-width: 0;
|
|
60
|
+
|
|
61
|
+
--gridkit-radius: 0.25rem;
|
|
62
|
+
--gridkit-menu-radius: 0.375rem;
|
|
63
|
+
--gridkit-control-radius: 0.25rem;
|
|
64
|
+
|
|
65
|
+
--gridkit-icon-size: 1rem;
|
|
66
|
+
--gridkit-header-icon-size: 14px;
|
|
67
|
+
--gridkit-focus-ring-width: 2px;
|
|
68
|
+
--gridkit-indicator-width: 2px;
|
|
69
|
+
/*
|
|
70
|
+
* The shadow's offset and blur. Its colour is the palette pair
|
|
71
|
+
* `--gridkit-overlay-shadow-color`, since a value declared here can't
|
|
72
|
+
* follow the palette.
|
|
73
|
+
*/
|
|
74
|
+
--gridkit-overlay-shadow: 0 4px 12px;
|
|
75
|
+
--gridkit-menu-min-width: 12rem;
|
|
76
|
+
--gridkit-column-chooser-width: 16rem;
|
|
77
|
+
--gridkit-filter-menu-width: 18rem;
|
|
78
|
+
--gridkit-column-chooser-max-height: 17.5rem;
|
|
79
|
+
--gridkit-filter-checklist-height: 12rem;
|
|
80
|
+
--gridkit-transition-duration: 0.1s;
|
|
81
|
+
|
|
82
|
+
--gridkit-surface-light: oklch(1 0 0);
|
|
83
|
+
--gridkit-surface-dark: oklch(0.21 0.01 250);
|
|
84
|
+
--gridkit-surface-muted-light: oklch(0.97 0.003 250);
|
|
85
|
+
--gridkit-surface-muted-dark: oklch(0.26 0.012 250);
|
|
86
|
+
--gridkit-line-light: oklch(0.92 0.005 250);
|
|
87
|
+
--gridkit-line-dark: oklch(0.33 0.014 250);
|
|
88
|
+
--gridkit-hover-line-light: oklch(0.65 0.09 255);
|
|
89
|
+
--gridkit-hover-line-dark: oklch(0.75 0.09 255);
|
|
90
|
+
--gridkit-fg-light: oklch(0.21 0.01 250);
|
|
91
|
+
--gridkit-fg-dark: oklch(0.97 0.003 250);
|
|
92
|
+
/*
|
|
93
|
+
* Secondary text sits on `surface-muted` and `selected` too (a group row
|
|
94
|
+
* and its hover), so each `fg-muted` keeps WCAG AA's 4.5:1 against those
|
|
95
|
+
* as well as against `surface`.
|
|
96
|
+
*/
|
|
97
|
+
--gridkit-fg-muted-light: oklch(0.5 0.015 250);
|
|
98
|
+
--gridkit-fg-muted-dark: oklch(0.7 0.015 250);
|
|
99
|
+
--gridkit-accent-light: oklch(0.6 0.17 255);
|
|
100
|
+
--gridkit-accent-dark: oklch(0.7 0.15 255);
|
|
101
|
+
--gridkit-selected-light: oklch(0.94 0.03 255);
|
|
102
|
+
--gridkit-selected-dark: oklch(0.32 0.05 255);
|
|
103
|
+
--gridkit-selected-strong-light: oklch(0.9 0.05 255);
|
|
104
|
+
--gridkit-selected-strong-dark: oklch(0.38 0.07 255);
|
|
105
|
+
|
|
106
|
+
/*
|
|
107
|
+
* The colours of single parts. Most default to a palette colour, so a
|
|
108
|
+
* change to the palette carries over to them; the header's text keeps the
|
|
109
|
+
* page's colour, as the cells' does, and rows are not striped.
|
|
110
|
+
*/
|
|
111
|
+
--gridkit-header-bg-light: var(--gridkit-surface-light);
|
|
112
|
+
--gridkit-header-bg-dark: var(--gridkit-surface-dark);
|
|
113
|
+
--gridkit-header-fg-light: currentColor;
|
|
114
|
+
--gridkit-header-fg-dark: currentColor;
|
|
115
|
+
--gridkit-group-row-bg-light: var(--gridkit-surface-muted-light);
|
|
116
|
+
--gridkit-group-row-bg-dark: var(--gridkit-surface-muted-dark);
|
|
117
|
+
--gridkit-row-hover-bg-light: var(--gridkit-surface-muted-light);
|
|
118
|
+
--gridkit-row-hover-bg-dark: var(--gridkit-surface-muted-dark);
|
|
119
|
+
--gridkit-row-stripe-bg-light: transparent;
|
|
120
|
+
--gridkit-row-stripe-bg-dark: transparent;
|
|
121
|
+
--gridkit-focus-ring-light: var(--gridkit-accent-light);
|
|
122
|
+
--gridkit-focus-ring-dark: var(--gridkit-accent-dark);
|
|
123
|
+
--gridkit-accent-fg-light: var(--gridkit-surface-light);
|
|
124
|
+
--gridkit-accent-fg-dark: var(--gridkit-surface-dark);
|
|
125
|
+
/* The accent turned red, as light or dark as the accent. */
|
|
126
|
+
--gridkit-error-light: oklch(from var(--gridkit-accent-light) l c 25);
|
|
127
|
+
--gridkit-error-dark: oklch(from var(--gridkit-accent-dark) l c 25);
|
|
128
|
+
--gridkit-scrollbar-thumb-light: color-mix(
|
|
129
|
+
in oklch,
|
|
130
|
+
var(--gridkit-fg-muted-light) 45%,
|
|
131
|
+
transparent
|
|
132
|
+
);
|
|
133
|
+
--gridkit-scrollbar-thumb-dark: color-mix(
|
|
134
|
+
in oklch,
|
|
135
|
+
var(--gridkit-fg-muted-dark) 45%,
|
|
136
|
+
transparent
|
|
137
|
+
);
|
|
138
|
+
--gridkit-overlay-shadow-color-light: oklch(0 0 0 / 0.15);
|
|
139
|
+
--gridkit-overlay-shadow-color-dark: oklch(0 0 0 / 0.15);
|
|
140
|
+
|
|
141
|
+
color-scheme: light;
|
|
142
|
+
--gridkit-surface: var(--gridkit-surface-light);
|
|
143
|
+
--gridkit-surface-muted: var(--gridkit-surface-muted-light);
|
|
144
|
+
--gridkit-line: var(--gridkit-line-light);
|
|
145
|
+
--gridkit-hover-line: var(--gridkit-hover-line-light);
|
|
146
|
+
--gridkit-fg: var(--gridkit-fg-light);
|
|
147
|
+
--gridkit-fg-muted: var(--gridkit-fg-muted-light);
|
|
148
|
+
--gridkit-accent: var(--gridkit-accent-light);
|
|
149
|
+
--gridkit-selected: var(--gridkit-selected-light);
|
|
150
|
+
--gridkit-selected-strong: var(--gridkit-selected-strong-light);
|
|
151
|
+
--gridkit-header-bg: var(--gridkit-header-bg-light);
|
|
152
|
+
--gridkit-header-fg: var(--gridkit-header-fg-light);
|
|
153
|
+
--gridkit-group-row-bg: var(--gridkit-group-row-bg-light);
|
|
154
|
+
--gridkit-row-hover-bg: var(--gridkit-row-hover-bg-light);
|
|
155
|
+
--gridkit-row-stripe-bg: var(--gridkit-row-stripe-bg-light);
|
|
156
|
+
--gridkit-focus-ring: var(--gridkit-focus-ring-light);
|
|
157
|
+
--gridkit-accent-fg: var(--gridkit-accent-fg-light);
|
|
158
|
+
--gridkit-error: var(--gridkit-error-light);
|
|
159
|
+
--gridkit-scrollbar-thumb: var(--gridkit-scrollbar-thumb-light);
|
|
160
|
+
--gridkit-overlay-shadow-color: var(--gridkit-overlay-shadow-color-light);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
@media (prefers-color-scheme: dark) {
|
|
164
|
+
:root {
|
|
165
|
+
color-scheme: dark;
|
|
166
|
+
--gridkit-surface: var(--gridkit-surface-dark);
|
|
167
|
+
--gridkit-surface-muted: var(--gridkit-surface-muted-dark);
|
|
168
|
+
--gridkit-line: var(--gridkit-line-dark);
|
|
169
|
+
--gridkit-hover-line: var(--gridkit-hover-line-dark);
|
|
170
|
+
--gridkit-fg: var(--gridkit-fg-dark);
|
|
171
|
+
--gridkit-fg-muted: var(--gridkit-fg-muted-dark);
|
|
172
|
+
--gridkit-accent: var(--gridkit-accent-dark);
|
|
173
|
+
--gridkit-selected: var(--gridkit-selected-dark);
|
|
174
|
+
--gridkit-selected-strong: var(--gridkit-selected-strong-dark);
|
|
175
|
+
--gridkit-header-bg: var(--gridkit-header-bg-dark);
|
|
176
|
+
--gridkit-header-fg: var(--gridkit-header-fg-dark);
|
|
177
|
+
--gridkit-group-row-bg: var(--gridkit-group-row-bg-dark);
|
|
178
|
+
--gridkit-row-hover-bg: var(--gridkit-row-hover-bg-dark);
|
|
179
|
+
--gridkit-row-stripe-bg: var(--gridkit-row-stripe-bg-dark);
|
|
180
|
+
--gridkit-focus-ring: var(--gridkit-focus-ring-dark);
|
|
181
|
+
--gridkit-accent-fg: var(--gridkit-accent-fg-dark);
|
|
182
|
+
--gridkit-error: var(--gridkit-error-dark);
|
|
183
|
+
--gridkit-scrollbar-thumb: var(--gridkit-scrollbar-thumb-dark);
|
|
184
|
+
--gridkit-overlay-shadow-color: var(--gridkit-overlay-shadow-color-dark);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/*
|
|
189
|
+
* Without relative colour syntax the error default above is invalid, and a
|
|
190
|
+
* declaration reading it would draw nothing at all, so there it is the text
|
|
191
|
+
* colour instead. A theme's own error colour, set on `:root` after this
|
|
192
|
+
* stylesheet, still wins.
|
|
193
|
+
*/
|
|
194
|
+
@supports not (color: oklch(from red l c h)) {
|
|
195
|
+
:root {
|
|
196
|
+
--gridkit-error-light: var(--gridkit-fg-light);
|
|
197
|
+
--gridkit-error-dark: var(--gridkit-fg-dark);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.gridkit-light {
|
|
202
|
+
color-scheme: light;
|
|
203
|
+
--gridkit-surface: var(--gridkit-surface-light);
|
|
204
|
+
--gridkit-surface-muted: var(--gridkit-surface-muted-light);
|
|
205
|
+
--gridkit-line: var(--gridkit-line-light);
|
|
206
|
+
--gridkit-hover-line: var(--gridkit-hover-line-light);
|
|
207
|
+
--gridkit-fg: var(--gridkit-fg-light);
|
|
208
|
+
--gridkit-fg-muted: var(--gridkit-fg-muted-light);
|
|
209
|
+
--gridkit-accent: var(--gridkit-accent-light);
|
|
210
|
+
--gridkit-selected: var(--gridkit-selected-light);
|
|
211
|
+
--gridkit-selected-strong: var(--gridkit-selected-strong-light);
|
|
212
|
+
--gridkit-header-bg: var(--gridkit-header-bg-light);
|
|
213
|
+
--gridkit-header-fg: var(--gridkit-header-fg-light);
|
|
214
|
+
--gridkit-group-row-bg: var(--gridkit-group-row-bg-light);
|
|
215
|
+
--gridkit-row-hover-bg: var(--gridkit-row-hover-bg-light);
|
|
216
|
+
--gridkit-row-stripe-bg: var(--gridkit-row-stripe-bg-light);
|
|
217
|
+
--gridkit-focus-ring: var(--gridkit-focus-ring-light);
|
|
218
|
+
--gridkit-accent-fg: var(--gridkit-accent-fg-light);
|
|
219
|
+
--gridkit-error: var(--gridkit-error-light);
|
|
220
|
+
--gridkit-scrollbar-thumb: var(--gridkit-scrollbar-thumb-light);
|
|
221
|
+
--gridkit-overlay-shadow-color: var(--gridkit-overlay-shadow-color-light);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.gridkit-dark {
|
|
225
|
+
color-scheme: dark;
|
|
226
|
+
--gridkit-surface: var(--gridkit-surface-dark);
|
|
227
|
+
--gridkit-surface-muted: var(--gridkit-surface-muted-dark);
|
|
228
|
+
--gridkit-line: var(--gridkit-line-dark);
|
|
229
|
+
--gridkit-hover-line: var(--gridkit-hover-line-dark);
|
|
230
|
+
--gridkit-fg: var(--gridkit-fg-dark);
|
|
231
|
+
--gridkit-fg-muted: var(--gridkit-fg-muted-dark);
|
|
232
|
+
--gridkit-accent: var(--gridkit-accent-dark);
|
|
233
|
+
--gridkit-selected: var(--gridkit-selected-dark);
|
|
234
|
+
--gridkit-selected-strong: var(--gridkit-selected-strong-dark);
|
|
235
|
+
--gridkit-header-bg: var(--gridkit-header-bg-dark);
|
|
236
|
+
--gridkit-header-fg: var(--gridkit-header-fg-dark);
|
|
237
|
+
--gridkit-group-row-bg: var(--gridkit-group-row-bg-dark);
|
|
238
|
+
--gridkit-row-hover-bg: var(--gridkit-row-hover-bg-dark);
|
|
239
|
+
--gridkit-row-stripe-bg: var(--gridkit-row-stripe-bg-dark);
|
|
240
|
+
--gridkit-focus-ring: var(--gridkit-focus-ring-dark);
|
|
241
|
+
--gridkit-accent-fg: var(--gridkit-accent-fg-dark);
|
|
242
|
+
--gridkit-error: var(--gridkit-error-dark);
|
|
243
|
+
--gridkit-scrollbar-thumb: var(--gridkit-scrollbar-thumb-dark);
|
|
244
|
+
--gridkit-overlay-shadow-color: var(--gridkit-overlay-shadow-color-dark);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/*
|
|
248
|
+
* Grid styles.
|
|
249
|
+
*/
|
|
250
|
+
|
|
251
|
+
@layer base {
|
|
252
|
+
/*
|
|
253
|
+
* What the rules below take for granted from Tailwind's Preflight, set on
|
|
254
|
+
* the grid's root and on what it renders into `document.body`, so they
|
|
255
|
+
* draw the same in an app without Preflight, and in theme-css's plain
|
|
256
|
+
* CSS. `:where()` keeps each at no specificity, as Preflight's are.
|
|
257
|
+
*/
|
|
258
|
+
:where(.gridkit-data-grid-viewport, .drag-ghost, .gridkit-overlay),
|
|
259
|
+
:where(.gridkit-data-grid-viewport, .drag-ghost, .gridkit-overlay) *,
|
|
260
|
+
:where(.gridkit-data-grid-viewport, .drag-ghost, .gridkit-overlay) ::before,
|
|
261
|
+
:where(.gridkit-data-grid-viewport, .drag-ghost, .gridkit-overlay) ::after {
|
|
262
|
+
box-sizing: border-box;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
:where(.gridkit-data-grid-viewport, .gridkit-overlay) :where(button, input) {
|
|
266
|
+
font: inherit;
|
|
267
|
+
letter-spacing: inherit;
|
|
268
|
+
color: inherit;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
:where(.gridkit-data-grid-viewport, .gridkit-overlay) :where(svg) {
|
|
272
|
+
vertical-align: middle;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/*
|
|
276
|
+
* The table is exactly as wide as its columns, so anything wider than the
|
|
277
|
+
* space available scrolls here rather than squashing the columns. Scrolls
|
|
278
|
+
* the header, body, and footer tables together, since all three are
|
|
279
|
+
* descendants of this one viewport.
|
|
280
|
+
*/
|
|
281
|
+
.gridkit-data-grid-viewport {
|
|
282
|
+
overflow-x: auto;
|
|
283
|
+
font-size: var(--gridkit-font-size);
|
|
284
|
+
border-radius: var(--gridkit-radius);
|
|
285
|
+
border: var(--gridkit-outer-border-width) var(--gridkit-border-style)
|
|
286
|
+
var(--gridkit-line);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/*
|
|
290
|
+
* The grid's text, set on its root and again on what it renders into
|
|
291
|
+
* `document.body`, which sits outside that root.
|
|
292
|
+
*/
|
|
293
|
+
.gridkit-data-grid-viewport,
|
|
294
|
+
.gridkit-data-grid.drag-ghost,
|
|
295
|
+
.group-by-chip.drag-ghost,
|
|
296
|
+
.gridkit-overlay {
|
|
297
|
+
font-family: var(--gridkit-font-family);
|
|
298
|
+
font-variant-numeric: var(--gridkit-font-variant-numeric);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/*
|
|
302
|
+
* The row area alone. `height` unset leaves this `auto` — exactly the
|
|
303
|
+
* content-driven height the single-table layout had before the
|
|
304
|
+
* header/body/footer split — and a consumer-set `height` bounds only this
|
|
305
|
+
* div, so the group-by bar, header, footer, and pager stay outside it and
|
|
306
|
+
* always visible while the rows scroll independently.
|
|
307
|
+
*
|
|
308
|
+
* No `position: sticky` here or anywhere else in this file for the header/
|
|
309
|
+
* footer: they don't need it. Splitting header, body, and footer into
|
|
310
|
+
* sibling `<table>`s already keeps the header and footer out of the region
|
|
311
|
+
* that scrolls — there's nothing to "stick," since they were never going
|
|
312
|
+
* to scroll away. A consumer wanting a divider or shadow at the seam adds
|
|
313
|
+
* their own CSS targeting `.gridkit-data-grid-header`/
|
|
314
|
+
* `.gridkit-data-grid-footer`.
|
|
315
|
+
*/
|
|
316
|
+
.gridkit-data-grid-body {
|
|
317
|
+
overflow-y: auto;
|
|
318
|
+
height: var(--gridkit-body-height, auto);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/*
|
|
322
|
+
* Slim scrollbars on the grid's own scroll regions, never on the page: the
|
|
323
|
+
* viewport, the row area, the menus, and the column chooser and filter
|
|
324
|
+
* checklist lists. Chromium and Firefox honour
|
|
325
|
+
* `scrollbar-width`/`scrollbar-color`; the `::-webkit-scrollbar` rules are
|
|
326
|
+
* only for engines that do not, since a browser that supports the standard
|
|
327
|
+
* properties ignores them anyway.
|
|
328
|
+
*/
|
|
329
|
+
.gridkit-data-grid-viewport,
|
|
330
|
+
.gridkit-data-grid-body,
|
|
331
|
+
.gridkit-menu,
|
|
332
|
+
.column-chooser-list,
|
|
333
|
+
.filter-menu-checklist {
|
|
334
|
+
scrollbar-width: thin;
|
|
335
|
+
scrollbar-color: var(--gridkit-scrollbar-thumb) transparent;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
@supports not (scrollbar-color: auto) {
|
|
339
|
+
.gridkit-data-grid-viewport::-webkit-scrollbar,
|
|
340
|
+
.gridkit-data-grid-body::-webkit-scrollbar,
|
|
341
|
+
.gridkit-menu::-webkit-scrollbar,
|
|
342
|
+
.column-chooser-list::-webkit-scrollbar,
|
|
343
|
+
.filter-menu-checklist::-webkit-scrollbar {
|
|
344
|
+
width: 8px;
|
|
345
|
+
height: 8px;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
.gridkit-data-grid-viewport::-webkit-scrollbar-track,
|
|
349
|
+
.gridkit-data-grid-body::-webkit-scrollbar-track,
|
|
350
|
+
.gridkit-menu::-webkit-scrollbar-track,
|
|
351
|
+
.column-chooser-list::-webkit-scrollbar-track,
|
|
352
|
+
.filter-menu-checklist::-webkit-scrollbar-track {
|
|
353
|
+
background: transparent;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
.gridkit-data-grid-viewport::-webkit-scrollbar-thumb,
|
|
357
|
+
.gridkit-data-grid-body::-webkit-scrollbar-thumb,
|
|
358
|
+
.gridkit-menu::-webkit-scrollbar-thumb,
|
|
359
|
+
.column-chooser-list::-webkit-scrollbar-thumb,
|
|
360
|
+
.filter-menu-checklist::-webkit-scrollbar-thumb {
|
|
361
|
+
background-color: var(--gridkit-scrollbar-thumb);
|
|
362
|
+
border-radius: 4px;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/*
|
|
367
|
+
* Read but not seen — the grid's live region, which reports a reorder or a
|
|
368
|
+
* resize that only a sighted user could otherwise notice.
|
|
369
|
+
*
|
|
370
|
+
* Clipped to nothing rather than hidden with `display: none` or
|
|
371
|
+
* `visibility: hidden`, either of which would take it out of the
|
|
372
|
+
* accessibility tree along with the announcement.
|
|
373
|
+
*/
|
|
374
|
+
.gridkit-sr-only {
|
|
375
|
+
position: absolute;
|
|
376
|
+
width: 1px;
|
|
377
|
+
height: 1px;
|
|
378
|
+
margin: -1px;
|
|
379
|
+
padding: 0;
|
|
380
|
+
overflow: hidden;
|
|
381
|
+
clip-path: inset(50%);
|
|
382
|
+
white-space: nowrap;
|
|
383
|
+
border-width: 0;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/*
|
|
387
|
+
* `fixed` is what makes a width a width. Under the default `auto` layout the
|
|
388
|
+
* browser treats the colgroup as a hint and re-apportions space by content,
|
|
389
|
+
* so dragging one column visibly shifts its neighbours.
|
|
390
|
+
*/
|
|
391
|
+
.gridkit-data-grid {
|
|
392
|
+
border-collapse: collapse;
|
|
393
|
+
table-layout: fixed;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/*
|
|
397
|
+
* Fixed layout does not grow a cell to fit, so content has to be told what to
|
|
398
|
+
* do when it does not. Keeping it on one line is also what lets a column be
|
|
399
|
+
* measured against its content.
|
|
400
|
+
*/
|
|
401
|
+
.gridkit-data-grid .header-cell,
|
|
402
|
+
.gridkit-data-grid .grid-cell {
|
|
403
|
+
overflow: hidden;
|
|
404
|
+
text-overflow: ellipsis;
|
|
405
|
+
white-space: nowrap;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/*
|
|
409
|
+
* A column that opts into `wrap` needs all three of the rule above undone —
|
|
410
|
+
* `overflow: hidden` alone would still clip a second line, and
|
|
411
|
+
* `text-overflow: ellipsis` only matters once `overflow` stops being
|
|
412
|
+
* `visible`. Fixed layout still holds the column's width; only its height
|
|
413
|
+
* stops being one line's worth.
|
|
414
|
+
*
|
|
415
|
+
* `white-space: normal` alone only breaks at spaces — a single word longer
|
|
416
|
+
* than the column (a long identifier, a URL) has nowhere to break and
|
|
417
|
+
* overflows the fixed width instead, now that `overflow: visible` no longer
|
|
418
|
+
* clips it. `overflow-wrap: anywhere` lets it break mid-word as a last
|
|
419
|
+
* resort, after normal word breaks are exhausted.
|
|
420
|
+
*/
|
|
421
|
+
.gridkit-data-grid .header-cell.is-wrapped,
|
|
422
|
+
.gridkit-data-grid .grid-cell.is-wrapped {
|
|
423
|
+
overflow: visible;
|
|
424
|
+
text-overflow: clip;
|
|
425
|
+
white-space: normal;
|
|
426
|
+
overflow-wrap: anywhere;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
.gridkit-data-grid .grid-header {
|
|
430
|
+
color: var(--gridkit-header-fg);
|
|
431
|
+
background-color: var(--gridkit-header-bg);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
.gridkit-data-grid .grid-header .header-cell {
|
|
435
|
+
padding: var(--gridkit-header-padding-y) var(--gridkit-header-padding-x);
|
|
436
|
+
position: relative;
|
|
437
|
+
font-weight: var(--gridkit-header-font-weight);
|
|
438
|
+
letter-spacing: var(--gridkit-header-letter-spacing);
|
|
439
|
+
text-transform: var(--gridkit-header-text-transform);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
.gridkit-data-grid .header-resize-handle {
|
|
443
|
+
position: absolute;
|
|
444
|
+
top: 0;
|
|
445
|
+
right: 0;
|
|
446
|
+
bottom: 0;
|
|
447
|
+
width: 6px;
|
|
448
|
+
cursor: col-resize;
|
|
449
|
+
/* Without this a touch drag scrolls the page instead of resizing. */
|
|
450
|
+
touch-action: none;
|
|
451
|
+
user-select: none;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/*
|
|
455
|
+
* A resize colours the edge being dragged on every cell in the column, so it
|
|
456
|
+
* reads as one line down the grid rather than a stack of outlined cells.
|
|
457
|
+
* `box-shadow` rather than `border-right`: under `borders="none"` there is no
|
|
458
|
+
* border to recolour, and adding one would shift the cell's content by a
|
|
459
|
+
* pixel mid-drag.
|
|
460
|
+
*/
|
|
461
|
+
.gridkit-data-grid .header-cell.is-resizing,
|
|
462
|
+
.gridkit-data-grid .grid-cell.is-resizing {
|
|
463
|
+
box-shadow: inset calc(var(--gridkit-indicator-width) * -1) 0 0 0
|
|
464
|
+
var(--gridkit-hover-line);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/*
|
|
468
|
+
* The grid is one tab stop and the arrow keys move within it, so the focused
|
|
469
|
+
* cell is the only sign of where that stop currently is — without this ring a
|
|
470
|
+
* keyboard user is navigating blind.
|
|
471
|
+
*
|
|
472
|
+
* Inset because the viewport clips its overflow: an outline drawn outwards
|
|
473
|
+
* would be cut off on the first and last columns.
|
|
474
|
+
*/
|
|
475
|
+
.gridkit-data-grid .header-cell:focus-visible,
|
|
476
|
+
.gridkit-data-grid .grid-cell:focus-visible {
|
|
477
|
+
outline: var(--gridkit-focus-ring-width) solid var(--gridkit-focus-ring);
|
|
478
|
+
outline-offset: calc(var(--gridkit-focus-ring-width) * -1);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/*
|
|
482
|
+
* A reorderable header is the grab zone for its own drag, so a press on it
|
|
483
|
+
* must not select the label instead. Asked for by name: every header is
|
|
484
|
+
* focusable now that the grid roves one tab stop, so a `tabindex` no longer
|
|
485
|
+
* distinguishes the ones that drag.
|
|
486
|
+
*/
|
|
487
|
+
.gridkit-data-grid .header-cell.is-reorderable {
|
|
488
|
+
cursor: grab;
|
|
489
|
+
touch-action: none;
|
|
490
|
+
user-select: none;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
.gridkit-data-grid .header-cell.is-dragging {
|
|
494
|
+
cursor: grabbing;
|
|
495
|
+
opacity: 0.5;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/*
|
|
499
|
+
* A header, cell or group row that opens the grid's context menu — its
|
|
500
|
+
* `aria-keyshortcuts` names Shift+F10 then — takes a long-press for that
|
|
501
|
+
* menu, so iOS must not show its own callout, or start selecting the text
|
|
502
|
+
* under the finger, on the same press.
|
|
503
|
+
*/
|
|
504
|
+
.gridkit-data-grid [aria-keyshortcuts~="Shift+F10"] {
|
|
505
|
+
-webkit-touch-callout: none;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
@media (pointer: coarse) {
|
|
509
|
+
.gridkit-data-grid [aria-keyshortcuts~="Shift+F10"] {
|
|
510
|
+
-webkit-user-select: none;
|
|
511
|
+
user-select: none;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/*
|
|
516
|
+
* The header trailing the pointer. It sits on the body rather than in the
|
|
517
|
+
* table, so it restates what a header cell gets from its place in the grid.
|
|
518
|
+
*
|
|
519
|
+
* `pointer-events: none` is load-bearing: sitting under the cursor, it would
|
|
520
|
+
* otherwise mask every header it passes over and there would be no drop
|
|
521
|
+
* target at all.
|
|
522
|
+
*/
|
|
523
|
+
.gridkit-data-grid.drag-ghost {
|
|
524
|
+
position: fixed;
|
|
525
|
+
top: 0;
|
|
526
|
+
left: 0;
|
|
527
|
+
z-index: 50;
|
|
528
|
+
padding: var(--gridkit-header-padding-y) var(--gridkit-header-padding-x);
|
|
529
|
+
font-size: var(--gridkit-font-size);
|
|
530
|
+
font-weight: var(--gridkit-header-font-weight);
|
|
531
|
+
letter-spacing: var(--gridkit-header-letter-spacing);
|
|
532
|
+
text-transform: var(--gridkit-header-text-transform);
|
|
533
|
+
text-align: center;
|
|
534
|
+
color: var(--gridkit-header-fg);
|
|
535
|
+
background-color: var(--gridkit-header-bg);
|
|
536
|
+
border: var(--gridkit-border-width) dashed var(--gridkit-accent);
|
|
537
|
+
opacity: 0.75;
|
|
538
|
+
pointer-events: none;
|
|
539
|
+
/*
|
|
540
|
+
* Restated because the rule that clips a header's text is scoped to a
|
|
541
|
+
* `.header-cell` inside the grid, and the ghost carries that class while
|
|
542
|
+
* being the grid element itself.
|
|
543
|
+
*/
|
|
544
|
+
overflow: hidden;
|
|
545
|
+
text-overflow: ellipsis;
|
|
546
|
+
white-space: nowrap;
|
|
547
|
+
/* Placed by a transform written straight to the node each pointer move. */
|
|
548
|
+
will-change: transform;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/*
|
|
552
|
+
* Where the column would land, drawn on the gap's own edge so the one gap
|
|
553
|
+
* between two columns reads as one line.
|
|
554
|
+
*
|
|
555
|
+
* `box-shadow` for the reason the resize line uses it, and because a
|
|
556
|
+
* recoloured `borders-vertical` border would land on the neighbour and read
|
|
557
|
+
* as a column out.
|
|
558
|
+
*/
|
|
559
|
+
.gridkit-data-grid .header-cell.is-drop-before {
|
|
560
|
+
box-shadow: inset var(--gridkit-indicator-width) 0 0 0 var(--gridkit-accent);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
.gridkit-data-grid .header-cell.is-drop-after {
|
|
564
|
+
box-shadow: inset calc(var(--gridkit-indicator-width) * -1) 0 0 0
|
|
565
|
+
var(--gridkit-accent);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/*
|
|
569
|
+
* Docked to the header's own right edge, absolutely — like the resize
|
|
570
|
+
* handle, and for the same reason: sitting in the label's normal flow, a
|
|
571
|
+
* long label under `text-overflow: ellipsis` pushes the toggle out past
|
|
572
|
+
* where `overflow: hidden` clips it, leaving it unclickable (a real click
|
|
573
|
+
* there lands on the header cell instead and selects the column). Docked
|
|
574
|
+
* to a fixed offset, it stays inside the clipped area — and clear of the
|
|
575
|
+
* resize handle's own 6px strip at `right: 0`, so a resizable, sortable
|
|
576
|
+
* column keeps two independent hit targets rather than one shadowing the
|
|
577
|
+
* other.
|
|
578
|
+
*/
|
|
579
|
+
.gridkit-data-grid .header-sort-toggle {
|
|
580
|
+
display: inline-flex;
|
|
581
|
+
position: absolute;
|
|
582
|
+
top: 50%;
|
|
583
|
+
right: calc(var(--gridkit-spacing) * 3);
|
|
584
|
+
transform: translateY(-50%);
|
|
585
|
+
align-items: center;
|
|
586
|
+
gap: calc(var(--gridkit-spacing) * 0.5);
|
|
587
|
+
cursor: pointer;
|
|
588
|
+
color: var(--gridkit-fg-muted);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
.gridkit-data-grid .header-sort-toggle svg {
|
|
592
|
+
width: var(--gridkit-header-icon-size);
|
|
593
|
+
height: var(--gridkit-header-icon-size);
|
|
594
|
+
flex-shrink: 0;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/*
|
|
598
|
+
* Hidden until the column has a direction or the header is hovered or
|
|
599
|
+
* focused — an unsorted, un-hovered header stays quiet.
|
|
600
|
+
*/
|
|
601
|
+
.gridkit-data-grid
|
|
602
|
+
.header-sort-toggle:not(.is-sorted-asc):not(.is-sorted-desc) {
|
|
603
|
+
opacity: 0;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
.gridkit-data-grid .grid-header .header-cell:hover .header-sort-toggle,
|
|
607
|
+
.gridkit-data-grid .header-cell:focus-visible .header-sort-toggle {
|
|
608
|
+
opacity: 1;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
.gridkit-data-grid .header-sort-toggle.is-sorted-asc,
|
|
612
|
+
.gridkit-data-grid .header-sort-toggle.is-sorted-desc {
|
|
613
|
+
opacity: 1;
|
|
614
|
+
color: var(--gridkit-accent);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
/* One chevron covers both directions; `desc` is `asc` turned upside down. */
|
|
618
|
+
.gridkit-data-grid .header-sort-toggle.is-sorted-desc svg {
|
|
619
|
+
transform: rotate(180deg);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
.gridkit-data-grid .header-sort-priority {
|
|
623
|
+
font-size: calc(var(--gridkit-hint-font-size) * 5 / 6);
|
|
624
|
+
line-height: 1;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
.gridkit-data-grid:not(.no-hover-columns) .grid-header .header-cell:hover {
|
|
628
|
+
background-color: var(--gridkit-surface-muted);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
/*
|
|
632
|
+
* Docked before the label, in normal flow rather than absolutely
|
|
633
|
+
* positioned like the sort toggle and resize handle — see the component's
|
|
634
|
+
* own note on why. Faint until grouped, hovered, or focused, the same
|
|
635
|
+
* restraint `.header-sort-toggle` uses for an unsorted header.
|
|
636
|
+
*/
|
|
637
|
+
.gridkit-data-grid .header-group-toggle {
|
|
638
|
+
display: inline-flex;
|
|
639
|
+
align-items: center;
|
|
640
|
+
vertical-align: middle;
|
|
641
|
+
margin-right: calc(var(--gridkit-spacing) * 1.5);
|
|
642
|
+
cursor: pointer;
|
|
643
|
+
color: var(--gridkit-fg-muted);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
.gridkit-data-grid .header-group-toggle svg {
|
|
647
|
+
width: var(--gridkit-header-icon-size);
|
|
648
|
+
height: var(--gridkit-header-icon-size);
|
|
649
|
+
flex-shrink: 0;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
.gridkit-data-grid .header-group-toggle:not(.is-grouped) {
|
|
653
|
+
opacity: 0.35;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
.gridkit-data-grid .grid-header .header-cell:hover .header-group-toggle,
|
|
657
|
+
.gridkit-data-grid .header-cell:focus-visible .header-group-toggle {
|
|
658
|
+
opacity: 1;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
.gridkit-data-grid .header-group-toggle.is-grouped {
|
|
662
|
+
opacity: 1;
|
|
663
|
+
color: var(--gridkit-accent);
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
/*
|
|
667
|
+
* Docked to the header's end, absolutely, for the sort toggle's reasons —
|
|
668
|
+
* at the very end, where a spreadsheet keeps its filter button, with a
|
|
669
|
+
* sortable column's sort toggle moved over beside it. Hidden until the
|
|
670
|
+
* header is hovered or focused, as an unsorted sort toggle is, and shown,
|
|
671
|
+
* filled in accent, while the column is filtered: the one sign of it on
|
|
672
|
+
* screen.
|
|
673
|
+
*/
|
|
674
|
+
.gridkit-data-grid .header-filter-toggle {
|
|
675
|
+
display: inline-flex;
|
|
676
|
+
position: absolute;
|
|
677
|
+
top: 50%;
|
|
678
|
+
right: calc(var(--gridkit-spacing) * 3);
|
|
679
|
+
transform: translateY(-50%);
|
|
680
|
+
align-items: center;
|
|
681
|
+
cursor: pointer;
|
|
682
|
+
color: var(--gridkit-fg-muted);
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
.gridkit-data-grid .header-filter-toggle svg {
|
|
686
|
+
width: var(--gridkit-header-icon-size);
|
|
687
|
+
height: var(--gridkit-header-icon-size);
|
|
688
|
+
flex-shrink: 0;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
.gridkit-data-grid .header-filter-toggle:not(.is-filtered) {
|
|
692
|
+
opacity: 0;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
.gridkit-data-grid .grid-header .header-cell:hover .header-filter-toggle,
|
|
696
|
+
.gridkit-data-grid .header-cell:focus-visible .header-filter-toggle {
|
|
697
|
+
opacity: 1;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
.gridkit-data-grid .header-filter-toggle.is-filtered {
|
|
701
|
+
color: var(--gridkit-accent);
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
.gridkit-data-grid .header-filter-toggle.is-filtered svg {
|
|
705
|
+
fill: currentColor;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
.gridkit-data-grid
|
|
709
|
+
.header-cell:has(> .header-filter-toggle)
|
|
710
|
+
.header-sort-toggle {
|
|
711
|
+
/* The filter button's offset and width, then a gap. */
|
|
712
|
+
right: calc(var(--gridkit-spacing) * 4.5 + var(--gridkit-header-icon-size));
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
.gridkit-data-grid .grid-cell {
|
|
716
|
+
padding: var(--gridkit-cell-padding-y) var(--gridkit-cell-padding-x);
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
.gridkit-data-grid:not(.no-hover-cells) .grid-cell:hover {
|
|
720
|
+
outline: var(--gridkit-border-width) solid var(--gridkit-hover-line);
|
|
721
|
+
background-color: var(--gridkit-surface-muted);
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
/*
|
|
725
|
+
* Every second row, told by its `data-gridkit-row-index` ending in an odd
|
|
726
|
+
* digit. Not `:nth-child`: a virtualized grid mounts only the rows near the
|
|
727
|
+
* scroll position, after a spacer row, so a row's place among its siblings
|
|
728
|
+
* changes as it scrolls while its index does not. Ahead of the hover and
|
|
729
|
+
* selection rules, which win over it.
|
|
730
|
+
*/
|
|
731
|
+
.gridkit-data-grid
|
|
732
|
+
.grid-row:where(
|
|
733
|
+
[data-gridkit-row-index$="1"],
|
|
734
|
+
[data-gridkit-row-index$="3"],
|
|
735
|
+
[data-gridkit-row-index$="5"],
|
|
736
|
+
[data-gridkit-row-index$="7"],
|
|
737
|
+
[data-gridkit-row-index$="9"]
|
|
738
|
+
) {
|
|
739
|
+
background-color: var(--gridkit-row-stripe-bg);
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
.gridkit-data-grid:not(.no-hover-rows) .grid-row:hover {
|
|
743
|
+
background-color: var(--gridkit-row-hover-bg);
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
/*
|
|
747
|
+
* A group header — one cell spanning every column, not a `.grid-cell` — so
|
|
748
|
+
* it gets its own rules rather than sharing the data-cell ones above.
|
|
749
|
+
*/
|
|
750
|
+
.gridkit-data-grid .grid-group-row {
|
|
751
|
+
cursor: pointer;
|
|
752
|
+
background-color: var(--gridkit-group-row-bg);
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
.gridkit-data-grid .grid-group-row:hover {
|
|
756
|
+
background-color: var(--gridkit-selected);
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
/*
|
|
760
|
+
* Padding lives on `.grid-group-cell-content` (the inner `div`), not here:
|
|
761
|
+
* see that component's own note on why the flex layout is one level in
|
|
762
|
+
* rather than on the `<td>` itself.
|
|
763
|
+
*/
|
|
764
|
+
.gridkit-data-grid .grid-group-cell {
|
|
765
|
+
padding: 0;
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
.gridkit-data-grid .grid-group-cell:focus-visible {
|
|
769
|
+
outline: var(--gridkit-focus-ring-width) solid var(--gridkit-focus-ring);
|
|
770
|
+
outline-offset: calc(var(--gridkit-focus-ring-width) * -1);
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
.gridkit-data-grid .grid-group-cell-content {
|
|
774
|
+
display: flex;
|
|
775
|
+
align-items: center;
|
|
776
|
+
gap: calc(var(--gridkit-spacing) * 2);
|
|
777
|
+
padding: var(--gridkit-cell-padding-y) var(--gridkit-cell-padding-x);
|
|
778
|
+
font-weight: var(--gridkit-group-font-weight);
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
/* A right-pointing triangle that rotates open on expand. */
|
|
782
|
+
.gridkit-data-grid .grid-group-row .group-toggle {
|
|
783
|
+
display: inline-block;
|
|
784
|
+
flex-shrink: 0;
|
|
785
|
+
width: 0;
|
|
786
|
+
height: 0;
|
|
787
|
+
border-style: solid;
|
|
788
|
+
border-width: calc(var(--gridkit-icon-size) / 4) 0
|
|
789
|
+
calc(var(--gridkit-icon-size) / 4) calc(var(--gridkit-icon-size) * 0.4);
|
|
790
|
+
border-color: transparent transparent transparent var(--gridkit-fg-muted);
|
|
791
|
+
transition: transform var(--gridkit-transition-duration) ease;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
.gridkit-data-grid .grid-group-row .group-toggle.is-expanded {
|
|
795
|
+
transform: rotate(90deg);
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
/*
|
|
799
|
+
* Set on the rule rather than on `--gridkit-transition-duration`, so a
|
|
800
|
+
* theme's own duration can't bring the motion back.
|
|
801
|
+
*/
|
|
802
|
+
@media (prefers-reduced-motion: reduce) {
|
|
803
|
+
.gridkit-data-grid .grid-group-row .group-toggle {
|
|
804
|
+
transition: none;
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
.gridkit-data-grid .grid-group-row .group-count {
|
|
809
|
+
font-weight: 400;
|
|
810
|
+
color: var(--gridkit-fg-muted);
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
/*
|
|
814
|
+
* A group's own subtotals, inline after its count — `gap` on the parent
|
|
815
|
+
* `.grid-group-cell-content` already spaces every child, this just keeps
|
|
816
|
+
* multiple aggregates readable as a list rather than running together.
|
|
817
|
+
*/
|
|
818
|
+
.gridkit-data-grid .grid-group-row .group-aggregates {
|
|
819
|
+
display: flex;
|
|
820
|
+
gap: calc(var(--gridkit-spacing) * 3);
|
|
821
|
+
margin-inline-start: calc(var(--gridkit-spacing) * 2);
|
|
822
|
+
font-weight: 400;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
.gridkit-data-grid .grid-group-row .group-aggregate {
|
|
826
|
+
color: var(--gridkit-fg-muted);
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
/*
|
|
830
|
+
* The grand-total footer, styled as the header's counterpart: the
|
|
831
|
+
* surface the header has by default, the same cell padding, and the weight
|
|
832
|
+
* of the group rows' totals. No border by default, matching the
|
|
833
|
+
* header's own `.header-cell` — see the `borders-*` variants below for
|
|
834
|
+
* the opt-in top border that echoes the header's bottom one.
|
|
835
|
+
*/
|
|
836
|
+
.gridkit-data-grid .grid-footer {
|
|
837
|
+
background-color: var(--gridkit-surface);
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
.gridkit-data-grid .grid-footer-cell {
|
|
841
|
+
padding: var(--gridkit-cell-padding-y) var(--gridkit-cell-padding-x);
|
|
842
|
+
font-weight: var(--gridkit-group-font-weight);
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
/*
|
|
846
|
+
* A group's own summary row (`groupAggregateDisplay: "row"`) — the
|
|
847
|
+
* per-column-cell alternative to `.group-aggregates`' inline text.
|
|
848
|
+
* Shares the group header's background so the pair read as one unit,
|
|
849
|
+
* but is presentational: no hover state, no pointer cursor, matching
|
|
850
|
+
* `GridGroupSummaryRow`'s own lack of any click/focus handling.
|
|
851
|
+
*/
|
|
852
|
+
.gridkit-data-grid .grid-group-summary-row {
|
|
853
|
+
background-color: var(--gridkit-group-row-bg);
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
.gridkit-data-grid .grid-group-summary-cell {
|
|
857
|
+
padding: var(--gridkit-cell-padding-y) var(--gridkit-cell-padding-x);
|
|
858
|
+
font-weight: var(--gridkit-group-font-weight);
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
/*
|
|
862
|
+
* `infiniteScroll`'s built-in loading row — aria-hidden and outside
|
|
863
|
+
* `aria-rowcount` (see `GridBody`), so this is a purely visual cue, not an
|
|
864
|
+
* announced one.
|
|
865
|
+
*/
|
|
866
|
+
.gridkit-data-grid .grid-loading-cell {
|
|
867
|
+
padding: var(--gridkit-cell-padding-y) var(--gridkit-cell-padding-x);
|
|
868
|
+
color: var(--gridkit-fg-muted);
|
|
869
|
+
text-align: center;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
/*
|
|
873
|
+
* Indents only the first cell, matching how `GridGroupRow`'s own
|
|
874
|
+
* `paddingInlineStart` indents just the one spanning cell it has — an
|
|
875
|
+
* empty, `aria-hidden` inline spacer rather than padding on the `<td>`
|
|
876
|
+
* itself, so the cell's own content still aligns flush with the column
|
|
877
|
+
* above and below it once the indent's width is accounted for.
|
|
878
|
+
*/
|
|
879
|
+
.gridkit-data-grid .grid-group-summary-indent {
|
|
880
|
+
display: inline-block;
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
/*
|
|
884
|
+
* Selection, after the hover rules so that a selected row hovered stays
|
|
885
|
+
* selected — the two would otherwise be the same colour, since hover already
|
|
886
|
+
* claims `--gridkit-surface-muted`.
|
|
887
|
+
*
|
|
888
|
+
* A selected cell wins over its row and its column: it is the more specific
|
|
889
|
+
* thing the user pointed at, and the rule below it says so by ordering.
|
|
890
|
+
*/
|
|
891
|
+
.gridkit-data-grid .grid-row.is-selected,
|
|
892
|
+
.gridkit-data-grid .header-cell.is-selected,
|
|
893
|
+
.gridkit-data-grid .grid-cell.is-selected {
|
|
894
|
+
background-color: var(--gridkit-selected);
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
.gridkit-data-grid:not(.no-hover-rows) .grid-row.is-selected:hover,
|
|
898
|
+
.gridkit-data-grid:not(.no-hover-cells) .grid-cell.is-selected:hover,
|
|
899
|
+
.gridkit-data-grid:not(.no-hover-columns)
|
|
900
|
+
.grid-header
|
|
901
|
+
.header-cell.is-selected:hover {
|
|
902
|
+
background-color: var(--gridkit-selected-strong);
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
/*
|
|
906
|
+
* Only where a press does something. A grid that merely displays data keeps
|
|
907
|
+
* the default cursor, which is what says it is not interactive.
|
|
908
|
+
*
|
|
909
|
+
* A reorderable header keeps its `grab`: it is the rarer affordance and the
|
|
910
|
+
* one a user would not otherwise guess, and its header still selects.
|
|
911
|
+
*/
|
|
912
|
+
.gridkit-data-grid.selectable-rows .grid-row,
|
|
913
|
+
.gridkit-data-grid.selectable-cells .grid-cell,
|
|
914
|
+
.gridkit-data-grid.selectable-columns
|
|
915
|
+
.grid-header
|
|
916
|
+
.header-cell:not(.is-reorderable) {
|
|
917
|
+
cursor: pointer;
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
/*
|
|
921
|
+
* A Shift-click takes a range of rows, and would otherwise take a range of
|
|
922
|
+
* text along with it — leaving the browser's own highlight smeared across
|
|
923
|
+
* every cell it crossed.
|
|
924
|
+
*
|
|
925
|
+
* The cost is that the text no longer drags out to be copied, which is why
|
|
926
|
+
* this is scoped to a grid that asked for selection rather than applied to
|
|
927
|
+
* all of them.
|
|
928
|
+
*/
|
|
929
|
+
.gridkit-data-grid.selectable-rows .grid-row,
|
|
930
|
+
.gridkit-data-grid.selectable-cells .grid-cell {
|
|
931
|
+
user-select: none;
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
/*
|
|
935
|
+
* Horizontal borders.
|
|
936
|
+
*
|
|
937
|
+
* Header, body, and footer are three separate `<table>`s, so
|
|
938
|
+
* `border-collapse` only ever merges borders within one of them — it
|
|
939
|
+
* cannot merge a header border against a body border the way it would
|
|
940
|
+
* merge two adjacent body rows' borders in one shared `<tbody>`. Each seam
|
|
941
|
+
* below is therefore deliberately defined from one side only, never both,
|
|
942
|
+
* or the two tables' independent borders would render as a doubled line
|
|
943
|
+
* instead of collapsing into one:
|
|
944
|
+
* - header/body seam: the header's own `border-bottom` here. The body's
|
|
945
|
+
* first row never sets a `border-top` of its own.
|
|
946
|
+
* - body/footer seam: the footer's own `border-top` (below, alongside
|
|
947
|
+
* `.grid-footer-cell`). The body's last row has its `border-bottom`
|
|
948
|
+
* stripped (below, `.grid-row:last-child`) specifically so it never
|
|
949
|
+
* supplies the other half of this seam.
|
|
950
|
+
*/
|
|
951
|
+
.gridkit-data-grid.borders-horizontal .grid-header .header-cell,
|
|
952
|
+
.gridkit-data-grid.borders-horizontal .grid-cell,
|
|
953
|
+
.gridkit-data-grid.borders-horizontal .grid-group-cell,
|
|
954
|
+
.gridkit-data-grid.borders-horizontal .grid-group-summary-cell {
|
|
955
|
+
border-bottom: var(--gridkit-row-line-width) var(--gridkit-border-style)
|
|
956
|
+
var(--gridkit-line);
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
/*
|
|
960
|
+
* The footer's own top border, echoing the header's bottom-anchored one —
|
|
961
|
+
* a `border-top` rather than a `border-bottom` on the last body row, since
|
|
962
|
+
* the footer sits in its own `<table>` entirely, sibling to the body's.
|
|
963
|
+
*/
|
|
964
|
+
.gridkit-data-grid.borders-horizontal .grid-footer-cell,
|
|
965
|
+
.gridkit-data-grid.borders-all .grid-footer-cell {
|
|
966
|
+
border-top: var(--gridkit-row-line-width) var(--gridkit-border-style)
|
|
967
|
+
var(--gridkit-line);
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
/*
|
|
971
|
+
* The last row's bottom edge has no row below it to collapse with, so
|
|
972
|
+
* unlike every internal boundary it is a genuinely extra line — the same
|
|
973
|
+
* reason `borders-vertical` drops its `:last-child` border-right below.
|
|
974
|
+
* Matched against both row kinds: the last rendered row can just as well
|
|
975
|
+
* be a collapsed group header as a data row.
|
|
976
|
+
*/
|
|
977
|
+
.gridkit-data-grid.borders-horizontal .grid-row:last-child .grid-cell,
|
|
978
|
+
.gridkit-data-grid.borders-horizontal
|
|
979
|
+
.grid-group-row:last-child
|
|
980
|
+
.grid-group-cell,
|
|
981
|
+
.gridkit-data-grid.borders-horizontal
|
|
982
|
+
.grid-group-summary-row:last-child
|
|
983
|
+
.grid-group-summary-cell {
|
|
984
|
+
border-bottom: none;
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
/* Vertical borders */
|
|
988
|
+
.gridkit-data-grid.borders-vertical .grid-header .header-cell,
|
|
989
|
+
.gridkit-data-grid.borders-vertical .grid-cell,
|
|
990
|
+
.gridkit-data-grid.borders-vertical .grid-footer-cell,
|
|
991
|
+
.gridkit-data-grid.borders-vertical .grid-group-summary-cell {
|
|
992
|
+
border-right: var(--gridkit-column-line-width) var(--gridkit-border-style)
|
|
993
|
+
var(--gridkit-line);
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
.gridkit-data-grid.borders-vertical .grid-header .header-cell:last-child,
|
|
997
|
+
.gridkit-data-grid.borders-vertical .grid-cell:last-child,
|
|
998
|
+
.gridkit-data-grid.borders-vertical .grid-footer-cell:last-child,
|
|
999
|
+
.gridkit-data-grid.borders-vertical .grid-group-summary-cell:last-child {
|
|
1000
|
+
border-right: none;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
/* Borders on all sides */
|
|
1004
|
+
.gridkit-data-grid.borders-all .grid-header .header-cell,
|
|
1005
|
+
.gridkit-data-grid.borders-all .grid-cell,
|
|
1006
|
+
.gridkit-data-grid.borders-all .grid-group-cell,
|
|
1007
|
+
.gridkit-data-grid.borders-all .grid-group-summary-cell {
|
|
1008
|
+
border-bottom: var(--gridkit-row-line-width) var(--gridkit-border-style)
|
|
1009
|
+
var(--gridkit-line);
|
|
1010
|
+
border-right: var(--gridkit-column-line-width) var(--gridkit-border-style)
|
|
1011
|
+
var(--gridkit-line);
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
.gridkit-data-grid.borders-all .grid-footer-cell {
|
|
1015
|
+
border-right: var(--gridkit-column-line-width) var(--gridkit-border-style)
|
|
1016
|
+
var(--gridkit-line);
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
/*
|
|
1020
|
+
* The outer left/right edges have no neighbouring cell to collapse with, so
|
|
1021
|
+
* unlike every internal boundary they are a genuinely extra line — without
|
|
1022
|
+
* this the table would render two lines wider than the sum of its columns. A
|
|
1023
|
+
* group cell is both its row's first and last child at once (it is the
|
|
1024
|
+
* only cell), so it takes both exceptions.
|
|
1025
|
+
*/
|
|
1026
|
+
.gridkit-data-grid.borders-all .grid-header .header-cell:first-child,
|
|
1027
|
+
.gridkit-data-grid.borders-all .grid-cell:first-child,
|
|
1028
|
+
.gridkit-data-grid.borders-all .grid-group-cell,
|
|
1029
|
+
.gridkit-data-grid.borders-all .grid-footer-cell:first-child,
|
|
1030
|
+
.gridkit-data-grid.borders-all .grid-group-summary-cell:first-child {
|
|
1031
|
+
border-left: none;
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
.gridkit-data-grid.borders-all .grid-header .header-cell:last-child,
|
|
1035
|
+
.gridkit-data-grid.borders-all .grid-cell:last-child,
|
|
1036
|
+
.gridkit-data-grid.borders-all .grid-group-cell,
|
|
1037
|
+
.gridkit-data-grid.borders-all .grid-footer-cell:last-child,
|
|
1038
|
+
.gridkit-data-grid.borders-all .grid-group-summary-cell:last-child {
|
|
1039
|
+
border-right: none;
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
.gridkit-data-grid.borders-all .grid-row:last-child .grid-cell,
|
|
1043
|
+
.gridkit-data-grid.borders-all .grid-group-row:last-child .grid-group-cell,
|
|
1044
|
+
.gridkit-data-grid.borders-all
|
|
1045
|
+
.grid-group-summary-row:last-child
|
|
1046
|
+
.grid-group-summary-cell {
|
|
1047
|
+
border-bottom: none;
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
/*
|
|
1051
|
+
* The toolbar: the grid's first child, above the group-by bar, and unscoped
|
|
1052
|
+
* by `.gridkit-data-grid` for the same reason that bar is. The grid scrolls
|
|
1053
|
+
* sideways with everything in it, so the toolbar sticks to its start edge
|
|
1054
|
+
* and stays in view while the tables scroll on under it.
|
|
1055
|
+
*
|
|
1056
|
+
* Its entries keep to one row at their own widths, which is what the
|
|
1057
|
+
* overflow measures: what does not fit goes into "More", and `overflow:
|
|
1058
|
+
* hidden` keeps the frame before that from spilling out of the toolbar.
|
|
1059
|
+
*/
|
|
1060
|
+
.gridkit-toolbar {
|
|
1061
|
+
position: sticky;
|
|
1062
|
+
inset-inline-start: 0;
|
|
1063
|
+
display: flex;
|
|
1064
|
+
align-items: center;
|
|
1065
|
+
gap: calc(var(--gridkit-spacing) * 2);
|
|
1066
|
+
padding: var(--gridkit-toolbar-padding);
|
|
1067
|
+
overflow: hidden;
|
|
1068
|
+
font-size: var(--gridkit-bar-font-size);
|
|
1069
|
+
color: var(--gridkit-fg);
|
|
1070
|
+
background-color: var(--gridkit-surface);
|
|
1071
|
+
border-bottom: var(--gridkit-border-width) var(--gridkit-border-style)
|
|
1072
|
+
var(--gridkit-line);
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
.gridkit-toolbar > * {
|
|
1076
|
+
flex-shrink: 0;
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
/*
|
|
1080
|
+
* The search box and custom entries never move into "More", so together
|
|
1081
|
+
* they can be wider than the toolbar. "More" then sticks to its end edge,
|
|
1082
|
+
* over what is clipped there, rather than being clipped itself.
|
|
1083
|
+
*/
|
|
1084
|
+
.gridkit-toolbar > .toolbar-more {
|
|
1085
|
+
position: sticky;
|
|
1086
|
+
/* Counted from the toolbar's padding edge, so its padding again. */
|
|
1087
|
+
inset-inline-end: var(--gridkit-toolbar-padding);
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
/* A command, a dropdown, or "More". */
|
|
1091
|
+
.toolbar-button {
|
|
1092
|
+
display: inline-flex;
|
|
1093
|
+
align-items: center;
|
|
1094
|
+
gap: calc(var(--gridkit-spacing) * 1.5);
|
|
1095
|
+
padding: var(--gridkit-spacing) calc(var(--gridkit-spacing) * 2.5);
|
|
1096
|
+
font: inherit;
|
|
1097
|
+
color: var(--gridkit-fg);
|
|
1098
|
+
white-space: nowrap;
|
|
1099
|
+
cursor: pointer;
|
|
1100
|
+
background-color: var(--gridkit-surface);
|
|
1101
|
+
border: var(--gridkit-border-width) solid var(--gridkit-line);
|
|
1102
|
+
border-radius: var(--gridkit-control-radius);
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
.toolbar-button:hover:not([aria-disabled="true"]),
|
|
1106
|
+
.toolbar-button[aria-expanded="true"] {
|
|
1107
|
+
background-color: var(--gridkit-surface-muted);
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
.toolbar-button:focus-visible {
|
|
1111
|
+
outline: var(--gridkit-focus-ring-width) solid var(--gridkit-focus-ring);
|
|
1112
|
+
outline-offset: 1px;
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
/* Still focusable, as a menu's disabled item is, so a screen reader finds it. */
|
|
1116
|
+
.toolbar-button[aria-disabled="true"] {
|
|
1117
|
+
color: var(--gridkit-fg-muted);
|
|
1118
|
+
cursor: default;
|
|
1119
|
+
opacity: 0.5;
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
/* A toggle that is on. */
|
|
1123
|
+
.toolbar-button[aria-pressed="true"],
|
|
1124
|
+
.toolbar-button[aria-pressed="true"]:hover {
|
|
1125
|
+
background-color: var(--gridkit-selected-strong);
|
|
1126
|
+
border-color: var(--gridkit-accent);
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
.toolbar-button-icon,
|
|
1130
|
+
.toolbar-button-indicator {
|
|
1131
|
+
display: inline-flex;
|
|
1132
|
+
color: var(--gridkit-fg-muted);
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
/* An icon key the grid has no glyph for draws nothing, and takes no room. */
|
|
1136
|
+
.toolbar-button-icon:empty {
|
|
1137
|
+
display: none;
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
.toolbar-button-icon svg,
|
|
1141
|
+
.toolbar-button-indicator svg {
|
|
1142
|
+
width: var(--gridkit-icon-size);
|
|
1143
|
+
height: var(--gridkit-icon-size);
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
.toolbar-button-indicator {
|
|
1147
|
+
margin-inline-end: calc(var(--gridkit-spacing) * -1);
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
/*
|
|
1151
|
+
* Narrower in a narrow toolbar, by the toolbar's width alone — never by
|
|
1152
|
+
* what else is in it, which the overflow would measure as a width of its
|
|
1153
|
+
* own — so it leaves room for "More" beside it.
|
|
1154
|
+
*/
|
|
1155
|
+
.toolbar-search {
|
|
1156
|
+
width: 12rem;
|
|
1157
|
+
max-width: 50%;
|
|
1158
|
+
padding: var(--gridkit-spacing) calc(var(--gridkit-spacing) * 2);
|
|
1159
|
+
font: inherit;
|
|
1160
|
+
color: var(--gridkit-fg);
|
|
1161
|
+
background-color: var(--gridkit-surface);
|
|
1162
|
+
border: var(--gridkit-border-width) solid var(--gridkit-line);
|
|
1163
|
+
border-radius: var(--gridkit-control-radius);
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
.toolbar-search::placeholder {
|
|
1167
|
+
color: var(--gridkit-fg-muted);
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
.toolbar-search:focus-visible {
|
|
1171
|
+
outline: var(--gridkit-focus-ring-width) solid var(--gridkit-focus-ring);
|
|
1172
|
+
outline-offset: 1px;
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
.toolbar-separator {
|
|
1176
|
+
align-self: stretch;
|
|
1177
|
+
width: var(--gridkit-border-width);
|
|
1178
|
+
margin: calc(var(--gridkit-spacing) * 0.5) 0;
|
|
1179
|
+
background-color: var(--gridkit-line);
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
/* Takes the free space, pushing what follows it to the far end. */
|
|
1183
|
+
.gridkit-toolbar > .toolbar-spacer {
|
|
1184
|
+
flex: 1 1 0;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
/* Holds what `renderToolbarItem` drew. */
|
|
1188
|
+
.toolbar-custom {
|
|
1189
|
+
display: inline-flex;
|
|
1190
|
+
align-items: center;
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
/*
|
|
1194
|
+
* The group-by bar. A sibling of the table, not a row inside it — see
|
|
1195
|
+
* `GroupByBar.tsx`'s own note on why — so it's unscoped by `.gridkit-data-grid`
|
|
1196
|
+
* the way `.gridkit-sr-only` is.
|
|
1197
|
+
*/
|
|
1198
|
+
.gridkit-group-by-bar {
|
|
1199
|
+
display: flex;
|
|
1200
|
+
flex-wrap: wrap;
|
|
1201
|
+
align-items: center;
|
|
1202
|
+
gap: calc(var(--gridkit-spacing) * 2);
|
|
1203
|
+
padding: var(--gridkit-group-by-bar-padding);
|
|
1204
|
+
background-color: var(--gridkit-surface);
|
|
1205
|
+
border-bottom: var(--gridkit-border-width) var(--gridkit-border-style)
|
|
1206
|
+
var(--gridkit-line);
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
/*
|
|
1210
|
+
* Drawn while a chip or an eligible header is being dragged — a dashed
|
|
1211
|
+
* outline marking the bar itself as a valid drop zone, load-bearing when
|
|
1212
|
+
* it's otherwise empty, with no chip of its own to show a drop indicator
|
|
1213
|
+
* on. Where exactly the drop would land is the chips' own
|
|
1214
|
+
* `is-drop-before`/`is-drop-after` marks; this outline doesn't also wash
|
|
1215
|
+
* the bar's background once hovered — the marks are enough on their own.
|
|
1216
|
+
*/
|
|
1217
|
+
.gridkit-group-by-bar.is-drag-target {
|
|
1218
|
+
outline: var(--gridkit-indicator-width) dashed var(--gridkit-accent);
|
|
1219
|
+
outline-offset: calc(var(--gridkit-indicator-width) * -1);
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
/*
|
|
1223
|
+
* A header already in the group-by stack, dragged back toward it — never a
|
|
1224
|
+
* valid drop, so no accent outline invites it: a muted dashed line in the
|
|
1225
|
+
* same neutral tone as the grid's own borders, plus a `not-allowed` cursor
|
|
1226
|
+
* for the pointer icon itself.
|
|
1227
|
+
*/
|
|
1228
|
+
.gridkit-group-by-bar.is-drag-blocked {
|
|
1229
|
+
cursor: not-allowed;
|
|
1230
|
+
outline: var(--gridkit-indicator-width) dashed var(--gridkit-line);
|
|
1231
|
+
outline-offset: calc(var(--gridkit-indicator-width) * -1);
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
.group-by-bar-placeholder {
|
|
1235
|
+
font-size: var(--gridkit-bar-font-size);
|
|
1236
|
+
color: var(--gridkit-fg-muted);
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
.group-by-chip {
|
|
1240
|
+
position: relative;
|
|
1241
|
+
display: inline-flex;
|
|
1242
|
+
align-items: center;
|
|
1243
|
+
gap: calc(var(--gridkit-spacing) * 1.5);
|
|
1244
|
+
padding: var(--gridkit-spacing) calc(var(--gridkit-spacing) * 2);
|
|
1245
|
+
font-size: var(--gridkit-bar-font-size);
|
|
1246
|
+
color: var(--gridkit-fg);
|
|
1247
|
+
background-color: var(--gridkit-selected);
|
|
1248
|
+
border-radius: 9999px;
|
|
1249
|
+
cursor: grab;
|
|
1250
|
+
touch-action: none;
|
|
1251
|
+
user-select: none;
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
.group-by-chip:focus-visible {
|
|
1255
|
+
outline: var(--gridkit-focus-ring-width) solid var(--gridkit-focus-ring);
|
|
1256
|
+
outline-offset: 1px;
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
.group-by-chip.is-dragging {
|
|
1260
|
+
cursor: grabbing;
|
|
1261
|
+
opacity: 0.5;
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
/*
|
|
1265
|
+
* Where the chip would land. `.header-cell.is-drop-before`/`.is-drop-after`
|
|
1266
|
+
* draw this as an inset line, but an inset line on a pill this round would
|
|
1267
|
+
* be clipped by the chip's own `border-radius` into a curved sliver rather
|
|
1268
|
+
* than a clean mark — so this is a `::before`/`::after` mark of its own
|
|
1269
|
+
* instead, centred in the bar's gap beside the chip. Absolutely positioned and
|
|
1270
|
+
* so out of flow, it never shifts the chip or its neighbors the way a
|
|
1271
|
+
* change to border or padding would.
|
|
1272
|
+
*/
|
|
1273
|
+
.group-by-chip.is-drop-before::before,
|
|
1274
|
+
.group-by-chip.is-drop-after::after {
|
|
1275
|
+
content: "";
|
|
1276
|
+
position: absolute;
|
|
1277
|
+
top: 0;
|
|
1278
|
+
bottom: 0;
|
|
1279
|
+
width: var(--gridkit-indicator-width);
|
|
1280
|
+
border-radius: calc(var(--gridkit-indicator-width) / 2);
|
|
1281
|
+
background-color: var(--gridkit-accent);
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
.group-by-chip.is-drop-before::before {
|
|
1285
|
+
left: calc(
|
|
1286
|
+
var(--gridkit-spacing) * -1 - var(--gridkit-indicator-width) / 2
|
|
1287
|
+
);
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
.group-by-chip.is-drop-after::after {
|
|
1291
|
+
right: calc(
|
|
1292
|
+
var(--gridkit-spacing) * -1 - var(--gridkit-indicator-width) / 2
|
|
1293
|
+
);
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
/*
|
|
1297
|
+
* The chip trailing the pointer mid-drag. Unlike the header's own
|
|
1298
|
+
* `.gridkit-data-grid.drag-ghost` this can't share that compound selector
|
|
1299
|
+
* — a chip ghost isn't part of the grid's own table — so it restates the
|
|
1300
|
+
* positioning in full rather than only the parts that differ.
|
|
1301
|
+
*/
|
|
1302
|
+
.group-by-chip.drag-ghost {
|
|
1303
|
+
position: fixed;
|
|
1304
|
+
top: 0;
|
|
1305
|
+
left: 0;
|
|
1306
|
+
z-index: 50;
|
|
1307
|
+
border: var(--gridkit-border-width) dashed var(--gridkit-accent);
|
|
1308
|
+
opacity: 0.75;
|
|
1309
|
+
pointer-events: none;
|
|
1310
|
+
will-change: transform;
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
.group-by-chip-remove {
|
|
1314
|
+
display: inline-flex;
|
|
1315
|
+
align-items: center;
|
|
1316
|
+
justify-content: center;
|
|
1317
|
+
width: var(--gridkit-icon-size);
|
|
1318
|
+
height: var(--gridkit-icon-size);
|
|
1319
|
+
padding: 0;
|
|
1320
|
+
line-height: 1;
|
|
1321
|
+
color: inherit;
|
|
1322
|
+
cursor: pointer;
|
|
1323
|
+
background: none;
|
|
1324
|
+
border: none;
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
.group-by-chip-remove:hover {
|
|
1328
|
+
color: var(--gridkit-accent);
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
.group-by-chip-remove:focus-visible {
|
|
1332
|
+
outline: var(--gridkit-focus-ring-width) solid var(--gridkit-focus-ring);
|
|
1333
|
+
outline-offset: 1px;
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
/*
|
|
1337
|
+
* The pager. A sibling of the table, not a row inside it — the same
|
|
1338
|
+
* reasoning `.gridkit-group-by-bar` gives for its own placement — so it's
|
|
1339
|
+
* unscoped by `.gridkit-data-grid` the way that bar is.
|
|
1340
|
+
*/
|
|
1341
|
+
.gridkit-grid-pager {
|
|
1342
|
+
display: flex;
|
|
1343
|
+
flex-wrap: wrap;
|
|
1344
|
+
align-items: center;
|
|
1345
|
+
gap: calc(var(--gridkit-spacing) * 2) calc(var(--gridkit-spacing) * 4);
|
|
1346
|
+
padding: var(--gridkit-pager-padding);
|
|
1347
|
+
font-size: var(--gridkit-bar-font-size);
|
|
1348
|
+
color: var(--gridkit-fg);
|
|
1349
|
+
background-color: var(--gridkit-surface);
|
|
1350
|
+
border-top: var(--gridkit-border-width) var(--gridkit-border-style)
|
|
1351
|
+
var(--gridkit-line);
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
/*
|
|
1355
|
+
* First, previous, the page numbers (or the compact status), next and
|
|
1356
|
+
* last as adjoining segments of one bar: an outer hairline, a shared one
|
|
1357
|
+
* between segments, and the radius on the bar's outer corners only. Every
|
|
1358
|
+
* number slot is the same width, sized by `--gridkit-pager-digits` (the
|
|
1359
|
+
* page count's digits, which the pager sets) in tabular numerals, so with
|
|
1360
|
+
* `paginationWindow`'s constant slot count the arrows never move.
|
|
1361
|
+
*/
|
|
1362
|
+
.grid-pager-bar {
|
|
1363
|
+
--gridkit-pager-segment: calc(var(--gridkit-spacing) * 8);
|
|
1364
|
+
display: inline-flex;
|
|
1365
|
+
align-items: stretch;
|
|
1366
|
+
height: var(--gridkit-pager-segment);
|
|
1367
|
+
font-variant-numeric: tabular-nums;
|
|
1368
|
+
background-color: var(--gridkit-surface);
|
|
1369
|
+
border: var(--gridkit-border-width) solid var(--gridkit-line);
|
|
1370
|
+
border-radius: var(--gridkit-radius);
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
.grid-pager-button,
|
|
1374
|
+
.grid-pager-ellipsis,
|
|
1375
|
+
.grid-pager-status-slot {
|
|
1376
|
+
position: relative;
|
|
1377
|
+
box-sizing: border-box;
|
|
1378
|
+
display: inline-flex;
|
|
1379
|
+
align-items: center;
|
|
1380
|
+
justify-content: center;
|
|
1381
|
+
min-width: var(--gridkit-pager-segment);
|
|
1382
|
+
margin: 0;
|
|
1383
|
+
padding: 0;
|
|
1384
|
+
font: inherit;
|
|
1385
|
+
line-height: 1;
|
|
1386
|
+
color: var(--gridkit-fg);
|
|
1387
|
+
background-color: transparent;
|
|
1388
|
+
border: 0;
|
|
1389
|
+
border-inline-start: var(--gridkit-border-width) solid var(--gridkit-line);
|
|
1390
|
+
border-radius: 0;
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
.grid-pager-bar > :first-child {
|
|
1394
|
+
border-inline-start: 0;
|
|
1395
|
+
border-start-start-radius: calc(
|
|
1396
|
+
var(--gridkit-radius) - var(--gridkit-border-width)
|
|
1397
|
+
);
|
|
1398
|
+
border-end-start-radius: calc(
|
|
1399
|
+
var(--gridkit-radius) - var(--gridkit-border-width)
|
|
1400
|
+
);
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
.grid-pager-bar > :last-child {
|
|
1404
|
+
border-start-end-radius: calc(
|
|
1405
|
+
var(--gridkit-radius) - var(--gridkit-border-width)
|
|
1406
|
+
);
|
|
1407
|
+
border-end-end-radius: calc(
|
|
1408
|
+
var(--gridkit-radius) - var(--gridkit-border-width)
|
|
1409
|
+
);
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
.grid-pager-button {
|
|
1413
|
+
cursor: pointer;
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
.grid-pager-page,
|
|
1417
|
+
.grid-pager-ellipsis {
|
|
1418
|
+
width: max(
|
|
1419
|
+
var(--gridkit-pager-segment),
|
|
1420
|
+
calc(var(--gridkit-pager-digits, 1) * 1ch + var(--gridkit-spacing) * 4)
|
|
1421
|
+
);
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
.grid-pager-nav svg {
|
|
1425
|
+
width: var(--gridkit-icon-size);
|
|
1426
|
+
height: var(--gridkit-icon-size);
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
.grid-pager-nav:dir(rtl) svg {
|
|
1430
|
+
transform: scaleX(-1);
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
.grid-pager-button:hover:not([aria-disabled="true"]) {
|
|
1434
|
+
background-color: var(--gridkit-surface-muted);
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
.grid-pager-button:focus-visible {
|
|
1438
|
+
z-index: 2;
|
|
1439
|
+
outline: var(--gridkit-focus-ring-width) solid var(--gridkit-focus-ring);
|
|
1440
|
+
outline-offset: calc(var(--gridkit-focus-ring-width) * -1);
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
.grid-pager-button[aria-disabled="true"] {
|
|
1444
|
+
color: var(--gridkit-fg-muted);
|
|
1445
|
+
cursor: default;
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
/*
|
|
1449
|
+
* The icon fades rather than the whole button: a disabled arrow keeps
|
|
1450
|
+
* focus once it has paged to the end, and its focus ring should not fade
|
|
1451
|
+
* with it.
|
|
1452
|
+
*/
|
|
1453
|
+
.grid-pager-button[aria-disabled="true"] svg {
|
|
1454
|
+
opacity: 0.45;
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
.grid-pager-button[aria-current="page"],
|
|
1458
|
+
.grid-pager-button[aria-current="page"]:hover {
|
|
1459
|
+
z-index: 1;
|
|
1460
|
+
color: var(--gridkit-accent);
|
|
1461
|
+
background-color: var(--gridkit-selected);
|
|
1462
|
+
box-shadow: inset 0 0 0 var(--gridkit-border-width) var(--gridkit-accent);
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
.grid-pager-ellipsis {
|
|
1466
|
+
color: var(--gridkit-fg-muted);
|
|
1467
|
+
cursor: default;
|
|
1468
|
+
user-select: none;
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
/*
|
|
1472
|
+
* The compact status, stacked on an invisible copy of its widest text so
|
|
1473
|
+
* its segment keeps one width from the first page to the last.
|
|
1474
|
+
*/
|
|
1475
|
+
.grid-pager-status-slot {
|
|
1476
|
+
display: inline-grid;
|
|
1477
|
+
padding: 0 calc(var(--gridkit-spacing) * 3);
|
|
1478
|
+
white-space: nowrap;
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
.grid-pager-status,
|
|
1482
|
+
.grid-pager-status-sizer {
|
|
1483
|
+
grid-area: 1 / 1;
|
|
1484
|
+
text-align: center;
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
.grid-pager-status {
|
|
1488
|
+
color: var(--gridkit-fg-muted);
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1491
|
+
.grid-pager-status-sizer {
|
|
1492
|
+
visibility: hidden;
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
.grid-pager-page-size {
|
|
1496
|
+
display: inline-flex;
|
|
1497
|
+
align-items: center;
|
|
1498
|
+
gap: calc(var(--gridkit-spacing) * 2);
|
|
1499
|
+
color: var(--gridkit-fg-muted);
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
.grid-pager-page-size select {
|
|
1503
|
+
box-sizing: border-box;
|
|
1504
|
+
/* As tall as the pager bar beside it. */
|
|
1505
|
+
height: calc(var(--gridkit-spacing) * 8);
|
|
1506
|
+
padding: 0 calc(var(--gridkit-spacing) * 1.5);
|
|
1507
|
+
font: inherit;
|
|
1508
|
+
font-variant-numeric: tabular-nums;
|
|
1509
|
+
color: var(--gridkit-fg);
|
|
1510
|
+
background-color: var(--gridkit-surface);
|
|
1511
|
+
border: var(--gridkit-border-width) solid var(--gridkit-line);
|
|
1512
|
+
border-radius: var(--gridkit-control-radius);
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
.grid-pager-page-size select:focus-visible {
|
|
1516
|
+
outline: var(--gridkit-focus-ring-width) solid var(--gridkit-focus-ring);
|
|
1517
|
+
outline-offset: 1px;
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
/*
|
|
1521
|
+
* Overlays — the grid's menus and panels — render into `document.body`, outside the
|
|
1522
|
+
* grid and any scrolling ancestor that would clip them, so every selector
|
|
1523
|
+
* from here on is top-level rather than under `.gridkit-data-grid`. The
|
|
1524
|
+
* grid copies the `.gridkit-light`/`.gridkit-dark` it sits under onto the
|
|
1525
|
+
* overlay, since the portal leaves that ancestor's token scope.
|
|
1526
|
+
*
|
|
1527
|
+
* Fixed from the start, so the overlay never takes room at the end of the
|
|
1528
|
+
* page before it is placed; above the grid's own drag ghosts.
|
|
1529
|
+
*/
|
|
1530
|
+
.gridkit-overlay {
|
|
1531
|
+
position: fixed;
|
|
1532
|
+
top: 0;
|
|
1533
|
+
left: 0;
|
|
1534
|
+
z-index: 60;
|
|
1535
|
+
color: var(--gridkit-fg);
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
/*
|
|
1539
|
+
* A menu too tall for the viewport scrolls inside itself — a scroll there
|
|
1540
|
+
* does not dismiss it, as one outside would.
|
|
1541
|
+
*/
|
|
1542
|
+
.gridkit-menu {
|
|
1543
|
+
min-width: var(--gridkit-menu-min-width);
|
|
1544
|
+
max-height: 100vh;
|
|
1545
|
+
overflow-y: auto;
|
|
1546
|
+
padding: var(--gridkit-spacing) 0;
|
|
1547
|
+
font-size: var(--gridkit-menu-font-size);
|
|
1548
|
+
background-color: var(--gridkit-surface);
|
|
1549
|
+
border: var(--gridkit-border-width) solid var(--gridkit-line);
|
|
1550
|
+
border-radius: var(--gridkit-menu-radius);
|
|
1551
|
+
box-shadow: var(--gridkit-overlay-shadow)
|
|
1552
|
+
var(--gridkit-overlay-shadow-color);
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
.menu-item {
|
|
1556
|
+
display: flex;
|
|
1557
|
+
align-items: center;
|
|
1558
|
+
gap: calc(var(--gridkit-spacing) * 2);
|
|
1559
|
+
padding: var(--gridkit-menu-item-padding-y)
|
|
1560
|
+
var(--gridkit-menu-item-padding-x);
|
|
1561
|
+
white-space: nowrap;
|
|
1562
|
+
cursor: pointer;
|
|
1563
|
+
user-select: none;
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
/*
|
|
1567
|
+
* `:focus` rather than `:focus-visible`: the pointer moves focus to the
|
|
1568
|
+
* item under it, so focus is the hover state too, and has to show
|
|
1569
|
+
* whichever moved it.
|
|
1570
|
+
*/
|
|
1571
|
+
.menu-item:focus {
|
|
1572
|
+
outline: none;
|
|
1573
|
+
background-color: var(--gridkit-selected);
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
/*
|
|
1577
|
+
* The item whose submenu is open, while focus is in that submenu — the
|
|
1578
|
+
* trail back to it.
|
|
1579
|
+
*/
|
|
1580
|
+
.menu-item[aria-expanded="true"]:not(:focus) {
|
|
1581
|
+
background-color: var(--gridkit-surface-muted);
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
/*
|
|
1585
|
+
* Still focusable, so a screen reader finds it: muted, and marked only
|
|
1586
|
+
* faintly when focused, since choosing it does nothing.
|
|
1587
|
+
*/
|
|
1588
|
+
.menu-item[aria-disabled="true"] {
|
|
1589
|
+
color: var(--gridkit-fg-muted);
|
|
1590
|
+
cursor: default;
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
.menu-item[aria-disabled="true"]:focus {
|
|
1594
|
+
background-color: var(--gridkit-surface-muted);
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
/*
|
|
1598
|
+
* Always there, empty for an item without an icon, so every label in a
|
|
1599
|
+
* menu starts at the same place. A checked item shows its check here.
|
|
1600
|
+
*/
|
|
1601
|
+
.menu-item-icon {
|
|
1602
|
+
display: inline-flex;
|
|
1603
|
+
flex-shrink: 0;
|
|
1604
|
+
align-items: center;
|
|
1605
|
+
justify-content: center;
|
|
1606
|
+
width: var(--gridkit-icon-size);
|
|
1607
|
+
height: var(--gridkit-icon-size);
|
|
1608
|
+
color: var(--gridkit-fg-muted);
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
.menu-item-icon svg,
|
|
1612
|
+
.menu-submenu-indicator svg {
|
|
1613
|
+
width: var(--gridkit-icon-size);
|
|
1614
|
+
height: var(--gridkit-icon-size);
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
.menu-item[aria-checked="true"] .menu-item-icon {
|
|
1618
|
+
color: var(--gridkit-accent);
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
.menu-item-label {
|
|
1622
|
+
flex: 1;
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
.menu-item-shortcut {
|
|
1626
|
+
margin-inline-start: calc(var(--gridkit-spacing) * 6);
|
|
1627
|
+
font-size: var(--gridkit-hint-font-size);
|
|
1628
|
+
color: var(--gridkit-fg-muted);
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
.menu-submenu-indicator {
|
|
1632
|
+
display: inline-flex;
|
|
1633
|
+
margin-inline-end: calc(var(--gridkit-spacing) * -1);
|
|
1634
|
+
color: var(--gridkit-fg-muted);
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
.menu-separator {
|
|
1638
|
+
height: var(--gridkit-border-width);
|
|
1639
|
+
margin: var(--gridkit-spacing) 0;
|
|
1640
|
+
background-color: var(--gridkit-line);
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1643
|
+
/*
|
|
1644
|
+
* The column chooser, an overlay like the menus: a search box, "Show all",
|
|
1645
|
+
* then a checkbox per column. A fixed width, so the panel does not jump
|
|
1646
|
+
* sideways as a search narrows the list.
|
|
1647
|
+
*/
|
|
1648
|
+
.gridkit-column-chooser {
|
|
1649
|
+
display: flex;
|
|
1650
|
+
flex-direction: column;
|
|
1651
|
+
gap: calc(var(--gridkit-spacing) * 1.5);
|
|
1652
|
+
width: var(--gridkit-column-chooser-width);
|
|
1653
|
+
padding: calc(var(--gridkit-spacing) * 2);
|
|
1654
|
+
font-size: var(--gridkit-menu-font-size);
|
|
1655
|
+
background-color: var(--gridkit-surface);
|
|
1656
|
+
border: var(--gridkit-border-width) solid var(--gridkit-line);
|
|
1657
|
+
border-radius: var(--gridkit-menu-radius);
|
|
1658
|
+
box-shadow: var(--gridkit-overlay-shadow)
|
|
1659
|
+
var(--gridkit-overlay-shadow-color);
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1662
|
+
.column-chooser-search {
|
|
1663
|
+
box-sizing: border-box;
|
|
1664
|
+
width: 100%;
|
|
1665
|
+
padding: var(--gridkit-spacing) calc(var(--gridkit-spacing) * 2);
|
|
1666
|
+
font: inherit;
|
|
1667
|
+
color: var(--gridkit-fg);
|
|
1668
|
+
background-color: var(--gridkit-surface);
|
|
1669
|
+
border: var(--gridkit-border-width) solid var(--gridkit-line);
|
|
1670
|
+
border-radius: var(--gridkit-control-radius);
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1673
|
+
.column-chooser-search::placeholder {
|
|
1674
|
+
color: var(--gridkit-fg-muted);
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1677
|
+
.column-chooser-search:focus-visible {
|
|
1678
|
+
outline: var(--gridkit-focus-ring-width) solid var(--gridkit-focus-ring);
|
|
1679
|
+
outline-offset: 1px;
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1682
|
+
/*
|
|
1683
|
+
* Past about ten columns the list scrolls inside itself — a scroll there
|
|
1684
|
+
* does not dismiss the chooser, as one outside would — while the search
|
|
1685
|
+
* box and "Show all" stay put above it.
|
|
1686
|
+
*/
|
|
1687
|
+
.column-chooser-list {
|
|
1688
|
+
max-height: var(--gridkit-column-chooser-max-height);
|
|
1689
|
+
margin: 0;
|
|
1690
|
+
padding: 0;
|
|
1691
|
+
overflow-y: auto;
|
|
1692
|
+
list-style: none;
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
/* One checkbox and its label: "Show all", or a column. */
|
|
1696
|
+
.column-chooser-option {
|
|
1697
|
+
display: flex;
|
|
1698
|
+
align-items: center;
|
|
1699
|
+
gap: calc(var(--gridkit-spacing) * 2);
|
|
1700
|
+
padding: var(--gridkit-spacing);
|
|
1701
|
+
border-radius: var(--gridkit-control-radius);
|
|
1702
|
+
cursor: pointer;
|
|
1703
|
+
user-select: none;
|
|
1704
|
+
}
|
|
1705
|
+
|
|
1706
|
+
.column-chooser-option:hover {
|
|
1707
|
+
background-color: var(--gridkit-surface-muted);
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1710
|
+
/* "Show all", set apart from the columns it acts on. */
|
|
1711
|
+
.column-chooser-all {
|
|
1712
|
+
padding-bottom: calc(var(--gridkit-spacing) * 1.5);
|
|
1713
|
+
border-bottom: var(--gridkit-border-width) solid var(--gridkit-line);
|
|
1714
|
+
border-radius: 0;
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
.column-chooser-option input {
|
|
1718
|
+
flex-shrink: 0;
|
|
1719
|
+
margin: 0;
|
|
1720
|
+
accent-color: var(--gridkit-accent);
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
.column-chooser-option input:focus-visible {
|
|
1724
|
+
outline: var(--gridkit-focus-ring-width) solid var(--gridkit-focus-ring);
|
|
1725
|
+
outline-offset: 1px;
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
/* A column that cannot be hidden, or the last one shown. */
|
|
1729
|
+
.column-chooser-option:has(> input:disabled) {
|
|
1730
|
+
color: var(--gridkit-fg-muted);
|
|
1731
|
+
cursor: default;
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1734
|
+
.column-chooser-option:has(> input:disabled):hover {
|
|
1735
|
+
background-color: transparent;
|
|
1736
|
+
}
|
|
1737
|
+
|
|
1738
|
+
.column-chooser-empty {
|
|
1739
|
+
margin: 0;
|
|
1740
|
+
padding: var(--gridkit-spacing);
|
|
1741
|
+
color: var(--gridkit-fg-muted);
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1744
|
+
/*
|
|
1745
|
+
* A column's filter menu, an overlay like the chooser: the column's sort
|
|
1746
|
+
* entries, its editor, then its buttons. A fixed width, so the panel does
|
|
1747
|
+
* not jump sideways as its editor changes.
|
|
1748
|
+
*/
|
|
1749
|
+
.gridkit-filter-menu {
|
|
1750
|
+
box-sizing: border-box;
|
|
1751
|
+
width: var(--gridkit-filter-menu-width);
|
|
1752
|
+
padding: calc(var(--gridkit-spacing) * 2);
|
|
1753
|
+
font-size: var(--gridkit-menu-font-size);
|
|
1754
|
+
background-color: var(--gridkit-surface);
|
|
1755
|
+
border: var(--gridkit-border-width) solid var(--gridkit-line);
|
|
1756
|
+
border-radius: var(--gridkit-menu-radius);
|
|
1757
|
+
box-shadow: var(--gridkit-overlay-shadow)
|
|
1758
|
+
var(--gridkit-overlay-shadow-color);
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1761
|
+
.filter-menu-form {
|
|
1762
|
+
display: flex;
|
|
1763
|
+
flex-direction: column;
|
|
1764
|
+
gap: calc(var(--gridkit-spacing) * 2);
|
|
1765
|
+
margin: 0;
|
|
1766
|
+
}
|
|
1767
|
+
|
|
1768
|
+
/* The sort entries, drawn as a menu's items and set apart from the editor. */
|
|
1769
|
+
.filter-menu-sort {
|
|
1770
|
+
display: flex;
|
|
1771
|
+
flex-direction: column;
|
|
1772
|
+
padding-bottom: calc(var(--gridkit-spacing) * 1.5);
|
|
1773
|
+
border-bottom: var(--gridkit-border-width) solid var(--gridkit-line);
|
|
1774
|
+
}
|
|
1775
|
+
|
|
1776
|
+
.filter-menu-sort-item {
|
|
1777
|
+
display: flex;
|
|
1778
|
+
align-items: center;
|
|
1779
|
+
gap: calc(var(--gridkit-spacing) * 2);
|
|
1780
|
+
padding: var(--gridkit-menu-item-padding-y) calc(var(--gridkit-spacing) * 2);
|
|
1781
|
+
font: inherit;
|
|
1782
|
+
color: inherit;
|
|
1783
|
+
text-align: start;
|
|
1784
|
+
background: none;
|
|
1785
|
+
border: 0;
|
|
1786
|
+
border-radius: var(--gridkit-control-radius);
|
|
1787
|
+
cursor: pointer;
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1790
|
+
.filter-menu-sort-item:hover {
|
|
1791
|
+
background-color: var(--gridkit-surface-muted);
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1794
|
+
.filter-menu-sort-item:focus-visible {
|
|
1795
|
+
outline: var(--gridkit-focus-ring-width) solid var(--gridkit-focus-ring);
|
|
1796
|
+
outline-offset: calc(var(--gridkit-focus-ring-width) * -1);
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
.filter-menu-sort-item:disabled {
|
|
1800
|
+
color: var(--gridkit-fg-muted);
|
|
1801
|
+
background: none;
|
|
1802
|
+
cursor: default;
|
|
1803
|
+
}
|
|
1804
|
+
|
|
1805
|
+
/* Always there, empty for "Clear sort", so every label starts in line. */
|
|
1806
|
+
.filter-menu-sort-icon {
|
|
1807
|
+
display: inline-flex;
|
|
1808
|
+
flex-shrink: 0;
|
|
1809
|
+
align-items: center;
|
|
1810
|
+
justify-content: center;
|
|
1811
|
+
width: var(--gridkit-icon-size);
|
|
1812
|
+
height: var(--gridkit-icon-size);
|
|
1813
|
+
color: var(--gridkit-fg-muted);
|
|
1814
|
+
}
|
|
1815
|
+
|
|
1816
|
+
.filter-menu-sort-icon svg {
|
|
1817
|
+
width: var(--gridkit-icon-size);
|
|
1818
|
+
height: var(--gridkit-icon-size);
|
|
1819
|
+
}
|
|
1820
|
+
|
|
1821
|
+
/* The direction the column sorts in now. */
|
|
1822
|
+
.filter-menu-sort-item[aria-pressed="true"] .filter-menu-sort-icon {
|
|
1823
|
+
color: var(--gridkit-accent);
|
|
1824
|
+
}
|
|
1825
|
+
|
|
1826
|
+
/*
|
|
1827
|
+
* The simple editor: its conditions in a column, And/Or between them, and
|
|
1828
|
+
* the message under them while one is marked invalid.
|
|
1829
|
+
*/
|
|
1830
|
+
.filter-menu-conditions {
|
|
1831
|
+
display: flex;
|
|
1832
|
+
flex-direction: column;
|
|
1833
|
+
gap: calc(var(--gridkit-spacing) * 2);
|
|
1834
|
+
}
|
|
1835
|
+
|
|
1836
|
+
/*
|
|
1837
|
+
* "Custom filter", or "Filtered by condition" above a checklist: a filter
|
|
1838
|
+
* the editor can't show, until it applies one in its place.
|
|
1839
|
+
*/
|
|
1840
|
+
.filter-menu-custom {
|
|
1841
|
+
margin: 0;
|
|
1842
|
+
padding: var(--gridkit-spacing) calc(var(--gridkit-spacing) * 2);
|
|
1843
|
+
color: var(--gridkit-fg-muted);
|
|
1844
|
+
background-color: var(--gridkit-surface-muted);
|
|
1845
|
+
border-radius: var(--gridkit-control-radius);
|
|
1846
|
+
}
|
|
1847
|
+
|
|
1848
|
+
/*
|
|
1849
|
+
* The operator picker on a line of its own, the value boxes sharing the
|
|
1850
|
+
* next: one fills it, and a "Between"'s two halve it.
|
|
1851
|
+
*/
|
|
1852
|
+
.filter-menu-condition {
|
|
1853
|
+
display: flex;
|
|
1854
|
+
flex-wrap: wrap;
|
|
1855
|
+
gap: calc(var(--gridkit-spacing) * 1.5);
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
.filter-menu-operator,
|
|
1859
|
+
.filter-menu-value {
|
|
1860
|
+
box-sizing: border-box;
|
|
1861
|
+
min-width: 0;
|
|
1862
|
+
padding: var(--gridkit-spacing) calc(var(--gridkit-spacing) * 2);
|
|
1863
|
+
font: inherit;
|
|
1864
|
+
color: var(--gridkit-fg);
|
|
1865
|
+
background-color: var(--gridkit-surface);
|
|
1866
|
+
border: var(--gridkit-border-width) solid var(--gridkit-line);
|
|
1867
|
+
border-radius: var(--gridkit-control-radius);
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
|
+
.filter-menu-operator {
|
|
1871
|
+
flex-basis: 100%;
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1874
|
+
.filter-menu-value {
|
|
1875
|
+
flex: 1 1 0;
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1878
|
+
.filter-menu-operator:focus-visible,
|
|
1879
|
+
.filter-menu-value:focus-visible {
|
|
1880
|
+
outline: var(--gridkit-focus-ring-width) solid var(--gridkit-focus-ring);
|
|
1881
|
+
outline-offset: 1px;
|
|
1882
|
+
}
|
|
1883
|
+
|
|
1884
|
+
.filter-menu-value[aria-invalid="true"] {
|
|
1885
|
+
border-color: var(--gridkit-error);
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1888
|
+
.filter-menu-invalid {
|
|
1889
|
+
margin: 0;
|
|
1890
|
+
color: var(--gridkit-error);
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1893
|
+
/* And/Or, native radio buttons between the two conditions. */
|
|
1894
|
+
.filter-menu-combinator {
|
|
1895
|
+
display: flex;
|
|
1896
|
+
gap: calc(var(--gridkit-spacing) * 4);
|
|
1897
|
+
}
|
|
1898
|
+
|
|
1899
|
+
.filter-menu-combinator-option {
|
|
1900
|
+
display: inline-flex;
|
|
1901
|
+
align-items: center;
|
|
1902
|
+
gap: calc(var(--gridkit-spacing) * 1.5);
|
|
1903
|
+
cursor: pointer;
|
|
1904
|
+
user-select: none;
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1907
|
+
.filter-menu-combinator-option input {
|
|
1908
|
+
margin: 0;
|
|
1909
|
+
accent-color: var(--gridkit-accent);
|
|
1910
|
+
}
|
|
1911
|
+
|
|
1912
|
+
.filter-menu-combinator-option input:focus-visible {
|
|
1913
|
+
outline: var(--gridkit-focus-ring-width) solid var(--gridkit-focus-ring);
|
|
1914
|
+
outline-offset: 1px;
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1917
|
+
/*
|
|
1918
|
+
* The excel editor: a search box, "Select all", then the checklist of the
|
|
1919
|
+
* column's values, with a note above or below it when one applies.
|
|
1920
|
+
*/
|
|
1921
|
+
.filter-menu-values {
|
|
1922
|
+
display: flex;
|
|
1923
|
+
flex-direction: column;
|
|
1924
|
+
gap: calc(var(--gridkit-spacing) * 1.5);
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1927
|
+
/*
|
|
1928
|
+
* The excel editor's "Number filters" button, drawn as a menu item whose
|
|
1929
|
+
* submenu opens beside it, and "Back to values" above a condition it
|
|
1930
|
+
* chose: the sort entries' look, an icon before the label in line with
|
|
1931
|
+
* theirs.
|
|
1932
|
+
*/
|
|
1933
|
+
.filter-menu-submenu,
|
|
1934
|
+
.filter-menu-back {
|
|
1935
|
+
display: flex;
|
|
1936
|
+
align-items: center;
|
|
1937
|
+
gap: calc(var(--gridkit-spacing) * 2);
|
|
1938
|
+
padding: var(--gridkit-menu-item-padding-y) calc(var(--gridkit-spacing) * 2);
|
|
1939
|
+
font: inherit;
|
|
1940
|
+
color: inherit;
|
|
1941
|
+
text-align: start;
|
|
1942
|
+
background: none;
|
|
1943
|
+
border: 0;
|
|
1944
|
+
border-radius: var(--gridkit-control-radius);
|
|
1945
|
+
cursor: pointer;
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
.filter-menu-submenu:hover,
|
|
1949
|
+
.filter-menu-submenu[aria-expanded="true"],
|
|
1950
|
+
.filter-menu-back:hover {
|
|
1951
|
+
background-color: var(--gridkit-surface-muted);
|
|
1952
|
+
}
|
|
1953
|
+
|
|
1954
|
+
.filter-menu-submenu:focus-visible,
|
|
1955
|
+
.filter-menu-back:focus-visible {
|
|
1956
|
+
outline: var(--gridkit-focus-ring-width) solid var(--gridkit-focus-ring);
|
|
1957
|
+
outline-offset: calc(var(--gridkit-focus-ring-width) * -1);
|
|
1958
|
+
}
|
|
1959
|
+
|
|
1960
|
+
.filter-menu-submenu-icon,
|
|
1961
|
+
.filter-menu-submenu-indicator,
|
|
1962
|
+
.filter-menu-back-icon {
|
|
1963
|
+
display: inline-flex;
|
|
1964
|
+
flex-shrink: 0;
|
|
1965
|
+
align-items: center;
|
|
1966
|
+
justify-content: center;
|
|
1967
|
+
width: var(--gridkit-icon-size);
|
|
1968
|
+
height: var(--gridkit-icon-size);
|
|
1969
|
+
color: var(--gridkit-fg-muted);
|
|
1970
|
+
}
|
|
1971
|
+
|
|
1972
|
+
.filter-menu-submenu svg,
|
|
1973
|
+
.filter-menu-back svg {
|
|
1974
|
+
width: var(--gridkit-icon-size);
|
|
1975
|
+
height: var(--gridkit-icon-size);
|
|
1976
|
+
}
|
|
1977
|
+
|
|
1978
|
+
/* Ticked while the column is filtered by conditions, as Excel's is. */
|
|
1979
|
+
.filter-menu-submenu-icon {
|
|
1980
|
+
color: var(--gridkit-accent);
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1983
|
+
/* The submenu's chevron, at the end of the line. */
|
|
1984
|
+
.filter-menu-submenu-indicator {
|
|
1985
|
+
margin-inline-start: auto;
|
|
1986
|
+
}
|
|
1987
|
+
|
|
1988
|
+
.filter-menu-search {
|
|
1989
|
+
box-sizing: border-box;
|
|
1990
|
+
width: 100%;
|
|
1991
|
+
padding: var(--gridkit-spacing) calc(var(--gridkit-spacing) * 2);
|
|
1992
|
+
font: inherit;
|
|
1993
|
+
color: var(--gridkit-fg);
|
|
1994
|
+
background-color: var(--gridkit-surface);
|
|
1995
|
+
border: var(--gridkit-border-width) solid var(--gridkit-line);
|
|
1996
|
+
border-radius: var(--gridkit-control-radius);
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
.filter-menu-search::placeholder {
|
|
2000
|
+
color: var(--gridkit-fg-muted);
|
|
2001
|
+
}
|
|
2002
|
+
|
|
2003
|
+
.filter-menu-search:focus-visible {
|
|
2004
|
+
outline: var(--gridkit-focus-ring-width) solid var(--gridkit-focus-ring);
|
|
2005
|
+
outline-offset: 1px;
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
/* A native checkbox, in line with the drawn ones in the list below. */
|
|
2009
|
+
.filter-menu-select-all {
|
|
2010
|
+
display: flex;
|
|
2011
|
+
align-items: center;
|
|
2012
|
+
gap: calc(var(--gridkit-spacing) * 2);
|
|
2013
|
+
padding: var(--gridkit-spacing)
|
|
2014
|
+
calc(var(--gridkit-spacing) * 2 + var(--gridkit-border-width));
|
|
2015
|
+
cursor: pointer;
|
|
2016
|
+
user-select: none;
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2019
|
+
.filter-menu-select-all input {
|
|
2020
|
+
flex-shrink: 0;
|
|
2021
|
+
width: var(--gridkit-icon-size);
|
|
2022
|
+
height: var(--gridkit-icon-size);
|
|
2023
|
+
margin: 0;
|
|
2024
|
+
accent-color: var(--gridkit-accent);
|
|
2025
|
+
}
|
|
2026
|
+
|
|
2027
|
+
.filter-menu-select-all input:focus-visible {
|
|
2028
|
+
outline: var(--gridkit-focus-ring-width) solid var(--gridkit-focus-ring);
|
|
2029
|
+
outline-offset: 1px;
|
|
2030
|
+
}
|
|
2031
|
+
|
|
2032
|
+
/* Nothing to select: the search matches no value. */
|
|
2033
|
+
.filter-menu-select-all:has(> input:disabled) {
|
|
2034
|
+
color: var(--gridkit-fg-muted);
|
|
2035
|
+
cursor: default;
|
|
2036
|
+
}
|
|
2037
|
+
|
|
2038
|
+
/*
|
|
2039
|
+
* The list scrolls inside itself, at a fixed height: the menu keeps its
|
|
2040
|
+
* size as a search narrows the list, and the virtualizer windowing it
|
|
2041
|
+
* knows from the start how many values it shows. "Type to search …"
|
|
2042
|
+
* takes the same box while the list waits for a search.
|
|
2043
|
+
*/
|
|
2044
|
+
.filter-menu-checklist,
|
|
2045
|
+
.filter-menu-search-first {
|
|
2046
|
+
box-sizing: border-box;
|
|
2047
|
+
height: var(--gridkit-filter-checklist-height);
|
|
2048
|
+
margin: 0;
|
|
2049
|
+
border: var(--gridkit-border-width) solid var(--gridkit-line);
|
|
2050
|
+
border-radius: var(--gridkit-control-radius);
|
|
2051
|
+
}
|
|
2052
|
+
|
|
2053
|
+
.filter-menu-checklist {
|
|
2054
|
+
overflow-y: auto;
|
|
2055
|
+
}
|
|
2056
|
+
|
|
2057
|
+
.filter-menu-search-first {
|
|
2058
|
+
padding: calc(var(--gridkit-spacing) * 2);
|
|
2059
|
+
color: var(--gridkit-fg-muted);
|
|
2060
|
+
}
|
|
2061
|
+
|
|
2062
|
+
/* One value: a drawn checkbox, its label, and its count when shown. */
|
|
2063
|
+
.filter-menu-option {
|
|
2064
|
+
display: flex;
|
|
2065
|
+
align-items: center;
|
|
2066
|
+
gap: calc(var(--gridkit-spacing) * 2);
|
|
2067
|
+
padding: var(--gridkit-spacing) calc(var(--gridkit-spacing) * 2);
|
|
2068
|
+
line-height: 1.25rem;
|
|
2069
|
+
cursor: pointer;
|
|
2070
|
+
user-select: none;
|
|
2071
|
+
}
|
|
2072
|
+
|
|
2073
|
+
.filter-menu-option:hover {
|
|
2074
|
+
background-color: var(--gridkit-surface-muted);
|
|
2075
|
+
}
|
|
2076
|
+
|
|
2077
|
+
.filter-menu-option:focus-visible {
|
|
2078
|
+
outline: var(--gridkit-focus-ring-width) solid var(--gridkit-focus-ring);
|
|
2079
|
+
outline-offset: calc(var(--gridkit-focus-ring-width) * -1);
|
|
2080
|
+
}
|
|
2081
|
+
|
|
2082
|
+
/*
|
|
2083
|
+
* An outline, filled with the accent and ticked in `--gridkit-accent-fg`
|
|
2084
|
+
* while the option is checked, as the native "Select all" above it is.
|
|
2085
|
+
*/
|
|
2086
|
+
.filter-menu-option-check {
|
|
2087
|
+
display: inline-flex;
|
|
2088
|
+
flex-shrink: 0;
|
|
2089
|
+
align-items: center;
|
|
2090
|
+
justify-content: center;
|
|
2091
|
+
box-sizing: border-box;
|
|
2092
|
+
width: var(--gridkit-icon-size);
|
|
2093
|
+
height: var(--gridkit-icon-size);
|
|
2094
|
+
color: var(--gridkit-accent-fg);
|
|
2095
|
+
border: var(--gridkit-border-width) solid var(--gridkit-fg-muted);
|
|
2096
|
+
border-radius: calc(var(--gridkit-control-radius) * 0.75);
|
|
2097
|
+
}
|
|
2098
|
+
|
|
2099
|
+
.filter-menu-option-check svg {
|
|
2100
|
+
width: calc(var(--gridkit-icon-size) * 0.75);
|
|
2101
|
+
height: calc(var(--gridkit-icon-size) * 0.75);
|
|
2102
|
+
visibility: hidden;
|
|
2103
|
+
}
|
|
2104
|
+
|
|
2105
|
+
.filter-menu-option[aria-checked="true"] .filter-menu-option-check {
|
|
2106
|
+
background-color: var(--gridkit-accent);
|
|
2107
|
+
border-color: var(--gridkit-accent);
|
|
2108
|
+
}
|
|
2109
|
+
|
|
2110
|
+
.filter-menu-option[aria-checked="true"] .filter-menu-option-check svg {
|
|
2111
|
+
visibility: visible;
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2114
|
+
/* A label too long for the menu ends in an ellipsis. */
|
|
2115
|
+
.filter-menu-option-label {
|
|
2116
|
+
flex: 1;
|
|
2117
|
+
min-width: 0;
|
|
2118
|
+
overflow: hidden;
|
|
2119
|
+
text-overflow: ellipsis;
|
|
2120
|
+
white-space: nowrap;
|
|
2121
|
+
}
|
|
2122
|
+
|
|
2123
|
+
/* How many rows hold the value, muted at the end of its line. */
|
|
2124
|
+
.filter-menu-option-count {
|
|
2125
|
+
flex-shrink: 0;
|
|
2126
|
+
font-size: var(--gridkit-hint-font-size);
|
|
2127
|
+
font-variant-numeric: tabular-nums;
|
|
2128
|
+
color: var(--gridkit-fg-muted);
|
|
2129
|
+
}
|
|
2130
|
+
|
|
2131
|
+
/* "250 more, refine the search", under a list the value limit cut short. */
|
|
2132
|
+
.filter-menu-more {
|
|
2133
|
+
margin: 0;
|
|
2134
|
+
padding: 0 calc(var(--gridkit-spacing) * 2);
|
|
2135
|
+
color: var(--gridkit-fg-muted);
|
|
2136
|
+
}
|
|
2137
|
+
|
|
2138
|
+
/* "Clear filter" at the start; Cancel and OK at the end. */
|
|
2139
|
+
.filter-menu-actions {
|
|
2140
|
+
display: flex;
|
|
2141
|
+
align-items: center;
|
|
2142
|
+
gap: calc(var(--gridkit-spacing) * 2);
|
|
2143
|
+
}
|
|
2144
|
+
|
|
2145
|
+
.filter-menu-actions button {
|
|
2146
|
+
padding: var(--gridkit-spacing) calc(var(--gridkit-spacing) * 3);
|
|
2147
|
+
font: inherit;
|
|
2148
|
+
color: var(--gridkit-fg);
|
|
2149
|
+
background-color: var(--gridkit-surface);
|
|
2150
|
+
border: var(--gridkit-border-width) solid var(--gridkit-line);
|
|
2151
|
+
border-radius: var(--gridkit-control-radius);
|
|
2152
|
+
cursor: pointer;
|
|
2153
|
+
}
|
|
2154
|
+
|
|
2155
|
+
.filter-menu-actions button:hover {
|
|
2156
|
+
background-color: var(--gridkit-surface-muted);
|
|
2157
|
+
}
|
|
2158
|
+
|
|
2159
|
+
.filter-menu-actions button:focus-visible {
|
|
2160
|
+
outline: var(--gridkit-focus-ring-width) solid var(--gridkit-focus-ring);
|
|
2161
|
+
outline-offset: 1px;
|
|
2162
|
+
}
|
|
2163
|
+
|
|
2164
|
+
.filter-menu-actions button:disabled {
|
|
2165
|
+
color: var(--gridkit-fg-muted);
|
|
2166
|
+
background-color: var(--gridkit-surface);
|
|
2167
|
+
cursor: default;
|
|
2168
|
+
}
|
|
2169
|
+
|
|
2170
|
+
.filter-menu-actions .filter-menu-clear {
|
|
2171
|
+
margin-inline-end: auto;
|
|
2172
|
+
}
|
|
2173
|
+
|
|
2174
|
+
/*
|
|
2175
|
+
* OK, the button Enter presses: tinted rather than filled with the accent,
|
|
2176
|
+
* which the text on it would not stand out from in the light palette.
|
|
2177
|
+
*/
|
|
2178
|
+
.filter-menu-actions .filter-menu-apply {
|
|
2179
|
+
background-color: var(--gridkit-selected);
|
|
2180
|
+
border-color: var(--gridkit-accent);
|
|
2181
|
+
}
|
|
2182
|
+
|
|
2183
|
+
.filter-menu-actions .filter-menu-apply:hover {
|
|
2184
|
+
background-color: var(--gridkit-selected-strong);
|
|
2185
|
+
}
|
|
2186
|
+
}
|
|
2187
|
+
|
|
2188
|
+
/*
|
|
2189
|
+
* The browser's own Ctrl+P of a page holding a grid: the grid as a plain
|
|
2190
|
+
* table, every row it has drawn flowing onto as many pages as it takes. Only
|
|
2191
|
+
* those rows — not one a virtualised grid has not mounted, nor another
|
|
2192
|
+
* page's — which is why printing through the grid's own Print, building a
|
|
2193
|
+
* document of every row in a hidden frame, is the supported path.
|
|
2194
|
+
*/
|
|
2195
|
+
@layer base {
|
|
2196
|
+
@media print {
|
|
2197
|
+
/* What is for using the grid, not reading it. */
|
|
2198
|
+
.gridkit-data-grid-viewport .gridkit-toolbar,
|
|
2199
|
+
.gridkit-data-grid-viewport .gridkit-group-by-bar,
|
|
2200
|
+
.gridkit-data-grid-viewport .gridkit-grid-pager,
|
|
2201
|
+
.gridkit-data-grid-viewport .header-resize-handle {
|
|
2202
|
+
display: none;
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2205
|
+
/* No height bound, and nothing scrolls, so no row is cut off. */
|
|
2206
|
+
.gridkit-data-grid-viewport,
|
|
2207
|
+
.gridkit-data-grid-viewport .gridkit-data-grid-body {
|
|
2208
|
+
height: auto;
|
|
2209
|
+
overflow: visible;
|
|
2210
|
+
}
|
|
2211
|
+
|
|
2212
|
+
.gridkit-data-grid-viewport :focus-visible {
|
|
2213
|
+
outline: none;
|
|
2214
|
+
}
|
|
2215
|
+
|
|
2216
|
+
/* Shading printed as it is, not dropped to save ink. */
|
|
2217
|
+
.gridkit-data-grid {
|
|
2218
|
+
-webkit-print-color-adjust: exact;
|
|
2219
|
+
print-color-adjust: exact;
|
|
2220
|
+
}
|
|
2221
|
+
|
|
2222
|
+
.gridkit-data-grid tr {
|
|
2223
|
+
break-inside: avoid;
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
}
|