@livenetworks/ashlar 2.1.13 → 2.2.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.
Files changed (101) hide show
  1. package/components/COMPONENTS.md +80 -80
  2. package/components/ln-api-connector/ln-api-connector.schema.json +105 -105
  3. package/components/ln-chart/ln-chart-dev.scss +0 -4
  4. package/components/ln-core/README.md +21 -21
  5. package/components/ln-core/ln-core.schema.json +120 -120
  6. package/components/ln-core/query.js +113 -113
  7. package/components/ln-data-coordinator/README.md +2 -0
  8. package/components/ln-data-coordinator/ln-data-coordinator.js +1 -1
  9. package/components/ln-data-coordinator/ln-data-coordinator.schema.json +196 -196
  10. package/components/ln-data-coordinator/src/ln-data-coordinator.js +457 -432
  11. package/components/ln-data-store/ln-data-store.schema.json +92 -92
  12. package/components/ln-date/ln-date.js +1 -1
  13. package/components/ln-date/src/ln-date.js +1 -1
  14. package/components/ln-debug/ln-debug.js +1 -1
  15. package/components/ln-debug/ln-debug.schema.json +28 -28
  16. package/components/ln-debug/src/generated-attributes.js +304 -302
  17. package/components/ln-dropdown/ln-dropdown.schema.json +90 -90
  18. package/components/ln-external-links/README.md +19 -19
  19. package/components/ln-external-links/ln-external-links.js +1 -1
  20. package/components/ln-external-links/ln-external-links.schema.json +9 -0
  21. package/components/ln-external-links/ln-external-links.scss +12 -0
  22. package/components/ln-external-links/src/ln-external-links.js +3 -2
  23. package/components/ln-filter/README.md +2 -1
  24. package/components/ln-filter/ln-filter.js +1 -1
  25. package/components/ln-filter/ln-filter.schema.json +157 -169
  26. package/components/ln-filter/src/ln-filter.js +1 -3
  27. package/components/ln-form/ln-form.schema.json +57 -57
  28. package/components/ln-key/ln-key.js +1 -1
  29. package/components/ln-key/ln-key.schema.json +8 -0
  30. package/components/ln-key/src/ln-key.js +8 -5
  31. package/components/ln-obfuscator/ln-obfuscator.js +1 -1
  32. package/components/ln-obfuscator/ln-obfuscator.schema.json +6 -0
  33. package/components/ln-obfuscator/src/ln-obfuscator.js +2 -2
  34. package/components/ln-options/ln-options.schema.json +47 -47
  35. package/components/ln-popover/ln-popover.schema.json +82 -82
  36. package/components/ln-progress/ln-progress.schema.json +0 -13
  37. package/components/ln-search/ln-search.schema.json +111 -111
  38. package/components/ln-sort/README.md +1 -0
  39. package/components/ln-sort/ln-sort.js +1 -1
  40. package/components/ln-sort/ln-sort.schema.json +100 -112
  41. package/components/ln-sort/src/sort-model.js +1 -6
  42. package/components/ln-sortable/ln-sortable.schema.json +38 -38
  43. package/components/ln-sortable/ln-sortable.scss +25 -25
  44. package/components/ln-table/README.md +8 -1
  45. package/components/ln-table/ln-table.js +1 -1
  46. package/components/ln-table/ln-table.schema.json +195 -195
  47. package/components/ln-table/src/ln-table.js +43 -7
  48. package/components/ln-table-coordinator/ln-table-coordinator.js +1 -1
  49. package/components/ln-table-coordinator/ln-table-coordinator.schema.json +18 -0
  50. package/components/ln-table-coordinator/src/ln-table-coordinator.js +104 -2
  51. package/components/ln-toast/README.md +1 -1
  52. package/components/ln-toast/ln-toast.js +1 -1
  53. package/components/ln-toast/ln-toast.schema.json +6 -0
  54. package/components/ln-toast/src/ln-toast.js +1 -1
  55. package/components/ln-validate/README.md +6 -6
  56. package/components/ln-validate/ln-validate-dev.scss +0 -5
  57. package/components/ln-validate/ln-validate.js +1 -1
  58. package/components/ln-validate/ln-validate.schema.json +0 -6
  59. package/components/ln-validate/src/ln-validate.js +48 -29
  60. package/ln-ashlar.html-data.json +1824 -1814
  61. package/package.json +95 -95
  62. package/theme/README.md +7 -6
  63. package/theme/base/_global.scss +2 -2
  64. package/theme/base/_reset.scss +11 -0
  65. package/theme/components/_app-shell.scss +0 -8
  66. package/theme/components/_form.scss +6 -6
  67. package/theme/components/_ln-table.scss +6 -3
  68. package/theme/components/_scrollbar.scss +5 -4
  69. package/theme/components/_sortable.scss +19 -19
  70. package/theme/components/_stat-card.scss +1 -0
  71. package/theme/components/_table.scss +10 -33
  72. package/theme/config/_density.scss +236 -104
  73. package/theme/config/_palette.scss +71 -49
  74. package/theme/config/_theme.scss +27 -31
  75. package/theme/config/_tokens.scss +28 -26
  76. package/theme/config/mixins/_app-shell.scss +17 -21
  77. package/theme/config/mixins/_btn.scss +4 -2
  78. package/theme/config/mixins/_card.scss +87 -67
  79. package/theme/config/mixins/_colors.scss +2 -1
  80. package/theme/config/mixins/_display.scss +12 -0
  81. package/theme/config/mixins/_footer.scss +3 -1
  82. package/theme/config/mixins/_form.scss +48 -16
  83. package/theme/config/mixins/_layout.scss +9 -0
  84. package/theme/config/mixins/_ln-table.scss +22 -15
  85. package/theme/config/mixins/_modal.scss +3 -0
  86. package/theme/config/mixins/_nav.scss +27 -4
  87. package/theme/config/mixins/_sidebar.scss +2 -1
  88. package/theme/config/mixins/_stat-card.scss +33 -2
  89. package/theme/config/mixins/_status-badge.scss +1 -0
  90. package/theme/config/mixins/_table.scss +81 -39
  91. package/theme/config/mixins/_tabs.scss +31 -0
  92. package/theme/config/mixins/_toast.scss +0 -1
  93. package/theme/designs/relaxed/_card.scss +12 -0
  94. package/theme/designs/relaxed/_layout.scss +24 -0
  95. package/theme/ln-ashlar-core.scss +1 -0
  96. package/theme/ln-ashlar-dev.scss +0 -1
  97. package/theme/ln-ashlar-relaxed.scss +67 -0
  98. package/theme/tailwind/components.css +561 -24
  99. package/theme/utilities/_utilities.scss +1 -11
  100. package/web-types.json +2351 -2337
  101. package/components/ln-progress/ln-progress-dev.scss +0 -8
