@livenetworks/ashlar 1.4.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 +189 -99
- 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 -55
- 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 -0
- package/scss/components/_form.scss +7 -0
- package/scss/components/_ln-table.scss +14 -5
- package/scss/components/_sort.scss +10 -0
- package/scss/components/_table.scss +68 -1
- 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 +48 -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 +47 -0
- package/scss/config/mixins/_footer.scss +1 -2
- package/scss/config/mixins/_form.scss +207 -21
- package/scss/config/mixins/_index.scss +4 -1
- package/scss/config/mixins/_ln-table.scss +51 -93
- 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 +232 -38
- 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 +39 -0
- package/scss/ln-ashlar.scss +8 -2
- 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 -1103
- 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 -168
- package/scss/components/_data-table.scss +0 -83
- package/scss/config/mixins/_data-table.scss +0 -346
|
@@ -21,15 +21,29 @@
|
|
|
21
21
|
// [data-ln-table] { @include ln-table; }
|
|
22
22
|
// .ln-table__toolbar { @include ln-table-toolbar; }
|
|
23
23
|
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
24
|
+
// Sort/filter button styling is SHARED via scss/components/_table.scss
|
|
25
|
+
// (.table-sort / .table-filter structural helper classes + the :has() stack
|
|
26
|
+
// in @mixin table-base). No ln-table-specific sort/filter button mixins here.
|
|
27
|
+
// Under D1 (Option A) the <th> is no longer the sort click target, so no
|
|
28
|
+
// ln-table-specific cursor:pointer / select-none on the <th> is needed.
|
|
29
|
+
//
|
|
30
|
+
// State-driven CSS (spacer rows, content overflow fix) stays in
|
|
31
|
+
// the co-located JS SCSS file.
|
|
26
32
|
|
|
27
33
|
@mixin ln-table {
|
|
28
34
|
@include border;
|
|
29
35
|
--radius: var(--radius-lg);
|
|
30
36
|
border-radius: var(--radius);
|
|
31
37
|
background: var(--color-bg);
|
|
32
|
-
|
|
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
|
+
}
|
|
33
47
|
|
|
34
48
|
// Table overrides inside component
|
|
35
49
|
table {
|
|
@@ -38,6 +52,8 @@
|
|
|
38
52
|
border-spacing: 0;
|
|
39
53
|
border-radius: 0;
|
|
40
54
|
box-shadow: none;
|
|
55
|
+
table-layout: auto !important;
|
|
56
|
+
min-width: var(--table-min-width, 768px);
|
|
41
57
|
}
|
|
42
58
|
|
|
43
59
|
// Whole thead sticky as one unit (toolbar row + column-headers row).
|
|
@@ -64,6 +80,8 @@
|
|
|
64
80
|
|
|
65
81
|
@mixin ln-table-toolbar {
|
|
66
82
|
@include panel-header;
|
|
83
|
+
justify-content: flex-start;
|
|
84
|
+
gap: var(--size-md);
|
|
67
85
|
position: sticky;
|
|
68
86
|
top: 0;
|
|
69
87
|
z-index: var(--z-sticky);
|
|
@@ -97,11 +115,24 @@
|
|
|
97
115
|
|
|
98
116
|
> div {
|
|
99
117
|
@include panel-header;
|
|
118
|
+
justify-content: flex-start;
|
|
119
|
+
gap: var(--size-md);
|
|
100
120
|
}
|
|
101
121
|
}
|
|
102
122
|
|
|
103
123
|
@mixin ln-table-toolbar-search {
|
|
104
|
-
|
|
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
|
+
}
|
|
105
136
|
}
|
|
106
137
|
|
|
107
138
|
// ─── Count badge ──────────────────────────────────────────
|
|
@@ -126,95 +157,6 @@
|
|
|
126
157
|
}
|
|
127
158
|
}
|
|
128
159
|
|
|
129
|
-
// ─── Column filter dropdowns in th ────────────────────────
|
|
130
|
-
|
|
131
|
-
@mixin ln-table-column-filter {
|
|
132
|
-
th [data-ln-dropdown] {
|
|
133
|
-
@include inline-flex;
|
|
134
|
-
@include items-center;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
th [data-ln-dropdown] > button {
|
|
138
|
-
@include flex;
|
|
139
|
-
@include items-center;
|
|
140
|
-
--gap: var(--size-xs);
|
|
141
|
-
gap: var(--gap);
|
|
142
|
-
background: none;
|
|
143
|
-
border: none;
|
|
144
|
-
color: inherit;
|
|
145
|
-
font: inherit;
|
|
146
|
-
@include cursor-pointer;
|
|
147
|
-
--btn-padding-y: 0;
|
|
148
|
-
--btn-padding-x: 0;
|
|
149
|
-
|
|
150
|
-
.ln-icon-filter {
|
|
151
|
-
opacity: 0.4;
|
|
152
|
-
@include motion-safe {
|
|
153
|
-
transition: opacity var(--transition-fast);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
&:hover .ln-icon-filter {
|
|
158
|
-
opacity: 1;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
th [data-ln-dropdown-menu] button[data-ln-filter-key] {
|
|
163
|
-
@include w-full;
|
|
164
|
-
@include flex;
|
|
165
|
-
@include items-center;
|
|
166
|
-
@include text-left;
|
|
167
|
-
--btn-padding-y: var(--size-xs);
|
|
168
|
-
--btn-padding-x: var(--size-sm);
|
|
169
|
-
@include text-sm;
|
|
170
|
-
@include font-normal;
|
|
171
|
-
background: none;
|
|
172
|
-
border: none;
|
|
173
|
-
border-radius: 0;
|
|
174
|
-
color: var(--color-fg);
|
|
175
|
-
@include cursor-pointer;
|
|
176
|
-
@include transition-fast;
|
|
177
|
-
|
|
178
|
-
&:hover {
|
|
179
|
-
--color-bg: var(--bg-sunken);
|
|
180
|
-
background: var(--color-bg);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
&[data-active] {
|
|
184
|
-
background-color: color-mix(in srgb, var(--color-accent) 10%, transparent);
|
|
185
|
-
color: var(--color-accent);
|
|
186
|
-
@include font-medium;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// ─── Sort indicators on th ────────────────────────────────
|
|
192
|
-
|
|
193
|
-
@mixin ln-table-sort {
|
|
194
|
-
th[data-ln-sort] {
|
|
195
|
-
@include cursor-pointer;
|
|
196
|
-
@include select-none;
|
|
197
|
-
|
|
198
|
-
[data-ln-sort-icon] {
|
|
199
|
-
@include size(0.875rem);
|
|
200
|
-
--margin-inline: var(--size-xs);
|
|
201
|
-
margin-left: var(--margin-inline);
|
|
202
|
-
vertical-align: middle;
|
|
203
|
-
opacity: 0.4;
|
|
204
|
-
@include motion-safe {
|
|
205
|
-
transition: opacity var(--transition-fast);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
&:hover [data-ln-sort-icon] {
|
|
210
|
-
opacity: 0.7;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
&[data-ln-sort-active] [data-ln-sort-icon] {
|
|
214
|
-
opacity: 1;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
160
|
|
|
219
161
|
// ─── Footer ───────────────────────────────────────────────
|
|
220
162
|
|
|
@@ -232,6 +174,9 @@
|
|
|
232
174
|
@include text-sm;
|
|
233
175
|
--color-fg: var(--fg-muted);
|
|
234
176
|
color: var(--color-fg);
|
|
177
|
+
position: sticky;
|
|
178
|
+
bottom: 0;
|
|
179
|
+
z-index: var(--z-sticky);
|
|
235
180
|
|
|
236
181
|
strong {
|
|
237
182
|
color: var(--color-fg);
|
|
@@ -418,3 +363,16 @@
|
|
|
418
363
|
background: transparent !important;
|
|
419
364
|
}
|
|
420
365
|
}
|
|
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
|
+
|
|
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
|
}
|
|
@@ -2,11 +2,15 @@
|
|
|
2
2
|
@use 'borders' as *;
|
|
3
3
|
@use 'motion' as *;
|
|
4
4
|
@use 'card' as *;
|
|
5
|
+
@use 'form' as *;
|
|
6
|
+
@use 'focus' as *;
|
|
5
7
|
|
|
6
8
|
@mixin popover {
|
|
7
9
|
@include floating-panel;
|
|
8
10
|
display: none;
|
|
9
11
|
position: fixed;
|
|
12
|
+
inset: auto;
|
|
13
|
+
margin: 0;
|
|
10
14
|
min-width: 14rem;
|
|
11
15
|
max-width: 24rem;
|
|
12
16
|
padding: var(--padding-y) var(--padding-x);
|
|
@@ -22,4 +26,39 @@
|
|
|
22
26
|
&:focus {
|
|
23
27
|
outline: none;
|
|
24
28
|
}
|
|
29
|
+
|
|
30
|
+
// Filter popover content: optional search + checkbox option list
|
|
31
|
+
> input[type="search"] {
|
|
32
|
+
width: 100%;
|
|
33
|
+
margin-bottom: var(--size-xs);
|
|
34
|
+
box-sizing: border-box;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
> ul {
|
|
38
|
+
list-style: none;
|
|
39
|
+
padding: 0;
|
|
40
|
+
margin: 0;
|
|
41
|
+
max-height: var(--filter-options-max-height, 15rem);
|
|
42
|
+
overflow-y: auto;
|
|
43
|
+
|
|
44
|
+
// Nav-link treatment for filter options (accent-tint wash on checked).
|
|
45
|
+
// Visually-hidden input (below) keeps the checkbox keyboard-focusable.
|
|
46
|
+
@include check-list-nav;
|
|
47
|
+
|
|
48
|
+
> li > label > input {
|
|
49
|
+
// Override pill's display:none — keep in focus order for keyboard nav
|
|
50
|
+
display: revert;
|
|
51
|
+
position: absolute;
|
|
52
|
+
width: 1px;
|
|
53
|
+
height: 1px;
|
|
54
|
+
overflow: hidden;
|
|
55
|
+
clip-path: inset(50%);
|
|
56
|
+
white-space: nowrap;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Focus ring on label when the hidden input receives keyboard focus
|
|
60
|
+
> li > label:has(> input:focus-visible) {
|
|
61
|
+
@include focus-ring;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
25
64
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
@use 'display' as *;
|
|
2
|
+
@use 'table' as *;
|
|
3
|
+
|
|
4
|
+
// ─── Sort control — 3-trigger cycle (none → asc → desc → none) ─────────
|
|
5
|
+
// Only one <button data-ln-sort-dir> is visible at a time; the circular
|
|
6
|
+
// order lives HERE in CSS, not in JS (js/ln-sort/README.md "No cycle
|
|
7
|
+
// logic in JS"). [data-ln-sort-state] on the root decides which trigger
|
|
8
|
+
// shows — the visible button is always the NEXT action, but the icon it
|
|
9
|
+
// carries reports the CURRENT state, not that action (icon-per-button
|
|
10
|
+
// mapping: js/ln-sort/README.md "Icon convention").
|
|
11
|
+
|
|
12
|
+
@mixin sort {
|
|
13
|
+
@include inline-flex;
|
|
14
|
+
list-style: none !important;
|
|
15
|
+
list-style-type: none !important;
|
|
16
|
+
margin: 0;
|
|
17
|
+
padding: 0;
|
|
18
|
+
vertical-align: middle;
|
|
19
|
+
|
|
20
|
+
li {
|
|
21
|
+
list-style: none !important;
|
|
22
|
+
list-style-type: none !important;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
button {
|
|
26
|
+
@include table-header-btn-base;
|
|
27
|
+
display: none;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
&[data-ln-sort-state="none"] [data-ln-sort-dir="asc"],
|
|
31
|
+
&[data-ln-sort-state="asc"] [data-ln-sort-dir="desc"],
|
|
32
|
+
&[data-ln-sort-state="desc"] [data-ln-sort-dir="none"] {
|
|
33
|
+
display: inline-flex;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@mixin sort-active {
|
|
38
|
+
[data-ln-sort-dir] {
|
|
39
|
+
opacity: 1;
|
|
40
|
+
color: var(--color-accent);
|
|
41
|
+
}
|
|
42
|
+
}
|