@livenetworks/ashlar 1.5.1 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +189 -177
- package/js/COMPONENTS.md +55 -49
- package/js/index.js +22 -5
- package/js/ln-accordion/README.md +186 -137
- package/js/ln-accordion/ln-accordion.js +1 -1
- package/js/ln-ajax/README.md +73 -4
- package/js/ln-ajax/ln-ajax.js +1 -1
- package/js/ln-ajax/src/ln-ajax.js +13 -13
- package/js/ln-api-connector/README.md +261 -150
- package/js/ln-api-connector/ln-api-connector.js +1 -1
- package/js/ln-api-connector/src/ln-api-connector.js +368 -265
- package/js/ln-api-queue/README.md +219 -0
- package/js/ln-api-queue/ln-api-queue.js +1 -0
- package/js/ln-api-queue/src/ln-api-queue.js +320 -0
- package/js/ln-api-queue/src/queue-storage.js +455 -0
- package/js/ln-autoresize/README.md +47 -0
- package/js/ln-autoresize/ln-autoresize.js +1 -1
- package/js/ln-autosave/README.md +33 -1
- package/js/ln-autosave/ln-autosave.js +1 -1
- package/js/ln-autosave/src/ln-autosave.js +4 -4
- package/js/ln-circular-progress/README.md +27 -13
- package/js/ln-circular-progress/ln-circular-progress.js +1 -1
- package/js/ln-circular-progress/src/ln-circular-progress.js +18 -5
- package/js/ln-confirm/README.md +162 -86
- package/js/ln-confirm/_ln-confirm.scss +11 -0
- package/js/ln-confirm/ln-confirm.js +1 -1
- package/js/ln-confirm/src/ln-confirm.js +77 -41
- package/js/ln-core/README.md +896 -0
- package/js/ln-core/hash.js +92 -0
- package/js/ln-core/helpers.js +337 -8
- package/js/ln-core/index.js +4 -2
- package/js/ln-core/persist.js +29 -3
- package/js/ln-core/positioning.js +1 -35
- package/js/ln-core/window-cache.js +213 -0
- package/js/ln-couchdb-connector/README.md +177 -156
- package/js/ln-couchdb-connector/ln-couchdb-connector.js +1 -1
- package/js/ln-couchdb-connector/src/ln-couchdb-connector.js +398 -348
- package/js/ln-data-coordinator/README.md +536 -165
- package/js/ln-data-coordinator/ln-data-coordinator.js +1 -1
- package/js/ln-data-coordinator/src/data-read-policy.js +18 -0
- package/js/ln-data-coordinator/src/ln-data-coordinator.js +1042 -249
- package/js/ln-data-coordinator/src/mutation-receipts.js +46 -0
- package/js/ln-data-store/README.md +241 -94
- package/js/ln-data-store/ln-data-store.js +1 -1
- package/js/ln-data-store/src/ln-data-store.js +694 -699
- package/js/ln-date/README.md +39 -1
- package/js/ln-date/ln-date-dev.scss +14 -0
- package/js/ln-date/ln-date.js +1 -1
- package/js/ln-date/src/ln-date.js +236 -178
- package/js/ln-debug/README.md +58 -0
- package/js/ln-debug/ln-debug.js +1 -0
- package/js/ln-debug/src/ln-debug.js +19 -0
- package/js/ln-dropdown/README.md +31 -8
- package/js/ln-dropdown/ln-dropdown.js +1 -1
- package/js/ln-dropdown/src/ln-dropdown.js +30 -13
- package/js/ln-editor/README.md +274 -0
- package/js/ln-editor/ln-editor.js +1 -0
- package/js/ln-editor/ln-editor.scss +43 -0
- package/js/ln-editor/src/ln-editor.js +619 -0
- package/js/ln-external-links/README.md +44 -5
- package/js/ln-external-links/ln-external-links.js +1 -1
- package/js/ln-fill/README.md +199 -0
- package/js/ln-fill/ln-fill.js +1 -0
- package/js/ln-fill/src/ln-fill.js +87 -0
- package/js/ln-filter/README.md +92 -2
- package/js/ln-filter/ln-filter-dev.scss +8 -0
- package/js/ln-filter/ln-filter.js +1 -1
- package/js/ln-filter/src/ln-filter.js +22 -7
- package/js/ln-form/README.md +212 -49
- package/js/ln-form/ln-form.js +1 -1
- package/js/ln-form/src/ln-form.js +99 -199
- package/js/ln-http/README.md +125 -89
- package/js/ln-http/ln-http.js +1 -1
- package/js/ln-http/src/ln-http.js +32 -13
- package/js/ln-icon/README.md +130 -0
- package/js/ln-icon/ln-icon.js +1 -0
- package/js/{ln-icons/src/ln-icons.js → ln-icon/src/ln-icon.js} +20 -15
- package/js/ln-link/README.md +47 -9
- package/js/ln-link/ln-link.js +1 -1
- package/js/ln-link/src/ln-link.js +22 -6
- package/js/ln-list/README.md +129 -0
- package/js/ln-list/ln-list.js +1 -0
- package/js/ln-list/ln-list.scss +28 -0
- package/js/ln-list/src/ln-list.js +1216 -0
- package/js/ln-modal/README.md +185 -154
- package/js/ln-modal/ln-modal-dev.scss +13 -0
- package/js/ln-modal/ln-modal.js +1 -1
- package/js/ln-modal/ln-modal.scss +28 -4
- package/js/ln-modal/src/ln-modal.js +137 -201
- package/js/ln-modal-coordinator/README.md +99 -0
- package/js/ln-modal-coordinator/ln-modal-coordinator-dev.scss +8 -0
- package/js/ln-modal-coordinator/ln-modal-coordinator.js +1 -0
- package/js/ln-modal-coordinator/src/ln-modal-coordinator.js +345 -0
- package/js/ln-nav/README.md +46 -3
- package/js/ln-nav/ln-nav.js +1 -1
- package/js/ln-nav/src/ln-nav.js +92 -127
- package/js/ln-number/README.md +28 -1
- package/js/ln-number/ln-number-dev.scss +13 -0
- package/js/ln-number/ln-number.js +1 -1
- package/js/ln-number/src/ln-number.js +443 -350
- package/js/ln-options/README.md +66 -0
- package/js/ln-options/ln-options.js +1 -0
- package/js/ln-options/src/ln-options.js +74 -0
- package/js/ln-popover/README.md +40 -5
- package/js/ln-popover/ln-popover.js +1 -1
- package/js/ln-popover/src/ln-popover.js +38 -11
- package/js/ln-progress/README.md +413 -442
- package/js/ln-progress/ln-progress.js +1 -1
- package/js/ln-progress/src/ln-progress.js +98 -150
- package/js/ln-router/README.md +432 -0
- package/js/ln-router/ln-router.js +1 -0
- package/js/ln-router/src/ln-router.js +539 -0
- package/js/ln-search/README.md +158 -83
- package/js/ln-search/ln-search-dev.scss +8 -0
- package/js/ln-search/ln-search.js +1 -1
- package/js/ln-search/src/ln-search.js +12 -9
- package/js/ln-slug/README.md +110 -0
- package/js/ln-slug/ln-slug.js +1 -0
- package/js/ln-slug/src/ln-slug.js +74 -0
- package/js/ln-sort/README.md +170 -0
- package/js/ln-sort/ln-sort-dev.scss +8 -0
- package/js/ln-sort/ln-sort.js +1 -0
- package/js/ln-sort/src/ln-sort.js +178 -0
- package/js/ln-sortable/README.md +133 -95
- package/js/ln-sortable/ln-sortable.js +1 -1
- package/js/ln-stat/README.md +55 -0
- package/js/ln-stat/ln-stat.js +1 -0
- package/js/ln-stat/src/ln-stat.js +55 -0
- package/js/ln-table/README.md +285 -101
- package/js/ln-table/ln-table-dev.scss +17 -0
- package/js/ln-table/ln-table.js +1 -1
- package/js/ln-table/ln-table.scss +1 -1
- package/js/ln-table/src/ln-table.js +1493 -473
- package/js/ln-table-coordinator/README.md +73 -0
- package/js/ln-table-coordinator/ln-table-coordinator.js +1 -0
- package/js/ln-table-coordinator/src/ln-table-coordinator.js +160 -0
- package/js/ln-tabs/README.md +221 -137
- package/js/ln-tabs/ln-tabs-dev.scss +18 -0
- package/js/ln-tabs/ln-tabs.js +1 -1
- package/js/ln-tabs/src/ln-tabs.js +41 -24
- package/js/ln-time/README.md +14 -0
- package/js/ln-time/ln-time.js +1 -1
- package/js/ln-time/src/ln-time.js +223 -192
- package/js/ln-toast/README.md +178 -122
- package/js/ln-toast/ln-toast.js +1 -15
- package/js/ln-toast/src/ln-toast.js +232 -210
- package/js/ln-toast/template.html +16 -12
- package/js/ln-toggle/README.md +61 -2
- package/js/ln-toggle/ln-toggle-dev.scss +13 -0
- package/js/ln-toggle/ln-toggle.js +1 -1
- package/js/ln-toggle/src/ln-toggle.js +56 -43
- package/js/ln-tooltip/README.md +95 -58
- package/js/ln-tooltip/ln-tooltip-dev.scss +9 -0
- package/js/ln-tooltip/ln-tooltip.js +1 -1
- package/js/ln-tooltip/src/ln-tooltip.js +45 -6
- package/js/ln-translations/README.md +118 -96
- package/js/ln-translations/ln-translations.js +1 -1
- package/js/ln-translations/src/ln-translations.js +10 -5
- package/js/ln-upload/README.md +85 -10
- package/js/ln-upload/ln-upload.js +1 -1
- package/js/ln-upload/src/ln-upload.js +26 -10
- package/js/ln-validate/README.md +72 -0
- package/js/ln-validate/ln-validate-dev.scss +15 -0
- package/js/ln-validate/ln-validate.js +1 -1
- package/js/ln-validate/src/ln-validate.js +64 -0
- package/package.json +61 -56
- package/scss/base/_global.scss +2 -2
- package/scss/base/_typography.scss +1 -2
- package/scss/components/_date.scss +1 -0
- package/scss/components/_dropdown.scss +0 -5
- package/scss/components/_editor.scss +5 -0
- package/scss/components/_filter.scss +26 -25
- package/scss/components/_form.scss +7 -0
- package/scss/components/_ln-table.scss +13 -3
- package/scss/components/_sort.scss +10 -0
- package/scss/components/_table.scss +36 -23
- package/scss/components/_toast.scss +68 -41
- package/scss/components/_toggle.scss +16 -0
- package/scss/config/_density.scss +205 -117
- package/scss/config/_icons.scss +10 -9
- package/scss/config/_tokens.scss +69 -47
- package/scss/config/mixins/_accordion.scss +2 -7
- package/scss/config/mixins/_alert.scss +4 -4
- package/scss/config/mixins/_breadcrumbs.scss +2 -2
- package/scss/config/mixins/_btn.scss +1 -1
- package/scss/config/mixins/_card.scss +89 -14
- package/scss/config/mixins/_collapsible.scss +3 -0
- package/scss/config/mixins/_colors.scss +1 -1
- package/scss/config/mixins/_diagnostics.scss +11 -0
- package/scss/config/mixins/_display.scss +1 -0
- package/scss/config/mixins/_dropdown.scss +3 -5
- package/scss/config/mixins/_editor.scss +124 -0
- package/scss/config/mixins/_empty-state.scss +7 -0
- package/scss/config/mixins/_filter.scss +3 -5
- package/scss/config/mixins/_footer.scss +1 -2
- package/scss/config/mixins/_form.scss +207 -21
- package/scss/config/mixins/_index.scss +2 -0
- package/scss/config/mixins/_ln-table.scss +41 -2
- package/scss/config/mixins/_modal.scss +149 -66
- package/scss/config/mixins/_nav.scss +3 -4
- package/scss/config/mixins/_popover.scss +39 -0
- package/scss/config/mixins/_sidebar.scss +1 -1
- package/scss/config/mixins/_sort.scss +42 -0
- package/scss/config/mixins/_table.scss +85 -60
- package/scss/config/mixins/_toast.scss +179 -152
- package/scss/config/mixins/_tooltip.scss +17 -7
- package/scss/config/mixins/_typography.scss +4 -2
- package/scss/ln-ashlar-dev.scss +27 -9
- package/scss/ln-ashlar.scss +7 -1
- package/js/ln-data-table/README.md +0 -110
- package/js/ln-data-table/ln-data-table.js +0 -1
- package/js/ln-data-table/ln-data-table.scss +0 -10
- package/js/ln-data-table/src/ln-data-table.js +0 -1087
- package/js/ln-icons/README.md +0 -88
- package/js/ln-icons/ln-icons.js +0 -1
- package/js/ln-table/ln-table-sort.js +0 -1
- package/js/ln-table/src/ln-table-sort.js +0 -156
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
// Tunables (consumer-overridable via --var with sane defaults):
|
|
21
21
|
// --filter-dropdown-max-height (default 20rem)
|
|
22
22
|
// --filter-dropdown-overflow-y (default auto)
|
|
23
|
-
// --filter-dropdown-text (default var(--text-xs)) ← sm density
|
|
24
23
|
// --filter-dropdown-item-pad-y (default var(--size-3xs))
|
|
25
24
|
//
|
|
26
25
|
// Usage:
|
|
@@ -34,15 +33,14 @@
|
|
|
34
33
|
[data-ln-filter-search] {
|
|
35
34
|
@include form-input;
|
|
36
35
|
font-size: var(--filter-dropdown-text, var(--text-xs));
|
|
37
|
-
--padding-y: var(--size-
|
|
36
|
+
--padding-y: var(--size-2xs);
|
|
38
37
|
--padding-x: var(--size-sm);
|
|
39
38
|
width: 100%;
|
|
40
|
-
margin-bottom: var(--size-
|
|
39
|
+
margin-bottom: var(--size-xs);
|
|
41
40
|
}
|
|
42
41
|
|
|
43
42
|
[data-ln-filter-options] {
|
|
44
|
-
@include check-list;
|
|
45
|
-
font-size: var(--filter-dropdown-text, var(--text-xs));
|
|
43
|
+
@include check-list-nav;
|
|
46
44
|
|
|
47
45
|
li { padding: var(--filter-dropdown-item-pad-y, var(--size-3xs)) 0; }
|
|
48
46
|
}
|
|
@@ -25,8 +25,7 @@
|
|
|
25
25
|
padding: var(--padding-y) var(--padding-x);
|
|
26
26
|
border-block-start: var(--border-block-start, var(--border-width) solid var(--color-border));
|
|
27
27
|
background: var(--color-bg);
|
|
28
|
-
|
|
29
|
-
line-height: var(--lh-body-sm);
|
|
28
|
+
@include typography(body-sm);
|
|
30
29
|
color: var(--color-fg);
|
|
31
30
|
@include flex;
|
|
32
31
|
@include items-center;
|
|
@@ -17,9 +17,8 @@
|
|
|
17
17
|
|
|
18
18
|
@mixin form-label {
|
|
19
19
|
@include block;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
@include font-medium;
|
|
20
|
+
@include typography(label-sm);
|
|
21
|
+
@include font-semibold;
|
|
23
22
|
color: var(--color-fg);
|
|
24
23
|
// Structural label-to-input gap (not shell rhythm).
|
|
25
24
|
--margin-block: var(--size-xs);
|
|
@@ -91,12 +90,13 @@
|
|
|
91
90
|
|
|
92
91
|
@mixin form-input {
|
|
93
92
|
@include w-full;
|
|
94
|
-
--padding-y: var(--size-sm);
|
|
93
|
+
--padding-y: var(--input-padding-y, var(--size-sm));
|
|
95
94
|
--padding-x: var(--size-md);
|
|
96
95
|
padding: var(--padding-y) var(--padding-x);
|
|
97
96
|
font-size: var(--font-size);
|
|
98
97
|
line-height: var(--line-height);
|
|
99
98
|
color: var(--color-fg);
|
|
99
|
+
--color-bg: var(--input-bg, var(--bg-recessed));
|
|
100
100
|
background: var(--color-bg);
|
|
101
101
|
@include border;
|
|
102
102
|
border-radius: var(--radius);
|
|
@@ -211,6 +211,7 @@
|
|
|
211
211
|
padding: var(--size-xs) var(--size-sm); // icon provides its own row spacing
|
|
212
212
|
--color-fg: var(--fg-subtle);
|
|
213
213
|
color: var(--color-fg);
|
|
214
|
+
box-sizing: content-box;
|
|
214
215
|
}
|
|
215
216
|
|
|
216
217
|
> input,
|
|
@@ -262,27 +263,93 @@
|
|
|
262
263
|
@mixin form-input-icon-group {
|
|
263
264
|
@include form-field-group;
|
|
264
265
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
266
|
+
// Visually hide the clear button while the field is empty (visibility:hidden
|
|
267
|
+
// preserves layout space so the input width stays stable).
|
|
268
|
+
// Structural target: the only button in this group is the clear control.
|
|
269
|
+
> input:placeholder-shown ~ button {
|
|
270
|
+
@include invisible;
|
|
270
271
|
}
|
|
271
272
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
273
|
+
// Clear control — square hit area, circular highlight on hover only.
|
|
274
|
+
// Overrides the flush date/submit-button styling inherited from
|
|
275
|
+
// form-field-group > button (equal specificity, emitted later → wins).
|
|
276
|
+
> button {
|
|
277
|
+
align-self: center; // cancel inherited stretch
|
|
278
|
+
aspect-ratio: 1; // square hit area
|
|
279
|
+
padding: var(--size-2xs); // equal padding all sides (cancels L+R size-sm and T+B 0)
|
|
280
|
+
border-radius: var(--radius-full); // circular highlight (square in flat theme)
|
|
281
|
+
background: transparent; // transparent idle
|
|
280
282
|
@include transition-colors;
|
|
281
283
|
|
|
282
|
-
|
|
284
|
+
> .ln-icon {
|
|
285
|
+
--color-fg: var(--fg-subtle); // idle icon color
|
|
283
286
|
color: var(--color-fg);
|
|
287
|
+
@include transition-colors; // icon recolor must animate (parent transition won't drive child color)
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
&:hover {
|
|
291
|
+
background: var(--btn-bg-hover); // circle highlight appears
|
|
292
|
+
> .ln-icon {
|
|
293
|
+
--color-fg: var(--fg-default);
|
|
294
|
+
}
|
|
284
295
|
}
|
|
285
296
|
}
|
|
297
|
+
|
|
298
|
+
// Fix C — pull the leading icon and the input text closer.
|
|
299
|
+
// Inherited from form-field-group at equal specificity; emitted later → wins per property.
|
|
300
|
+
|
|
301
|
+
// 1. Zero the input's OWN adjacent side padding (the user's explicit minimum).
|
|
302
|
+
// Mirror form-field-group's :not() structure so the override lands at equal
|
|
303
|
+
// specificity and replaces only the horizontal padding it set.
|
|
304
|
+
> input,
|
|
305
|
+
> select {
|
|
306
|
+
&:not(:first-child) {
|
|
307
|
+
padding-left: 0;
|
|
308
|
+
}
|
|
309
|
+
&:not(:last-child) {
|
|
310
|
+
padding-right: 0;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// 2. Reduce ONLY the leading icon's INNER (right) padding so the magnifier sits
|
|
315
|
+
// close to the text. KEEP the left padding (inherited --size-sm outer breathing
|
|
316
|
+
// room) and KEEP vertical padding. Set padding-right ONLY — never the `padding`
|
|
317
|
+
// shorthand (it would clobber left + vertical).
|
|
318
|
+
> .ln-icon {
|
|
319
|
+
padding-right: var(--size-xs); // 8px → 4px; left + vertical inherited from form-field-group
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// ─── Search field — compact icon-group variant (delta-only) ───────
|
|
324
|
+
//
|
|
325
|
+
// Opt-in refinements layered on top of the icon-group chrome that the
|
|
326
|
+
// global auto-bind (components/_form.scss: label:has(> .ln-icon):has(>
|
|
327
|
+
// search/text input)) already supplies. PREREQUISITE: the consumer is an
|
|
328
|
+
// icon + search-input <label> so the auto-bind provides the base shell;
|
|
329
|
+
// on a plain label this emits only the tweaks below, no chrome.
|
|
330
|
+
//
|
|
331
|
+
// Usage (project/demo SCSS):
|
|
332
|
+
// label.search { @include search; }
|
|
333
|
+
|
|
334
|
+
@mixin search {
|
|
335
|
+
width: min(100%, 20rem); // intrinsic capped field width
|
|
336
|
+
--color-bg: var(--bg-recessed); // recessed fill so the white clear-hover reads
|
|
337
|
+
--btn-bg-hover: var(--bg-base); // clear button highlights white on hover (token rebind, no specificity override)
|
|
338
|
+
|
|
339
|
+
// Density-immune: pin to the dense base scale so the field is one size
|
|
340
|
+
// everywhere, regardless of ambient [data-density]. Mirror the values
|
|
341
|
+
// in config/_density.scss — keep in sync.
|
|
342
|
+
--size-xs: 0.125rem;
|
|
343
|
+
--size-sm: 0.375rem;
|
|
344
|
+
--font-size: 0.875rem;
|
|
345
|
+
--line-height: 1.5;
|
|
346
|
+
|
|
347
|
+
// Compact field — smaller vertical padding. form-input self-declares
|
|
348
|
+
// --padding-y on the input, so override it on the input directly.
|
|
349
|
+
> input { --padding-y: var(--size-xs); }
|
|
350
|
+
|
|
351
|
+
// Compact icons via the --icon-size primitive (no ln-icon--sm class in markup).
|
|
352
|
+
.ln-icon { --icon-size: 1rem; }
|
|
286
353
|
}
|
|
287
354
|
|
|
288
355
|
// ─── Checkbox & Radio ───────────────────────────────────────────
|
|
@@ -349,7 +416,7 @@
|
|
|
349
416
|
@include flex;
|
|
350
417
|
@include items-center;
|
|
351
418
|
gap: var(--gap);
|
|
352
|
-
--padding-y: var(--size-sm);
|
|
419
|
+
--padding-y: var(--input-padding-y, var(--size-sm));
|
|
353
420
|
--padding-x: var(--size-md);
|
|
354
421
|
padding: var(--padding-y) var(--padding-x);
|
|
355
422
|
@include cursor-pointer;
|
|
@@ -516,6 +583,71 @@
|
|
|
516
583
|
}
|
|
517
584
|
}
|
|
518
585
|
|
|
586
|
+
// Segmented track control pills
|
|
587
|
+
@mixin pills-segmented {
|
|
588
|
+
@include inline-flex;
|
|
589
|
+
@include items-center;
|
|
590
|
+
list-style: none;
|
|
591
|
+
padding: 2px;
|
|
592
|
+
margin: 0;
|
|
593
|
+
background-color: var(--bg-recessed);
|
|
594
|
+
border-radius: var(--radius);
|
|
595
|
+
border: var(--border-width) solid var(--color-border);
|
|
596
|
+
width: 100%;
|
|
597
|
+
|
|
598
|
+
> li {
|
|
599
|
+
flex: 1 1 0%;
|
|
600
|
+
margin: 0;
|
|
601
|
+
padding: 0;
|
|
602
|
+
display: block;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
> li > label:has(> input[type="checkbox"]),
|
|
606
|
+
> li > label:has(> input[type="radio"]) {
|
|
607
|
+
@include flex;
|
|
608
|
+
@include items-center;
|
|
609
|
+
@include justify-center;
|
|
610
|
+
padding: var(--size-xs) var(--size-md);
|
|
611
|
+
border-radius: calc(var(--radius) - 2px);
|
|
612
|
+
@include cursor-pointer;
|
|
613
|
+
@include text-sm;
|
|
614
|
+
@include font-medium;
|
|
615
|
+
color: var(--fg-muted);
|
|
616
|
+
@include transition;
|
|
617
|
+
user-select: none;
|
|
618
|
+
margin: 0;
|
|
619
|
+
text-align: center;
|
|
620
|
+
border: none;
|
|
621
|
+
background: transparent;
|
|
622
|
+
|
|
623
|
+
> input {
|
|
624
|
+
position: absolute;
|
|
625
|
+
width: 1px;
|
|
626
|
+
height: 1px;
|
|
627
|
+
padding: 0;
|
|
628
|
+
margin: -1px;
|
|
629
|
+
overflow: hidden;
|
|
630
|
+
clip: rect(0, 0, 0, 0);
|
|
631
|
+
border: 0;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
&:hover {
|
|
635
|
+
color: var(--color-fg);
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
&:has(> input:checked) {
|
|
639
|
+
background-color: var(--bg-base);
|
|
640
|
+
color: var(--color-fg);
|
|
641
|
+
@include font-semibold;
|
|
642
|
+
box-shadow: var(--shadow-resting);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
&:has(> input:focus-visible) {
|
|
646
|
+
@include focus-ring;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
519
651
|
@mixin toggle-switch {
|
|
520
652
|
appearance: none;
|
|
521
653
|
position: relative;
|
|
@@ -616,6 +748,50 @@
|
|
|
616
748
|
li label { @include pill; }
|
|
617
749
|
}
|
|
618
750
|
|
|
751
|
+
// ─── Check list nav — filter list styled with the nav-link vocabulary ──
|
|
752
|
+
// Same checkbox-filter list as check-list, but the selected item uses the
|
|
753
|
+
// sidebar nav-link active treatment (accent-tint wash + accent text +
|
|
754
|
+
// semibold) instead of the solid-accent pill fill. Shared by the filter
|
|
755
|
+
// popover (@mixin popover) and the ln-table column-filter dropdown
|
|
756
|
+
// (@mixin filter-dropdown) so every filter list matches the sidebar nav
|
|
757
|
+
// (nav-links-rounded). Extends check-list to keep the hidden-input filled
|
|
758
|
+
// structure; overrides only color, weight and size. Consumers that need
|
|
759
|
+
// the checkbox kept keyboard-focusable (popover a11y) re-reveal the input
|
|
760
|
+
// themselves after including this.
|
|
761
|
+
@mixin check-list-nav {
|
|
762
|
+
@include check-list;
|
|
763
|
+
|
|
764
|
+
li label {
|
|
765
|
+
// Smaller — match the nav link (13px).
|
|
766
|
+
@include typography(body-sm);
|
|
767
|
+
// Muted idle text, transparent surface (nav idle).
|
|
768
|
+
--color-fg: var(--fg-muted);
|
|
769
|
+
color: var(--color-fg);
|
|
770
|
+
background: transparent;
|
|
771
|
+
border: none;
|
|
772
|
+
// Tighter vertical padding — match nav link height (~31px).
|
|
773
|
+
--padding-y: var(--size-xs-up);
|
|
774
|
+
padding: var(--padding-y) var(--padding-x);
|
|
775
|
+
|
|
776
|
+
// Hover (unchecked) — subtle accent wash (nav hover).
|
|
777
|
+
&:hover:not(:has(> input:checked)) {
|
|
778
|
+
background-color: color-mix(in srgb, var(--color-accent) 7%, transparent);
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
// Selected — nav active vocabulary (replaces solid-accent + white).
|
|
782
|
+
&:has(> input:checked) {
|
|
783
|
+
background-color: var(--color-accent-tint-strong);
|
|
784
|
+
color: var(--color-accent);
|
|
785
|
+
@include font-semibold;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
// Selected + hover — keep the wash, don't darken (nav has no darken).
|
|
789
|
+
&:hover:has(> input:checked) {
|
|
790
|
+
background-color: var(--color-accent-tint-strong);
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
|
|
619
795
|
// ─── Validation states ─────────────────────────────────────────
|
|
620
796
|
// Status colors (error/success) stay raw — no logical --color-status
|
|
621
797
|
// token in scope (see parent plan §6.2).
|
|
@@ -642,7 +818,17 @@
|
|
|
642
818
|
// Structural error-list margin (not shell rhythm).
|
|
643
819
|
--margin-block: var(--size-xs);
|
|
644
820
|
margin-top: var(--margin-block);
|
|
645
|
-
|
|
646
|
-
line-height: var(--lh-caption);
|
|
821
|
+
@include typography(caption);
|
|
647
822
|
color: hsl(var(--color-error));
|
|
823
|
+
min-height: 1.25rem; // Reserves space to prevent form layout shifts when errors appear
|
|
824
|
+
list-style: none;
|
|
825
|
+
padding: 0;
|
|
826
|
+
margin-bottom: 0;
|
|
827
|
+
|
|
828
|
+
li {
|
|
829
|
+
margin: 0;
|
|
830
|
+
&.hidden {
|
|
831
|
+
display: none;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
648
834
|
}
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
@forward 'loader';
|
|
32
32
|
@forward 'tabs';
|
|
33
33
|
@forward 'table';
|
|
34
|
+
@forward 'sort';
|
|
34
35
|
@forward 'avatar';
|
|
35
36
|
@forward 'footer';
|
|
36
37
|
@forward 'sidebar';
|
|
@@ -43,6 +44,7 @@
|
|
|
43
44
|
@forward 'timeline';
|
|
44
45
|
@forward 'stat-card';
|
|
45
46
|
@forward 'prose';
|
|
47
|
+
@forward 'editor';
|
|
46
48
|
@forward 'kbd';
|
|
47
49
|
@forward 'tooltip';
|
|
48
50
|
@forward 'popover';
|
|
@@ -35,7 +35,15 @@
|
|
|
35
35
|
--radius: var(--radius-lg);
|
|
36
36
|
border-radius: var(--radius);
|
|
37
37
|
background: var(--color-bg);
|
|
38
|
-
|
|
38
|
+
// `clip` not `auto` — no scroll container, so the sticky thead/footer
|
|
39
|
+
// bind to the outer .app-main > section scroll surface (same doctrine
|
|
40
|
+
// as @mixin section-card).
|
|
41
|
+
overflow-x: clip;
|
|
42
|
+
max-width: 100%;
|
|
43
|
+
|
|
44
|
+
colgroup {
|
|
45
|
+
display: none !important;
|
|
46
|
+
}
|
|
39
47
|
|
|
40
48
|
// Table overrides inside component
|
|
41
49
|
table {
|
|
@@ -44,6 +52,8 @@
|
|
|
44
52
|
border-spacing: 0;
|
|
45
53
|
border-radius: 0;
|
|
46
54
|
box-shadow: none;
|
|
55
|
+
table-layout: auto !important;
|
|
56
|
+
min-width: var(--table-min-width, 768px);
|
|
47
57
|
}
|
|
48
58
|
|
|
49
59
|
// Whole thead sticky as one unit (toolbar row + column-headers row).
|
|
@@ -70,6 +80,8 @@
|
|
|
70
80
|
|
|
71
81
|
@mixin ln-table-toolbar {
|
|
72
82
|
@include panel-header;
|
|
83
|
+
justify-content: flex-start;
|
|
84
|
+
gap: var(--size-md);
|
|
73
85
|
position: sticky;
|
|
74
86
|
top: 0;
|
|
75
87
|
z-index: var(--z-sticky);
|
|
@@ -103,11 +115,24 @@
|
|
|
103
115
|
|
|
104
116
|
> div {
|
|
105
117
|
@include panel-header;
|
|
118
|
+
justify-content: flex-start;
|
|
119
|
+
gap: var(--size-md);
|
|
106
120
|
}
|
|
107
121
|
}
|
|
108
122
|
|
|
109
123
|
@mixin ln-table-toolbar-search {
|
|
110
|
-
|
|
124
|
+
--padding-y: var(--size-2xs); // lowers panel-header min-height floor for this label
|
|
125
|
+
width: auto; // hug the 10rem input; cancel .search's 20rem label cap inside toolbars
|
|
126
|
+
|
|
127
|
+
> .ln-icon {
|
|
128
|
+
padding-top: var(--size-2xs); // tighten leading icon vertical padding (was var(--size-xs))
|
|
129
|
+
padding-bottom: var(--size-2xs); // horizontal padding (size-sm) inherited from form-field-group
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
> input {
|
|
133
|
+
--padding-y: var(--size-2xs); // tighten vertical padding on the input itself
|
|
134
|
+
width: 10rem; // preserve existing width cap
|
|
135
|
+
}
|
|
111
136
|
}
|
|
112
137
|
|
|
113
138
|
// ─── Count badge ──────────────────────────────────────────
|
|
@@ -149,6 +174,9 @@
|
|
|
149
174
|
@include text-sm;
|
|
150
175
|
--color-fg: var(--fg-muted);
|
|
151
176
|
color: var(--color-fg);
|
|
177
|
+
position: sticky;
|
|
178
|
+
bottom: 0;
|
|
179
|
+
z-index: var(--z-sticky);
|
|
152
180
|
|
|
153
181
|
strong {
|
|
154
182
|
color: var(--color-fg);
|
|
@@ -336,4 +364,15 @@
|
|
|
336
364
|
}
|
|
337
365
|
}
|
|
338
366
|
|
|
367
|
+
// Windowed-virtualization placeholder row — static fill, row-height chrome
|
|
368
|
+
// only. No shimmer (window-cache.md §4); height stays JS-owned via inline
|
|
369
|
+
// px, spacer geometry depends on the exact value so nothing here may touch it.
|
|
370
|
+
@mixin ln-table-placeholder-row {
|
|
371
|
+
td {
|
|
372
|
+
padding: 0 !important;
|
|
373
|
+
border: none !important;
|
|
374
|
+
background: var(--bg-sunken);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
339
378
|
|
|
@@ -1,66 +1,149 @@
|
|
|
1
|
-
@use 'display' as *;
|
|
2
|
-
@use 'spacing' as *;
|
|
3
|
-
@use 'position' as *;
|
|
4
|
-
@use 'motion' as *;
|
|
5
|
-
@use 'card' as *;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
//
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@mixin modal-
|
|
12
|
-
@mixin modal-
|
|
13
|
-
@mixin modal-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
@include
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
1
|
+
@use 'display' as *;
|
|
2
|
+
@use 'spacing' as *;
|
|
3
|
+
@use 'position' as *;
|
|
4
|
+
@use 'motion' as *;
|
|
5
|
+
@use 'card' as *;
|
|
6
|
+
@use 'typography' as *;
|
|
7
|
+
|
|
8
|
+
// Modal size mixins
|
|
9
|
+
// Usage: #my-modal > form { @include modal-lg; }
|
|
10
|
+
|
|
11
|
+
@mixin modal-sm { max-width: 28rem; }
|
|
12
|
+
@mixin modal-md { max-width: 32rem; }
|
|
13
|
+
@mixin modal-lg { max-width: 42rem; }
|
|
14
|
+
@mixin modal-xl { max-width: 48rem; }
|
|
15
|
+
|
|
16
|
+
// ─── Modal layout ──────────────────────────────────────
|
|
17
|
+
|
|
18
|
+
// Overlay backdrop — covers viewport, darkened + blurred.
|
|
19
|
+
// Default: hidden (display:none). JS sets [data-ln-modal="open"]
|
|
20
|
+
// to show — that state rule lives in the co-located JS SCSS.
|
|
21
|
+
@mixin modal-overlay {
|
|
22
|
+
display: none;
|
|
23
|
+
@include fixed;
|
|
24
|
+
@include inset-0;
|
|
25
|
+
z-index: var(--z-modal);
|
|
26
|
+
@include items-center;
|
|
27
|
+
@include justify-center;
|
|
28
|
+
|
|
29
|
+
&::backdrop {
|
|
30
|
+
background-color: var(--color-scrim);
|
|
31
|
+
backdrop-filter: blur(4px);
|
|
32
|
+
-webkit-backdrop-filter: blur(4px);
|
|
33
|
+
opacity: 1;
|
|
34
|
+
|
|
35
|
+
@include motion-safe {
|
|
36
|
+
transition: opacity var(--transition);
|
|
37
|
+
transition-behavior: allow-discrete;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@starting-style {
|
|
41
|
+
opacity: 0;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ─── Modal header ──────────────────────────────────────
|
|
47
|
+
// Rich modal header recipe: optional tinted icon square + title/subtitle
|
|
48
|
+
// hgroup + close-button reset. Applied by modal-panel to its > header.
|
|
49
|
+
@mixin modal-header {
|
|
50
|
+
// Modal-specific: white bg overrides section-card's gray panel-header.
|
|
51
|
+
// Section-cards and cards are unaffected (this is modal-panel scope only).
|
|
52
|
+
--color-bg: var(--bg-base);
|
|
53
|
+
gap: var(--size-sm-up);
|
|
54
|
+
|
|
55
|
+
:is(h1, h2, h3, h4, h5, h6) {
|
|
56
|
+
@include typography(heading-sm);
|
|
57
|
+
font-weight: var(--font-semibold);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
button[data-ln-modal-close] {
|
|
61
|
+
--btn-bg: transparent;
|
|
62
|
+
--btn-border: transparent;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Optional icon square — tinted rounded square with primary-colored icon.
|
|
66
|
+
// Usage: <span class="icon"><svg class="ln-icon" aria-hidden="true">…</svg></span>
|
|
67
|
+
.icon {
|
|
68
|
+
flex-shrink: 0;
|
|
69
|
+
display: inline-flex;
|
|
70
|
+
align-items: center;
|
|
71
|
+
justify-content: center;
|
|
72
|
+
width: 2rem;
|
|
73
|
+
height: 2rem;
|
|
74
|
+
border-radius: var(--radius);
|
|
75
|
+
background: var(--color-accent-tint);
|
|
76
|
+
|
|
77
|
+
.ln-icon {
|
|
78
|
+
color: var(--color-accent);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Optional title+subtitle group — <hgroup><h3>…</h3><p>…</p></hgroup>.
|
|
83
|
+
hgroup {
|
|
84
|
+
display: flex;
|
|
85
|
+
flex-direction: column;
|
|
86
|
+
gap: var(--size-xs);
|
|
87
|
+
flex: 1;
|
|
88
|
+
min-width: 0;
|
|
89
|
+
margin: 0;
|
|
90
|
+
|
|
91
|
+
p {
|
|
92
|
+
margin: 0;
|
|
93
|
+
@include typography(caption);
|
|
94
|
+
color: var(--fg-muted);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Content panel — the <form> inside .ln-modal.
|
|
100
|
+
// Structurally IS a section-card: reuse its chrome and its nested
|
|
101
|
+
// > header / > main / > footer recipes. Add only the modal-specific
|
|
102
|
+
// behaviour on top: fixed size envelope, scrollable body, sticky
|
|
103
|
+
// footer, slide-in animation, deeper shadow.
|
|
104
|
+
@mixin modal-panel {
|
|
105
|
+
@include section-card;
|
|
106
|
+
margin-bottom: 0;
|
|
107
|
+
// Explicit role-scale read — modals use max elevation (deeper than
|
|
108
|
+
// the --shadow-floating default used by floating panels).
|
|
109
|
+
box-shadow: var(--shadow-xl);
|
|
110
|
+
display: grid;
|
|
111
|
+
grid-template-rows: auto 1fr auto;
|
|
112
|
+
max-width: 600px;
|
|
113
|
+
width: 90%;
|
|
114
|
+
max-height: 90vh;
|
|
115
|
+
@include motion-safe {
|
|
116
|
+
animation: ln-modal-slideIn var(--transition-slow);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
> main {
|
|
120
|
+
min-height: 0;
|
|
121
|
+
overflow-y: auto;
|
|
122
|
+
overflow-x: hidden;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
> footer {
|
|
126
|
+
position: sticky;
|
|
127
|
+
bottom: 0;
|
|
128
|
+
|
|
129
|
+
// Destructive footer split: add class="delete-action" to the first
|
|
130
|
+
// button to push it left. The footer gap still applies between all buttons.
|
|
131
|
+
// Color: --color-primary cascades through @mixin btn (same pattern as
|
|
132
|
+
// .delete-action documented in _global.scss).
|
|
133
|
+
.delete-action {
|
|
134
|
+
margin-inline-end: auto;
|
|
135
|
+
--btn-bg: hsl(var(--color-error) / 0.08);
|
|
136
|
+
--btn-fg: hsl(var(--color-error));
|
|
137
|
+
--btn-border: hsl(var(--color-error) / 0.4);
|
|
138
|
+
--btn-bg-hover: hsl(var(--color-error) / 0.16);
|
|
139
|
+
--btn-fg-hover: hsl(var(--color-error));
|
|
140
|
+
--btn-border-hover: hsl(var(--color-error));
|
|
141
|
+
backdrop-filter: blur(4px);
|
|
142
|
+
-webkit-backdrop-filter: blur(4px);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
> header {
|
|
147
|
+
@include modal-header;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -39,8 +39,7 @@
|
|
|
39
39
|
@include items-center;
|
|
40
40
|
gap: var(--gap);
|
|
41
41
|
padding-block: var(--padding-y);
|
|
42
|
-
|
|
43
|
-
line-height: var(--lh-body-sm);
|
|
42
|
+
@include typography(body-sm);
|
|
44
43
|
color: var(--color-fg);
|
|
45
44
|
text-decoration: none;
|
|
46
45
|
// Always-present 1px border slot. Color defaults to transparent
|
|
@@ -97,7 +96,7 @@
|
|
|
97
96
|
}
|
|
98
97
|
|
|
99
98
|
&.active {
|
|
100
|
-
color: var(--color-accent);
|
|
99
|
+
color: var(--color-accent-hover);
|
|
101
100
|
border-color: var(--nav-link-border-color-active, transparent);
|
|
102
101
|
@include font-semibold;
|
|
103
102
|
}
|
|
@@ -135,7 +134,7 @@
|
|
|
135
134
|
&.active {
|
|
136
135
|
// accent wash vocabulary (CLAUDE.md L532) — was reaching
|
|
137
136
|
// through to --color-primary-lighter scale.
|
|
138
|
-
background-color: var(--color-accent-tint);
|
|
137
|
+
background-color: var(--color-accent-tint-strong);
|
|
139
138
|
}
|
|
140
139
|
}
|
|
141
140
|
}
|