@@ -22,7 +22,7 @@
22
22
  // .ln-table__toolbar { @include ln-table-toolbar; }
23
23
  //
24
24
  // Sort/filter button styling is SHARED via scss/components/_table.scss
25
- // (.table-sort / .table-filter structural helper classes + the :has() stack
25
+ // (.table-sort helper class, [data-ln-table-col-filter] binding + the :has() stack
26
26
  // in @mixin table-base). No ln-table-specific sort/filter button mixins here.
27
27
  // Under D1 (Option A) the <th> is no longer the sort click target, so no
28
28
  // ln-table-specific cursor:pointer / select-none on the <th> is needed.
@@ -53,10 +53,10 @@
53
53
  min-width: var(--table-min-width, 768px);
54
54
  }
55
55
 
56
- // Whole thead sticky as one unit (toolbar row + column-headers row).
57
- // Solid opaque background prevents underlying scrolled rows from bleeding through.
56
+ // Pinned under the sibling toolbar when one exists (ln-table-toolbar-stack).
57
+ // Opaque so scrolled rows never bleed through.
58
58
  thead {
59
- @include sticky-top;
59
+ @include sticky-top(var(--table-toolbar-block-size, 0));
60
60
  background: var(--color-bg);
61
61
  isolation: isolate;
62
62
  }
