@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.
Files changed (232) hide show
  1. package/README.md +177 -0
  2. package/js/COMPONENTS.md +1102 -0
  3. package/js/index.js +41 -0
  4. package/js/ln-accordion/README.md +137 -0
  5. package/js/ln-accordion/ln-accordion.js +1 -0
  6. package/js/ln-accordion/src/ln-accordion.js +41 -0
  7. package/js/ln-ajax/README.md +91 -0
  8. package/js/ln-ajax/ln-ajax.js +1 -0
  9. package/js/ln-ajax/src/ln-ajax.js +277 -0
  10. package/js/ln-api-connector/README.md +150 -0
  11. package/js/ln-api-connector/ln-api-connector.js +1 -0
  12. package/js/ln-api-connector/src/ln-api-connector.js +265 -0
  13. package/js/ln-autoresize/README.md +80 -0
  14. package/js/ln-autoresize/ln-autoresize.js +1 -0
  15. package/js/ln-autoresize/src/ln-autoresize.js +47 -0
  16. package/js/ln-autosave/README.md +92 -0
  17. package/js/ln-autosave/ln-autosave.js +1 -0
  18. package/js/ln-autosave/src/ln-autosave.js +147 -0
  19. package/js/ln-circular-progress/README.md +161 -0
  20. package/js/ln-circular-progress/ln-circular-progress.js +1 -0
  21. package/js/ln-circular-progress/src/ln-circular-progress.js +133 -0
  22. package/js/ln-confirm/README.md +86 -0
  23. package/js/ln-confirm/_ln-confirm.scss +13 -0
  24. package/js/ln-confirm/ln-confirm.js +1 -0
  25. package/js/ln-confirm/src/ln-confirm.js +131 -0
  26. package/js/ln-core/crypto.js +83 -0
  27. package/js/ln-core/helpers.js +411 -0
  28. package/js/ln-core/index.js +5 -0
  29. package/js/ln-core/persist.js +71 -0
  30. package/js/ln-core/positioning.js +207 -0
  31. package/js/ln-core/reactive.js +74 -0
  32. package/js/ln-couchdb-connector/README.md +156 -0
  33. package/js/ln-couchdb-connector/ln-couchdb-connector.js +1 -0
  34. package/js/ln-couchdb-connector/src/ln-couchdb-connector.js +348 -0
  35. package/js/ln-data-coordinator/README.md +165 -0
  36. package/js/ln-data-coordinator/ln-data-coordinator.js +1 -0
  37. package/js/ln-data-coordinator/src/ln-data-coordinator.js +249 -0
  38. package/js/ln-data-store/README.md +94 -0
  39. package/js/ln-data-store/ln-data-store.js +1 -0
  40. package/js/ln-data-store/src/ln-data-store.js +699 -0
  41. package/js/ln-data-table/README.md +110 -0
  42. package/js/ln-data-table/ln-data-table.js +1 -0
  43. package/js/ln-data-table/ln-data-table.scss +10 -0
  44. package/js/ln-data-table/src/ln-data-table.js +1103 -0
  45. package/js/ln-date/README.md +151 -0
  46. package/js/ln-date/ln-date.js +1 -0
  47. package/js/ln-date/src/ln-date.js +442 -0
  48. package/js/ln-dropdown/README.md +117 -0
  49. package/js/ln-dropdown/ln-dropdown.js +1 -0
  50. package/js/ln-dropdown/ln-dropdown.scss +15 -0
  51. package/js/ln-dropdown/src/ln-dropdown.js +174 -0
  52. package/js/ln-external-links/README.md +341 -0
  53. package/js/ln-external-links/ln-external-links.js +1 -0
  54. package/js/ln-external-links/src/ln-external-links.js +116 -0
  55. package/js/ln-filter/README.md +99 -0
  56. package/js/ln-filter/ln-filter.js +1 -0
  57. package/js/ln-filter/ln-filter.scss +7 -0
  58. package/js/ln-filter/src/ln-filter.js +404 -0
  59. package/js/ln-form/README.md +101 -0
  60. package/js/ln-form/ln-form.js +1 -0
  61. package/js/ln-form/src/ln-form.js +199 -0
  62. package/js/ln-http/README.md +89 -0
  63. package/js/ln-http/ln-http.js +1 -0
  64. package/js/ln-http/src/ln-http.js +219 -0
  65. package/js/ln-icons/README.md +88 -0
  66. package/js/ln-icons/ln-icons.js +1 -0
  67. package/js/ln-icons/src/ln-icons.js +169 -0
  68. package/js/ln-link/README.md +303 -0
  69. package/js/ln-link/ln-link.js +1 -0
  70. package/js/ln-link/src/ln-link.js +196 -0
  71. package/js/ln-modal/README.md +154 -0
  72. package/js/ln-modal/ln-modal.js +1 -0
  73. package/js/ln-modal/ln-modal.scss +11 -0
  74. package/js/ln-modal/src/ln-modal.js +201 -0
  75. package/js/ln-nav/README.md +70 -0
  76. package/js/ln-nav/ln-nav.js +1 -0
  77. package/js/ln-nav/src/ln-nav.js +177 -0
  78. package/js/ln-number/README.md +122 -0
  79. package/js/ln-number/ln-number.js +1 -0
  80. package/js/ln-number/src/ln-number.js +302 -0
  81. package/js/ln-popover/README.md +127 -0
  82. package/js/ln-popover/ln-popover.js +1 -0
  83. package/js/ln-popover/src/ln-popover.js +288 -0
  84. package/js/ln-progress/README.md +442 -0
  85. package/js/ln-progress/ln-progress.js +1 -0
  86. package/js/ln-progress/src/ln-progress.js +150 -0
  87. package/js/ln-search/README.md +83 -0
  88. package/js/ln-search/ln-search.js +1 -0
  89. package/js/ln-search/ln-search.scss +7 -0
  90. package/js/ln-search/src/ln-search.js +114 -0
  91. package/js/ln-sortable/README.md +95 -0
  92. package/js/ln-sortable/ln-sortable.js +1 -0
  93. package/js/ln-sortable/src/ln-sortable.js +203 -0
  94. package/js/ln-table/README.md +101 -0
  95. package/js/ln-table/ln-table-sort.js +1 -0
  96. package/js/ln-table/ln-table.js +1 -0
  97. package/js/ln-table/ln-table.scss +11 -0
  98. package/js/ln-table/src/ln-table-sort.js +168 -0
  99. package/js/ln-table/src/ln-table.js +473 -0
  100. package/js/ln-tabs/README.md +137 -0
  101. package/js/ln-tabs/ln-tabs.js +1 -0
  102. package/js/ln-tabs/src/ln-tabs.js +171 -0
  103. package/js/ln-time/README.md +81 -0
  104. package/js/ln-time/ln-time.js +1 -0
  105. package/js/ln-time/src/ln-time.js +192 -0
  106. package/js/ln-toast/README.md +122 -0
  107. package/js/ln-toast/ln-toast.js +15 -0
  108. package/js/ln-toast/src/ln-toast.js +210 -0
  109. package/js/ln-toast/template.html +14 -0
  110. package/js/ln-toggle/README.md +137 -0
  111. package/js/ln-toggle/ln-toggle.js +1 -0
  112. package/js/ln-toggle/src/ln-toggle.js +139 -0
  113. package/js/ln-tooltip/README.md +58 -0
  114. package/js/ln-tooltip/ln-tooltip.js +1 -0
  115. package/js/ln-tooltip/ln-tooltip.scss +9 -0
  116. package/js/ln-tooltip/src/ln-tooltip.js +169 -0
  117. package/js/ln-translations/README.md +96 -0
  118. package/js/ln-translations/ln-translations.js +1 -0
  119. package/js/ln-translations/src/ln-translations.js +275 -0
  120. package/js/ln-upload/README.md +180 -0
  121. package/js/ln-upload/ln-upload.js +1 -0
  122. package/js/ln-upload/ln-upload.scss +20 -0
  123. package/js/ln-upload/src/ln-upload.js +407 -0
  124. package/js/ln-validate/README.md +108 -0
  125. package/js/ln-validate/ln-validate.js +1 -0
  126. package/js/ln-validate/src/ln-validate.js +160 -0
  127. package/package.json +55 -0
  128. package/scss/base/_global.scss +83 -0
  129. package/scss/base/_reset.scss +17 -0
  130. package/scss/base/_typography.scss +125 -0
  131. package/scss/components/_accordion.scss +34 -0
  132. package/scss/components/_ajax.scss +15 -0
  133. package/scss/components/_alert.scss +5 -0
  134. package/scss/components/_app-shell.scss +15 -0
  135. package/scss/components/_avatar.scss +6 -0
  136. package/scss/components/_breadcrumbs.scss +33 -0
  137. package/scss/components/_button.scss +20 -0
  138. package/scss/components/_card.scss +10 -0
  139. package/scss/components/_chip.scss +5 -0
  140. package/scss/components/_circular-progress.scss +29 -0
  141. package/scss/components/_confirm.scss +5 -0
  142. package/scss/components/_data-table.scss +83 -0
  143. package/scss/components/_dropdown.scss +25 -0
  144. package/scss/components/_empty-state.scss +22 -0
  145. package/scss/components/_form.scss +100 -0
  146. package/scss/components/_layout.scss +8 -0
  147. package/scss/components/_link.scss +11 -0
  148. package/scss/components/_ln-table.scss +60 -0
  149. package/scss/components/_loader.scss +6 -0
  150. package/scss/components/_modal.scss +20 -0
  151. package/scss/components/_nav.scss +9 -0
  152. package/scss/components/_page-header.scss +10 -0
  153. package/scss/components/_popover.scss +10 -0
  154. package/scss/components/_progress.scss +17 -0
  155. package/scss/components/_prose.scss +5 -0
  156. package/scss/components/_scrollbar.scss +32 -0
  157. package/scss/components/_sections.scss +12 -0
  158. package/scss/components/_sidebar.scss +5 -0
  159. package/scss/components/_stat-card.scss +5 -0
  160. package/scss/components/_status-badge.scss +4 -0
  161. package/scss/components/_stepper.scss +5 -0
  162. package/scss/components/_table.scss +19 -0
  163. package/scss/components/_tabs.scss +21 -0
  164. package/scss/components/_timeline.scss +14 -0
  165. package/scss/components/_toast.scss +41 -0
  166. package/scss/components/_toggle.scss +81 -0
  167. package/scss/components/_tooltip.scss +18 -0
  168. package/scss/components/_translations.scss +111 -0
  169. package/scss/components/_upload.scss +51 -0
  170. package/scss/config/_breakpoints.scss +72 -0
  171. package/scss/config/_density.scss +117 -0
  172. package/scss/config/_icons.scss +37 -0
  173. package/scss/config/_mixins.scss +13 -0
  174. package/scss/config/_theme.scss +216 -0
  175. package/scss/config/_tokens.scss +419 -0
  176. package/scss/config/mixins/_accordion.scss +52 -0
  177. package/scss/config/mixins/_ajax.scss +39 -0
  178. package/scss/config/mixins/_alert.scss +82 -0
  179. package/scss/config/mixins/_app-shell.scss +312 -0
  180. package/scss/config/mixins/_avatar.scss +109 -0
  181. package/scss/config/mixins/_borders.scss +36 -0
  182. package/scss/config/mixins/_breadcrumbs.scss +72 -0
  183. package/scss/config/mixins/_breakpoints.scss +62 -0
  184. package/scss/config/mixins/_btn.scss +179 -0
  185. package/scss/config/mixins/_card.scss +338 -0
  186. package/scss/config/mixins/_chip.scss +66 -0
  187. package/scss/config/mixins/_circular-progress.scss +71 -0
  188. package/scss/config/mixins/_collapsible.scss +24 -0
  189. package/scss/config/mixins/_colors.scss +46 -0
  190. package/scss/config/mixins/_confirm.scss +31 -0
  191. package/scss/config/mixins/_data-table.scss +346 -0
  192. package/scss/config/mixins/_display.scss +32 -0
  193. package/scss/config/mixins/_dropdown.scss +143 -0
  194. package/scss/config/mixins/_empty-state.scss +30 -0
  195. package/scss/config/mixins/_focus.scss +55 -0
  196. package/scss/config/mixins/_footer.scss +42 -0
  197. package/scss/config/mixins/_form.scss +601 -0
  198. package/scss/config/mixins/_index.scss +58 -0
  199. package/scss/config/mixins/_interaction.scss +15 -0
  200. package/scss/config/mixins/_kbd.scss +22 -0
  201. package/scss/config/mixins/_layout.scss +117 -0
  202. package/scss/config/mixins/_link.scss +55 -0
  203. package/scss/config/mixins/_ln-table.scss +420 -0
  204. package/scss/config/mixins/_loader.scss +26 -0
  205. package/scss/config/mixins/_modal.scss +66 -0
  206. package/scss/config/mixins/_motion.scss +19 -0
  207. package/scss/config/mixins/_nav.scss +273 -0
  208. package/scss/config/mixins/_page-header.scss +69 -0
  209. package/scss/config/mixins/_popover.scss +25 -0
  210. package/scss/config/mixins/_position.scss +32 -0
  211. package/scss/config/mixins/_progress.scss +56 -0
  212. package/scss/config/mixins/_prose.scss +127 -0
  213. package/scss/config/mixins/_shadows.scss +8 -0
  214. package/scss/config/mixins/_sidebar.scss +95 -0
  215. package/scss/config/mixins/_sizing.scss +6 -0
  216. package/scss/config/mixins/_spacing.scss +19 -0
  217. package/scss/config/mixins/_stat-card.scss +68 -0
  218. package/scss/config/mixins/_status-badge.scss +83 -0
  219. package/scss/config/mixins/_stepper.scss +78 -0
  220. package/scss/config/mixins/_table.scss +215 -0
  221. package/scss/config/mixins/_tabs.scss +64 -0
  222. package/scss/config/mixins/_timeline.scss +69 -0
  223. package/scss/config/mixins/_toast.scss +148 -0
  224. package/scss/config/mixins/_tooltip.scss +111 -0
  225. package/scss/config/mixins/_transitions.scss +10 -0
  226. package/scss/config/mixins/_translations.scss +124 -0
  227. package/scss/config/mixins/_typography.scss +57 -0
  228. package/scss/config/mixins/_upload.scss +168 -0
  229. package/scss/ln-ashlar.scss +62 -0
  230. package/scss/tabler-icons.txt +5039 -0
  231. package/scss/utilities/_animations.scss +83 -0
  232. package/scss/utilities/_utilities.scss +49 -0
