@visns-studio/visns-components 6.3.2 → 6.3.4
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/package.json +1 -1
- package/src/components/Field.jsx +10 -0
- package/src/components/Form.jsx +32 -0
- package/src/components/generic/GenericDetail.jsx +16 -0
- package/src/components/styles/DataGrid.module.scss +11 -0
- package/src/components/styles/Field.module.scss +31 -3
- package/src/components/styles/Form.module.scss +117 -35
- package/src/components/styles/GenericDetail.module.scss +93 -17
- package/src/components/styles/GenericFormBuilder.module.scss +15 -2
- package/src/components/styles/GenericIndex.module.scss +31 -14
- package/src/components/styles/TableFilter.module.scss +96 -62
package/package.json
CHANGED
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"react-dom": "^17.0.0 || ^18.0.0"
|
|
92
92
|
},
|
|
93
93
|
"name": "@visns-studio/visns-components",
|
|
94
|
-
"version": "6.3.
|
|
94
|
+
"version": "6.3.4",
|
|
95
95
|
"description": "Various packages to assist in the development of our Custom Applications.",
|
|
96
96
|
"main": "src/index.js",
|
|
97
97
|
"files": [
|
package/src/components/Field.jsx
CHANGED
|
@@ -2306,6 +2306,11 @@ function Field({
|
|
|
2306
2306
|
data-name={settings.id}
|
|
2307
2307
|
type="radio"
|
|
2308
2308
|
className={`${styles.fi__customcheckbox} radio-input`}
|
|
2309
|
+
// Radio renderers previously ignored the
|
|
2310
|
+
// field's read-only state, leaving
|
|
2311
|
+
// `readOnlyWhen` configs claiming a lock
|
|
2312
|
+
// the UI didn't enforce.
|
|
2313
|
+
disabled={isFieldReadOnly}
|
|
2309
2314
|
value={option.id}
|
|
2310
2315
|
checked={
|
|
2311
2316
|
inputValue !== undefined &&
|
|
@@ -2336,6 +2341,11 @@ function Field({
|
|
|
2336
2341
|
data-name={settings.id}
|
|
2337
2342
|
type="radio"
|
|
2338
2343
|
className={`${styles.fi__customcheckbox} radio-input`}
|
|
2344
|
+
// Radio renderers previously ignored the
|
|
2345
|
+
// field's read-only state, leaving
|
|
2346
|
+
// `readOnlyWhen` configs claiming a lock
|
|
2347
|
+
// the UI didn't enforce.
|
|
2348
|
+
disabled={isFieldReadOnly}
|
|
2339
2349
|
value={option.id}
|
|
2340
2350
|
checked={
|
|
2341
2351
|
inputValue !== undefined &&
|
package/src/components/Form.jsx
CHANGED
|
@@ -115,6 +115,12 @@ function Form({
|
|
|
115
115
|
const [inputClass, setInputClass] = useState({});
|
|
116
116
|
const [tableData, setTableData] = useState({ columns: [], dataSource: [] });
|
|
117
117
|
const [tableProps, setTableProps] = useState({});
|
|
118
|
+
// A `save.return.type: 'table'` form (the report filter rows in
|
|
119
|
+
// GenericDetail) renders nothing at all when the query comes back empty,
|
|
120
|
+
// so "no rows matched" and "you have not run it yet" looked identical: an
|
|
121
|
+
// unchanged blank panel under a "generated successfully" toast. This
|
|
122
|
+
// separates the two so the empty result can say so.
|
|
123
|
+
const [hasQueried, setHasQueried] = useState(false);
|
|
118
124
|
const [uploadProgress, setUploadProgress] = useState(0);
|
|
119
125
|
|
|
120
126
|
// Group selection state management
|
|
@@ -2091,6 +2097,11 @@ function Form({
|
|
|
2091
2097
|
);
|
|
2092
2098
|
}
|
|
2093
2099
|
|
|
2100
|
+
// Set before the branch: an empty result is
|
|
2101
|
+
// still a result, and that is the case the
|
|
2102
|
+
// empty state exists for.
|
|
2103
|
+
setHasQueried(true);
|
|
2104
|
+
|
|
2094
2105
|
if (
|
|
2095
2106
|
res.data[formSettings.save.return.param]
|
|
2096
2107
|
?.length > 0
|
|
@@ -3300,6 +3311,27 @@ function Form({
|
|
|
3300
3311
|
/>
|
|
3301
3312
|
</div>
|
|
3302
3313
|
)}
|
|
3314
|
+
|
|
3315
|
+
{/* Empty result. Only ever after a run — before that the
|
|
3316
|
+
panel is a filter row waiting to be used, and telling
|
|
3317
|
+
the user there is nothing there would be wrong. Copy is
|
|
3318
|
+
overridable per report via `save.return.empty`. */}
|
|
3319
|
+
{hasQueried &&
|
|
3320
|
+
formSettings?.save?.return?.type === 'table' &&
|
|
3321
|
+
!(tableData?.dataSource?.length > 0) && (
|
|
3322
|
+
<div
|
|
3323
|
+
className={`${styles.formItem} ${styles.fwItem} ${styles.emptyResult}`}
|
|
3324
|
+
>
|
|
3325
|
+
<p>
|
|
3326
|
+
{formSettings.save.return.empty?.title ||
|
|
3327
|
+
'No records matched'}
|
|
3328
|
+
</p>
|
|
3329
|
+
<span>
|
|
3330
|
+
{formSettings.save.return.empty?.message ||
|
|
3331
|
+
'Nothing came back for these filters. Widen them and run the report again.'}
|
|
3332
|
+
</span>
|
|
3333
|
+
</div>
|
|
3334
|
+
)}
|
|
3303
3335
|
</form>
|
|
3304
3336
|
<div className={styles.polActions}>
|
|
3305
3337
|
{formSettings.hasOwnProperty('customButton') &&
|
|
@@ -2679,6 +2679,22 @@ function GenericDetail({
|
|
|
2679
2679
|
>
|
|
2680
2680
|
<span>{formConfig.title}</span>
|
|
2681
2681
|
</div>
|
|
2682
|
+
{/* Optional one-line subtitle. A
|
|
2683
|
+
report tab is a name and a set
|
|
2684
|
+
of controls with nothing saying
|
|
2685
|
+
what it returns; a tab that has
|
|
2686
|
+
something to say can now say
|
|
2687
|
+
it, and one that has not is
|
|
2688
|
+
unchanged. */}
|
|
2689
|
+
{formConfig.description && (
|
|
2690
|
+
<p
|
|
2691
|
+
className={
|
|
2692
|
+
styles.gridtxt__description
|
|
2693
|
+
}
|
|
2694
|
+
>
|
|
2695
|
+
{formConfig.description}
|
|
2696
|
+
</p>
|
|
2697
|
+
)}
|
|
2682
2698
|
<Form
|
|
2683
2699
|
key={`form-${activeTabConfig.id}`}
|
|
2684
2700
|
columnId={routeParams[urlParam]}
|
|
@@ -205,8 +205,16 @@
|
|
|
205
205
|
}
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
+
/* The gallery modal's close control — this class is consumed by
|
|
209
|
+
modals/GalleryModal.jsx, which imports this stylesheet (DataGrid.jsx itself
|
|
210
|
+
never uses it). Same hardening as the header close in Form.module.scss; the
|
|
211
|
+
long note on the svg block there explains why a close glyph needs an
|
|
212
|
+
explicit box and `flex: none` rather than trusting its size attributes. */
|
|
208
213
|
.modal__close {
|
|
209
214
|
width: max-content;
|
|
215
|
+
min-width: 2rem;
|
|
216
|
+
min-height: 2rem;
|
|
217
|
+
box-sizing: border-box;
|
|
210
218
|
background: rgba(var(--paragraph-rgb), 0.05);
|
|
211
219
|
cursor: pointer;
|
|
212
220
|
padding: 0.25rem;
|
|
@@ -225,6 +233,9 @@
|
|
|
225
233
|
}
|
|
226
234
|
|
|
227
235
|
svg {
|
|
236
|
+
width: 1.25rem;
|
|
237
|
+
height: 1.25rem;
|
|
238
|
+
flex: none;
|
|
228
239
|
color: var(--primary-color);
|
|
229
240
|
display: block;
|
|
230
241
|
}
|
|
@@ -708,24 +708,52 @@ input[type='file']:hover {
|
|
|
708
708
|
font-size: 1.15em;
|
|
709
709
|
}
|
|
710
710
|
|
|
711
|
+
/* The "Edit Canvas" modal's close control (Field.jsx). Hardened
|
|
712
|
+
the same way as the header close in Form.module.scss — see the
|
|
713
|
+
note on the svg block there. */
|
|
711
714
|
.modal__close {
|
|
712
715
|
width: max-content;
|
|
716
|
+
min-width: 2rem;
|
|
717
|
+
min-height: 2rem;
|
|
713
718
|
position: absolute;
|
|
714
719
|
right: 5px;
|
|
715
720
|
top: 5px;
|
|
716
721
|
box-sizing: border-box;
|
|
717
|
-
|
|
722
|
+
/* Was `rgba(var(--primary-color), 1.08)`, which is not a
|
|
723
|
+
colour: `--primary-color` is a hex, rgba() wants three
|
|
724
|
+
channels, and an alpha above 1 is out of range either way.
|
|
725
|
+
The declaration was invalid and dropped, so this button had
|
|
726
|
+
no background at all. It sits on `&__header`, which is
|
|
727
|
+
`var(--primary-color)`, so what it wants is a light lift off
|
|
728
|
+
that ground — the same treatment the equivalent control in
|
|
729
|
+
GenericFormBuilder.module.scss uses on its coloured header. */
|
|
730
|
+
background: rgba(255, 255, 255, 0.15);
|
|
718
731
|
cursor: pointer;
|
|
719
732
|
padding: 8px 8px;
|
|
720
733
|
margin: 0;
|
|
721
734
|
outline: none;
|
|
722
735
|
border: none;
|
|
723
736
|
border-radius: var(--br);
|
|
724
|
-
display:
|
|
737
|
+
display: flex;
|
|
738
|
+
align-items: center;
|
|
739
|
+
justify-content: center;
|
|
725
740
|
line-height: 1;
|
|
741
|
+
transition: background 0.2s ease;
|
|
742
|
+
|
|
743
|
+
&:hover {
|
|
744
|
+
background: rgba(255, 255, 255, 0.25);
|
|
745
|
+
}
|
|
726
746
|
|
|
727
747
|
svg {
|
|
728
|
-
|
|
748
|
+
width: 1.25rem;
|
|
749
|
+
height: 1.25rem;
|
|
750
|
+
flex: none;
|
|
751
|
+
/* The header behind this is `--primary-color`, so the
|
|
752
|
+
glyph is set against it rather than in a brand hue that
|
|
753
|
+
may be a near-match for it. Field.jsx also passes
|
|
754
|
+
`color="#FFF"`, which lucide writes as a `stroke`
|
|
755
|
+
attribute; this keeps the two in agreement. */
|
|
756
|
+
color: #fff;
|
|
729
757
|
display: block;
|
|
730
758
|
}
|
|
731
759
|
}
|
|
@@ -242,23 +242,63 @@ input[type='file'] {
|
|
|
242
242
|
justify-content: center;
|
|
243
243
|
width: 2rem;
|
|
244
244
|
height: 2rem;
|
|
245
|
+
/* The box is stated three ways on purpose. `width`/`height` alone is not a
|
|
246
|
+
box a consuming app cannot move: every one of these buttons lives under
|
|
247
|
+
whatever ambient `button { … }` rule the host stylesheet carries, and
|
|
248
|
+
with the library's own `* { box-sizing: border-box }` in play, a host
|
|
249
|
+
padding rule eats this button's *content* box rather than growing it.
|
|
250
|
+
The min-* pair holds the outer size and `box-sizing` states the
|
|
251
|
+
assumption rather than inheriting it — but see the svg block for what
|
|
252
|
+
actually keeps the glyph safe. */
|
|
253
|
+
min-width: 2rem;
|
|
254
|
+
min-height: 2rem;
|
|
255
|
+
box-sizing: border-box;
|
|
245
256
|
flex: none;
|
|
246
257
|
background: none;
|
|
247
258
|
cursor: pointer;
|
|
248
259
|
padding: 0;
|
|
249
260
|
margin: 0;
|
|
250
261
|
border: none;
|
|
251
|
-
border-radius: var(--radius-sm);
|
|
262
|
+
border-radius: var(--radius-sm, 6px);
|
|
252
263
|
line-height: 1;
|
|
253
|
-
transition: background-color var(--speed) var(--ease);
|
|
264
|
+
transition: background-color var(--speed, 0.18s) var(--ease, ease);
|
|
254
265
|
|
|
255
266
|
&:hover {
|
|
256
|
-
background: var(--hover-color);
|
|
267
|
+
background: var(--hover-color, rgba(var(--paragraph-color-rgb, 34, 30, 51), 0.06));
|
|
257
268
|
}
|
|
258
269
|
|
|
259
270
|
svg {
|
|
260
|
-
|
|
271
|
+
/* This is the rule that stops the icon disappearing.
|
|
272
|
+
|
|
273
|
+
An `<svg width="24" height="24">` inside a flex container is a flex
|
|
274
|
+
item with the default `flex-shrink: 1`, so when the button's content
|
|
275
|
+
box is squeezed the glyph shrinks with it — all the way down.
|
|
276
|
+
Hartway's plant-floor stylesheet carries
|
|
277
|
+
`body.tablet-mode button:not([class*='InovuaReactDataGrid'])
|
|
278
|
+
{ padding: 8px 14px }`,
|
|
279
|
+
which outweighs this module's single class (0,2,2 against 0,1,0) and
|
|
280
|
+
left a 2rem border-box button with a 4px content box; the X
|
|
281
|
+
collapsed with it and read as a smudge at the end of the header.
|
|
282
|
+
|
|
283
|
+
`flex: none` refuses to shrink, and the explicit width/height also
|
|
284
|
+
makes the glyph immune to the `width: 100%` sizing pattern used on
|
|
285
|
+
svgs elsewhere in this library. Both are needed: the size fixes the
|
|
286
|
+
basis, `flex: none` stops it being overruled. Sized here rather than
|
|
287
|
+
trusting the `size` prop at each call site, so every modal header
|
|
288
|
+
agrees on one glyph. */
|
|
289
|
+
width: 1.25rem;
|
|
290
|
+
height: 1.25rem;
|
|
291
|
+
flex: none;
|
|
292
|
+
/* Recessive, but a control the user has to be able to find has no
|
|
293
|
+
business being fainter than the body text around it. */
|
|
294
|
+
color: var(--muted-color, #6b7688);
|
|
261
295
|
display: block;
|
|
296
|
+
transition: color var(--speed, 0.18s) var(--ease, ease);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
&:hover svg,
|
|
300
|
+
&:focus-visible svg {
|
|
301
|
+
color: var(--paragraph-color, #374151);
|
|
262
302
|
}
|
|
263
303
|
}
|
|
264
304
|
|
|
@@ -295,43 +335,54 @@ input[type='file'] {
|
|
|
295
335
|
|
|
296
336
|
|
|
297
337
|
|
|
298
|
-
.
|
|
299
|
-
width: max-content;
|
|
300
|
-
display: inline-block;
|
|
301
|
-
position: relative;
|
|
302
|
-
padding: 0.65rem 1rem;
|
|
303
|
-
cursor: pointer;
|
|
304
|
-
font-size: 1rem;
|
|
305
|
-
color: var(--tertiary-color);
|
|
306
|
-
text-decoration: none;
|
|
307
|
-
overflow: hidden;
|
|
308
|
-
background: var(--primary-color);
|
|
309
|
-
border: 1px solid rgba(var(--primary-color--rgb), 1.1);
|
|
310
|
-
border-radius: var(--br);
|
|
311
|
-
outline: none;
|
|
312
|
-
transition: all 0.2s cubic-bezier(0.85, 0, 0.15, 1) 0s;
|
|
313
|
-
font-size: 1.25em;
|
|
338
|
+
/* The form's primary action (Save / View Report / Refresh).
|
|
314
339
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
340
|
+
This was a bespoke button — 1.25em type on 0.65rem padding, its own radius
|
|
341
|
+
token, its own transition curve, and a hover that swapped to pale blue on
|
|
342
|
+
blue. Sat next to `.btn` (the shared primary) in the same action bar, so the
|
|
343
|
+
two controls that are meant to read as a pair were a different height, a
|
|
344
|
+
different type size and a different hover. It is the same button as every
|
|
345
|
+
other primary in the library; it just needed to say so. */
|
|
346
|
+
.saveBtn {
|
|
347
|
+
@include button-primary;
|
|
320
348
|
}
|
|
321
349
|
|
|
350
|
+
/* The inline form's action bar.
|
|
351
|
+
|
|
352
|
+
Was `position: fixed; bottom: 15px; right: 20px` with `float: left`
|
|
353
|
+
children: the buttons left the form entirely and parked in the corner of
|
|
354
|
+
the *viewport*. On a short form (the report filter rows in GenericDetail —
|
|
355
|
+
one row of dropdowns) that put "View Report" nowhere near the filters it
|
|
356
|
+
runs; on a form that returns a results grid it floated on top of the grid's
|
|
357
|
+
last rows and its horizontal scrollbar.
|
|
358
|
+
|
|
359
|
+
It is a footer to the form it belongs to, so it lives at the end of the
|
|
360
|
+
form. `sticky` keeps what the fixed positioning was actually for — the
|
|
361
|
+
action stays reachable while a long form or a 550px results grid is
|
|
362
|
+
scrolled — without detaching it from its panel. */
|
|
322
363
|
.polActions {
|
|
323
|
-
position:
|
|
324
|
-
bottom:
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
364
|
+
position: sticky;
|
|
365
|
+
bottom: 0;
|
|
366
|
+
z-index: 5;
|
|
367
|
+
display: flex;
|
|
368
|
+
align-items: center;
|
|
369
|
+
justify-content: flex-end;
|
|
370
|
+
gap: var(--spacing-sm, 0.5rem);
|
|
371
|
+
width: 100%;
|
|
372
|
+
margin-top: var(--spacing-lg, 1.5rem);
|
|
373
|
+
padding: var(--spacing-sm, 0.5rem) 0;
|
|
374
|
+
/* Opaque, or the form scrolls through the bar while it is stuck. */
|
|
375
|
+
background: var(--surface-color, #fff);
|
|
376
|
+
border-top: 1px solid var(--border-color, #e1e1e1);
|
|
328
377
|
}
|
|
329
378
|
|
|
330
|
-
.
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
379
|
+
/* One primary per bar. Download / Sort / Save & Exit are alternatives to the
|
|
380
|
+
main action, not competitors: identical geometry, no fill. Previously every
|
|
381
|
+
button in here was a filled brand-blue block, so a filter row offering
|
|
382
|
+
"Download Report" and "View Report" gave no clue which one was the thing
|
|
383
|
+
you came to do. */
|
|
384
|
+
.polActions .btn {
|
|
385
|
+
@include button-secondary;
|
|
335
386
|
}
|
|
336
387
|
|
|
337
388
|
/* For in-place editing mode */
|
|
@@ -381,6 +432,37 @@ input[type='file'] {
|
|
|
381
432
|
display: none;
|
|
382
433
|
}
|
|
383
434
|
|
|
435
|
+
/* Empty result for `save.return.type: 'table'` forms. Deliberately not a
|
|
436
|
+
card and not an alert: an empty report is an ordinary outcome, so it is a
|
|
437
|
+
quiet block of centred text on the panel it would have filled, drawn with
|
|
438
|
+
the same hairline the rest of the page separates things with. */
|
|
439
|
+
.emptyResult {
|
|
440
|
+
display: flex;
|
|
441
|
+
flex-direction: column;
|
|
442
|
+
align-items: center;
|
|
443
|
+
justify-content: center;
|
|
444
|
+
gap: var(--spacing-xs, 0.25rem);
|
|
445
|
+
padding: var(--spacing-2xl, 3rem) var(--spacing-md, 1rem);
|
|
446
|
+
text-align: center;
|
|
447
|
+
border: 1px dashed var(--border-color, #e1e1e1);
|
|
448
|
+
border-radius: var(--radius-md, 10px);
|
|
449
|
+
background: var(--alternate-color, transparent);
|
|
450
|
+
|
|
451
|
+
p {
|
|
452
|
+
margin: 0;
|
|
453
|
+
font-size: var(--font-size-md, 0.9375rem);
|
|
454
|
+
font-weight: var(--font-weight-semibold, 600);
|
|
455
|
+
color: var(--heading-color, inherit);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
span {
|
|
459
|
+
max-width: 42ch;
|
|
460
|
+
font-size: var(--font-size-sm, 0.8125rem);
|
|
461
|
+
line-height: 1.5;
|
|
462
|
+
color: var(--muted-color, #6e7276);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
384
466
|
.buttonContainer {
|
|
385
467
|
display: flex;
|
|
386
468
|
justify-content: center;
|
|
@@ -86,15 +86,31 @@
|
|
|
86
86
|
gap: 0.5rem;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
/* The tab rail. Identical spec to `.grid__subnav` in GenericIndex.module.scss
|
|
90
|
+
— the two pages share one rail, so keep them in step.
|
|
91
|
+
|
|
92
|
+
It was a white panel under a 50px brand-tinted blur, holding one tinted blue
|
|
93
|
+
pill per tab. Every item therefore carried the same weight as the selected
|
|
94
|
+
one, and a seven-tab rail (the reports page) read as a stack of seven
|
|
95
|
+
buttons rather than as navigation with one thing chosen. 6.3's answer
|
|
96
|
+
everywhere else on the page is a flat surface, a hairline and quiet ink, so
|
|
97
|
+
that is what the rail gets: unselected tabs are plain text on the panel, and
|
|
98
|
+
the brand blue is spent once, on the tab you are actually on. */
|
|
89
99
|
.grid__subnav {
|
|
100
|
+
/* `flex: 1` (basis 0) against `.grid__subcontent`'s `flex: 0 1 80%` is
|
|
101
|
+
left exactly as it was: `.grid__subrow` is `flex-wrap: wrap`, so a
|
|
102
|
+
flex-basis here large enough to overflow the row would wrap the content
|
|
103
|
+
panel onto its own line rather than shrink it. Only the treatment
|
|
104
|
+
changes below. */
|
|
90
105
|
flex: 1;
|
|
91
|
-
background:
|
|
106
|
+
background: var(--surface-color, #fff);
|
|
107
|
+
border: 1px solid var(--border-color, #e1e1e1);
|
|
92
108
|
border-radius: var(--br);
|
|
93
109
|
box-sizing: border-box;
|
|
94
|
-
padding:
|
|
110
|
+
padding: var(--spacing-xs, 0.25rem);
|
|
95
111
|
margin: 8px 0;
|
|
96
112
|
height: auto;
|
|
97
|
-
box-shadow:
|
|
113
|
+
box-shadow: none;
|
|
98
114
|
}
|
|
99
115
|
|
|
100
116
|
.grid__subnav > ul {
|
|
@@ -108,32 +124,54 @@
|
|
|
108
124
|
|
|
109
125
|
.grid__subnav > ul li {
|
|
110
126
|
width: 100%;
|
|
111
|
-
margin-bottom:
|
|
127
|
+
margin-bottom: var(--spacing-xs, 0.25rem);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.grid__subnav > ul li:last-child {
|
|
131
|
+
margin-bottom: 0;
|
|
112
132
|
}
|
|
113
133
|
|
|
114
134
|
.grid__subnav > ul li a {
|
|
115
135
|
width: 100%;
|
|
116
|
-
|
|
136
|
+
/* 0.35rem was a 5px-tall hit area for a control people click all day. */
|
|
137
|
+
padding: var(--spacing-sm, 0.5rem) var(--spacing-md, 1rem);
|
|
117
138
|
box-sizing: border-box;
|
|
118
139
|
display: block;
|
|
119
140
|
text-decoration: none;
|
|
120
|
-
background:
|
|
121
|
-
color: var(--
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
141
|
+
background: none;
|
|
142
|
+
color: var(--text-color, #374151);
|
|
143
|
+
font-size: var(--font-size-sm, 0.8125rem);
|
|
144
|
+
font-weight: var(--font-weight-medium, 500);
|
|
145
|
+
line-height: 1.35;
|
|
146
|
+
border-radius: var(--radius-sm, 6px);
|
|
147
|
+
transition:
|
|
148
|
+
background-color var(--speed, 0.18s) var(--ease, ease),
|
|
149
|
+
color var(--speed, 0.18s) var(--ease, ease);
|
|
125
150
|
cursor: pointer;
|
|
126
151
|
}
|
|
127
152
|
|
|
128
153
|
.grid__subnav > ul li:hover a {
|
|
129
|
-
|
|
130
|
-
|
|
154
|
+
/* Hover is a hint, not a commitment. It used to fill solid brand blue —
|
|
155
|
+
indistinguishable from the selected tab, so passing the mouse across the
|
|
156
|
+
rail made it look as though the selection was following the cursor. */
|
|
157
|
+
background: var(--hover-color, rgba(0, 0, 0, 0.04));
|
|
158
|
+
color: var(--heading-color, inherit);
|
|
131
159
|
}
|
|
132
160
|
|
|
133
161
|
.grid__subnav > ul li .subactive {
|
|
134
|
-
font-weight:
|
|
162
|
+
font-weight: var(--font-weight-semibold, 600);
|
|
135
163
|
background: var(--primary-color);
|
|
136
|
-
|
|
164
|
+
/* Was --background-color, the page's off-white; white is what the button
|
|
165
|
+
and nav-pill treatments elsewhere put on this blue. */
|
|
166
|
+
color: #fff;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/* `outline: none` used to sit on the link with nothing put back, so the rail
|
|
170
|
+
was unusable by keyboard. The app's own ring token, same as every other
|
|
171
|
+
control. */
|
|
172
|
+
.grid__subnav > ul li a:focus-visible {
|
|
173
|
+
outline: none;
|
|
174
|
+
box-shadow: var(--focus-ring, 0 0 0 3px rgba(0, 118, 192, 0.32));
|
|
137
175
|
}
|
|
138
176
|
|
|
139
177
|
.grid__minheight {
|
|
@@ -146,9 +184,12 @@
|
|
|
146
184
|
|
|
147
185
|
.grid__subcontent {
|
|
148
186
|
flex: 0 1 80%;
|
|
149
|
-
background: var(--
|
|
187
|
+
background: var(--surface-color, #fff);
|
|
150
188
|
border-radius: var(--br);
|
|
151
|
-
|
|
189
|
+
/* Was the brand blue at 5% — a tint so faint the panel had no edge at all
|
|
190
|
+
while the rail beside it did. The shared hairline, same as every other
|
|
191
|
+
surface on the page. */
|
|
192
|
+
border: 1px solid var(--border-color, #e1e1e1);
|
|
152
193
|
box-sizing: border-box;
|
|
153
194
|
padding: 2px;
|
|
154
195
|
margin: 8px 0;
|
|
@@ -163,6 +204,24 @@
|
|
|
163
204
|
margin: 0 0 30px 0;
|
|
164
205
|
}
|
|
165
206
|
|
|
207
|
+
/* The tab panel's own inset.
|
|
208
|
+
|
|
209
|
+
`.gridtxt` had no rule at all, and its container (`.grid__subcontent`,
|
|
210
|
+
`.grid__full`) carries `padding: 2px` — so a panel's section heading and any
|
|
211
|
+
form inside it sat 2px from the panel border. Only the overview `<ul>` was
|
|
212
|
+
readable, because it padded itself. On the reports page that meant the
|
|
213
|
+
filter row's dropdowns and date pickers were flush against the panel edge.
|
|
214
|
+
|
|
215
|
+
The inset belongs to the panel, not to one child of it, so it is stated
|
|
216
|
+
here once and the `<ul>` below gives up its horizontal padding to match.
|
|
217
|
+
The `<ul>`'s vertical padding stays: with several heading/list pairs in one
|
|
218
|
+
`.gridtxt` (the overview tabs) that is what separates one section from the
|
|
219
|
+
next. */
|
|
220
|
+
.gridtxt {
|
|
221
|
+
padding: var(--spacing-md, 1rem) var(--spacing-lg, 1.5rem)
|
|
222
|
+
var(--spacing-lg, 1.5rem);
|
|
223
|
+
}
|
|
224
|
+
|
|
166
225
|
.gridtxt__header {
|
|
167
226
|
width: 100%;
|
|
168
227
|
display: block;
|
|
@@ -192,6 +251,21 @@
|
|
|
192
251
|
font-weight: 700;
|
|
193
252
|
}
|
|
194
253
|
|
|
254
|
+
/* Optional one-line subtitle under a section heading (GenericDetail renders it
|
|
255
|
+
from a tab's `description`). Sits in the heading's own space — it belongs to
|
|
256
|
+
the label, not to the content — so it takes over the heading's bottom margin
|
|
257
|
+
rather than adding a third gap. */
|
|
258
|
+
.gridtxt__description {
|
|
259
|
+
/* Pulls back half of the heading's 1rem bottom margin, so the subtitle sits
|
|
260
|
+
close under its heading and the whole block is separated from the
|
|
261
|
+
content below rather than floating between the two. */
|
|
262
|
+
margin: calc(-1 * var(--spacing-sm, 0.5rem)) 0 var(--spacing-lg, 1.5rem);
|
|
263
|
+
max-width: 70ch;
|
|
264
|
+
font-size: var(--font-size-sm, 0.8125rem);
|
|
265
|
+
line-height: 1.55;
|
|
266
|
+
color: var(--muted-color, #6e7276);
|
|
267
|
+
}
|
|
268
|
+
|
|
195
269
|
.gridtxt > ul {
|
|
196
270
|
width: 100%;
|
|
197
271
|
display: flex;
|
|
@@ -200,7 +274,9 @@
|
|
|
200
274
|
flex-wrap: wrap;
|
|
201
275
|
list-style: none;
|
|
202
276
|
box-sizing: border-box;
|
|
203
|
-
padding
|
|
277
|
+
/* Horizontal padding removed — `.gridtxt` owns the panel inset now (see
|
|
278
|
+
the note there). The vertical padding separates stacked sections. */
|
|
279
|
+
padding: 0.85rem 0;
|
|
204
280
|
margin: 0;
|
|
205
281
|
}
|
|
206
282
|
|
|
@@ -741,8 +741,13 @@ select:not(:placeholder-shown) + .fi__span {
|
|
|
741
741
|
letter-spacing: 0.01em;
|
|
742
742
|
}
|
|
743
743
|
|
|
744
|
+
/* The form builder's modal close control (GenericFormBuilder.jsx, two call
|
|
745
|
+
sites). Hardened the same way as the header close in Form.module.scss — see
|
|
746
|
+
the note on the svg block there. */
|
|
744
747
|
.modal__close {
|
|
745
748
|
width: max-content;
|
|
749
|
+
min-width: 2rem;
|
|
750
|
+
min-height: 2rem;
|
|
746
751
|
position: absolute;
|
|
747
752
|
right: 8px;
|
|
748
753
|
top: 8px;
|
|
@@ -754,7 +759,9 @@ select:not(:placeholder-shown) + .fi__span {
|
|
|
754
759
|
outline: none;
|
|
755
760
|
border: none;
|
|
756
761
|
border-radius: 6px;
|
|
757
|
-
display:
|
|
762
|
+
display: flex;
|
|
763
|
+
align-items: center;
|
|
764
|
+
justify-content: center;
|
|
758
765
|
line-height: 1;
|
|
759
766
|
transition: background 0.2s ease;
|
|
760
767
|
|
|
@@ -764,7 +771,13 @@ select:not(:placeholder-shown) + .fi__span {
|
|
|
764
771
|
}
|
|
765
772
|
|
|
766
773
|
.modal__close svg {
|
|
767
|
-
|
|
774
|
+
width: 1.25rem;
|
|
775
|
+
height: 1.25rem;
|
|
776
|
+
flex: none;
|
|
777
|
+
/* `.modal__header` above is `var(--primary-color)`, so the glyph is set
|
|
778
|
+
against that ground rather than in a second brand hue that may be a
|
|
779
|
+
near-match for it — which is what `--secondary-color` was doing here. */
|
|
780
|
+
color: #fff;
|
|
768
781
|
display: block;
|
|
769
782
|
}
|
|
770
783
|
|
|
@@ -114,15 +114,19 @@
|
|
|
114
114
|
gap: 0.5rem;
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
+
/* The tab rail. Identical spec to `.grid__subnav` in GenericDetail.module.scss
|
|
118
|
+
— the two pages share one rail, so keep them in step; the reasoning for the
|
|
119
|
+
treatment is written out there. */
|
|
117
120
|
.grid__subnav {
|
|
118
121
|
flex: 1;
|
|
119
|
-
background:
|
|
122
|
+
background: var(--surface-color, #fff);
|
|
123
|
+
border: 1px solid var(--border-color, #e1e1e1);
|
|
120
124
|
border-radius: var(--br);
|
|
121
125
|
box-sizing: border-box;
|
|
122
|
-
padding:
|
|
126
|
+
padding: var(--spacing-xs, 0.25rem);
|
|
123
127
|
margin: 8px 0;
|
|
124
128
|
height: auto;
|
|
125
|
-
box-shadow:
|
|
129
|
+
box-shadow: none;
|
|
126
130
|
}
|
|
127
131
|
|
|
128
132
|
.grid__subnav > ul {
|
|
@@ -136,32 +140,45 @@
|
|
|
136
140
|
|
|
137
141
|
.grid__subnav > ul li {
|
|
138
142
|
width: 100%;
|
|
139
|
-
margin-bottom:
|
|
143
|
+
margin-bottom: var(--spacing-xs, 0.25rem);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.grid__subnav > ul li:last-child {
|
|
147
|
+
margin-bottom: 0;
|
|
140
148
|
}
|
|
141
149
|
|
|
142
150
|
.grid__subnav > ul li a {
|
|
143
151
|
width: 100%;
|
|
144
|
-
padding: 0.
|
|
152
|
+
padding: var(--spacing-sm, 0.5rem) var(--spacing-md, 1rem);
|
|
145
153
|
box-sizing: border-box;
|
|
146
154
|
display: block;
|
|
147
155
|
text-decoration: none;
|
|
148
|
-
background:
|
|
149
|
-
color: var(--
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
156
|
+
background: none;
|
|
157
|
+
color: var(--text-color, #374151);
|
|
158
|
+
font-size: var(--font-size-sm, 0.8125rem);
|
|
159
|
+
font-weight: var(--font-weight-medium, 500);
|
|
160
|
+
line-height: 1.35;
|
|
161
|
+
border-radius: var(--radius-sm, 6px);
|
|
162
|
+
transition:
|
|
163
|
+
background-color var(--speed, 0.18s) var(--ease, ease),
|
|
164
|
+
color var(--speed, 0.18s) var(--ease, ease);
|
|
153
165
|
cursor: pointer;
|
|
154
166
|
}
|
|
155
167
|
|
|
156
168
|
.grid__subnav > ul li:hover a {
|
|
157
|
-
background: var(--
|
|
158
|
-
color: var(--
|
|
169
|
+
background: var(--hover-color, rgba(0, 0, 0, 0.04));
|
|
170
|
+
color: var(--heading-color, inherit);
|
|
159
171
|
}
|
|
160
172
|
|
|
161
173
|
.grid__subnav > ul li .subactive {
|
|
162
|
-
font-weight:
|
|
174
|
+
font-weight: var(--font-weight-semibold, 600);
|
|
163
175
|
background: var(--primary-color);
|
|
164
|
-
color:
|
|
176
|
+
color: #fff;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.grid__subnav > ul li a:focus-visible {
|
|
180
|
+
outline: none;
|
|
181
|
+
box-shadow: var(--focus-ring, 0 0 0 3px rgba(0, 118, 192, 0.32));
|
|
165
182
|
}
|
|
166
183
|
|
|
167
184
|
.grid__subnav__alternate {
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The tab rail's own stylesheet, which predates the 6.3 token language: it was
|
|
3
|
+
* still drawing its own card (a hardcoded rgba drop shadow and radius) and its
|
|
4
|
+
* own type scale (0.85/0.9rem literals) around items that the host surface —
|
|
5
|
+
* `.grid__subnav` in GenericIndex/GenericDetail — already frames. Two nested
|
|
6
|
+
* cards, two shadows, and a rail whose type did not match anything else on the
|
|
7
|
+
* page. Everything here now reads the same tokens as the rest of the library,
|
|
8
|
+
* and the framing is left to the surface it sits on.
|
|
9
|
+
*
|
|
10
|
+
* Literal fallbacks throughout: a bare `var()` for a token a consuming app has
|
|
11
|
+
* not declared is invalid at computed-value time and the whole declaration is
|
|
12
|
+
* dropped, which is exactly how a rail like this loses its padding.
|
|
13
|
+
*/
|
|
14
|
+
|
|
1
15
|
.tableFilterContainer {
|
|
2
16
|
width: 100%;
|
|
3
17
|
position: relative;
|
|
@@ -9,11 +23,11 @@
|
|
|
9
23
|
list-style: none;
|
|
10
24
|
padding: 0;
|
|
11
25
|
margin: 0;
|
|
12
|
-
font-size: 0.
|
|
26
|
+
font-size: var(--font-size-sm, 0.8125rem);
|
|
13
27
|
width: 100%;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
28
|
+
/* No radius, no shadow, no `overflow: hidden`. The panel around this list
|
|
29
|
+
supplies the surface; the clipping additionally cut the focus ring off
|
|
30
|
+
the first and last items. */
|
|
17
31
|
}
|
|
18
32
|
|
|
19
33
|
/* Parent category styling */
|
|
@@ -29,19 +43,23 @@
|
|
|
29
43
|
display: flex;
|
|
30
44
|
justify-content: space-between;
|
|
31
45
|
align-items: center;
|
|
32
|
-
padding:
|
|
33
|
-
|
|
34
|
-
font-
|
|
46
|
+
padding: var(--spacing-sm, 0.5rem) var(--spacing-md, 1rem);
|
|
47
|
+
border-radius: var(--radius-sm, 6px);
|
|
48
|
+
font-weight: var(--font-weight-semibold, 600);
|
|
49
|
+
font-size: var(--font-size-sm, 0.8125rem);
|
|
35
50
|
background-color: var(--primary-color, #000);
|
|
36
|
-
color:
|
|
37
|
-
|
|
51
|
+
color: #fff;
|
|
52
|
+
/* Was `all 0.2s`, which animates layout properties too. */
|
|
53
|
+
transition:
|
|
54
|
+
background-color var(--speed, 0.18s) var(--ease, ease),
|
|
55
|
+
color var(--speed, 0.18s) var(--ease, ease);
|
|
38
56
|
position: relative;
|
|
39
57
|
text-decoration: none;
|
|
40
58
|
}
|
|
41
59
|
|
|
42
60
|
.parentLink:hover {
|
|
43
|
-
background-color: var(--
|
|
44
|
-
color:
|
|
61
|
+
background-color: var(--primary-color-darker, #222) !important;
|
|
62
|
+
color: #fff !important;
|
|
45
63
|
text-decoration: none;
|
|
46
64
|
}
|
|
47
65
|
|
|
@@ -63,7 +81,9 @@
|
|
|
63
81
|
overflow: hidden;
|
|
64
82
|
transition: max-height 0.3s ease-out, opacity 0.3s ease-out;
|
|
65
83
|
opacity: 0;
|
|
66
|
-
|
|
84
|
+
/* Flush with the rail. The child links carry their own hover surface now,
|
|
85
|
+
so a tint behind the whole submenu only made a second panel edge. */
|
|
86
|
+
background: none;
|
|
67
87
|
}
|
|
68
88
|
|
|
69
89
|
.visibleMenu {
|
|
@@ -74,7 +94,7 @@
|
|
|
74
94
|
.childItem {
|
|
75
95
|
margin: 0;
|
|
76
96
|
position: relative;
|
|
77
|
-
border-bottom: 1px solid
|
|
97
|
+
border-bottom: 1px solid var(--border-color, #e1e1e1);
|
|
78
98
|
}
|
|
79
99
|
|
|
80
100
|
.childItem:last-child {
|
|
@@ -82,18 +102,20 @@
|
|
|
82
102
|
}
|
|
83
103
|
|
|
84
104
|
.childLink {
|
|
85
|
-
padding:
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
font-
|
|
105
|
+
padding: var(--spacing-sm, 0.5rem) var(--spacing-md, 1rem) var(--spacing-sm, 0.5rem)
|
|
106
|
+
var(--spacing-xl, 1.75rem);
|
|
107
|
+
background: none;
|
|
108
|
+
color: var(--text-color, #333);
|
|
109
|
+
font-weight: var(--font-weight-regular, 400);
|
|
110
|
+
font-size: var(--font-size-sm, 0.8125rem);
|
|
111
|
+
border-radius: var(--radius-sm, 6px);
|
|
90
112
|
display: block;
|
|
91
113
|
text-decoration: none;
|
|
92
114
|
}
|
|
93
115
|
|
|
94
116
|
.childLink:hover {
|
|
95
117
|
background-color: var(--hover-color, #e8e8e8) !important;
|
|
96
|
-
color: var(--
|
|
118
|
+
color: var(--heading-color, #000) !important;
|
|
97
119
|
text-decoration: none;
|
|
98
120
|
}
|
|
99
121
|
|
|
@@ -104,37 +126,55 @@
|
|
|
104
126
|
color: rgba(var(--paragraph-color-rgb, 153, 153, 153), 0.6);
|
|
105
127
|
}
|
|
106
128
|
|
|
107
|
-
/* Active states
|
|
129
|
+
/* Active states. The brand fill is the one loud thing in the rail, and it
|
|
130
|
+
marks exactly one item — which is what makes it readable as a selection
|
|
131
|
+
rather than as decoration. */
|
|
108
132
|
.subactive {
|
|
109
|
-
font-weight: 600;
|
|
133
|
+
font-weight: var(--font-weight-semibold, 600);
|
|
110
134
|
background: var(--primary-color, #000) !important;
|
|
111
|
-
|
|
135
|
+
/* Was --tertiary-color, which several projects set to their page
|
|
136
|
+
off-white; white is what sits on this blue elsewhere. */
|
|
137
|
+
color: #fff !important;
|
|
112
138
|
}
|
|
113
139
|
|
|
114
140
|
.subactivechildren {
|
|
115
|
-
font-weight: 500;
|
|
116
|
-
background-color: var(--
|
|
141
|
+
font-weight: var(--font-weight-medium, 500);
|
|
142
|
+
background-color: var(--primary-color-light, #f0f0f0) !important;
|
|
117
143
|
color: var(--primary-color, #000) !important;
|
|
118
144
|
}
|
|
119
145
|
|
|
120
|
-
/* Base link styling
|
|
146
|
+
/* Base link styling. Unselected tabs are text on the panel, not tinted
|
|
147
|
+
blocks — see the note on `.grid__subnav` in GenericDetail.module.scss. */
|
|
121
148
|
.link {
|
|
122
149
|
display: block;
|
|
123
|
-
padding:
|
|
150
|
+
padding: var(--spacing-sm, 0.5rem) var(--spacing-md, 1rem);
|
|
124
151
|
text-decoration: none;
|
|
125
|
-
background:
|
|
126
|
-
color: var(--
|
|
127
|
-
font-size: 0.
|
|
128
|
-
|
|
152
|
+
background: none;
|
|
153
|
+
color: var(--text-color, #333);
|
|
154
|
+
font-size: var(--font-size-sm, 0.8125rem);
|
|
155
|
+
font-weight: var(--font-weight-medium, 500);
|
|
156
|
+
border-radius: var(--radius-sm, 6px);
|
|
157
|
+
transition:
|
|
158
|
+
background-color var(--speed, 0.18s) var(--ease, ease),
|
|
159
|
+
color var(--speed, 0.18s) var(--ease, ease);
|
|
129
160
|
cursor: pointer;
|
|
130
161
|
}
|
|
131
162
|
|
|
132
163
|
.link:hover {
|
|
133
164
|
background: var(--hover-color, #e8e8e8) !important;
|
|
134
|
-
|
|
165
|
+
/* Was the brand blue, which on hover made an unselected tab look like the
|
|
166
|
+
selected one. */
|
|
167
|
+
color: var(--heading-color, #000) !important;
|
|
135
168
|
text-decoration: none;
|
|
136
169
|
}
|
|
137
170
|
|
|
171
|
+
.link:focus-visible,
|
|
172
|
+
.childLink:focus-visible,
|
|
173
|
+
.parentLink:focus-visible {
|
|
174
|
+
outline: none;
|
|
175
|
+
box-shadow: var(--focus-ring, 0 0 0 3px rgba(0, 118, 192, 0.32));
|
|
176
|
+
}
|
|
177
|
+
|
|
138
178
|
.activetab button {
|
|
139
179
|
font-weight: bold;
|
|
140
180
|
background: var(--hover-color, #e0e0e0) !important;
|
|
@@ -146,19 +186,20 @@
|
|
|
146
186
|
display: none;
|
|
147
187
|
align-items: center;
|
|
148
188
|
justify-content: space-between;
|
|
149
|
-
padding:
|
|
189
|
+
padding: var(--spacing-sm, 0.75rem) var(--spacing-md, 1rem);
|
|
150
190
|
background: var(--primary-color, #000);
|
|
151
|
-
color:
|
|
152
|
-
border-radius:
|
|
191
|
+
color: #fff;
|
|
192
|
+
border-radius: var(--radius-sm, 6px);
|
|
153
193
|
cursor: pointer;
|
|
154
|
-
margin-bottom:
|
|
194
|
+
margin-bottom: var(--spacing-sm, 0.5rem);
|
|
155
195
|
border: none;
|
|
156
|
-
box-shadow: 0 1px 3px rgba(
|
|
196
|
+
box-shadow: var(--shadow-sm, 0 1px 3px rgba(0, 0, 0, 0.2));
|
|
157
197
|
}
|
|
158
198
|
|
|
159
199
|
.activeFilterLabel {
|
|
160
|
-
font-weight: 600;
|
|
161
|
-
|
|
200
|
+
font-weight: var(--font-weight-semibold, 600);
|
|
201
|
+
font-size: var(--font-size-sm, 0.8125rem);
|
|
202
|
+
color: #fff;
|
|
162
203
|
}
|
|
163
204
|
|
|
164
205
|
.mobileMenuIcon {
|
|
@@ -175,7 +216,7 @@
|
|
|
175
216
|
display: block;
|
|
176
217
|
height: 2px;
|
|
177
218
|
width: 100%;
|
|
178
|
-
background-color:
|
|
219
|
+
background-color: #fff;
|
|
179
220
|
border-radius: 2px;
|
|
180
221
|
transition: all 0.3s ease;
|
|
181
222
|
}
|
|
@@ -206,20 +247,17 @@
|
|
|
206
247
|
display: none; /* Hide hamburger menu on tablets */
|
|
207
248
|
}
|
|
208
249
|
|
|
209
|
-
/*
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
250
|
+
/* Roomier tap targets. Only the padding moves: the literal 0.85/0.9rem
|
|
251
|
+
sizes that used to sit here re-declared the rail's type at a scale
|
|
252
|
+
nothing else on the page uses, so the labels changed size at 1024px for
|
|
253
|
+
no reason. Density is a padding question. */
|
|
254
|
+
.parentLink,
|
|
215
255
|
.link {
|
|
216
|
-
padding:
|
|
217
|
-
font-size: 0.85rem;
|
|
256
|
+
padding: 0.65rem var(--spacing-md, 1rem);
|
|
218
257
|
}
|
|
219
258
|
|
|
220
259
|
.childLink {
|
|
221
|
-
padding:
|
|
222
|
-
font-size: 0.85rem;
|
|
260
|
+
padding: 0.65rem var(--spacing-md, 1rem) 0.65rem var(--spacing-xl, 1.75rem);
|
|
223
261
|
}
|
|
224
262
|
}
|
|
225
263
|
|
|
@@ -240,25 +278,21 @@
|
|
|
240
278
|
display: block;
|
|
241
279
|
max-height: 1000px;
|
|
242
280
|
overflow-y: auto;
|
|
243
|
-
|
|
244
|
-
border
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
.parentLink {
|
|
250
|
-
padding: 10px 16px; /* Slightly larger touch targets for mobile */
|
|
251
|
-
font-size: 0.9rem;
|
|
281
|
+
padding: var(--spacing-xs, 0.25rem);
|
|
282
|
+
border: 1px solid var(--border-color, #e1e1e1);
|
|
283
|
+
border-radius: var(--br, 8px);
|
|
284
|
+
margin-bottom: var(--spacing-sm, 0.5rem);
|
|
285
|
+
box-shadow: var(--shadow-sm, 0 2px 5px rgba(0, 0, 0, 0.1));
|
|
252
286
|
}
|
|
253
287
|
|
|
288
|
+
/* Larger tap targets on a phone; the type scale is left alone, as above. */
|
|
289
|
+
.parentLink,
|
|
254
290
|
.link {
|
|
255
|
-
padding:
|
|
256
|
-
font-size: 0.85rem;
|
|
291
|
+
padding: 0.75rem var(--spacing-md, 1rem);
|
|
257
292
|
}
|
|
258
293
|
|
|
259
294
|
.childLink {
|
|
260
|
-
padding:
|
|
261
|
-
font-size: 0.85rem;
|
|
295
|
+
padding: 0.75rem var(--spacing-md, 1rem) 0.75rem var(--spacing-xl, 1.75rem);
|
|
262
296
|
}
|
|
263
297
|
|
|
264
298
|
.collapsibleMenu {
|