@@ -89,7 +89,8 @@
89
89
  gap: var(--size-md);
90
90
  position: sticky;
91
91
  top: 0;
92
- z-index: var(--z-sticky);
92
+ // One step above the thead: at the table's end the thead slides under it.
93
+ z-index: calc(var(--z-sticky) + 1);
93
94
  border-radius: 0;
94
95
  background: var(--color-bg);
95
96
  border-bottom: var(--border-width) solid var(--border-subtle);
@@ -99,6 +100,22 @@
99
100
  font-size: 1rem;
100
101
  font-weight: 600;
101
102
  color: var(--color-fg);
103
+ // Single line keeps the toolbar at its token block-size.
104
+ @include truncate;
105
+ min-inline-size: 0;
106
+ }
107
+ }
108
+
109
+ // ─── Toolbar + sticky thead stack ─────────────────────────
110
+ // Applied to the toolbar's parent. The toolbar is one control row, so its
111
+ // block-size is known from tokens; every sticky thead below pins under it.
112
+ // Declared on the parent: the thead is in a sibling subtree.
113
+
114
+ @mixin ln-table-toolbar-stack {
115
+ --table-toolbar-block-size: calc(2 * var(--card-padding-y) + var(--control-line-height) + 2 * var(--size-xs) + 3 * var(--border-width));
116
+
117
+ > :has(+ table) {
118
+ min-block-size: var(--table-toolbar-block-size);
102
119
  }
103
120
  }
104
121
 
@@ -173,16 +190,6 @@
173
190
  }
174
191
  }
175
192
 
176
- // ─── Card mode container query ────────────────────────────
177
-
178
- @mixin ln-table-card-mode {
179
- @container table (max-width: 640px) {
180
- colgroup { display: none; }
181
- table { table-layout: auto !important; }
182
- }
183
- }
184
-
185
-
186
193
  // ─── Footer ───────────────────────────────────────────────
187
194
 
