@devslab/dds-css 0.10.0 → 0.11.1
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/dist/components/base.css +15 -0
- package/dist/components/console-shell.css +360 -0
- package/dist/components/table.css +226 -0
- package/dist/dds.css +603 -0
- package/package.json +1 -1
package/dist/components/base.css
CHANGED
|
@@ -29,3 +29,18 @@
|
|
|
29
29
|
outline-color: Highlight;
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
|
+
|
|
33
|
+
/* Visually hidden — content that stays in the accessibility tree (screen
|
|
34
|
+
* readers, AT) but takes up no visual space. Unlike display: none, which
|
|
35
|
+
* removes the element from the tree too, this only clips it out of view.
|
|
36
|
+
* Consumers: DataTable captions, icon-only header labels, skip links.
|
|
37
|
+
* The ancestor needs position: relative for this to clip against the right
|
|
38
|
+
* box (see table.css's .dds-table-wrap note) rather than the page. */
|
|
39
|
+
.dds-visually-hidden {
|
|
40
|
+
position: absolute;
|
|
41
|
+
inline-size: 1px;
|
|
42
|
+
block-size: 1px;
|
|
43
|
+
overflow: hidden;
|
|
44
|
+
clip-path: inset(50%);
|
|
45
|
+
white-space: nowrap;
|
|
46
|
+
}
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
/* Console shell — the 232px rail + below-900px drawer that a console route
|
|
2
|
+
* renders around its content. The fold breakpoint below is written in the
|
|
3
|
+
* same rem form as table.css's column fold (56.25rem = 900px at a 16px root
|
|
4
|
+
* font size), so a visitor with any browser default font size sees the rail
|
|
5
|
+
* change shape and the table's columns fold at the same viewport width
|
|
6
|
+
* inside the same console.
|
|
7
|
+
*
|
|
8
|
+
* Tokens only. Every class that declares `display` re-declares
|
|
9
|
+
* `[hidden] { display: none }` beside it, at a class+attribute specificity
|
|
10
|
+
* that beats every later `display` declaration for that class — including
|
|
11
|
+
* the ones inside the media query below — so a hidden rail, toggle, or
|
|
12
|
+
* scrim can never be drawn on screen regardless of viewport width. */
|
|
13
|
+
|
|
14
|
+
.dds-console-shell {
|
|
15
|
+
min-block-size: 100vh;
|
|
16
|
+
display: grid;
|
|
17
|
+
grid-template-columns: 14.5rem minmax(0, 1fr);
|
|
18
|
+
background: var(--dds-color-bg-default);
|
|
19
|
+
color: var(--dds-color-text-primary);
|
|
20
|
+
font-size: 1rem;
|
|
21
|
+
line-height: 1.5;
|
|
22
|
+
}
|
|
23
|
+
.dds-console-shell[hidden] {
|
|
24
|
+
display: none;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* The skip link is hidden by .dds-visually-hidden (applied by the
|
|
28
|
+
* component) and only needs to say what it looks like once focused —
|
|
29
|
+
* a visually-hidden element is never in the focus-visible/`:focus` chain
|
|
30
|
+
* while `hidden`, so no `[hidden]` guard applies here. */
|
|
31
|
+
.dds-console-skip:focus {
|
|
32
|
+
position: fixed;
|
|
33
|
+
inset-block-start: var(--dds-space-8);
|
|
34
|
+
inset-inline-start: var(--dds-space-8);
|
|
35
|
+
z-index: 100;
|
|
36
|
+
clip-path: none;
|
|
37
|
+
inline-size: auto;
|
|
38
|
+
block-size: auto;
|
|
39
|
+
overflow: visible;
|
|
40
|
+
white-space: normal;
|
|
41
|
+
padding: var(--dds-space-12) var(--dds-space-16);
|
|
42
|
+
background: var(--dds-color-bg-elevated);
|
|
43
|
+
color: var(--dds-color-text-primary);
|
|
44
|
+
border: 2px solid var(--dds-color-border-focus);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.dds-console-rail {
|
|
48
|
+
position: sticky;
|
|
49
|
+
inset-block-start: 0;
|
|
50
|
+
block-size: 100vh;
|
|
51
|
+
display: flex;
|
|
52
|
+
flex-direction: column;
|
|
53
|
+
gap: var(--dds-space-16);
|
|
54
|
+
padding: var(--dds-space-20) var(--dds-space-12);
|
|
55
|
+
overflow-y: auto;
|
|
56
|
+
border-inline-end: 1px solid var(--dds-color-border-default);
|
|
57
|
+
background: var(--dds-color-bg-elevated);
|
|
58
|
+
}
|
|
59
|
+
.dds-console-rail[hidden] {
|
|
60
|
+
display: none;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.dds-console-rail__brand {
|
|
64
|
+
display: inline-flex;
|
|
65
|
+
align-items: center;
|
|
66
|
+
gap: var(--dds-space-8);
|
|
67
|
+
padding-inline: var(--dds-space-8);
|
|
68
|
+
color: inherit;
|
|
69
|
+
font-size: .9375rem;
|
|
70
|
+
font-weight: 700;
|
|
71
|
+
letter-spacing: -.02em;
|
|
72
|
+
text-decoration: none;
|
|
73
|
+
}
|
|
74
|
+
.dds-console-rail__brand[hidden] {
|
|
75
|
+
display: none;
|
|
76
|
+
}
|
|
77
|
+
.dds-console-rail__brand img {
|
|
78
|
+
inline-size: 20px;
|
|
79
|
+
block-size: 20px;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.dds-console-rail__context {
|
|
83
|
+
display: grid;
|
|
84
|
+
gap: var(--dds-space-4);
|
|
85
|
+
margin: 0;
|
|
86
|
+
padding-inline: var(--dds-space-8);
|
|
87
|
+
font-size: var(--dds-typo-caption-font-size);
|
|
88
|
+
line-height: var(--dds-typo-caption-line-height);
|
|
89
|
+
}
|
|
90
|
+
.dds-console-rail__context[hidden] {
|
|
91
|
+
display: none;
|
|
92
|
+
}
|
|
93
|
+
.dds-console-rail__context dt {
|
|
94
|
+
color: var(--dds-color-text-muted);
|
|
95
|
+
}
|
|
96
|
+
.dds-console-rail__context dd {
|
|
97
|
+
margin: 0;
|
|
98
|
+
font-family: var(--dds-font-family-mono);
|
|
99
|
+
overflow-wrap: anywhere;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.dds-console-rail__nav {
|
|
103
|
+
display: grid;
|
|
104
|
+
gap: var(--dds-space-16);
|
|
105
|
+
}
|
|
106
|
+
.dds-console-rail__nav[hidden] {
|
|
107
|
+
display: none;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.dds-console-rail__group {
|
|
111
|
+
display: grid;
|
|
112
|
+
gap: var(--dds-space-2, 2px);
|
|
113
|
+
}
|
|
114
|
+
.dds-console-rail__group[hidden] {
|
|
115
|
+
display: none;
|
|
116
|
+
}
|
|
117
|
+
.dds-console-rail__group ul {
|
|
118
|
+
margin: 0;
|
|
119
|
+
padding: 0;
|
|
120
|
+
list-style: none;
|
|
121
|
+
display: grid;
|
|
122
|
+
gap: 2px;
|
|
123
|
+
}
|
|
124
|
+
.dds-console-rail__group ul[hidden] {
|
|
125
|
+
display: none;
|
|
126
|
+
}
|
|
127
|
+
.dds-console-rail__group-label {
|
|
128
|
+
margin: 0;
|
|
129
|
+
padding: 0 var(--dds-space-8) var(--dds-space-4);
|
|
130
|
+
color: var(--dds-color-text-muted);
|
|
131
|
+
font-size: .6875rem;
|
|
132
|
+
font-weight: 600;
|
|
133
|
+
letter-spacing: .05em;
|
|
134
|
+
text-transform: uppercase;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.dds-console-rail__item {
|
|
138
|
+
display: flex;
|
|
139
|
+
align-items: center;
|
|
140
|
+
justify-content: space-between;
|
|
141
|
+
gap: var(--dds-space-8);
|
|
142
|
+
min-block-size: var(--dds-space-40);
|
|
143
|
+
padding-inline: var(--dds-space-8);
|
|
144
|
+
border-radius: var(--dds-radius-md);
|
|
145
|
+
color: var(--dds-color-text-secondary);
|
|
146
|
+
font-size: .875rem;
|
|
147
|
+
font-weight: 500;
|
|
148
|
+
text-decoration: none;
|
|
149
|
+
}
|
|
150
|
+
.dds-console-rail__item[hidden] {
|
|
151
|
+
display: none;
|
|
152
|
+
}
|
|
153
|
+
.dds-console-rail__item:hover {
|
|
154
|
+
background: var(--dds-color-bg-subtle);
|
|
155
|
+
color: var(--dds-color-text-primary);
|
|
156
|
+
}
|
|
157
|
+
.dds-console-rail__item[aria-current="page"] {
|
|
158
|
+
background: var(--dds-color-bg-brand-subtle);
|
|
159
|
+
color: var(--dds-color-text-brand);
|
|
160
|
+
font-weight: 650;
|
|
161
|
+
}
|
|
162
|
+
.dds-console-rail__item:focus-visible {
|
|
163
|
+
outline: 2px solid var(--dds-color-border-focus);
|
|
164
|
+
outline-offset: 2px;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.dds-console-rail__badge {
|
|
168
|
+
display: inline-grid;
|
|
169
|
+
place-items: center;
|
|
170
|
+
min-inline-size: 1.125rem;
|
|
171
|
+
block-size: 1.125rem;
|
|
172
|
+
padding-inline: .3125rem;
|
|
173
|
+
border-radius: var(--dds-radius-full);
|
|
174
|
+
background: var(--dds-color-bg-brand);
|
|
175
|
+
color: var(--dds-color-text-on-brand);
|
|
176
|
+
font-size: .6875rem;
|
|
177
|
+
font-weight: 700;
|
|
178
|
+
font-variant-numeric: tabular-nums;
|
|
179
|
+
}
|
|
180
|
+
.dds-console-rail__badge[hidden] {
|
|
181
|
+
display: none;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.dds-console-rail__foot {
|
|
185
|
+
margin-block-start: auto;
|
|
186
|
+
display: grid;
|
|
187
|
+
gap: var(--dds-space-8);
|
|
188
|
+
justify-items: start;
|
|
189
|
+
padding: var(--dds-space-12) var(--dds-space-8) 0;
|
|
190
|
+
border-block-start: 1px solid var(--dds-color-border-default);
|
|
191
|
+
}
|
|
192
|
+
.dds-console-rail__foot[hidden] {
|
|
193
|
+
display: none;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.dds-console-rail__toggle {
|
|
197
|
+
display: none;
|
|
198
|
+
}
|
|
199
|
+
.dds-console-rail__toggle[hidden] {
|
|
200
|
+
display: none;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.dds-console-rail__scrim {
|
|
204
|
+
display: none;
|
|
205
|
+
}
|
|
206
|
+
.dds-console-rail__scrim[hidden] {
|
|
207
|
+
display: none;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.dds-console-main {
|
|
211
|
+
min-inline-size: 0;
|
|
212
|
+
padding: clamp(1rem, 3vw, 2rem);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.dds-console-page-header {
|
|
216
|
+
display: flex;
|
|
217
|
+
align-items: flex-start;
|
|
218
|
+
justify-content: space-between;
|
|
219
|
+
gap: var(--dds-space-32);
|
|
220
|
+
margin-block-end: var(--dds-space-32);
|
|
221
|
+
}
|
|
222
|
+
.dds-console-page-header[hidden] {
|
|
223
|
+
display: none;
|
|
224
|
+
}
|
|
225
|
+
.dds-console-page-header h1 {
|
|
226
|
+
max-inline-size: 24ch;
|
|
227
|
+
margin: .25rem 0 0;
|
|
228
|
+
font-size: clamp(1.75rem, 2.2vw, 2.25rem);
|
|
229
|
+
line-height: 1.1;
|
|
230
|
+
letter-spacing: -.03em;
|
|
231
|
+
text-wrap: balance;
|
|
232
|
+
}
|
|
233
|
+
.dds-console-page-header__actions {
|
|
234
|
+
display: flex;
|
|
235
|
+
gap: var(--dds-space-8);
|
|
236
|
+
}
|
|
237
|
+
.dds-console-page-header__actions[hidden] {
|
|
238
|
+
display: none;
|
|
239
|
+
}
|
|
240
|
+
.dds-console-page-eyebrow {
|
|
241
|
+
margin: 0;
|
|
242
|
+
color: var(--dds-color-text-muted);
|
|
243
|
+
font-size: var(--dds-typo-caption-font-size);
|
|
244
|
+
line-height: var(--dds-typo-caption-line-height);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/* Console density: every dds-css control inside the shell reads at the body-2
|
|
248
|
+
* size (14px), not dds-btn's own default (13px, --dds-typo-label-font-size).
|
|
249
|
+
* Scoped to .dds-console-shell rather than left as a global override on
|
|
250
|
+
* .dds-btn/.dds-input/.dds-select/.dds-textarea themselves — a shell that
|
|
251
|
+
* establishes a density owns the override for controls inside it, the same
|
|
252
|
+
* way a shared class must never carry a layout rule that only makes sense
|
|
253
|
+
* for one consumer's container.
|
|
254
|
+
*
|
|
255
|
+
* .dds-btn's :not() exclusions matter: this selector's specificity (0,2,0)
|
|
256
|
+
* beats every size modifier in button.css (.dds-btn--lg, .dds-btn--sm, both
|
|
257
|
+
* 0,1,0), so an unqualified `.dds-console-shell .dds-btn` would override
|
|
258
|
+
* --lg's own font-size back down to body-2 and would give --sm the same
|
|
259
|
+
* font-size as a default button (--sm declares none of its own, so it was
|
|
260
|
+
* inheriting whichever rule won for plain .dds-btn) — the one outcome a
|
|
261
|
+
* size modifier exists to prevent. .dds-input/.dds-select/.dds-textarea
|
|
262
|
+
* carry no such modifiers today, so no matching exclusion is needed there. */
|
|
263
|
+
.dds-console-shell .dds-btn:not(.dds-btn--lg):not(.dds-btn--sm),
|
|
264
|
+
.dds-console-shell .dds-input,
|
|
265
|
+
.dds-console-shell .dds-select,
|
|
266
|
+
.dds-console-shell .dds-textarea {
|
|
267
|
+
font-size: var(--dds-typo-body-2-font-size);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
@media (max-width: 56.25rem) {
|
|
271
|
+
.dds-console-shell {
|
|
272
|
+
grid-template-columns: minmax(0, 1fr);
|
|
273
|
+
}
|
|
274
|
+
.dds-console-rail__toggle {
|
|
275
|
+
position: fixed;
|
|
276
|
+
inset-block-start: .75rem;
|
|
277
|
+
inset-inline-start: .75rem;
|
|
278
|
+
z-index: 70;
|
|
279
|
+
display: inline-grid;
|
|
280
|
+
place-items: center;
|
|
281
|
+
inline-size: 2.5rem;
|
|
282
|
+
block-size: 2.5rem;
|
|
283
|
+
border: 1px solid var(--dds-color-border-default);
|
|
284
|
+
border-radius: var(--dds-radius-md);
|
|
285
|
+
background: var(--dds-color-bg-elevated);
|
|
286
|
+
cursor: pointer;
|
|
287
|
+
}
|
|
288
|
+
.dds-console-rail__toggle > span[aria-hidden] {
|
|
289
|
+
position: relative;
|
|
290
|
+
display: block;
|
|
291
|
+
inline-size: 16px;
|
|
292
|
+
block-size: 2px;
|
|
293
|
+
border-radius: 2px;
|
|
294
|
+
background: currentColor;
|
|
295
|
+
}
|
|
296
|
+
.dds-console-rail__toggle > span[aria-hidden]::before,
|
|
297
|
+
.dds-console-rail__toggle > span[aria-hidden]::after {
|
|
298
|
+
content: "";
|
|
299
|
+
position: absolute;
|
|
300
|
+
inset-inline-start: 0;
|
|
301
|
+
inline-size: 16px;
|
|
302
|
+
block-size: 2px;
|
|
303
|
+
border-radius: 2px;
|
|
304
|
+
background: currentColor;
|
|
305
|
+
}
|
|
306
|
+
.dds-console-rail__toggle > span[aria-hidden]::before {
|
|
307
|
+
inset-block-start: -5px;
|
|
308
|
+
}
|
|
309
|
+
.dds-console-rail__toggle > span[aria-hidden]::after {
|
|
310
|
+
inset-block-start: 5px;
|
|
311
|
+
}
|
|
312
|
+
/* Translated off-screen is not gone: a closed drawer still takes Tab. Hide
|
|
313
|
+
it from the focus order with visibility, delayed by the slide's
|
|
314
|
+
duration so closing still animates, and lifted with no delay when it
|
|
315
|
+
opens. */
|
|
316
|
+
.dds-console-rail {
|
|
317
|
+
position: fixed;
|
|
318
|
+
inset: 0 auto 0 0;
|
|
319
|
+
z-index: 60;
|
|
320
|
+
inline-size: min(84vw, 18rem);
|
|
321
|
+
block-size: 100dvh;
|
|
322
|
+
visibility: hidden;
|
|
323
|
+
translate: -100% 0;
|
|
324
|
+
transition: translate .22s cubic-bezier(.16, 1, .3, 1), visibility 0s linear .22s;
|
|
325
|
+
box-shadow: var(--dds-elevation-2);
|
|
326
|
+
}
|
|
327
|
+
.dds-console-rail[data-open="true"] {
|
|
328
|
+
visibility: visible;
|
|
329
|
+
translate: 0 0;
|
|
330
|
+
transition-delay: 0s, 0s;
|
|
331
|
+
}
|
|
332
|
+
.dds-console-rail__scrim {
|
|
333
|
+
display: block;
|
|
334
|
+
position: fixed;
|
|
335
|
+
inset: 0;
|
|
336
|
+
z-index: 55;
|
|
337
|
+
background: var(--dds-color-overlay-dim);
|
|
338
|
+
opacity: 0;
|
|
339
|
+
pointer-events: none;
|
|
340
|
+
transition: opacity .22s ease;
|
|
341
|
+
}
|
|
342
|
+
.dds-console-rail__scrim[data-open="true"] {
|
|
343
|
+
opacity: 1;
|
|
344
|
+
pointer-events: auto;
|
|
345
|
+
}
|
|
346
|
+
.dds-console-main {
|
|
347
|
+
padding-block-start: 4rem;
|
|
348
|
+
}
|
|
349
|
+
.dds-console-page-header {
|
|
350
|
+
display: grid;
|
|
351
|
+
gap: var(--dds-space-16);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
@media (prefers-reduced-motion: reduce) {
|
|
356
|
+
.dds-console-rail,
|
|
357
|
+
.dds-console-rail__scrim {
|
|
358
|
+
transition: none;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/* Table — the console list surface. Geometry comes from VisionLinq's shipped
|
|
2
|
+
* console (40px rows, 36px dense, sticky header in the tall variant); the
|
|
3
|
+
* colours are tokens only.
|
|
4
|
+
*
|
|
5
|
+
* .dds-table-wrap keeps position: relative even though it looks like dead
|
|
6
|
+
* positioning: it is what lets an absolutely-positioned .dds-visually-hidden
|
|
7
|
+
* caption or header label (see base.css) resolve against the table's own
|
|
8
|
+
* box instead of the page once the wrap is scrolling horizontally. Don't
|
|
9
|
+
* "clean up" this rule. */
|
|
10
|
+
|
|
11
|
+
.dds-table-wrap {
|
|
12
|
+
position: relative;
|
|
13
|
+
overflow-x: auto;
|
|
14
|
+
border: 1px solid var(--dds-color-border-default);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.dds-table-wrap--tall {
|
|
18
|
+
max-block-size: 70vh;
|
|
19
|
+
overflow: auto;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.dds-table {
|
|
23
|
+
inline-size: 100%;
|
|
24
|
+
border-collapse: collapse;
|
|
25
|
+
background: var(--dds-color-bg-elevated);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.dds-table caption {
|
|
29
|
+
padding: var(--dds-space-16);
|
|
30
|
+
text-align: start;
|
|
31
|
+
font-weight: 650;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.dds-table th,
|
|
35
|
+
.dds-table td {
|
|
36
|
+
padding: .625rem var(--dds-space-16);
|
|
37
|
+
border-block-start: 1px solid var(--dds-color-border-default);
|
|
38
|
+
font-size: .875rem;
|
|
39
|
+
line-height: 1.5;
|
|
40
|
+
text-align: start;
|
|
41
|
+
vertical-align: middle;
|
|
42
|
+
white-space: nowrap;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.dds-table tbody tr {
|
|
46
|
+
block-size: var(--dds-space-40);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.dds-table--fixed {
|
|
50
|
+
table-layout: fixed;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.dds-table [data-numeric] {
|
|
54
|
+
text-align: end;
|
|
55
|
+
font-variant-numeric: tabular-nums;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/* Code cells: ids, keys and hashes are read character by character, so a
|
|
59
|
+
* <code> inside a cell takes the mono family at 13px — a notch under the
|
|
60
|
+
* 14px cell text, which is the size mono needs to sit at the same visual
|
|
61
|
+
* weight as the sans around it. */
|
|
62
|
+
.dds-table code {
|
|
63
|
+
font-family: var(--dds-font-family-mono);
|
|
64
|
+
font-size: .8125rem;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.dds-table th small {
|
|
68
|
+
display: block;
|
|
69
|
+
color: var(--dds-color-text-muted);
|
|
70
|
+
font-weight: 400;
|
|
71
|
+
}
|
|
72
|
+
.dds-table th small[hidden] {
|
|
73
|
+
display: none;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.dds-table--dense th,
|
|
77
|
+
.dds-table--dense td {
|
|
78
|
+
padding-block: .375rem;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.dds-table--dense tbody tr {
|
|
82
|
+
block-size: 2.25rem;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.dds-table-wrap--tall thead th {
|
|
86
|
+
position: sticky;
|
|
87
|
+
inset-block-start: 0;
|
|
88
|
+
z-index: 1;
|
|
89
|
+
background: var(--dds-color-bg-elevated);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* Separate borders under the sticky header: with border-collapse: collapse
|
|
93
|
+
* the cell borders belong to the table rather than the cells, and that can
|
|
94
|
+
* keep a sticky header from actually sticking when the wrap scrolls (the
|
|
95
|
+
* header row slides away, or its border stays behind). Every cell border
|
|
96
|
+
* here is block-start only, so separate borders with zero spacing draw the
|
|
97
|
+
* same lines. */
|
|
98
|
+
.dds-table-wrap--tall .dds-table {
|
|
99
|
+
border-collapse: separate;
|
|
100
|
+
border-spacing: 0;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.dds-table__sort {
|
|
104
|
+
appearance: none;
|
|
105
|
+
display: inline-flex;
|
|
106
|
+
align-items: center;
|
|
107
|
+
gap: .375rem;
|
|
108
|
+
padding: 0;
|
|
109
|
+
border: 0;
|
|
110
|
+
background: none;
|
|
111
|
+
font: inherit;
|
|
112
|
+
font-weight: 650;
|
|
113
|
+
color: inherit;
|
|
114
|
+
cursor: pointer;
|
|
115
|
+
}
|
|
116
|
+
.dds-table__sort[hidden] {
|
|
117
|
+
display: none;
|
|
118
|
+
}
|
|
119
|
+
.dds-table__sort:focus-visible {
|
|
120
|
+
outline: 2px solid var(--dds-color-border-focus);
|
|
121
|
+
outline-offset: 2px;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.dds-table__sort-mark {
|
|
125
|
+
inline-size: .5rem;
|
|
126
|
+
block-size: .5rem;
|
|
127
|
+
border-inline-end: 2px solid currentColor;
|
|
128
|
+
border-block-end: 2px solid currentColor;
|
|
129
|
+
rotate: 45deg;
|
|
130
|
+
opacity: .35;
|
|
131
|
+
translate: 0 -.125rem;
|
|
132
|
+
}
|
|
133
|
+
.dds-table__sort-mark[data-sort-state="ascending"] {
|
|
134
|
+
rotate: -135deg;
|
|
135
|
+
opacity: 1;
|
|
136
|
+
translate: 0 .125rem;
|
|
137
|
+
}
|
|
138
|
+
.dds-table__sort-mark[data-sort-state="descending"] {
|
|
139
|
+
opacity: 1;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.dds-table__actions {
|
|
143
|
+
display: flex;
|
|
144
|
+
justify-content: flex-end;
|
|
145
|
+
gap: var(--dds-space-8);
|
|
146
|
+
}
|
|
147
|
+
.dds-table__actions[hidden] {
|
|
148
|
+
display: none;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/* Row actions are 32px and stay on one line. A button's own geometry (40px
|
|
152
|
+
* default, 32px --sm, both with wrapping labels) plus the cell's 10px block
|
|
153
|
+
* padding made a row carrying a button measure ~53px against its 40px
|
|
154
|
+
* neighbours — a table whose rows are not one height reads as broken. So an
|
|
155
|
+
* action button is held to the --sm height whatever its size modifier
|
|
156
|
+
* (padding included, or a default button would still be 34px), its label
|
|
157
|
+
* never wraps (the wrap scrolls horizontally, nothing is clipped), and the
|
|
158
|
+
* actions cell trims its block padding so 32px fits inside the 40px row. */
|
|
159
|
+
.dds-table__actions .dds-btn {
|
|
160
|
+
min-block-size: var(--dds-space-32);
|
|
161
|
+
padding-block: var(--dds-space-4);
|
|
162
|
+
white-space: nowrap;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/* The same trim for any cell holding a small button (a copy button beside
|
|
166
|
+
* an id): its own 10px padding around a 32px button is a 53px row, and even
|
|
167
|
+
* in a dense table 6px around a 24px button plus the 1px border is 37px, a
|
|
168
|
+
* pixel over the 36px row. A default-size button outside the actions cell
|
|
169
|
+
* keeps full padding — that is an explicit choice to be taller. */
|
|
170
|
+
.dds-table td:has(> .dds-table__actions),
|
|
171
|
+
.dds-table td:has(.dds-btn--sm) {
|
|
172
|
+
padding-block: var(--dds-space-4);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/* Small buttons in a dense table are 24px — a copy button beside an id in
|
|
176
|
+
* any cell, and every row action whatever its size modifier (the same
|
|
177
|
+
* "whatever its modifier" as the 32px rule above, one density down) — so
|
|
178
|
+
* they fit the 36px dense row. Zero block padding is what gets there:
|
|
179
|
+
* --sm's own 4px padding around a 16px label already makes 26px, which
|
|
180
|
+
* min-block-size can't pull back down. 24px is exactly the §6 web floor.
|
|
181
|
+
* A default-size button outside the actions cell is left alone: that is an
|
|
182
|
+
* explicit choice to be taller. The actions selector out-specifies the
|
|
183
|
+
* 32px rule; the --sm one ties it and wins on source order. Middle
|
|
184
|
+
* alignment keeps an inline button beside text from growing the line box
|
|
185
|
+
* past its own 24px by sitting on the text baseline. */
|
|
186
|
+
.dds-table--dense .dds-btn--sm,
|
|
187
|
+
.dds-table--dense .dds-table__actions .dds-btn {
|
|
188
|
+
min-block-size: var(--dds-space-24);
|
|
189
|
+
padding-block: 0;
|
|
190
|
+
vertical-align: middle;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/* Touch pointers keep the 44px floor (spec §6, button.css). The two rules
|
|
194
|
+
* above out-specify button.css's coarse-pointer rule, so without restating
|
|
195
|
+
* it here a table would silently shrink every action below the touch
|
|
196
|
+
* target on a phone. Uniform row height yields on touch; the target does
|
|
197
|
+
* not (docs/decisions.md D-025). */
|
|
198
|
+
@media (pointer: coarse) {
|
|
199
|
+
.dds-table__actions .dds-btn,
|
|
200
|
+
.dds-table--dense .dds-btn--sm,
|
|
201
|
+
.dds-table--dense .dds-table__actions .dds-btn {
|
|
202
|
+
min-block-size: 44px;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.dds-table__order {
|
|
207
|
+
margin: 0 0 var(--dds-space-8);
|
|
208
|
+
font-size: .8125rem;
|
|
209
|
+
color: var(--dds-color-text-muted);
|
|
210
|
+
font-family: var(--dds-font-family-mono);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.dds-table__pagination {
|
|
214
|
+
display: flex;
|
|
215
|
+
justify-content: flex-end;
|
|
216
|
+
margin-block-start: var(--dds-space-16);
|
|
217
|
+
}
|
|
218
|
+
.dds-table__pagination[hidden] {
|
|
219
|
+
display: none;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
@media (max-width: 56.25rem) {
|
|
223
|
+
.dds-table [data-fold] {
|
|
224
|
+
display: none;
|
|
225
|
+
}
|
|
226
|
+
}
|
package/dist/dds.css
CHANGED
|
@@ -33,6 +33,21 @@
|
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
/* Visually hidden — content that stays in the accessibility tree (screen
|
|
37
|
+
* readers, AT) but takes up no visual space. Unlike display: none, which
|
|
38
|
+
* removes the element from the tree too, this only clips it out of view.
|
|
39
|
+
* Consumers: DataTable captions, icon-only header labels, skip links.
|
|
40
|
+
* The ancestor needs position: relative for this to clip against the right
|
|
41
|
+
* box (see table.css's .dds-table-wrap note) rather than the page. */
|
|
42
|
+
.dds-visually-hidden {
|
|
43
|
+
position: absolute;
|
|
44
|
+
inline-size: 1px;
|
|
45
|
+
block-size: 1px;
|
|
46
|
+
overflow: hidden;
|
|
47
|
+
clip-path: inset(50%);
|
|
48
|
+
white-space: nowrap;
|
|
49
|
+
}
|
|
50
|
+
|
|
36
51
|
/* Button — spec §4.2: default → hover → pressed → focus-visible → disabled → loading.
|
|
37
52
|
* Variants: primary / secondary / ghost / danger. Sizes: sm / md(default) / lg.
|
|
38
53
|
* Control heights come from the spacing scale (32/40/48); type from the typo
|
|
@@ -1207,3 +1222,591 @@ dialog.dds-dialog::backdrop {
|
|
|
1207
1222
|
gap: var(--dds-space-8);
|
|
1208
1223
|
margin-top: var(--dds-space-8);
|
|
1209
1224
|
}
|
|
1225
|
+
|
|
1226
|
+
/* Table — the console list surface. Geometry comes from VisionLinq's shipped
|
|
1227
|
+
* console (40px rows, 36px dense, sticky header in the tall variant); the
|
|
1228
|
+
* colours are tokens only.
|
|
1229
|
+
*
|
|
1230
|
+
* .dds-table-wrap keeps position: relative even though it looks like dead
|
|
1231
|
+
* positioning: it is what lets an absolutely-positioned .dds-visually-hidden
|
|
1232
|
+
* caption or header label (see base.css) resolve against the table's own
|
|
1233
|
+
* box instead of the page once the wrap is scrolling horizontally. Don't
|
|
1234
|
+
* "clean up" this rule. */
|
|
1235
|
+
|
|
1236
|
+
.dds-table-wrap {
|
|
1237
|
+
position: relative;
|
|
1238
|
+
overflow-x: auto;
|
|
1239
|
+
border: 1px solid var(--dds-color-border-default);
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
.dds-table-wrap--tall {
|
|
1243
|
+
max-block-size: 70vh;
|
|
1244
|
+
overflow: auto;
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
.dds-table {
|
|
1248
|
+
inline-size: 100%;
|
|
1249
|
+
border-collapse: collapse;
|
|
1250
|
+
background: var(--dds-color-bg-elevated);
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
.dds-table caption {
|
|
1254
|
+
padding: var(--dds-space-16);
|
|
1255
|
+
text-align: start;
|
|
1256
|
+
font-weight: 650;
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
.dds-table th,
|
|
1260
|
+
.dds-table td {
|
|
1261
|
+
padding: .625rem var(--dds-space-16);
|
|
1262
|
+
border-block-start: 1px solid var(--dds-color-border-default);
|
|
1263
|
+
font-size: .875rem;
|
|
1264
|
+
line-height: 1.5;
|
|
1265
|
+
text-align: start;
|
|
1266
|
+
vertical-align: middle;
|
|
1267
|
+
white-space: nowrap;
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
.dds-table tbody tr {
|
|
1271
|
+
block-size: var(--dds-space-40);
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
.dds-table--fixed {
|
|
1275
|
+
table-layout: fixed;
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
.dds-table [data-numeric] {
|
|
1279
|
+
text-align: end;
|
|
1280
|
+
font-variant-numeric: tabular-nums;
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
/* Code cells: ids, keys and hashes are read character by character, so a
|
|
1284
|
+
* <code> inside a cell takes the mono family at 13px — a notch under the
|
|
1285
|
+
* 14px cell text, which is the size mono needs to sit at the same visual
|
|
1286
|
+
* weight as the sans around it. */
|
|
1287
|
+
.dds-table code {
|
|
1288
|
+
font-family: var(--dds-font-family-mono);
|
|
1289
|
+
font-size: .8125rem;
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
.dds-table th small {
|
|
1293
|
+
display: block;
|
|
1294
|
+
color: var(--dds-color-text-muted);
|
|
1295
|
+
font-weight: 400;
|
|
1296
|
+
}
|
|
1297
|
+
.dds-table th small[hidden] {
|
|
1298
|
+
display: none;
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
.dds-table--dense th,
|
|
1302
|
+
.dds-table--dense td {
|
|
1303
|
+
padding-block: .375rem;
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
.dds-table--dense tbody tr {
|
|
1307
|
+
block-size: 2.25rem;
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
.dds-table-wrap--tall thead th {
|
|
1311
|
+
position: sticky;
|
|
1312
|
+
inset-block-start: 0;
|
|
1313
|
+
z-index: 1;
|
|
1314
|
+
background: var(--dds-color-bg-elevated);
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
/* Separate borders under the sticky header: with border-collapse: collapse
|
|
1318
|
+
* the cell borders belong to the table rather than the cells, and that can
|
|
1319
|
+
* keep a sticky header from actually sticking when the wrap scrolls (the
|
|
1320
|
+
* header row slides away, or its border stays behind). Every cell border
|
|
1321
|
+
* here is block-start only, so separate borders with zero spacing draw the
|
|
1322
|
+
* same lines. */
|
|
1323
|
+
.dds-table-wrap--tall .dds-table {
|
|
1324
|
+
border-collapse: separate;
|
|
1325
|
+
border-spacing: 0;
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
.dds-table__sort {
|
|
1329
|
+
appearance: none;
|
|
1330
|
+
display: inline-flex;
|
|
1331
|
+
align-items: center;
|
|
1332
|
+
gap: .375rem;
|
|
1333
|
+
padding: 0;
|
|
1334
|
+
border: 0;
|
|
1335
|
+
background: none;
|
|
1336
|
+
font: inherit;
|
|
1337
|
+
font-weight: 650;
|
|
1338
|
+
color: inherit;
|
|
1339
|
+
cursor: pointer;
|
|
1340
|
+
}
|
|
1341
|
+
.dds-table__sort[hidden] {
|
|
1342
|
+
display: none;
|
|
1343
|
+
}
|
|
1344
|
+
.dds-table__sort:focus-visible {
|
|
1345
|
+
outline: 2px solid var(--dds-color-border-focus);
|
|
1346
|
+
outline-offset: 2px;
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
.dds-table__sort-mark {
|
|
1350
|
+
inline-size: .5rem;
|
|
1351
|
+
block-size: .5rem;
|
|
1352
|
+
border-inline-end: 2px solid currentColor;
|
|
1353
|
+
border-block-end: 2px solid currentColor;
|
|
1354
|
+
rotate: 45deg;
|
|
1355
|
+
opacity: .35;
|
|
1356
|
+
translate: 0 -.125rem;
|
|
1357
|
+
}
|
|
1358
|
+
.dds-table__sort-mark[data-sort-state="ascending"] {
|
|
1359
|
+
rotate: -135deg;
|
|
1360
|
+
opacity: 1;
|
|
1361
|
+
translate: 0 .125rem;
|
|
1362
|
+
}
|
|
1363
|
+
.dds-table__sort-mark[data-sort-state="descending"] {
|
|
1364
|
+
opacity: 1;
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
.dds-table__actions {
|
|
1368
|
+
display: flex;
|
|
1369
|
+
justify-content: flex-end;
|
|
1370
|
+
gap: var(--dds-space-8);
|
|
1371
|
+
}
|
|
1372
|
+
.dds-table__actions[hidden] {
|
|
1373
|
+
display: none;
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
/* Row actions are 32px and stay on one line. A button's own geometry (40px
|
|
1377
|
+
* default, 32px --sm, both with wrapping labels) plus the cell's 10px block
|
|
1378
|
+
* padding made a row carrying a button measure ~53px against its 40px
|
|
1379
|
+
* neighbours — a table whose rows are not one height reads as broken. So an
|
|
1380
|
+
* action button is held to the --sm height whatever its size modifier
|
|
1381
|
+
* (padding included, or a default button would still be 34px), its label
|
|
1382
|
+
* never wraps (the wrap scrolls horizontally, nothing is clipped), and the
|
|
1383
|
+
* actions cell trims its block padding so 32px fits inside the 40px row. */
|
|
1384
|
+
.dds-table__actions .dds-btn {
|
|
1385
|
+
min-block-size: var(--dds-space-32);
|
|
1386
|
+
padding-block: var(--dds-space-4);
|
|
1387
|
+
white-space: nowrap;
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1390
|
+
/* The same trim for any cell holding a small button (a copy button beside
|
|
1391
|
+
* an id): its own 10px padding around a 32px button is a 53px row, and even
|
|
1392
|
+
* in a dense table 6px around a 24px button plus the 1px border is 37px, a
|
|
1393
|
+
* pixel over the 36px row. A default-size button outside the actions cell
|
|
1394
|
+
* keeps full padding — that is an explicit choice to be taller. */
|
|
1395
|
+
.dds-table td:has(> .dds-table__actions),
|
|
1396
|
+
.dds-table td:has(.dds-btn--sm) {
|
|
1397
|
+
padding-block: var(--dds-space-4);
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
/* Small buttons in a dense table are 24px — a copy button beside an id in
|
|
1401
|
+
* any cell, and every row action whatever its size modifier (the same
|
|
1402
|
+
* "whatever its modifier" as the 32px rule above, one density down) — so
|
|
1403
|
+
* they fit the 36px dense row. Zero block padding is what gets there:
|
|
1404
|
+
* --sm's own 4px padding around a 16px label already makes 26px, which
|
|
1405
|
+
* min-block-size can't pull back down. 24px is exactly the §6 web floor.
|
|
1406
|
+
* A default-size button outside the actions cell is left alone: that is an
|
|
1407
|
+
* explicit choice to be taller. The actions selector out-specifies the
|
|
1408
|
+
* 32px rule; the --sm one ties it and wins on source order. Middle
|
|
1409
|
+
* alignment keeps an inline button beside text from growing the line box
|
|
1410
|
+
* past its own 24px by sitting on the text baseline. */
|
|
1411
|
+
.dds-table--dense .dds-btn--sm,
|
|
1412
|
+
.dds-table--dense .dds-table__actions .dds-btn {
|
|
1413
|
+
min-block-size: var(--dds-space-24);
|
|
1414
|
+
padding-block: 0;
|
|
1415
|
+
vertical-align: middle;
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
/* Touch pointers keep the 44px floor (spec §6, button.css). The two rules
|
|
1419
|
+
* above out-specify button.css's coarse-pointer rule, so without restating
|
|
1420
|
+
* it here a table would silently shrink every action below the touch
|
|
1421
|
+
* target on a phone. Uniform row height yields on touch; the target does
|
|
1422
|
+
* not (docs/decisions.md D-025). */
|
|
1423
|
+
@media (pointer: coarse) {
|
|
1424
|
+
.dds-table__actions .dds-btn,
|
|
1425
|
+
.dds-table--dense .dds-btn--sm,
|
|
1426
|
+
.dds-table--dense .dds-table__actions .dds-btn {
|
|
1427
|
+
min-block-size: 44px;
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
.dds-table__order {
|
|
1432
|
+
margin: 0 0 var(--dds-space-8);
|
|
1433
|
+
font-size: .8125rem;
|
|
1434
|
+
color: var(--dds-color-text-muted);
|
|
1435
|
+
font-family: var(--dds-font-family-mono);
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
.dds-table__pagination {
|
|
1439
|
+
display: flex;
|
|
1440
|
+
justify-content: flex-end;
|
|
1441
|
+
margin-block-start: var(--dds-space-16);
|
|
1442
|
+
}
|
|
1443
|
+
.dds-table__pagination[hidden] {
|
|
1444
|
+
display: none;
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
@media (max-width: 56.25rem) {
|
|
1448
|
+
.dds-table [data-fold] {
|
|
1449
|
+
display: none;
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
/* Console shell — the 232px rail + below-900px drawer that a console route
|
|
1454
|
+
* renders around its content. The fold breakpoint below is written in the
|
|
1455
|
+
* same rem form as table.css's column fold (56.25rem = 900px at a 16px root
|
|
1456
|
+
* font size), so a visitor with any browser default font size sees the rail
|
|
1457
|
+
* change shape and the table's columns fold at the same viewport width
|
|
1458
|
+
* inside the same console.
|
|
1459
|
+
*
|
|
1460
|
+
* Tokens only. Every class that declares `display` re-declares
|
|
1461
|
+
* `[hidden] { display: none }` beside it, at a class+attribute specificity
|
|
1462
|
+
* that beats every later `display` declaration for that class — including
|
|
1463
|
+
* the ones inside the media query below — so a hidden rail, toggle, or
|
|
1464
|
+
* scrim can never be drawn on screen regardless of viewport width. */
|
|
1465
|
+
|
|
1466
|
+
.dds-console-shell {
|
|
1467
|
+
min-block-size: 100vh;
|
|
1468
|
+
display: grid;
|
|
1469
|
+
grid-template-columns: 14.5rem minmax(0, 1fr);
|
|
1470
|
+
background: var(--dds-color-bg-default);
|
|
1471
|
+
color: var(--dds-color-text-primary);
|
|
1472
|
+
font-size: 1rem;
|
|
1473
|
+
line-height: 1.5;
|
|
1474
|
+
}
|
|
1475
|
+
.dds-console-shell[hidden] {
|
|
1476
|
+
display: none;
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
/* The skip link is hidden by .dds-visually-hidden (applied by the
|
|
1480
|
+
* component) and only needs to say what it looks like once focused —
|
|
1481
|
+
* a visually-hidden element is never in the focus-visible/`:focus` chain
|
|
1482
|
+
* while `hidden`, so no `[hidden]` guard applies here. */
|
|
1483
|
+
.dds-console-skip:focus {
|
|
1484
|
+
position: fixed;
|
|
1485
|
+
inset-block-start: var(--dds-space-8);
|
|
1486
|
+
inset-inline-start: var(--dds-space-8);
|
|
1487
|
+
z-index: 100;
|
|
1488
|
+
clip-path: none;
|
|
1489
|
+
inline-size: auto;
|
|
1490
|
+
block-size: auto;
|
|
1491
|
+
overflow: visible;
|
|
1492
|
+
white-space: normal;
|
|
1493
|
+
padding: var(--dds-space-12) var(--dds-space-16);
|
|
1494
|
+
background: var(--dds-color-bg-elevated);
|
|
1495
|
+
color: var(--dds-color-text-primary);
|
|
1496
|
+
border: 2px solid var(--dds-color-border-focus);
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
.dds-console-rail {
|
|
1500
|
+
position: sticky;
|
|
1501
|
+
inset-block-start: 0;
|
|
1502
|
+
block-size: 100vh;
|
|
1503
|
+
display: flex;
|
|
1504
|
+
flex-direction: column;
|
|
1505
|
+
gap: var(--dds-space-16);
|
|
1506
|
+
padding: var(--dds-space-20) var(--dds-space-12);
|
|
1507
|
+
overflow-y: auto;
|
|
1508
|
+
border-inline-end: 1px solid var(--dds-color-border-default);
|
|
1509
|
+
background: var(--dds-color-bg-elevated);
|
|
1510
|
+
}
|
|
1511
|
+
.dds-console-rail[hidden] {
|
|
1512
|
+
display: none;
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
.dds-console-rail__brand {
|
|
1516
|
+
display: inline-flex;
|
|
1517
|
+
align-items: center;
|
|
1518
|
+
gap: var(--dds-space-8);
|
|
1519
|
+
padding-inline: var(--dds-space-8);
|
|
1520
|
+
color: inherit;
|
|
1521
|
+
font-size: .9375rem;
|
|
1522
|
+
font-weight: 700;
|
|
1523
|
+
letter-spacing: -.02em;
|
|
1524
|
+
text-decoration: none;
|
|
1525
|
+
}
|
|
1526
|
+
.dds-console-rail__brand[hidden] {
|
|
1527
|
+
display: none;
|
|
1528
|
+
}
|
|
1529
|
+
.dds-console-rail__brand img {
|
|
1530
|
+
inline-size: 20px;
|
|
1531
|
+
block-size: 20px;
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
.dds-console-rail__context {
|
|
1535
|
+
display: grid;
|
|
1536
|
+
gap: var(--dds-space-4);
|
|
1537
|
+
margin: 0;
|
|
1538
|
+
padding-inline: var(--dds-space-8);
|
|
1539
|
+
font-size: var(--dds-typo-caption-font-size);
|
|
1540
|
+
line-height: var(--dds-typo-caption-line-height);
|
|
1541
|
+
}
|
|
1542
|
+
.dds-console-rail__context[hidden] {
|
|
1543
|
+
display: none;
|
|
1544
|
+
}
|
|
1545
|
+
.dds-console-rail__context dt {
|
|
1546
|
+
color: var(--dds-color-text-muted);
|
|
1547
|
+
}
|
|
1548
|
+
.dds-console-rail__context dd {
|
|
1549
|
+
margin: 0;
|
|
1550
|
+
font-family: var(--dds-font-family-mono);
|
|
1551
|
+
overflow-wrap: anywhere;
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
.dds-console-rail__nav {
|
|
1555
|
+
display: grid;
|
|
1556
|
+
gap: var(--dds-space-16);
|
|
1557
|
+
}
|
|
1558
|
+
.dds-console-rail__nav[hidden] {
|
|
1559
|
+
display: none;
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
.dds-console-rail__group {
|
|
1563
|
+
display: grid;
|
|
1564
|
+
gap: var(--dds-space-2, 2px);
|
|
1565
|
+
}
|
|
1566
|
+
.dds-console-rail__group[hidden] {
|
|
1567
|
+
display: none;
|
|
1568
|
+
}
|
|
1569
|
+
.dds-console-rail__group ul {
|
|
1570
|
+
margin: 0;
|
|
1571
|
+
padding: 0;
|
|
1572
|
+
list-style: none;
|
|
1573
|
+
display: grid;
|
|
1574
|
+
gap: 2px;
|
|
1575
|
+
}
|
|
1576
|
+
.dds-console-rail__group ul[hidden] {
|
|
1577
|
+
display: none;
|
|
1578
|
+
}
|
|
1579
|
+
.dds-console-rail__group-label {
|
|
1580
|
+
margin: 0;
|
|
1581
|
+
padding: 0 var(--dds-space-8) var(--dds-space-4);
|
|
1582
|
+
color: var(--dds-color-text-muted);
|
|
1583
|
+
font-size: .6875rem;
|
|
1584
|
+
font-weight: 600;
|
|
1585
|
+
letter-spacing: .05em;
|
|
1586
|
+
text-transform: uppercase;
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
.dds-console-rail__item {
|
|
1590
|
+
display: flex;
|
|
1591
|
+
align-items: center;
|
|
1592
|
+
justify-content: space-between;
|
|
1593
|
+
gap: var(--dds-space-8);
|
|
1594
|
+
min-block-size: var(--dds-space-40);
|
|
1595
|
+
padding-inline: var(--dds-space-8);
|
|
1596
|
+
border-radius: var(--dds-radius-md);
|
|
1597
|
+
color: var(--dds-color-text-secondary);
|
|
1598
|
+
font-size: .875rem;
|
|
1599
|
+
font-weight: 500;
|
|
1600
|
+
text-decoration: none;
|
|
1601
|
+
}
|
|
1602
|
+
.dds-console-rail__item[hidden] {
|
|
1603
|
+
display: none;
|
|
1604
|
+
}
|
|
1605
|
+
.dds-console-rail__item:hover {
|
|
1606
|
+
background: var(--dds-color-bg-subtle);
|
|
1607
|
+
color: var(--dds-color-text-primary);
|
|
1608
|
+
}
|
|
1609
|
+
.dds-console-rail__item[aria-current="page"] {
|
|
1610
|
+
background: var(--dds-color-bg-brand-subtle);
|
|
1611
|
+
color: var(--dds-color-text-brand);
|
|
1612
|
+
font-weight: 650;
|
|
1613
|
+
}
|
|
1614
|
+
.dds-console-rail__item:focus-visible {
|
|
1615
|
+
outline: 2px solid var(--dds-color-border-focus);
|
|
1616
|
+
outline-offset: 2px;
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
.dds-console-rail__badge {
|
|
1620
|
+
display: inline-grid;
|
|
1621
|
+
place-items: center;
|
|
1622
|
+
min-inline-size: 1.125rem;
|
|
1623
|
+
block-size: 1.125rem;
|
|
1624
|
+
padding-inline: .3125rem;
|
|
1625
|
+
border-radius: var(--dds-radius-full);
|
|
1626
|
+
background: var(--dds-color-bg-brand);
|
|
1627
|
+
color: var(--dds-color-text-on-brand);
|
|
1628
|
+
font-size: .6875rem;
|
|
1629
|
+
font-weight: 700;
|
|
1630
|
+
font-variant-numeric: tabular-nums;
|
|
1631
|
+
}
|
|
1632
|
+
.dds-console-rail__badge[hidden] {
|
|
1633
|
+
display: none;
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
.dds-console-rail__foot {
|
|
1637
|
+
margin-block-start: auto;
|
|
1638
|
+
display: grid;
|
|
1639
|
+
gap: var(--dds-space-8);
|
|
1640
|
+
justify-items: start;
|
|
1641
|
+
padding: var(--dds-space-12) var(--dds-space-8) 0;
|
|
1642
|
+
border-block-start: 1px solid var(--dds-color-border-default);
|
|
1643
|
+
}
|
|
1644
|
+
.dds-console-rail__foot[hidden] {
|
|
1645
|
+
display: none;
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1648
|
+
.dds-console-rail__toggle {
|
|
1649
|
+
display: none;
|
|
1650
|
+
}
|
|
1651
|
+
.dds-console-rail__toggle[hidden] {
|
|
1652
|
+
display: none;
|
|
1653
|
+
}
|
|
1654
|
+
|
|
1655
|
+
.dds-console-rail__scrim {
|
|
1656
|
+
display: none;
|
|
1657
|
+
}
|
|
1658
|
+
.dds-console-rail__scrim[hidden] {
|
|
1659
|
+
display: none;
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1662
|
+
.dds-console-main {
|
|
1663
|
+
min-inline-size: 0;
|
|
1664
|
+
padding: clamp(1rem, 3vw, 2rem);
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
.dds-console-page-header {
|
|
1668
|
+
display: flex;
|
|
1669
|
+
align-items: flex-start;
|
|
1670
|
+
justify-content: space-between;
|
|
1671
|
+
gap: var(--dds-space-32);
|
|
1672
|
+
margin-block-end: var(--dds-space-32);
|
|
1673
|
+
}
|
|
1674
|
+
.dds-console-page-header[hidden] {
|
|
1675
|
+
display: none;
|
|
1676
|
+
}
|
|
1677
|
+
.dds-console-page-header h1 {
|
|
1678
|
+
max-inline-size: 24ch;
|
|
1679
|
+
margin: .25rem 0 0;
|
|
1680
|
+
font-size: clamp(1.75rem, 2.2vw, 2.25rem);
|
|
1681
|
+
line-height: 1.1;
|
|
1682
|
+
letter-spacing: -.03em;
|
|
1683
|
+
text-wrap: balance;
|
|
1684
|
+
}
|
|
1685
|
+
.dds-console-page-header__actions {
|
|
1686
|
+
display: flex;
|
|
1687
|
+
gap: var(--dds-space-8);
|
|
1688
|
+
}
|
|
1689
|
+
.dds-console-page-header__actions[hidden] {
|
|
1690
|
+
display: none;
|
|
1691
|
+
}
|
|
1692
|
+
.dds-console-page-eyebrow {
|
|
1693
|
+
margin: 0;
|
|
1694
|
+
color: var(--dds-color-text-muted);
|
|
1695
|
+
font-size: var(--dds-typo-caption-font-size);
|
|
1696
|
+
line-height: var(--dds-typo-caption-line-height);
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
/* Console density: every dds-css control inside the shell reads at the body-2
|
|
1700
|
+
* size (14px), not dds-btn's own default (13px, --dds-typo-label-font-size).
|
|
1701
|
+
* Scoped to .dds-console-shell rather than left as a global override on
|
|
1702
|
+
* .dds-btn/.dds-input/.dds-select/.dds-textarea themselves — a shell that
|
|
1703
|
+
* establishes a density owns the override for controls inside it, the same
|
|
1704
|
+
* way a shared class must never carry a layout rule that only makes sense
|
|
1705
|
+
* for one consumer's container.
|
|
1706
|
+
*
|
|
1707
|
+
* .dds-btn's :not() exclusions matter: this selector's specificity (0,2,0)
|
|
1708
|
+
* beats every size modifier in button.css (.dds-btn--lg, .dds-btn--sm, both
|
|
1709
|
+
* 0,1,0), so an unqualified `.dds-console-shell .dds-btn` would override
|
|
1710
|
+
* --lg's own font-size back down to body-2 and would give --sm the same
|
|
1711
|
+
* font-size as a default button (--sm declares none of its own, so it was
|
|
1712
|
+
* inheriting whichever rule won for plain .dds-btn) — the one outcome a
|
|
1713
|
+
* size modifier exists to prevent. .dds-input/.dds-select/.dds-textarea
|
|
1714
|
+
* carry no such modifiers today, so no matching exclusion is needed there. */
|
|
1715
|
+
.dds-console-shell .dds-btn:not(.dds-btn--lg):not(.dds-btn--sm),
|
|
1716
|
+
.dds-console-shell .dds-input,
|
|
1717
|
+
.dds-console-shell .dds-select,
|
|
1718
|
+
.dds-console-shell .dds-textarea {
|
|
1719
|
+
font-size: var(--dds-typo-body-2-font-size);
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
@media (max-width: 56.25rem) {
|
|
1723
|
+
.dds-console-shell {
|
|
1724
|
+
grid-template-columns: minmax(0, 1fr);
|
|
1725
|
+
}
|
|
1726
|
+
.dds-console-rail__toggle {
|
|
1727
|
+
position: fixed;
|
|
1728
|
+
inset-block-start: .75rem;
|
|
1729
|
+
inset-inline-start: .75rem;
|
|
1730
|
+
z-index: 70;
|
|
1731
|
+
display: inline-grid;
|
|
1732
|
+
place-items: center;
|
|
1733
|
+
inline-size: 2.5rem;
|
|
1734
|
+
block-size: 2.5rem;
|
|
1735
|
+
border: 1px solid var(--dds-color-border-default);
|
|
1736
|
+
border-radius: var(--dds-radius-md);
|
|
1737
|
+
background: var(--dds-color-bg-elevated);
|
|
1738
|
+
cursor: pointer;
|
|
1739
|
+
}
|
|
1740
|
+
.dds-console-rail__toggle > span[aria-hidden] {
|
|
1741
|
+
position: relative;
|
|
1742
|
+
display: block;
|
|
1743
|
+
inline-size: 16px;
|
|
1744
|
+
block-size: 2px;
|
|
1745
|
+
border-radius: 2px;
|
|
1746
|
+
background: currentColor;
|
|
1747
|
+
}
|
|
1748
|
+
.dds-console-rail__toggle > span[aria-hidden]::before,
|
|
1749
|
+
.dds-console-rail__toggle > span[aria-hidden]::after {
|
|
1750
|
+
content: "";
|
|
1751
|
+
position: absolute;
|
|
1752
|
+
inset-inline-start: 0;
|
|
1753
|
+
inline-size: 16px;
|
|
1754
|
+
block-size: 2px;
|
|
1755
|
+
border-radius: 2px;
|
|
1756
|
+
background: currentColor;
|
|
1757
|
+
}
|
|
1758
|
+
.dds-console-rail__toggle > span[aria-hidden]::before {
|
|
1759
|
+
inset-block-start: -5px;
|
|
1760
|
+
}
|
|
1761
|
+
.dds-console-rail__toggle > span[aria-hidden]::after {
|
|
1762
|
+
inset-block-start: 5px;
|
|
1763
|
+
}
|
|
1764
|
+
/* Translated off-screen is not gone: a closed drawer still takes Tab. Hide
|
|
1765
|
+
it from the focus order with visibility, delayed by the slide's
|
|
1766
|
+
duration so closing still animates, and lifted with no delay when it
|
|
1767
|
+
opens. */
|
|
1768
|
+
.dds-console-rail {
|
|
1769
|
+
position: fixed;
|
|
1770
|
+
inset: 0 auto 0 0;
|
|
1771
|
+
z-index: 60;
|
|
1772
|
+
inline-size: min(84vw, 18rem);
|
|
1773
|
+
block-size: 100dvh;
|
|
1774
|
+
visibility: hidden;
|
|
1775
|
+
translate: -100% 0;
|
|
1776
|
+
transition: translate .22s cubic-bezier(.16, 1, .3, 1), visibility 0s linear .22s;
|
|
1777
|
+
box-shadow: var(--dds-elevation-2);
|
|
1778
|
+
}
|
|
1779
|
+
.dds-console-rail[data-open="true"] {
|
|
1780
|
+
visibility: visible;
|
|
1781
|
+
translate: 0 0;
|
|
1782
|
+
transition-delay: 0s, 0s;
|
|
1783
|
+
}
|
|
1784
|
+
.dds-console-rail__scrim {
|
|
1785
|
+
display: block;
|
|
1786
|
+
position: fixed;
|
|
1787
|
+
inset: 0;
|
|
1788
|
+
z-index: 55;
|
|
1789
|
+
background: var(--dds-color-overlay-dim);
|
|
1790
|
+
opacity: 0;
|
|
1791
|
+
pointer-events: none;
|
|
1792
|
+
transition: opacity .22s ease;
|
|
1793
|
+
}
|
|
1794
|
+
.dds-console-rail__scrim[data-open="true"] {
|
|
1795
|
+
opacity: 1;
|
|
1796
|
+
pointer-events: auto;
|
|
1797
|
+
}
|
|
1798
|
+
.dds-console-main {
|
|
1799
|
+
padding-block-start: 4rem;
|
|
1800
|
+
}
|
|
1801
|
+
.dds-console-page-header {
|
|
1802
|
+
display: grid;
|
|
1803
|
+
gap: var(--dds-space-16);
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1808
|
+
.dds-console-rail,
|
|
1809
|
+
.dds-console-rail__scrim {
|
|
1810
|
+
transition: none;
|
|
1811
|
+
}
|
|
1812
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devslab/dds-css",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "DDS CSS component layer — class-based, framework-neutral, semantic-token-only (spec §4.3 v1 inventory, 20 components)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|