@livenetworks/ashlar 1.3.2
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 +177 -0
- package/js/COMPONENTS.md +1102 -0
- package/js/index.js +41 -0
- package/js/ln-accordion/README.md +137 -0
- package/js/ln-accordion/ln-accordion.js +1 -0
- package/js/ln-accordion/src/ln-accordion.js +41 -0
- package/js/ln-ajax/README.md +91 -0
- package/js/ln-ajax/ln-ajax.js +1 -0
- package/js/ln-ajax/src/ln-ajax.js +277 -0
- package/js/ln-api-connector/README.md +150 -0
- package/js/ln-api-connector/ln-api-connector.js +1 -0
- package/js/ln-api-connector/src/ln-api-connector.js +265 -0
- package/js/ln-autoresize/README.md +80 -0
- package/js/ln-autoresize/ln-autoresize.js +1 -0
- package/js/ln-autoresize/src/ln-autoresize.js +47 -0
- package/js/ln-autosave/README.md +92 -0
- package/js/ln-autosave/ln-autosave.js +1 -0
- package/js/ln-autosave/src/ln-autosave.js +147 -0
- package/js/ln-circular-progress/README.md +161 -0
- package/js/ln-circular-progress/ln-circular-progress.js +1 -0
- package/js/ln-circular-progress/src/ln-circular-progress.js +133 -0
- package/js/ln-confirm/README.md +86 -0
- package/js/ln-confirm/_ln-confirm.scss +13 -0
- package/js/ln-confirm/ln-confirm.js +1 -0
- package/js/ln-confirm/src/ln-confirm.js +131 -0
- package/js/ln-core/crypto.js +83 -0
- package/js/ln-core/helpers.js +411 -0
- package/js/ln-core/index.js +5 -0
- package/js/ln-core/persist.js +71 -0
- package/js/ln-core/positioning.js +207 -0
- package/js/ln-core/reactive.js +74 -0
- package/js/ln-couchdb-connector/README.md +156 -0
- package/js/ln-couchdb-connector/ln-couchdb-connector.js +1 -0
- package/js/ln-couchdb-connector/src/ln-couchdb-connector.js +348 -0
- package/js/ln-data-coordinator/README.md +165 -0
- package/js/ln-data-coordinator/ln-data-coordinator.js +1 -0
- package/js/ln-data-coordinator/src/ln-data-coordinator.js +249 -0
- package/js/ln-data-store/README.md +94 -0
- package/js/ln-data-store/ln-data-store.js +1 -0
- package/js/ln-data-store/src/ln-data-store.js +699 -0
- package/js/ln-data-table/README.md +110 -0
- package/js/ln-data-table/ln-data-table.js +1 -0
- package/js/ln-data-table/ln-data-table.scss +10 -0
- package/js/ln-data-table/src/ln-data-table.js +1103 -0
- package/js/ln-date/README.md +151 -0
- package/js/ln-date/ln-date.js +1 -0
- package/js/ln-date/src/ln-date.js +442 -0
- package/js/ln-dropdown/README.md +117 -0
- package/js/ln-dropdown/ln-dropdown.js +1 -0
- package/js/ln-dropdown/ln-dropdown.scss +15 -0
- package/js/ln-dropdown/src/ln-dropdown.js +174 -0
- package/js/ln-external-links/README.md +341 -0
- package/js/ln-external-links/ln-external-links.js +1 -0
- package/js/ln-external-links/src/ln-external-links.js +116 -0
- package/js/ln-filter/README.md +99 -0
- package/js/ln-filter/ln-filter.js +1 -0
- package/js/ln-filter/ln-filter.scss +7 -0
- package/js/ln-filter/src/ln-filter.js +404 -0
- package/js/ln-form/README.md +101 -0
- package/js/ln-form/ln-form.js +1 -0
- package/js/ln-form/src/ln-form.js +199 -0
- package/js/ln-http/README.md +89 -0
- package/js/ln-http/ln-http.js +1 -0
- package/js/ln-http/src/ln-http.js +219 -0
- package/js/ln-icons/README.md +88 -0
- package/js/ln-icons/ln-icons.js +1 -0
- package/js/ln-icons/src/ln-icons.js +169 -0
- package/js/ln-link/README.md +303 -0
- package/js/ln-link/ln-link.js +1 -0
- package/js/ln-link/src/ln-link.js +196 -0
- package/js/ln-modal/README.md +154 -0
- package/js/ln-modal/ln-modal.js +1 -0
- package/js/ln-modal/ln-modal.scss +11 -0
- package/js/ln-modal/src/ln-modal.js +201 -0
- package/js/ln-nav/README.md +70 -0
- package/js/ln-nav/ln-nav.js +1 -0
- package/js/ln-nav/src/ln-nav.js +177 -0
- package/js/ln-number/README.md +122 -0
- package/js/ln-number/ln-number.js +1 -0
- package/js/ln-number/src/ln-number.js +302 -0
- package/js/ln-popover/README.md +127 -0
- package/js/ln-popover/ln-popover.js +1 -0
- package/js/ln-popover/src/ln-popover.js +288 -0
- package/js/ln-progress/README.md +442 -0
- package/js/ln-progress/ln-progress.js +1 -0
- package/js/ln-progress/src/ln-progress.js +150 -0
- package/js/ln-search/README.md +83 -0
- package/js/ln-search/ln-search.js +1 -0
- package/js/ln-search/ln-search.scss +7 -0
- package/js/ln-search/src/ln-search.js +114 -0
- package/js/ln-sortable/README.md +95 -0
- package/js/ln-sortable/ln-sortable.js +1 -0
- package/js/ln-sortable/src/ln-sortable.js +203 -0
- package/js/ln-table/README.md +101 -0
- package/js/ln-table/ln-table-sort.js +1 -0
- package/js/ln-table/ln-table.js +1 -0
- package/js/ln-table/ln-table.scss +11 -0
- package/js/ln-table/src/ln-table-sort.js +168 -0
- package/js/ln-table/src/ln-table.js +473 -0
- package/js/ln-tabs/README.md +137 -0
- package/js/ln-tabs/ln-tabs.js +1 -0
- package/js/ln-tabs/src/ln-tabs.js +171 -0
- package/js/ln-time/README.md +81 -0
- package/js/ln-time/ln-time.js +1 -0
- package/js/ln-time/src/ln-time.js +192 -0
- package/js/ln-toast/README.md +122 -0
- package/js/ln-toast/ln-toast.js +15 -0
- package/js/ln-toast/src/ln-toast.js +210 -0
- package/js/ln-toast/template.html +14 -0
- package/js/ln-toggle/README.md +137 -0
- package/js/ln-toggle/ln-toggle.js +1 -0
- package/js/ln-toggle/src/ln-toggle.js +139 -0
- package/js/ln-tooltip/README.md +58 -0
- package/js/ln-tooltip/ln-tooltip.js +1 -0
- package/js/ln-tooltip/ln-tooltip.scss +9 -0
- package/js/ln-tooltip/src/ln-tooltip.js +169 -0
- package/js/ln-translations/README.md +96 -0
- package/js/ln-translations/ln-translations.js +1 -0
- package/js/ln-translations/src/ln-translations.js +275 -0
- package/js/ln-upload/README.md +180 -0
- package/js/ln-upload/ln-upload.js +1 -0
- package/js/ln-upload/ln-upload.scss +20 -0
- package/js/ln-upload/src/ln-upload.js +407 -0
- package/js/ln-validate/README.md +108 -0
- package/js/ln-validate/ln-validate.js +1 -0
- package/js/ln-validate/src/ln-validate.js +160 -0
- package/package.json +55 -0
- package/scss/base/_global.scss +83 -0
- package/scss/base/_reset.scss +17 -0
- package/scss/base/_typography.scss +125 -0
- package/scss/components/_accordion.scss +34 -0
- package/scss/components/_ajax.scss +15 -0
- package/scss/components/_alert.scss +5 -0
- package/scss/components/_app-shell.scss +15 -0
- package/scss/components/_avatar.scss +6 -0
- package/scss/components/_breadcrumbs.scss +33 -0
- package/scss/components/_button.scss +20 -0
- package/scss/components/_card.scss +10 -0
- package/scss/components/_chip.scss +5 -0
- package/scss/components/_circular-progress.scss +29 -0
- package/scss/components/_confirm.scss +5 -0
- package/scss/components/_data-table.scss +83 -0
- package/scss/components/_dropdown.scss +25 -0
- package/scss/components/_empty-state.scss +22 -0
- package/scss/components/_form.scss +100 -0
- package/scss/components/_layout.scss +8 -0
- package/scss/components/_link.scss +11 -0
- package/scss/components/_ln-table.scss +60 -0
- package/scss/components/_loader.scss +6 -0
- package/scss/components/_modal.scss +20 -0
- package/scss/components/_nav.scss +9 -0
- package/scss/components/_page-header.scss +10 -0
- package/scss/components/_popover.scss +10 -0
- package/scss/components/_progress.scss +17 -0
- package/scss/components/_prose.scss +5 -0
- package/scss/components/_scrollbar.scss +32 -0
- package/scss/components/_sections.scss +12 -0
- package/scss/components/_sidebar.scss +5 -0
- package/scss/components/_stat-card.scss +5 -0
- package/scss/components/_status-badge.scss +4 -0
- package/scss/components/_stepper.scss +5 -0
- package/scss/components/_table.scss +19 -0
- package/scss/components/_tabs.scss +21 -0
- package/scss/components/_timeline.scss +14 -0
- package/scss/components/_toast.scss +41 -0
- package/scss/components/_toggle.scss +81 -0
- package/scss/components/_tooltip.scss +18 -0
- package/scss/components/_translations.scss +111 -0
- package/scss/components/_upload.scss +51 -0
- package/scss/config/_breakpoints.scss +72 -0
- package/scss/config/_density.scss +117 -0
- package/scss/config/_icons.scss +37 -0
- package/scss/config/_mixins.scss +13 -0
- package/scss/config/_theme.scss +216 -0
- package/scss/config/_tokens.scss +419 -0
- package/scss/config/mixins/_accordion.scss +52 -0
- package/scss/config/mixins/_ajax.scss +39 -0
- package/scss/config/mixins/_alert.scss +82 -0
- package/scss/config/mixins/_app-shell.scss +312 -0
- package/scss/config/mixins/_avatar.scss +109 -0
- package/scss/config/mixins/_borders.scss +36 -0
- package/scss/config/mixins/_breadcrumbs.scss +72 -0
- package/scss/config/mixins/_breakpoints.scss +62 -0
- package/scss/config/mixins/_btn.scss +179 -0
- package/scss/config/mixins/_card.scss +338 -0
- package/scss/config/mixins/_chip.scss +66 -0
- package/scss/config/mixins/_circular-progress.scss +71 -0
- package/scss/config/mixins/_collapsible.scss +24 -0
- package/scss/config/mixins/_colors.scss +46 -0
- package/scss/config/mixins/_confirm.scss +31 -0
- package/scss/config/mixins/_data-table.scss +346 -0
- package/scss/config/mixins/_display.scss +32 -0
- package/scss/config/mixins/_dropdown.scss +143 -0
- package/scss/config/mixins/_empty-state.scss +30 -0
- package/scss/config/mixins/_focus.scss +55 -0
- package/scss/config/mixins/_footer.scss +42 -0
- package/scss/config/mixins/_form.scss +601 -0
- package/scss/config/mixins/_index.scss +58 -0
- package/scss/config/mixins/_interaction.scss +15 -0
- package/scss/config/mixins/_kbd.scss +22 -0
- package/scss/config/mixins/_layout.scss +117 -0
- package/scss/config/mixins/_link.scss +55 -0
- package/scss/config/mixins/_ln-table.scss +420 -0
- package/scss/config/mixins/_loader.scss +26 -0
- package/scss/config/mixins/_modal.scss +66 -0
- package/scss/config/mixins/_motion.scss +19 -0
- package/scss/config/mixins/_nav.scss +273 -0
- package/scss/config/mixins/_page-header.scss +69 -0
- package/scss/config/mixins/_popover.scss +25 -0
- package/scss/config/mixins/_position.scss +32 -0
- package/scss/config/mixins/_progress.scss +56 -0
- package/scss/config/mixins/_prose.scss +127 -0
- package/scss/config/mixins/_shadows.scss +8 -0
- package/scss/config/mixins/_sidebar.scss +95 -0
- package/scss/config/mixins/_sizing.scss +6 -0
- package/scss/config/mixins/_spacing.scss +19 -0
- package/scss/config/mixins/_stat-card.scss +68 -0
- package/scss/config/mixins/_status-badge.scss +83 -0
- package/scss/config/mixins/_stepper.scss +78 -0
- package/scss/config/mixins/_table.scss +215 -0
- package/scss/config/mixins/_tabs.scss +64 -0
- package/scss/config/mixins/_timeline.scss +69 -0
- package/scss/config/mixins/_toast.scss +148 -0
- package/scss/config/mixins/_tooltip.scss +111 -0
- package/scss/config/mixins/_transitions.scss +10 -0
- package/scss/config/mixins/_translations.scss +124 -0
- package/scss/config/mixins/_typography.scss +57 -0
- package/scss/config/mixins/_upload.scss +168 -0
- package/scss/ln-ashlar.scss +62 -0
- package/scss/tabler-icons.txt +5039 -0
- package/scss/utilities/_animations.scss +83 -0
- package/scss/utilities/_utilities.scss +49 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Spacing — accepts CSS variable or value
|
|
2
|
+
|
|
3
|
+
@mixin p($val) { padding: $val; }
|
|
4
|
+
@mixin px($val) { padding-left: $val; padding-right: $val; }
|
|
5
|
+
@mixin py($val) { padding-top: $val; padding-bottom: $val; }
|
|
6
|
+
@mixin pt($val) { padding-top: $val; }
|
|
7
|
+
@mixin pb($val) { padding-bottom: $val; }
|
|
8
|
+
@mixin pl($val) { padding-left: $val; }
|
|
9
|
+
@mixin pr($val) { padding-right: $val; }
|
|
10
|
+
|
|
11
|
+
@mixin m($val) { margin: $val; }
|
|
12
|
+
@mixin mx($val) { margin-left: $val; margin-right: $val; }
|
|
13
|
+
@mixin my($val) { margin-top: $val; margin-bottom: $val; }
|
|
14
|
+
@mixin mt($val) { margin-top: $val; }
|
|
15
|
+
@mixin mb($val) { margin-bottom: $val; }
|
|
16
|
+
@mixin ml($val) { margin-left: $val; }
|
|
17
|
+
@mixin mr($val) { margin-right: $val; }
|
|
18
|
+
|
|
19
|
+
@mixin gap($val) { gap: $val; }
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
@use 'spacing' as *;
|
|
2
|
+
@use 'display' as *;
|
|
3
|
+
@use 'typography' as *;
|
|
4
|
+
@use 'colors' as *;
|
|
5
|
+
@use 'borders' as *;
|
|
6
|
+
@use 'transitions' as *;
|
|
7
|
+
|
|
8
|
+
@mixin stat-card {
|
|
9
|
+
--shadow: var(--shadow-resting);
|
|
10
|
+
@include flex-col;
|
|
11
|
+
--gap: var(--size-xs);
|
|
12
|
+
gap: var(--gap);
|
|
13
|
+
--padding-y: var(--size-lg);
|
|
14
|
+
--padding-x: var(--size-lg);
|
|
15
|
+
padding: var(--padding-y) var(--padding-x);
|
|
16
|
+
background: var(--color-bg);
|
|
17
|
+
--radius: var(--radius-lg);
|
|
18
|
+
border-radius: var(--radius);
|
|
19
|
+
box-shadow: var(--shadow);
|
|
20
|
+
border-block-start: var(--border-block-start, var(--border-width) solid var(--color-border));
|
|
21
|
+
border-block-end: var(--border-block-end, var(--border-width) solid var(--color-border));
|
|
22
|
+
border-inline-start: var(--border-inline-start, var(--border-width) solid var(--color-border));
|
|
23
|
+
border-inline-end: var(--border-inline-end, var(--border-width) solid var(--color-border));
|
|
24
|
+
@include transition;
|
|
25
|
+
|
|
26
|
+
> [data-ln-stat-label] {
|
|
27
|
+
--color-fg: var(--fg-muted);
|
|
28
|
+
@include typography(label-md);
|
|
29
|
+
color: var(--color-fg);
|
|
30
|
+
text-transform: uppercase;
|
|
31
|
+
letter-spacing: var(--tracking-wide);
|
|
32
|
+
margin: 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
> [data-ln-stat-value] {
|
|
36
|
+
@include typography(heading-lg);
|
|
37
|
+
font-weight: var(--font-bold);
|
|
38
|
+
font-variant-numeric: tabular-nums;
|
|
39
|
+
color: var(--color-fg);
|
|
40
|
+
margin: 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
> [data-ln-stat-trend] {
|
|
44
|
+
@include flex-row;
|
|
45
|
+
@include items-center;
|
|
46
|
+
--gap: var(--size-xs);
|
|
47
|
+
gap: var(--gap);
|
|
48
|
+
@include typography(body-sm);
|
|
49
|
+
--margin-block: var(--size-xs);
|
|
50
|
+
margin: var(--margin-block) 0 0;
|
|
51
|
+
|
|
52
|
+
svg.ln-icon {
|
|
53
|
+
width: 1rem;
|
|
54
|
+
height: 1rem;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
&[data-ln-stat-trend="up"] {
|
|
58
|
+
color: hsl(var(--color-success));
|
|
59
|
+
}
|
|
60
|
+
&[data-ln-stat-trend="down"] {
|
|
61
|
+
color: hsl(var(--color-error));
|
|
62
|
+
}
|
|
63
|
+
&[data-ln-stat-trend="neutral"] {
|
|
64
|
+
--color-fg: var(--fg-subtle);
|
|
65
|
+
color: var(--color-fg);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
@use 'colors' as *;
|
|
2
|
+
@use 'motion' as *;
|
|
3
|
+
|
|
4
|
+
// Status Badge — inline semantic indicator with colored dot
|
|
5
|
+
//
|
|
6
|
+
// Usage:
|
|
7
|
+
// <span class="badge success">Active</span>
|
|
8
|
+
// <span class="badge warning live">Syncing</span>
|
|
9
|
+
// <button class="badge error">Blocked</button>
|
|
10
|
+
//
|
|
11
|
+
// Variants (override --color-primary):
|
|
12
|
+
// .success → --color-success
|
|
13
|
+
// .warning → --color-warning
|
|
14
|
+
// .error → --color-error
|
|
15
|
+
// .info → --color-info
|
|
16
|
+
// .neutral → --color-neutral-400
|
|
17
|
+
//
|
|
18
|
+
// Live: .badge.live adds pulse animation to the dot
|
|
19
|
+
|
|
20
|
+
// ─── Base ──────────────────────────────────────────────
|
|
21
|
+
@mixin badge {
|
|
22
|
+
display: inline-flex;
|
|
23
|
+
align-items: center;
|
|
24
|
+
gap: 0;
|
|
25
|
+
border-radius: var(--radius-full);
|
|
26
|
+
padding: 0.2em 0.65em;
|
|
27
|
+
font-size: var(--text-xs);
|
|
28
|
+
font-weight: var(--font-medium);
|
|
29
|
+
@include tinted-surface(0.12);
|
|
30
|
+
line-height: 1.5;
|
|
31
|
+
|
|
32
|
+
// Colored dot
|
|
33
|
+
&::before {
|
|
34
|
+
content: '';
|
|
35
|
+
display: block;
|
|
36
|
+
width: 0.45em;
|
|
37
|
+
height: 0.45em;
|
|
38
|
+
border-radius: 50%;
|
|
39
|
+
background: currentColor;
|
|
40
|
+
margin-right: 0.4em;
|
|
41
|
+
flex-shrink: 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// When on <button> — override global gray hover
|
|
45
|
+
&:is(button) {
|
|
46
|
+
cursor: pointer;
|
|
47
|
+
transition: background var(--transition-fast);
|
|
48
|
+
border: none;
|
|
49
|
+
font-family: inherit;
|
|
50
|
+
|
|
51
|
+
&:hover {
|
|
52
|
+
background: color-mix(in srgb, var(--color-accent) 20%, transparent);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
&:active {
|
|
56
|
+
background: color-mix(in srgb, var(--color-accent) 28%, transparent);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ─── Live / pulse ──────────────────────────────────────
|
|
62
|
+
// Ring radius in `em` so it scales with badge font-size.
|
|
63
|
+
// 0.9em ≈ 2× the dot width — visibly extends beyond the dot.
|
|
64
|
+
// `70%, 100%` holds the final (invisible) frame for a short
|
|
65
|
+
// rest between beats, giving a heartbeat rhythm instead of
|
|
66
|
+
// a constant fade.
|
|
67
|
+
@mixin badge-live {
|
|
68
|
+
@keyframes badge-pulse {
|
|
69
|
+
0% {
|
|
70
|
+
box-shadow: 0 0 0 0 color-mix(in srgb, var(--color-accent) 70%, transparent);
|
|
71
|
+
}
|
|
72
|
+
70%,
|
|
73
|
+
100% {
|
|
74
|
+
box-shadow: 0 0 0 0.6em color-mix(in srgb, var(--color-accent) 0%, transparent);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
&::before {
|
|
79
|
+
@include motion-safe {
|
|
80
|
+
animation: badge-pulse 1.8s ease-out infinite;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
@use 'display' as *;
|
|
2
|
+
@use 'typography' as *;
|
|
3
|
+
|
|
4
|
+
@mixin stepper {
|
|
5
|
+
display: flex;
|
|
6
|
+
gap: 0;
|
|
7
|
+
counter-reset: ln-step;
|
|
8
|
+
|
|
9
|
+
> li {
|
|
10
|
+
counter-increment: ln-step;
|
|
11
|
+
flex: 1;
|
|
12
|
+
position: relative;
|
|
13
|
+
@include flex-col;
|
|
14
|
+
@include items-center;
|
|
15
|
+
gap: var(--gap);
|
|
16
|
+
min-width: 0;
|
|
17
|
+
|
|
18
|
+
// Numbered circle bullet
|
|
19
|
+
&::before {
|
|
20
|
+
content: counter(ln-step);
|
|
21
|
+
@include flex-center;
|
|
22
|
+
width: 2rem;
|
|
23
|
+
height: 2rem;
|
|
24
|
+
border-radius: 50%;
|
|
25
|
+
background: var(--color-border);
|
|
26
|
+
--color-fg: var(--fg-muted);
|
|
27
|
+
color: var(--color-fg);
|
|
28
|
+
@include typography(label-md);
|
|
29
|
+
font-weight: var(--font-semibold);
|
|
30
|
+
z-index: 1;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Connector line to next step
|
|
34
|
+
&:not(:last-child)::after {
|
|
35
|
+
content: '';
|
|
36
|
+
position: absolute;
|
|
37
|
+
top: var(--size-md); // Geometric — connector vertical center matches bullet radius.
|
|
38
|
+
// Geometric — connector horizontal endpoints clear bullet edge.
|
|
39
|
+
left: calc(50% + var(--size-md));
|
|
40
|
+
right: calc(-50% + var(--size-md));
|
|
41
|
+
height: 2px;
|
|
42
|
+
background: var(--color-border);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
> [data-ln-step-label] {
|
|
46
|
+
@include typography(label-md);
|
|
47
|
+
--color-fg: var(--fg-muted);
|
|
48
|
+
color: var(--color-fg);
|
|
49
|
+
text-align: center;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// States
|
|
53
|
+
&[data-ln-step="complete"] {
|
|
54
|
+
&::before {
|
|
55
|
+
background: var(--color-accent);
|
|
56
|
+
color: var(--color-accent-fg);
|
|
57
|
+
}
|
|
58
|
+
&::after {
|
|
59
|
+
background: var(--color-accent);
|
|
60
|
+
}
|
|
61
|
+
> [data-ln-step-label] {
|
|
62
|
+
color: var(--color-fg);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
&[data-ln-step="current"] {
|
|
67
|
+
&::before {
|
|
68
|
+
background: var(--color-accent);
|
|
69
|
+
color: var(--color-accent-fg);
|
|
70
|
+
box-shadow: 0 0 0 4px color-mix(in srgb, var(--color-accent) 20%, transparent);
|
|
71
|
+
}
|
|
72
|
+
> [data-ln-step-label] {
|
|
73
|
+
color: var(--color-fg);
|
|
74
|
+
font-weight: var(--font-semibold);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
@use 'display' as *;
|
|
2
|
+
@use 'spacing' as *;
|
|
3
|
+
@use 'sizing' as *;
|
|
4
|
+
@use 'typography' as *;
|
|
5
|
+
@use 'colors' as *;
|
|
6
|
+
@use 'borders' as *;
|
|
7
|
+
@use 'transitions' as *;
|
|
8
|
+
@use 'position' as *;
|
|
9
|
+
|
|
10
|
+
// ─── Base table ─────────────────────────────────────────────────
|
|
11
|
+
|
|
12
|
+
@mixin table-base {
|
|
13
|
+
@include w-full;
|
|
14
|
+
background: var(--color-bg);
|
|
15
|
+
--radius: var(--radius-lg);
|
|
16
|
+
border-radius: var(--radius);
|
|
17
|
+
// `overflow: clip` not `overflow: hidden` — clips at rounded corners
|
|
18
|
+
// without establishing a scroll container, so sticky descendants
|
|
19
|
+
// (e.g. `@mixin data-table` thead/tfoot) bind to the outer
|
|
20
|
+
// `.app-main > section` scroll surface instead of being trapped
|
|
21
|
+
// inside the <table> element. Same rationale as `@mixin section-card`
|
|
22
|
+
// and `@mixin ln-table`.
|
|
23
|
+
overflow: clip;
|
|
24
|
+
--shadow: var(--shadow-resting);
|
|
25
|
+
box-shadow: var(--shadow);
|
|
26
|
+
border-collapse: collapse;
|
|
27
|
+
font-variant-numeric: tabular-nums;
|
|
28
|
+
|
|
29
|
+
thead {
|
|
30
|
+
--color-bg: var(--bg-sunken);
|
|
31
|
+
background: var(--color-bg);
|
|
32
|
+
border-block-end: var(--border-block-end, var(--border-width-strong) solid var(--color-border));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
th {
|
|
36
|
+
@include text-left;
|
|
37
|
+
padding: var(--padding-y) var(--padding-x);
|
|
38
|
+
@include font-semibold;
|
|
39
|
+
font-size: var(--text-label-sm);
|
|
40
|
+
line-height: var(--line-height);
|
|
41
|
+
letter-spacing: 0.4px;
|
|
42
|
+
@include uppercase;
|
|
43
|
+
color: var(--color-fg);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
tbody tr {
|
|
47
|
+
@include transition;
|
|
48
|
+
min-height: var(--density-row-h);
|
|
49
|
+
|
|
50
|
+
&:hover {
|
|
51
|
+
// Default hover stays --bg-sunken for standalone tables. Data-table
|
|
52
|
+
// re-binds --color-bg locally (see _data-table.scss) so its hover
|
|
53
|
+
// disambiguates from chrome that also uses --bg-sunken.
|
|
54
|
+
--color-bg: var(--bg-sunken);
|
|
55
|
+
background: var(--color-bg);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
td {
|
|
60
|
+
padding: var(--padding-y) var(--padding-x);
|
|
61
|
+
@include border-b;
|
|
62
|
+
font-size: var(--font-size);
|
|
63
|
+
line-height: var(--line-height);
|
|
64
|
+
vertical-align: top;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
tr:last-child td {
|
|
68
|
+
@include border-none;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
td.numeric,
|
|
72
|
+
th.numeric {
|
|
73
|
+
@include text-right;
|
|
74
|
+
font-variant-numeric: tabular-nums;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
td.center,
|
|
78
|
+
th.center {
|
|
79
|
+
@include text-center;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
td.nowrap,
|
|
83
|
+
th.nowrap {
|
|
84
|
+
@include whitespace-nowrap;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// ─── Responsive (mobile stacked layout) ─────────────────────────
|
|
89
|
+
// Requires data-label attribute on <td> for column headers.
|
|
90
|
+
|
|
91
|
+
@mixin table-responsive {
|
|
92
|
+
th {
|
|
93
|
+
@include hidden;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
tbody tr {
|
|
97
|
+
@include block;
|
|
98
|
+
// Structural gap between stacked row-cards.
|
|
99
|
+
--margin-block: var(--size-md);
|
|
100
|
+
margin-bottom: var(--margin-block);
|
|
101
|
+
@include border;
|
|
102
|
+
border-radius: var(--radius);
|
|
103
|
+
@include overflow-hidden;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
td {
|
|
107
|
+
@include block;
|
|
108
|
+
@include text-right;
|
|
109
|
+
// Stacked rows need taller vertical rhythm than desktop table cells.
|
|
110
|
+
--padding-y: var(--size-sm-up);
|
|
111
|
+
--padding-x: var(--size-md);
|
|
112
|
+
padding: var(--padding-y) var(--padding-x);
|
|
113
|
+
@include border-b;
|
|
114
|
+
@include relative;
|
|
115
|
+
padding-left: 50%;
|
|
116
|
+
|
|
117
|
+
&:last-child {
|
|
118
|
+
@include border-none;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
&::before {
|
|
122
|
+
content: attr(data-label);
|
|
123
|
+
@include absolute;
|
|
124
|
+
top: 0;
|
|
125
|
+
bottom: 0;
|
|
126
|
+
left: var(--size-md); // Geometric — ::before label inset matches td padding-x.
|
|
127
|
+
// Geometric — label width less the gutter to value column.
|
|
128
|
+
width: calc(50% - var(--size-lg));
|
|
129
|
+
@include flex;
|
|
130
|
+
@include items-center;
|
|
131
|
+
@include text-left;
|
|
132
|
+
@include font-semibold;
|
|
133
|
+
--color-fg: var(--fg-muted);
|
|
134
|
+
color: var(--color-fg);
|
|
135
|
+
@include text-xs;
|
|
136
|
+
@include uppercase;
|
|
137
|
+
@include truncate;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// ─── Variants ───────────────────────────────────────────────────
|
|
143
|
+
|
|
144
|
+
@mixin table-striped {
|
|
145
|
+
tbody tr:nth-child(odd) {
|
|
146
|
+
--color-bg: var(--bg-sunken);
|
|
147
|
+
background: var(--color-bg);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
@mixin table-section-header {
|
|
152
|
+
--color-bg: var(--bg-sunken);
|
|
153
|
+
background: var(--color-bg);
|
|
154
|
+
@include font-semibold;
|
|
155
|
+
@include text-sm;
|
|
156
|
+
--color-fg: var(--fg-muted);
|
|
157
|
+
color: var(--color-fg);
|
|
158
|
+
letter-spacing: 0.3px;
|
|
159
|
+
|
|
160
|
+
&:hover {
|
|
161
|
+
background-color: var(--bg-sunken);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
@mixin table-action {
|
|
166
|
+
@include inline-flex;
|
|
167
|
+
@include items-center;
|
|
168
|
+
@include justify-center;
|
|
169
|
+
--padding-y: var(--size-xs);
|
|
170
|
+
--padding-x: var(--size-sm);
|
|
171
|
+
padding: var(--padding-y) var(--padding-x);
|
|
172
|
+
@include text-sm;
|
|
173
|
+
@include transition-colors;
|
|
174
|
+
|
|
175
|
+
&:hover {
|
|
176
|
+
--color-bg: var(--bg-sunken);
|
|
177
|
+
background: var(--color-bg);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
svg {
|
|
181
|
+
@include size(1.5rem);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// ─── Column filter button ──────────────────────────────────────
|
|
186
|
+
// Button inside <th> that triggers a filter popover/dropdown.
|
|
187
|
+
// Convention: add class="filter" to the trigger button.
|
|
188
|
+
// ln-table.js sets data-ln-filter-active on the <th> when active.
|
|
189
|
+
|
|
190
|
+
@mixin table-filter-button {
|
|
191
|
+
th .filter {
|
|
192
|
+
@include inline-flex;
|
|
193
|
+
@include items-center;
|
|
194
|
+
float: right;
|
|
195
|
+
--btn-padding-y: var(--size-2xs);
|
|
196
|
+
--btn-padding-x: var(--size-2xs);
|
|
197
|
+
@include rounded-sm;
|
|
198
|
+
opacity: 0.5;
|
|
199
|
+
|
|
200
|
+
&:hover {
|
|
201
|
+
opacity: 1;
|
|
202
|
+
--color-bg: var(--bg-sunken);
|
|
203
|
+
background: var(--color-bg);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
th [data-ln-dropdown] {
|
|
208
|
+
float: right;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
th[data-ln-filter-active] .filter {
|
|
212
|
+
opacity: 1;
|
|
213
|
+
color: var(--color-accent);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
@use 'display' as *;
|
|
2
|
+
@use 'typography' as *;
|
|
3
|
+
@use 'borders' as *;
|
|
4
|
+
@use 'transitions' as *;
|
|
5
|
+
@use 'interaction' as *;
|
|
6
|
+
|
|
7
|
+
// Tabs — underline style
|
|
8
|
+
|
|
9
|
+
@mixin tabs-nav {
|
|
10
|
+
@include flex;
|
|
11
|
+
@include border-b;
|
|
12
|
+
|
|
13
|
+
[data-ln-tab][data-active] {
|
|
14
|
+
color: var(--color-accent);
|
|
15
|
+
border-bottom-color: var(--color-accent);
|
|
16
|
+
background: none;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
[data-ln-tab][disabled] {
|
|
20
|
+
--color-fg: var(--fg-subtle);
|
|
21
|
+
color: var(--color-fg);
|
|
22
|
+
@include cursor-not-allowed;
|
|
23
|
+
@include opacity-50;
|
|
24
|
+
|
|
25
|
+
&:hover {
|
|
26
|
+
background: none;
|
|
27
|
+
border-bottom-color: transparent;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@mixin tabs-tab {
|
|
33
|
+
--color-fg: var(--fg-muted);
|
|
34
|
+
all: unset;
|
|
35
|
+
box-sizing: border-box;
|
|
36
|
+
--padding-y: var(--size-sm);
|
|
37
|
+
--padding-x: var(--size-md);
|
|
38
|
+
padding: var(--padding-y) var(--padding-x);
|
|
39
|
+
@include text-sm;
|
|
40
|
+
@include font-medium;
|
|
41
|
+
color: var(--color-fg);
|
|
42
|
+
@include cursor-pointer;
|
|
43
|
+
@include transition;
|
|
44
|
+
border-bottom: 2px solid transparent;
|
|
45
|
+
margin-bottom: -1px;
|
|
46
|
+
|
|
47
|
+
&:hover {
|
|
48
|
+
color: var(--color-accent);
|
|
49
|
+
background-color: color-mix(in srgb, var(--color-accent) 5%, transparent);
|
|
50
|
+
border-bottom-color: color-mix(in srgb, var(--color-accent) 30%, transparent);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
&:focus,
|
|
54
|
+
&:active,
|
|
55
|
+
&:visited {
|
|
56
|
+
background: none;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@mixin tabs-panel {
|
|
61
|
+
--padding-y: var(--size-lg);
|
|
62
|
+
--padding-x: var(--size-lg);
|
|
63
|
+
padding: var(--padding-y) var(--padding-x);
|
|
64
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
@use 'display' as *;
|
|
2
|
+
@use 'typography' as *;
|
|
3
|
+
|
|
4
|
+
@mixin timeline {
|
|
5
|
+
position: relative;
|
|
6
|
+
|
|
7
|
+
// Vertical rail — concentric with the bullet on both axes.
|
|
8
|
+
// X: bullet center = 0.125rem + 0.375rem = 0.5rem; rail = 0.5rem - 1px.
|
|
9
|
+
// Y: start/end at the first/last bullet center = 0.525rem from li edge.
|
|
10
|
+
&::before {
|
|
11
|
+
content: '';
|
|
12
|
+
position: absolute;
|
|
13
|
+
top: calc(var(--lh-caption) * var(--text-caption) / 2);
|
|
14
|
+
bottom: calc(var(--lh-caption) * var(--text-caption) / 2);
|
|
15
|
+
left: calc(var(--size-sm) - var(--border-width)); // Geometric — rail x-position aligned with bullet center.
|
|
16
|
+
width: 2px;
|
|
17
|
+
background: var(--color-border);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
> li {
|
|
21
|
+
position: relative;
|
|
22
|
+
--padding-x: var(--size-xl);
|
|
23
|
+
padding-left: var(--padding-x);
|
|
24
|
+
--padding-y: var(--size-lg);
|
|
25
|
+
padding-bottom: var(--padding-y);
|
|
26
|
+
|
|
27
|
+
&:last-child {
|
|
28
|
+
padding-bottom: 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Bullet — centered on the first line of <time> (caption role).
|
|
32
|
+
// Line-box height = var(--lh-caption) * var(--text-caption) = 1.05rem.
|
|
33
|
+
// Line center = 0.525rem; bullet is 0.75rem tall so top = 0.15rem.
|
|
34
|
+
&::before {
|
|
35
|
+
content: '';
|
|
36
|
+
position: absolute;
|
|
37
|
+
top: calc((var(--lh-caption) * var(--text-caption) - var(--size-sm-up)) / 2); // Geometric — bullet vertical alignment to caption baseline.
|
|
38
|
+
left: var(--size-2xs); // Geometric — bullet x-position inside li padding.
|
|
39
|
+
width: 0.75rem;
|
|
40
|
+
height: 0.75rem;
|
|
41
|
+
border-radius: 50%;
|
|
42
|
+
background: var(--color-accent);
|
|
43
|
+
box-shadow: 0 0 0 3px var(--color-bg);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
> time {
|
|
47
|
+
display: block;
|
|
48
|
+
@include typography(caption);
|
|
49
|
+
--color-fg: var(--fg-subtle);
|
|
50
|
+
color: var(--color-fg);
|
|
51
|
+
--margin-block: var(--size-xs);
|
|
52
|
+
margin-bottom: var(--margin-block);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
> h4 {
|
|
56
|
+
@include typography(title-sm);
|
|
57
|
+
color: var(--color-fg);
|
|
58
|
+
margin: 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
> p {
|
|
62
|
+
@include typography(body-sm);
|
|
63
|
+
--color-fg: var(--fg-muted);
|
|
64
|
+
color: var(--color-fg);
|
|
65
|
+
--margin-block: var(--size-xs);
|
|
66
|
+
margin: var(--margin-block) 0 0;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|