188
195
  @mixin ln-table-footer {
@@ -99,6 +99,9 @@
99
99
  @mixin modal-panel {
100
100
  @include section-card;
101
101
  margin-bottom: 0;
102
+ // Overlays take the larger radius step — the same corner as a resting
103
+ // card would make the dialog read as another panel, not a layer above.
104
+ border-radius: var(--modal-radius, var(--radius-lg));
102
105
  // Explicit role-scale read — modals use max elevation (deeper than
103
106
  // the --shadow-floating default used by floating panels).
104
107
  box-shadow: var(--shadow-xl);
@@ -40,6 +40,7 @@
40
40
  gap: var(--gap);
41
41
  padding-block: var(--padding-y);
42
42
  @include typography(body-sm);
43
+ @include font-medium;
43
44
  color: var(--color-fg);
44
45
  text-decoration: none;
45
46
  // Always-present 1px border slot. Color defaults to transparent
@@ -50,7 +51,8 @@
50
51
  margin: calc(-1 * var(--border-width));
51
52
  }
52
53
 
53
- .nav-icon {
54
+ .nav-icon,
55
+ a > .ln-icon {
54
56
  @include flex-shrink-0;
55
57
  @include size(1.25rem);
56
58
  }
@@ -60,15 +62,36 @@
60
62
  @include truncate;
61
63
  }
62
64
 
65
+ // Trailing counter — <data value="24">24</data> as the last child of a.
66
+ a > data {
67
+ @include flex-shrink-0;
68
+ margin-inline-start: auto;
69
+ padding: 0 var(--size-xs-up);
70
+ min-width: 1.5rem;
71
+ text-align: center;
72
+ border-radius: var(--radius-full);
73
+ @include text-xs;
74
+ @include font-semibold;
75
+ font-variant-numeric: tabular-nums;
76
+ background: color-mix(in srgb, var(--color-fg) 12%, transparent);
77
+ }
78
+
79
+ a[aria-current="page"] > data {
80
+ background: var(--color-accent);
81
+ color: var(--color-accent-fg);
82
+ }
83
+
84
+ // Section heading — small uppercase eyebrow, clearly not a link.
63
85
  .nav-section {
64
86
  --color-fg: var(--fg-muted);
65
87
  --padding-y: var(--size-sm);
66
88
  padding-block: var(--padding-y);
89
+ padding-inline: var(--padding-x);
67
90
  @include text-xs;
68
- @include font-medium;
91
+ @include font-semibold;
69
92
  color: var(--color-fg);
70
- @include normal-case;
71
- letter-spacing: normal;
93
+ @include uppercase;
94
+ letter-spacing: var(--tracking-wider);
72
95
  // Structural margin above section header.
73
96
  --margin-block: var(--size-md);
74
97
  margin-top: var(--margin-block);
@@ -60,7 +60,8 @@
60
60
  > .app-name {
61
61
  @include text-lg;
62
62
  @include font-bold;
63
- @include text-primary;
63
+ @include tracking-tight;
64
+ color: var(--color-fg);
64
65
  @include truncate;
65
66
  }
66
67
 
@@ -4,9 +4,11 @@
4
4
  @use 'colors' as *;
5
5
  @use 'borders' as *;
6
6
  @use 'transitions' as *;
7
+ @use 'position' as *;
7
8
 
8
9
  @mixin stat-card {
9
10
  --shadow: var(--shadow-resting);
11
+ @include relative;
10
12
  @include flex-col;
11
13
  --gap: var(--size-xs);
12
14
  gap: var(--gap);
@@ -27,12 +29,31 @@
27
29
  > [data-ln-stat-label] {
28
30
  --color-fg: var(--fg-muted);
29
31
  @include typography(label-md);
32
+ @include font-medium;
30
33
  color: var(--color-fg);
31
- text-transform: uppercase;
32
- letter-spacing: var(--tracking-wide);
33
34
  margin: 0;
34
35
  }
35
36
 
37
+ // Icon tile — a direct-child <svg class="ln-icon"> pinned top-right,
38
+ // tinted with the card's accent (tone).
39
+ > .ln-icon {
40
+ position: absolute;
41
+ inset-block-start: var(--padding-y);
42
+ inset-inline-end: var(--padding-x);
43
+ width: 1.25rem;
44
+ height: 1.25rem;
45
+ padding: var(--size-xs-up);
46
+ box-sizing: content-box;
47
+ border-radius: var(--radius);
48
+ background: var(--color-accent-tint-strong);
49
+ color: var(--color-accent);
50
+ }
51
+
52
+ &:has(> .ln-icon) > [data-ln-stat-label] {
53
+ padding-inline-end: 2.75rem;
54
+ min-block-size: 2rem;
55
+ }
56
+
36
57
  > [data-ln-stat-value] {
37
58
  @include typography(heading-lg);
38
59
  font-weight: var(--font-bold);
@@ -67,3 +88,13 @@
67
88
  }
68
89
  }
69
90
  }
91
+
92
+ // ─── Tone ────────────────────────────────────────────────────────
93
+ // Accent strip on the leading edge in the card's accent colour. The
94
+ // tone itself comes from the semantic-color cascade (--color-primary →
95
+ // --color-accent), e.g. [data-ln-stat-card].success.
96
+ @mixin stat-card-tone {
97
+ --border-inline-start: var(--size-2xs) solid var(--color-accent);
98
+ --color-accent: hsl(var(--color-primary));
99
+ --color-accent-tint-strong: hsl(var(--color-primary-light));
100
+ }
@@ -29,6 +29,7 @@
29
29
  border: var(--border-width) solid color-mix(in srgb, var(--color-accent) 20%, transparent);
30
30
  @include tinted-surface(0.09);
31
31
  line-height: 1.5;
32
+ white-space: nowrap; // a status is one token — never wrap mid-label
32
33
 
33
34
  // Colored dot
34
35
  &::before {
@@ -6,16 +6,16 @@
6
6
  @use 'borders' as *;
7
7
  @use 'transitions' as *;
8
8
  @use 'position' as *;
9
+ @use 'breakpoints' as *;
9
10
  @use 'motion' as *;
10
11
  @use 'interaction' as *;
11
12
  @use 'form' as *;
12
13
  @use 'btn' as *;
13
14
  @use 'card' as *;
14
- @use 'ln-table';
15
15
 
16
16
  // ─── Base table ─────────────────────────────────────────────────
17
17
 
18
- @mixin table-base($sticky: false) {
18
+ @mixin table-base($sticky: true, $responsive: true) {
19
19
  @include w-full;
20
20
  background: var(--color-bg);
21
21
  --radius: var(--radius-lg);
@@ -46,23 +46,23 @@
46
46
  thead {
47
47
  --color-bg: var(--bg-sunken);
48
48
  background: var(--color-bg);
49
- border-block-end: var(--border-block-end, var(--border-width) solid var(--border-subtle));
50
-
49
+
51
50
  @if $sticky {
52
- @include sticky-top;
51
+ @include sticky-top(var(--table-toolbar-block-size, 0));
53
52
  }
54
- }
55
53
 
56
- // Support for in-thead toolbar inside sticky tables
57
- @if $sticky {
58
- thead > tr:first-child:has(> th[colspan]) > th {
59
- @include ln-table.ln-table-thead-toolbar;
54
+ // Opaque, so scrolled rows never show through the pinned header.
55
+ th { background: var(--color-bg); }
56
+
57
+ // On the cells: the separate border model ignores row-group borders.
58
+ > tr:last-child > th {
59
+ border-block-end: var(--border-block-end, var(--border-width) solid var(--border-subtle));
60
60
  }
61
61
  }
62
62
 
63
63
  th {
64
64
  @include text-left;
65
- padding: var(--padding-y) var(--padding-x);
65
+ padding: var(--table-cell-padding-y) var(--table-cell-padding-x);
66
66
  @include font-semibold;
67
67
  font-size: var(--text-xs);
68
68
  letter-spacing: 0.05em;
@@ -78,11 +78,11 @@
78
78
  text-overflow: ellipsis;
79
79
 
80
80
  // Shared header-button stack — cascading single vs double action
81
- &:has(:is([data-ln-sort], .table-filter)) {
81
+ &:has(:is([data-ln-sort], [data-ln-table-col-filter])) {
82
82
  min-width: var(--th-single-action-min-width, 6rem);
83
83
  padding-inline-end: calc(var(--padding-x, var(--size-md)) + 2rem);
84
84
 
85
- .table-filter,
85
+ [data-ln-table-col-filter],
86
86
  [data-ln-sort] {
87
87
  position: absolute;
88
88
  top: 50%;
@@ -92,7 +92,11 @@
92
92
  }
93
93
  }
94
94
 
95
- &:has([data-ln-sort]):has(.table-filter) {
95
+ &:hover [data-ln-table-col-filter] {
96
+ opacity: 0.7;
97
+ }
98
+
99
+ &:has([data-ln-sort]):has([data-ln-table-col-filter]) {
96
100
  min-width: var(--th-double-action-min-width, 8.5rem);
97
101
  padding-inline-end: calc(var(--padding-x, var(--size-md)) + 3.75rem);
98
102
 
@@ -119,7 +123,7 @@
119
123
  }
120
124
 
121
125
  td {
122
- padding: var(--padding-y) var(--padding-x);
126
+ padding: var(--table-cell-padding-y) var(--table-cell-padding-x);
123
127
  border-block-end: var(--border-width) solid var(--border-subtle);
124
128
  font-size: var(--text-sm);
125
129
  line-height: var(--line-height);
@@ -150,7 +154,7 @@
150
154
  // Sticky section footer inside sticky/enhanced tables
151
155
  @if $sticky {
152
156
  > footer {
153
- padding: var(--padding-y) var(--padding-x);
157
+ padding: var(--table-cell-padding-y) var(--table-cell-padding-x);
154
158
  border-block-start: var(--border-block-start, var(--border-width) solid var(--color-border));
155
159
  --color-bg: var(--bg-sunken);
156
160
  background: var(--color-bg);
@@ -161,52 +165,72 @@
161
165
  z-index: var(--z-sticky);
162
166
  }
163
167
  }
168
+
169
+ // Narrow viewports: one record per card. Viewport, not container — a table
170
+ // box cannot be a size container (inner display type table).
171
+ @if $responsive {
172
+ @include mq-down(md) {
173
+ @include table-responsive;
174
+ }
175
+ }
164
176
  }
165
177
 
166
- // ─── Responsive (mobile stacked layout) ─────────────────────────
167
- // Requires data-label attribute on <td> for column headers.
178
+ // ─── Responsive (stacked record cards) ──────────────────────────
179
+ // Applied ON the table. Label column comes from td[data-label]; cells
180
+ // without it span the card (section headers, empty state, checkboxes).
168
181
 
169
182
  @mixin table-responsive {
170
- th {
183
+ // Drop column geometry: wrapper min-widths, row-height clamp, and
184
+ // ln-table's inline fixed layout + locked colgroup.
185
+ --table-min-width: 0px;
186
+ --density-row-h: auto;
187
+ table-layout: auto !important;
188
+
189
+ // Column-header row only: an in-thead toolbar row (first row) stays.
190
+ > colgroup,
191
+ > thead > tr:last-child {
171
192
  @include hidden;
172
193
  }
173
194
 
174
- tbody tr {
195
+ // Flush records: separation lives inside offsetHeight, so ln-table's
196
+ // virtual row-height maths stays exact.
197
+ > tbody > tr {
175
198
  @include block;
176
- // Structural gap between stacked row-cards.
177
- --margin-block: var(--size-md);
178
- margin-bottom: var(--margin-block);
179
- @include border;
180
- border-radius: var(--radius);
181
- @include overflow-hidden;
199
+ border-block-end: var(--border-width-strong) solid var(--color-border);
200
+
201
+ &:last-child {
202
+ border-block-end: none;
203
+ }
182
204
  }
183
205
 
184
206
  td {
185
207
  @include block;
186
- @include text-right;
187
- // Stacked rows need taller vertical rhythm than desktop table cells.
208
+ text-align: start;
188
209
  --padding-y: var(--size-sm-up);
189
210
  --padding-x: var(--size-md);
190
211
  padding: var(--padding-y) var(--padding-x);
191
- @include border-b;
212
+ border-block-end: none;
192
213
  @include relative;
193
- padding-left: 50%;
214
+ }
194
215
 
195
- &:last-child {
196
- @include border-none;
197
- }
216
+ // Outranks table-base's `tr:last-child td` by source order.
217
+ tr > td:not(:last-child) {
218
+ @include border-b;
219
+ }
220
+
221
+ td[data-label] {
222
+ text-align: end;
223
+ padding-inline-start: 50%;
198
224
 
199
225
  &::before {
200
226
  content: attr(data-label);
201
227
  @include absolute;
202
- top: 0;
203
- bottom: 0;
204
- left: var(--size-md); // Geometric — ::before label inset matches td padding-x.
205
- // Geometric — label width less the gutter to value column.
206
- width: calc(50% - var(--size-lg));
228
+ inset-block: 0;
229
+ inset-inline-start: var(--padding-x);
230
+ inline-size: calc(50% - var(--size-lg));
207
231
  @include flex;
208
232
  @include items-center;
209
- @include text-left;
233
+ text-align: start;
210
234
  @include font-semibold;
211
235
  --color-fg: var(--fg-muted);
212
236
  color: var(--color-fg);
@@ -215,6 +239,22 @@
215
239
  @include truncate;
216
240
  }
217
241
  }
242
+
243
+ .table-row-actions {
244
+ position: static !important;
245
+ opacity: 1 !important;
246
+ visibility: visible !important;
247
+ pointer-events: auto !important;
248
+ transform: none !important;
249
+ background: transparent !important;
250
+ padding-inline-start: 0 !important;
251
+ justify-content: flex-end;
252
+ margin-block-start: var(--size-xs);
253
+
254
+ &::before {
255
+ display: none !important;
256
+ }
257
+ }
218
258
  }
219
259
 
220
260
  // ─── Variants ───────────────────────────────────────────────────
@@ -293,6 +333,8 @@
293
333
  @include table-header-btn-base;
294
334
  vertical-align: middle;
295
335
  position: relative;
336
+
337
+ &.ln-filter-active { @include table-filter-active; }
296
338
  }
297
339
 
298
340
  @mixin table-filter-active {
@@ -57,6 +57,37 @@
57
57
  }
58
58
  }
59
59
 
60
+ // ─── Segmented variant ──────────────────────────────────────────
61
+ // Pill track for compact panel-level switches (e.g. in a panel header).
62
+ // Usage: #register-tabs > nav { @include tabs-nav-segmented; }
63
+ @mixin tabs-nav-segmented {
64
+ display: inline-flex;
65
+ gap: var(--size-2xs);
66
+ padding: var(--size-2xs);
67
+ border: 0;
68
+ border-radius: var(--radius);
69
+ background: var(--bg-recessed);
70
+
71
+ [data-ln-tab] {
72
+ --padding-y: var(--size-xs);
73
+ --padding-x: var(--size-sm-up);
74
+ margin: 0;
75
+ border-block-end: 0;
76
+ border-radius: calc(var(--radius) - var(--size-2xs));
77
+
78
+ &:hover {
79
+ background: transparent;
80
+ color: var(--color-fg);
81
+ }
82
+ }
83
+
84
+ [data-ln-tab][data-active] {
85
+ background: var(--bg-elevated);
86
+ color: var(--color-accent);
87
+ box-shadow: var(--shadow-xs);
88
+ }
89
+ }
90
+
60
91
  @mixin tabs-panel {
61
92
  --padding-y: var(--size-lg);
62
93
  --padding-x: var(--size-lg);
@@ -106,7 +106,6 @@
106
106
 
107
107
  @mixin toast-icon {
108
108
  --color-accent: hsl(var(--color-primary));
109
- --color-accent-fg: hsl(var(--color-white));
110
109
  flex: 0 0 44px;
111
110
  @include flex;
112
111
  align-items: flex-start;
@@ -0,0 +1,12 @@
1
+ @use '../../config/mixins' as *;
2
+
3
+ // Same bindings as components/_card.scss, except .section-card renders a
4
+ // transparent titled group on the canvas (header = title row, no frame).
5
+ .card {
6
+ @include card;
7
+ @include card-field-list;
8
+ }
9
+
10
+ .section-card {
11
+ @include section-card($group: true);
12
+ }
@@ -0,0 +1,24 @@
1
+ @use '../../config/mixins' as *;
2
+
3
+ // Relaxed groupings — grid/flex layouts bound on markup the demo already
4
+ // uses. Composition only: no tokens are declared here.
5
+
6
+ // Cards placed directly in a section's body flow into an auto-fit grid.
7
+ .section-card > main:has(> .card) {
8
+ @include grid-auto;
9
+ }
10
+
11
+ // Stat-card lists flow as a wrapping row; the cards drop their elevation.
12
+ ul:has(> li > [data-ln-stat-card]) {
13
+ display: flex;
14
+ flex-wrap: wrap;
15
+ gap: var(--size-lg);
16
+
17
+ > li {
18
+ flex: 1 1 var(--grid-item-min-width);
19
+ }
20
+
21
+ [data-ln-stat-card] {
22
+ --shadow: none;
23
+ }
24
+ }
@@ -10,6 +10,7 @@
10
10
  @use '../components/ln-confirm/ln-confirm';
11
11
  @use '../components/ln-dropdown/ln-dropdown';
12
12
  @use '../components/ln-editor/ln-editor';
13
+ @use '../components/ln-external-links/ln-external-links';
13
14
  @use '../components/ln-filter/ln-filter';
14
15
  @use '../components/ln-list/ln-list';
15
16
  @use '../components/ln-modal/ln-modal';
@@ -31,7 +31,6 @@
31
31
  @use '../components/ln-options/ln-options-dev';
32
32
  @use '../components/ln-picklist/ln-picklist-dev';
33
33
  @use '../components/ln-popover/ln-popover-dev';
34
- @use '../components/ln-progress/ln-progress-dev';
35
34
  @use '../components/ln-router/ln-router-dev';
36
35
  @use '../components/ln-search/ln-search-dev';
37
36
  @use '../components/ln-slug/ln-slug-dev';
@@ -0,0 +1,67 @@
1
+ // ==========================================================================
2
+ // ln-ashlar relaxed design — mirrors ln-ashlar-theme.scss and adds the
3
+ // designs/relaxed/* bindings after it. Same palette and tokens: a design
4
+ // declares no tokens, only composition.
5
+ // ==========================================================================
6
+
7
+ @use 'ln-ashlar-core';
8
+
9
+ @use 'config/tokens';
10
+ @use 'config/breakpoints';
11
+ @use 'config/density';
12
+ @use 'config/theme';
13
+ @use 'config/icons';
14
+
15
+ @use 'base/reset';
16
+ @use 'base/global';
17
+ @use 'base/typography';
18
+
19
+ @use 'components/button';
20
+ @use 'components/form';
21
+ @use 'components/date';
22
+ @use 'components/layout';
23
+ @use 'components/table';
24
+ @use 'components/sort';
25
+ @use 'components/sortable';
26
+ @use 'components/tabs';
27
+ @use 'components/toggle';
28
+ @use 'components/accordion';
29
+ @use 'designs/relaxed/card';
30
+ @use 'components/sections';
31
+ @use 'designs/relaxed/layout' as relaxed-layout;
32
+ @use 'components/nav';
33
+ @use 'components/sidebar';
34
+ @use 'components/app-shell';
35
+ @use 'components/breadcrumbs';
36
+ @use 'components/avatar';
37
+ @use 'components/status-badge';
38
+ @use 'components/alert';
39
+ @use 'components/empty-state';
40
+ @use 'components/page-header';
41
+ @use 'components/stepper';
42
+ @use 'components/timeline';
43
+ @use 'components/stat-card';
44
+ @use 'components/prose';
45
+ @use 'components/editor';
46
+ @use 'components/scrollbar';
47
+ @use 'components/tooltip';
48
+ @use 'components/popover';
49
+ @use 'components/filter';
50
+ @use 'components/chip';
51
+ @use 'components/loader';
52
+ @use 'components/progress';
53
+ @use 'components/link';
54
+ @use 'components/confirm';
55
+ @use 'components/circular-progress';
56
+ @use 'components/modal';
57
+ @use 'components/dropdown';
58
+ @use 'components/toast';
59
+ @use 'components/upload';
60
+ @use 'components/picklist';
61
+ @use 'components/translations';
62
+ @use 'components/ln-table';
63
+ @use 'components/chart';
64
+ @use 'components/ajax';
65
+
66
+ @use 'utilities/utilities';
67
+ @use 'utilities/animations';