@@ -0,0 +1,273 @@
1
+ @use 'spacing' as *;
2
+ @use 'display' as *;
3
+ @use 'sizing' as *;
4
+ @use 'typography' as *;
5
+ @use 'colors' as *;
6
+ @use 'borders' as *;
7
+ @use 'transitions' as *;
8
+ @use 'motion' as *;
9
+ @use 'interaction' as *;
10
+ @use 'position' as *;
11
+
12
+ // ─── Nav ────────────────────────────────────────────────────────────────────
13
+ // Navigation structure reset. Layout (flex-col, h-full) and background come
14
+ // from the parent container.
15
+ //
16
+ // Link appearance is controlled by a style preset mixin. The default is
17
+ // nav-links-rounded. Override by applying a different preset after:
18
+ //
19
+ // nav { @include nav; } ← rounded (default)
20
+ // nav { @include nav; @include nav-links-border-grow; }
21
+ // nav { @include nav; @include nav-links-border-left; }
22
+ // nav { @include nav; @include nav-links-border-top; } ← horizontal navs
23
+
24
+ @mixin nav {
25
+ @include select-none;
26
+
27
+ ul {
28
+ margin-inline: var(--nav-list-bleed, 0);
29
+ }
30
+
31
+ li {
32
+ margin: 0;
33
+ }
34
+
35
+ a {
36
+ --gap: var(--size-sm-up);
37
+ --color-fg: var(--fg-muted);
38
+ @include flex;
39
+ @include items-center;
40
+ gap: var(--gap);
41
+ padding-block: var(--padding-y);
42
+ font-size: var(--text-body-sm);
43
+ line-height: var(--lh-body-sm);
44
+ color: var(--color-fg);
45
+ text-decoration: none;
46
+ // Always-present 1px border slot. Color defaults to transparent
47
+ // (default theme = invisible). Themes that opt in (Glass) rebind
48
+ // --nav-link-border-color* at theme :root. Negative margin
49
+ // compensates so the slot doesn't shift adjacent siblings.
50
+ border: var(--border-width) solid var(--nav-link-border-color, transparent);
51
+ margin: calc(-1 * var(--border-width));
52
+ }
53
+
54
+ .nav-icon {
55
+ @include flex-shrink-0;
56
+ @include size(1.25rem);
57
+ }
58
+
59
+ .nav-label {
60
+ @include flex-1;
61
+ @include truncate;
62
+ }
63
+
64
+ .nav-section {
65
+ --color-fg: var(--fg-subtle);
66
+ --padding-y: var(--size-sm);
67
+ padding-block: var(--padding-y);
68
+ @include text-xs;
69
+ @include font-medium;
70
+ color: var(--color-fg);
71
+ @include normal-case;
72
+ letter-spacing: normal;
73
+ // Structural margin above section header.
74
+ --margin-block: var(--size-md);
75
+ margin-top: var(--margin-block);
76
+ }
77
+
78
+ .nav-divider {
79
+ @include border-t;
80
+ // Structural block margin around divider.
81
+ --margin-block: var(--size-sm);
82
+ margin-block: var(--margin-block);
83
+ }
84
+
85
+ // Default link style — override by applying a nav-links-* mixin after @include nav
86
+ @include nav-links-rounded;
87
+ }
88
+
89
+
90
+ // ─── Nav Link Style Presets ──────────────────────────────────────────────────
91
+
92
+ @mixin _nav-link-active {
93
+ a {
94
+ &:hover {
95
+ color: var(--color-fg);
96
+ border-color: var(--nav-link-border-color-hover, transparent);
97
+ }
98
+
99
+ &.active {
100
+ color: var(--color-accent);
101
+ border-color: var(--nav-link-border-color-active, transparent);
102
+ @include font-semibold;
103
+ }
104
+ }
105
+ }
106
+
107
+
108
+ // ── 1. Rounded floating (default) ────────────────────────────────────────────
109
+
110
+ @mixin nav-links-rounded {
111
+ @include _nav-link-active;
112
+
113
+ li {
114
+ &::before { display: none; }
115
+ }
116
+
117
+ // Structural spacing between floating pills.
118
+ li + li {
119
+ --margin-block: var(--size-2xs);
120
+ margin-top: var(--margin-block);
121
+ }
122
+
123
+ a {
124
+ padding-inline: var(--padding-x);
125
+ border-radius: var(--radius);
126
+ transition:
127
+ background-color 150ms ease,
128
+ color 150ms ease,
129
+ border-color 150ms ease;
130
+
131
+ &:hover {
132
+ background-color: color-mix(in srgb, var(--color-accent) 7%, transparent);
133
+ }
134
+
135
+ &.active {
136
+ // accent wash vocabulary (CLAUDE.md L532) — was reaching
137
+ // through to --color-primary-lighter scale.
138
+ background-color: var(--color-accent-tint);
139
+ }
140
+ }
141
+ }
142
+
143
+
144
+ // ── 2. Left border — instant (inset shadow) ───────────────────────────────────
145
+
146
+ @mixin nav-links-border-left {
147
+ @include _nav-link-active;
148
+
149
+ li {
150
+ &::before { display: none; }
151
+ }
152
+
153
+ a {
154
+ margin-inline: 0;
155
+ --padding-x: var(--size-md);
156
+ padding-inline: var(--padding-x);
157
+ border-radius: 0;
158
+ transition: box-shadow 150ms ease, background-color 150ms ease, color 150ms ease;
159
+
160
+ &:hover {
161
+ box-shadow: inset 2px 0 0 color-mix(in srgb, var(--color-accent) 30%, transparent);
162
+ background-color: color-mix(in srgb, var(--color-accent) 4%, transparent);
163
+ }
164
+
165
+ &.active {
166
+ box-shadow: inset 3px 0 0 var(--color-accent);
167
+ background-color: color-mix(in srgb, var(--color-accent) 7%, transparent);
168
+ }
169
+ }
170
+ }
171
+
172
+
173
+ // ── 3. Growing left bar — animated (spring easing) ──────────────────────────
174
+
175
+ @mixin nav-links-border-grow {
176
+ @include _nav-link-active;
177
+
178
+ li {
179
+ @include relative;
180
+
181
+ &::before {
182
+ content: '';
183
+ @include absolute;
184
+ left: 0;
185
+ top: 0;
186
+ bottom: 0;
187
+ width: 3px;
188
+ background-color: var(--color-accent);
189
+ border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
190
+ transform: scaleY(0);
191
+ transform-origin: center;
192
+ opacity: 0;
193
+ @include motion-safe {
194
+ transition:
195
+ transform 220ms var(--easing-spring),
196
+ opacity 180ms ease;
197
+ }
198
+ }
199
+
200
+ &:has(a:hover)::before {
201
+ opacity: 0.4;
202
+ }
203
+
204
+ &:has(a.active)::before {
205
+ transform: scaleY(1);
206
+ opacity: 1;
207
+ }
208
+ }
209
+
210
+ a {
211
+ margin-inline: 0;
212
+ --padding-x: var(--size-md);
213
+ padding-inline: var(--padding-x);
214
+ border-radius: 0;
215
+ transition: background-color 150ms ease, color 150ms ease;
216
+
217
+ &:hover {
218
+ background-color: color-mix(in srgb, var(--color-accent) 4%, transparent);
219
+ }
220
+
221
+ &.active {
222
+ background-color: color-mix(in srgb, var(--color-accent) 7%, transparent);
223
+ }
224
+ }
225
+ }
226
+
227
+
228
+ // ── 4. Top bar — grow from center (horizontal navs) ──────────────────────────
229
+
230
+ @mixin nav-links-border-top {
231
+ @include _nav-link-active;
232
+
233
+ li {
234
+ @include relative;
235
+
236
+ &::before {
237
+ content: '';
238
+ @include absolute;
239
+ top: 0;
240
+ left: 50%;
241
+ right: 50%;
242
+ height: 2px;
243
+ background-color: var(--color-accent);
244
+ border-radius: 0 0 var(--radius-sm) var(--radius-sm);
245
+ opacity: 0;
246
+ @include motion-safe {
247
+ transition:
248
+ left 200ms ease,
249
+ right 200ms ease,
250
+ opacity 150ms ease;
251
+ }
252
+ }
253
+
254
+ &:has(a:hover)::before {
255
+ left: 20%;
256
+ right: 20%;
257
+ opacity: 0.45;
258
+ }
259
+
260
+ &:has(a.active)::before {
261
+ left: 0;
262
+ right: 0;
263
+ opacity: 1;
264
+ }
265
+ }
266
+
267
+ a {
268
+ margin-inline: 0;
269
+ padding-inline: var(--padding-x);
270
+ border-radius: 0;
271
+ transition: color 150ms ease;
272
+ }
273
+ }
@@ -0,0 +1,69 @@
1
+ @use 'spacing' as *;
2
+ @use 'display' as *;
3
+ @use 'typography' as *;
4
+ @use 'colors' as *;
5
+ @use 'borders' as *;
6
+ @use 'breadcrumbs' as *;
7
+ @use 'breakpoints' as *;
8
+
9
+ @mixin page-header {
10
+ container-type: inline-size;
11
+ container-name: page-header;
12
+ display: grid;
13
+ grid-template-areas:
14
+ 'breadcrumbs'
15
+ 'title'
16
+ 'actions';
17
+ --gap: var(--size-md);
18
+ gap: var(--gap);
19
+ --padding-y: var(--size-lg);
20
+ padding-bottom: var(--padding-y);
21
+ --margin-block: var(--size-lg);
22
+ margin-bottom: var(--margin-block);
23
+ border-block-end: var(--border-block-end, var(--border-width) solid var(--color-border));
24
+
25
+ @include cq-up(medium, page-header) {
26
+ grid-template-areas:
27
+ 'breadcrumbs breadcrumbs'
28
+ 'title actions';
29
+ grid-template-columns: 1fr auto;
30
+ align-items: end;
31
+ }
32
+
33
+ > nav {
34
+ grid-area: breadcrumbs;
35
+ @include breadcrumbs;
36
+ }
37
+
38
+ > div:has(> h1) {
39
+ grid-area: title;
40
+
41
+ h1 {
42
+ @include typography(display-sm);
43
+ // Override the global h1 `mb(1rem)` from scss/base/_typography.scss —
44
+ // the page-header grid supplies vertical rhythm via `gap`, so a
45
+ // trailing margin on the title would stack on top of the gap.
46
+ margin: 0;
47
+ }
48
+
49
+ p {
50
+ --color-fg: var(--fg-muted);
51
+ @include typography(body-md);
52
+ color: var(--color-fg);
53
+ --margin-block: var(--size-xs);
54
+ margin: var(--margin-block) 0 0;
55
+ }
56
+ }
57
+
58
+ > div:has(> button),
59
+ > div:has(> a) {
60
+ grid-area: actions;
61
+ @include flex-row;
62
+ --gap: var(--size-sm);
63
+ gap: var(--gap);
64
+
65
+ @include cq-down(medium, page-header) {
66
+ justify-content: flex-start;
67
+ }
68
+ }
69
+ }
@@ -0,0 +1,25 @@
1
+ @use 'spacing' as *;
2
+ @use 'borders' as *;
3
+ @use 'motion' as *;
4
+ @use 'card' as *;
5
+
6
+ @mixin popover {
7
+ @include floating-panel;
8
+ display: none;
9
+ position: fixed;
10
+ min-width: 14rem;
11
+ max-width: 24rem;
12
+ padding: var(--padding-y) var(--padding-x);
13
+
14
+ &[data-ln-popover="open"] {
15
+ display: block;
16
+
17
+ @include motion-safe {
18
+ animation: ln-popover-fade var(--transition-fast);
19
+ }
20
+ }
21
+
22
+ &:focus {
23
+ outline: none;
24
+ }
25
+ }
@@ -0,0 +1,32 @@
1
+ // Position & Overflow
2
+
3
+ @mixin relative { position: relative; }
4
+ @mixin absolute { position: absolute; }
5
+ @mixin fixed { position: fixed; }
6
+ @mixin sticky { position: sticky; }
7
+
8
+ @mixin inset-0 { top: 0; right: 0; bottom: 0; left: 0; }
9
+
10
+ @mixin overflow-hidden { overflow: hidden; }
11
+ @mixin overflow-auto { overflow: auto; }
12
+ @mixin overflow-x-auto { overflow-x: auto; -webkit-overflow-scrolling: touch; }
13
+
14
+ // Sticky pin to the top of the nearest scroll container.
15
+ //
16
+ // Default $top: 0 — most common case (pin flush at scroll port top).
17
+ // Pass a positive value to offset (e.g. when stacking sticky elements,
18
+ // or when a sibling above this one is also pinned).
19
+ //
20
+ // Example:
21
+ // thead { @include sticky-top; } // top: 0
22
+ // .sidebar-card { @include sticky-top(var(--app-header-height)); }
23
+ // .below-toolbar { @include sticky-top(2rem); }
24
+ //
25
+ // Z-index is fixed at var(--z-sticky) by design — sticky elements
26
+ // across the system share the same z-layer.
27
+
28
+ @mixin sticky-top($top: 0) {
29
+ position: sticky;
30
+ top: $top;
31
+ z-index: var(--z-sticky);
32
+ }
@@ -0,0 +1,56 @@
1
+ @use 'display' as *;
2
+ @use 'sizing' as *;
3
+ @use 'borders' as *;
4
+ @use 'colors' as *;
5
+ @use 'motion' as *;
6
+
7
+ // Progress bar — horizontal track with animated fill segments.
8
+ //
9
+ // Usage:
10
+ // .progress { @include progress; }
11
+ //
12
+ // HTML:
13
+ // <div class="progress">
14
+ // <div data-ln-progress="60" class="success"></div>
15
+ // <div data-ln-progress="20" class="error"></div>
16
+ // </div>
17
+ //
18
+ // Color variants: .success, .warning, .error override background-color
19
+ // on the inner bar(s).
20
+
21
+ @mixin progress {
22
+ height: var(--size-xs); // Intrinsic component dimension — track thickness.
23
+ @include w-full;
24
+ @include rounded-full;
25
+ --color-bg: var(--bg-recessed);
26
+ background-color: var(--color-bg);
27
+ overflow: hidden;
28
+ @include flex;
29
+
30
+ // Inner bar segments
31
+ > [data-ln-progress] {
32
+ width: 0;
33
+ @include motion-safe {
34
+ transition: width var(--transition-base);
35
+ }
36
+ border-radius: 0;
37
+
38
+ &:last-child {
39
+ border-top-right-radius: var(--radius-full);
40
+ border-bottom-right-radius: var(--radius-full);
41
+ }
42
+ }
43
+ }
44
+
45
+ // ─── Color variants ────────────────────────────────────
46
+ @mixin progress-success {
47
+ background-color: hsl(var(--color-success));
48
+ }
49
+
50
+ @mixin progress-error {
51
+ background-color: hsl(var(--color-error));
52
+ }
53
+
54
+ @mixin progress-warning {
55
+ background-color: hsl(var(--color-warning));
56
+ }
@@ -0,0 +1,127 @@
1
+ @use 'spacing' as *;
2
+ @use 'typography' as *;
3
+ @use 'colors' as *;
4
+ @use 'borders' as *;
5
+
6
+ @mixin prose {
7
+ max-width: var(--max-w-prose);
8
+ color: var(--color-fg);
9
+
10
+ > * + * {
11
+ margin-top: 1em;
12
+ }
13
+
14
+ h1 { @include typography(heading-lg); margin-top: 2em; margin-bottom: 0.5em; }
15
+ h2 { @include typography(heading-md); margin-top: 1.5em; margin-bottom: 0.5em; }
16
+ h3 { @include typography(heading-sm); margin-top: 1.25em; margin-bottom: 0.5em; }
17
+ h4 { @include typography(title-md); margin-top: 1em; margin-bottom: 0.5em; }
18
+
19
+ p { @include typography(body-md); }
20
+
21
+ a {
22
+ color: var(--color-accent);
23
+ text-decoration: underline;
24
+ text-decoration-thickness: 1px;
25
+ text-underline-offset: 2px;
26
+
27
+ &:hover {
28
+ text-decoration-thickness: 2px;
29
+ }
30
+ }
31
+
32
+ strong { font-weight: var(--font-semibold); }
33
+ em { font-style: italic; }
34
+
35
+ ul, ol {
36
+ padding-left: 1.5em;
37
+
38
+ li {
39
+ margin-top: 0.5em;
40
+ }
41
+ }
42
+
43
+ ul { list-style: disc; }
44
+ ol { list-style: decimal; }
45
+
46
+ blockquote {
47
+ border-left: 3px solid var(--color-accent);
48
+ --padding-x: var(--size-md);
49
+ padding-left: var(--padding-x);
50
+ --color-fg: var(--fg-muted);
51
+ color: var(--color-fg);
52
+ font-style: italic;
53
+ }
54
+
55
+ code {
56
+ --color-bg: var(--bg-sunken);
57
+ background: var(--color-bg);
58
+ --padding-x: var(--size-xs-up);
59
+ padding-inline: var(--padding-x);
60
+ --padding-y: var(--size-2xs);
61
+ padding-block: var(--padding-y);
62
+ @include rounded-sm;
63
+ font-family: var(--font-mono);
64
+ @include typography(body-sm);
65
+ color: var(--color-accent);
66
+ }
67
+
68
+ pre {
69
+ --color-bg: var(--bg-sunken);
70
+ background: var(--color-bg);
71
+ --padding-y: var(--size-md);
72
+ --padding-x: var(--size-md);
73
+ padding: var(--padding-y) var(--padding-x);
74
+ @include rounded-md;
75
+ overflow-x: auto;
76
+
77
+ code {
78
+ background: none;
79
+ padding: 0;
80
+ color: inherit;
81
+ }
82
+ }
83
+
84
+ img {
85
+ max-width: 100%;
86
+ height: auto;
87
+ @include rounded-md;
88
+ }
89
+
90
+ figure {
91
+ margin: 1.5em 0;
92
+
93
+ figcaption {
94
+ @include typography(caption);
95
+ --color-fg: var(--fg-subtle);
96
+ color: var(--color-fg);
97
+ text-align: center;
98
+ margin-top: 0.5em;
99
+ }
100
+ }
101
+
102
+ table {
103
+ width: 100%;
104
+ border-collapse: collapse;
105
+ margin-top: 1.5em;
106
+
107
+ th, td {
108
+ --padding-y: var(--size-sm);
109
+ --padding-x: var(--size-sm-up);
110
+ padding: var(--padding-y) var(--padding-x);
111
+ border-bottom: 1px solid var(--color-border);
112
+ text-align: left;
113
+ }
114
+
115
+ th {
116
+ @include typography(label-md);
117
+ color: var(--color-fg);
118
+ font-weight: var(--font-semibold);
119
+ }
120
+ }
121
+
122
+ hr {
123
+ border: none;
124
+ border-top: 1px solid var(--color-border);
125
+ margin: 2em 0;
126
+ }
127
+ }
@@ -0,0 +1,8 @@
1
+ // Shadows — references --shadow-* tokens
2
+
3
+ @mixin shadow-none { box-shadow: var(--shadow-none); }
4
+ @mixin shadow-xs { box-shadow: var(--shadow-xs); }
5
+ @mixin shadow-sm { box-shadow: var(--shadow-sm); }
6
+ @mixin shadow-md { box-shadow: var(--shadow-md); }
7
+ @mixin shadow-lg { box-shadow: var(--shadow-lg); }
8
+ @mixin shadow-xl { box-shadow: var(--shadow-xl); }
@@ -0,0 +1,95 @@
1
+ @use 'spacing' as *;
2
+ @use 'display' as *;
3
+ @use 'sizing' as *;
4
+ @use 'typography' as *;
5
+ @use 'colors' as *;
6
+ @use 'borders' as *;
7
+ @use 'position' as *;
8
+ @use 'footer' as *;
9
+
10
+ // ─── Sidebar ───────────────────────────────────────────────────────
11
+ // Structural shell for a sidebar layout. Provides flex column, right
12
+ // border, background, and consistent horizontal padding via
13
+ // --padding-x. Projects add width, position, animation.
14
+ //
15
+ // Expected HTML:
16
+ // <aside>
17
+ // <header>...</header>
18
+ // <main>...</main>
19
+ // <footer>...</footer>
20
+ // </aside>
21
+ //
22
+ // Usage:
23
+ // #my-sidebar { @include sidebar; width: 16rem; @include fixed; }
24
+ //
25
+ // Project override — same-rhythm adjustment:
26
+ // #my-sidebar { @include sidebar; --padding-x: var(--size-lg); }
27
+
28
+ @mixin sidebar {
29
+ // Sidebar-wide horizontal rhythm. All direct children inherit this.
30
+ --padding-x: var(--size-md);
31
+ @include flex-col;
32
+ background: var(--color-bg);
33
+ @include border-r;
34
+ overflow: hidden;
35
+
36
+ > * {
37
+ padding-inline: var(--padding-x);
38
+ }
39
+
40
+ > header {
41
+ --gap: var(--size-sm-up);
42
+ @include relative;
43
+ @include flex;
44
+ @include items-center;
45
+ @include flex-wrap;
46
+ gap: var(--gap);
47
+ --padding-y: var(--size-sm-up);
48
+ padding-block: var(--padding-y);
49
+ @include border-b;
50
+ @include shadow-b;
51
+
52
+ // Brand row: logo + name, with optional drawer close button
53
+ // absolutely positioned top-right. Library owns the
54
+ // data-ln-toggle-action and data-ln-search attributes.
55
+ > img {
56
+ @include flex-shrink-0;
57
+ @include size(2rem);
58
+ }
59
+
60
+ > .app-name {
61
+ @include text-lg;
62
+ @include font-bold;
63
+ @include text-primary;
64
+ @include truncate;
65
+ }
66
+
67
+ > [data-ln-toggle-action="close"] {
68
+ --padding-y: var(--size-2xs);
69
+ --padding-x: var(--size-2xs);
70
+ @include absolute;
71
+ // Geometric — close button positioned inside header padding.
72
+ top: var(--size-sm);
73
+ right: var(--size-sm);
74
+ }
75
+
76
+ // Search field drops to a full-width second row below the
77
+ // brand triad (enabled by `flex-wrap` above).
78
+ > [data-ln-search] {
79
+ @include w-full;
80
+ --margin-block: var(--size-xs);
81
+ @include mt(var(--margin-block));
82
+ }
83
+ }
84
+
85
+ > main {
86
+ @include flex-1;
87
+ overflow-y: auto;
88
+ --padding-y: var(--size-xs);
89
+ padding-block: var(--padding-y);
90
+ }
91
+
92
+ > footer {
93
+ @include app-footer;
94
+ }
95
+ }
@@ -0,0 +1,6 @@
1
+ // Width & Height
2
+
3
+ @mixin w-full { width: 100%; }
4
+ @mixin h-full { height: 100%; }
5
+ @mixin min-h-screen { min-height: 100vh; }
6
+ @mixin size($val) { width: $val; height: $val; }