@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,81 @@
1
+ @use '../config/mixins' as *;
2
+
3
+ // ==========================================================================
4
+ // Toggle — collapse/expand CSS
5
+ // ==========================================================================
6
+ // data-ln-toggle = JS (adds .open class)
7
+ // .collapsible = CSS (grid collapse animation)
8
+ //
9
+ // The parent (.collapsible) NEVER has padding — it collapses to 0.
10
+ // Padding/margins go on the child element (.collapsible-body).
11
+ //
12
+ // HTML structure:
13
+ // <main data-ln-toggle class="collapsible">
14
+ // <section class="collapsible-body">
15
+ // <p>...</p> ← content with padding, margins etc.
16
+ // </section>
17
+ // </main>
18
+ //
19
+ // Or via @include in project SCSS:
20
+ // .my-panel { @include collapsible; }
21
+ // .my-panel > .inner { @include collapsible-content; }
22
+ // ==========================================================================
23
+
24
+ // .collapsible parent is always a zero-padding grid container — that
25
+ // contract comes from @include collapsible. The child (.collapsible-body
26
+ // or anything else @include collapsible-content lands on) owns padding
27
+ // and margins. Do NOT re-bind `.collapsible` on a selector that forces a
28
+ // different display or non-zero padding — it will break the
29
+ // grid-template-rows animation.
30
+ .collapsible {
31
+ @include collapsible;
32
+
33
+ > * {
34
+ @include collapsible-content;
35
+ }
36
+ }
37
+
38
+ // ──────────────────────────────────────────────────────────────────────
39
+ // Chevron — generic toggle behavior
40
+ // ──────────────────────────────────────────────────────────────────────
41
+ // .ln-chevron is the icon-class convention for "this is a chevron-style
42
+ // indicator inside a toggle trigger". The rotation is driven by
43
+ // aria-expanded (set by ln-toggle.js on every [data-ln-toggle-for]
44
+ // when its target panel opens/closes). Works for accordion items and
45
+ // standalone toggles alike — no DOM-proximity dependency.
46
+
47
+ [data-ln-toggle-for] .ln-chevron {
48
+ @include flex-shrink-0;
49
+ @include motion-safe {
50
+ transition: transform var(--transition);
51
+ }
52
+ }
53
+
54
+ [data-ln-toggle-for][aria-expanded="true"] .ln-chevron {
55
+ transform: rotate(180deg);
56
+ }
57
+
58
+ // ──────────────────────────────────────────────────────────────────────
59
+ // Icon-only trigger button — strip default button chrome
60
+ // ──────────────────────────────────────────────────────────────────────
61
+ // When the trigger is <button data-ln-toggle-for> with a single .ln-icon
62
+ // child, it should read as a subtle affordance, not a chunky action
63
+ // button. Hover gets a soft bg lift to confirm clickability.
64
+ //
65
+ // Text triggers (<button data-ln-toggle-for>Options</button>) and
66
+ // triggers with class="btn" keep full button chrome — the
67
+ // :has(> .ln-icon:only-child) predicate excludes them.
68
+ // <header data-ln-toggle-for> in accordion is unaffected — element
69
+ // match is `button` only.
70
+ //
71
+ // Per CLAUDE.md "Variant rebinds the surface, doesn't redeclare":
72
+ // this rebinds --btn-* tokens; the @mixin button-base body still
73
+ // owns background/border-color declarations and hover/active blocks.
74
+
75
+ button[data-ln-toggle-for]:has(> .ln-icon:only-child) {
76
+ --btn-bg: transparent;
77
+ --btn-border: transparent;
78
+ --btn-bg-hover: var(--bg-sunken);
79
+ --btn-border-hover: transparent;
80
+ --btn-fg-hover: var(--color-fg);
81
+ }
@@ -0,0 +1,18 @@
1
+ @use '../config/mixins' as *;
2
+
3
+ [data-ln-tooltip] {
4
+ @include tooltip;
5
+ }
6
+
7
+ #ln-tooltip-portal {
8
+ @include tooltip-portal;
9
+ }
10
+
11
+ .ln-tooltip {
12
+ @include tooltip-element;
13
+ }
14
+
15
+ @keyframes ln-tooltip-fade {
16
+ from { opacity: 0; transform: translateY(2px); }
17
+ to { opacity: 1; transform: translateY(0); }
18
+ }
@@ -0,0 +1,111 @@
1
+ @use '../config/mixins' as *;
2
+
3
+ [data-ln-translatable-lang] {
4
+ @include translations-flag-input;
5
+ }
6
+
7
+ [data-ln-toggle] button[data-ln-translations-lang] {
8
+ @include translations-dropdown-flag;
9
+ }
10
+
11
+ // ─── Flag icons per language ─────────────────────────────────────
12
+ // Lang code (ISO 639-1) -> country flag (ISO 3166-1 alpha-2).
13
+
14
+ $lang-flag-overrides: (
15
+ en: 'gb',
16
+ sq: 'al',
17
+ sr: 'rs',
18
+ ja: 'jp',
19
+ ko: 'kr',
20
+ zh: 'cn',
21
+ cs: 'cz',
22
+ da: 'dk',
23
+ el: 'gr',
24
+ he: 'il',
25
+ hi: 'in',
26
+ uk: 'ua',
27
+ vi: 'vn',
28
+ sv: 'se',
29
+ nb: 'no',
30
+ nn: 'no',
31
+ ca: 'es',
32
+ eu: 'es',
33
+ gl: 'es',
34
+ fa: 'ir',
35
+ ar: 'sa',
36
+ ms: 'my',
37
+ sl: 'si',
38
+ et: 'ee',
39
+ ka: 'ge',
40
+ hy: 'am',
41
+ be: 'by',
42
+ bs: 'ba',
43
+ hr: 'hr',
44
+ ga: 'ie',
45
+ cy: 'gb',
46
+ sw: 'ke',
47
+ bn: 'bd',
48
+ ur: 'pk',
49
+ ta: 'lk',
50
+ te: 'in',
51
+ ml: 'in',
52
+ kn: 'in',
53
+ mr: 'in',
54
+ gu: 'in',
55
+ pa: 'in',
56
+ ne: 'np',
57
+ km: 'kh',
58
+ lo: 'la',
59
+ my: 'mm',
60
+ af: 'za',
61
+ zu: 'za',
62
+ );
63
+
64
+ $lang-auto: mk, de, fr, it, bg, pt, ro, nl, pl, fi, hu, lt, lv, tr, az, is, mt, lb, no, ru, th, id;
65
+
66
+ @each $lang, $country in $lang-flag-overrides {
67
+ [data-ln-translatable-lang="#{$lang}"],
68
+ [data-ln-translations-active] [data-ln-translations-lang="#{$lang}"],
69
+ [data-ln-toggle] button[data-ln-translations-lang="#{$lang}"]::before {
70
+ background-image: url('/assets/flags/#{$country}.svg');
71
+ }
72
+ }
73
+
74
+ @each $lang in $lang-auto {
75
+ [data-ln-translatable-lang="#{$lang}"],
76
+ [data-ln-translations-active] [data-ln-translations-lang="#{$lang}"],
77
+ [data-ln-toggle] button[data-ln-translations-lang="#{$lang}"]::before {
78
+ background-image: url('/assets/flags/#{$lang}.svg');
79
+ }
80
+ }
81
+
82
+ // ─── Header actions ──────────────────────────────────────────────
83
+
84
+ .ln-translations__actions {
85
+ @include translations-actions;
86
+ }
87
+
88
+ [data-ln-translations-active] {
89
+ @include translations-active-list;
90
+ }
91
+
92
+ [data-ln-translations-active] p {
93
+ @include translations-badge;
94
+ }
95
+
96
+ [data-ln-translations-active] button {
97
+ @include translations-badge-remove;
98
+ }
99
+
100
+ [data-ln-translations-add] {
101
+ @include translations-add-button;
102
+ }
103
+
104
+ // ─── Reduced motion ─────────────────────────────────────────────
105
+
106
+ @media (prefers-reduced-motion: reduce) {
107
+ [data-ln-translations-add],
108
+ [data-ln-translations-active] button {
109
+ transition: none;
110
+ }
111
+ }
@@ -0,0 +1,51 @@
1
+ @use '../config/mixins' as *;
2
+
3
+ .ln-upload {
4
+ @include upload;
5
+ }
6
+
7
+ .ln-upload__zone {
8
+ @include upload-zone;
9
+ }
10
+
11
+ .ln-upload__zone--dragover {
12
+ @include upload-zone-dragover;
13
+ }
14
+
15
+ .ln-upload__list {
16
+ @include upload-list;
17
+ }
18
+
19
+ .ln-upload__item {
20
+ @include upload-item;
21
+ }
22
+
23
+ .ln-upload__name {
24
+ @include upload-name;
25
+ }
26
+
27
+ .ln-upload__size {
28
+ @include upload-size;
29
+ }
30
+
31
+ .ln-upload__progress {
32
+ @include upload-progress;
33
+ }
34
+
35
+ .ln-upload__progress-bar {
36
+ @include upload-progress-bar;
37
+ }
38
+
39
+ .ln-upload__item--error {
40
+ @include upload-item-error;
41
+ }
42
+
43
+ .ln-upload__item--deleting::before {
44
+ @include upload-item-deleting-spinner;
45
+ }
46
+
47
+ @keyframes ln-upload-spin {
48
+ to {
49
+ transform: rotate(360deg);
50
+ }
51
+ }
@@ -0,0 +1,72 @@
1
+ @use 'sass:map';
2
+
3
+ // ==========================================================================
4
+ // Breakpoints — ln-ashlar
5
+ // ==========================================================================
6
+ // App-shell media breakpoints:
7
+ // @use 'config/breakpoints' as *;
8
+ // @media (min-width: $bp-md) { ... }
9
+ //
10
+ // Container-query breakpoints:
11
+ // @use 'config/breakpoints' as *;
12
+ // @container foldersgrid (min-width: $cq-medium) { ... }
13
+ //
14
+ // CSS custom properties are also exposed at :root so JS can read via
15
+ // getComputedStyle(document.documentElement).getPropertyValue('--bp-md').
16
+ //
17
+ // See docs/css/breakpoints.md for full usage guide.
18
+ // See docs/ln-ashlar-container-queries.md for container-query doctrine.
19
+ // ==========================================================================
20
+
21
+ // -----------------------------------------------------------------------
22
+ // App-shell media breakpoints (for @media — layout columns only)
23
+ // -----------------------------------------------------------------------
24
+ $bp-sm: 480px;
25
+ $bp-md: 768px;
26
+ $bp-lg: 1024px;
27
+ $bp-xl: 1280px;
28
+ $bp-2xl: 1536px;
29
+ $bp-3xl: 1920px;
30
+
31
+ // -----------------------------------------------------------------------
32
+ // Container-query breakpoints (for @container — components)
33
+ // -----------------------------------------------------------------------
34
+ $cq-narrow: 480px;
35
+ $cq-compact: 580px;
36
+ $cq-medium: 880px;
37
+ $cq-wide: 1120px;
38
+
39
+ // -----------------------------------------------------------------------
40
+ // CSS custom properties — JS readable via getComputedStyle
41
+ // -----------------------------------------------------------------------
42
+ :root {
43
+ --bp-sm: #{$bp-sm};
44
+ --bp-md: #{$bp-md};
45
+ --bp-lg: #{$bp-lg};
46
+ --bp-xl: #{$bp-xl};
47
+ --bp-2xl: #{$bp-2xl};
48
+ --bp-3xl: #{$bp-3xl};
49
+
50
+ --cq-narrow: #{$cq-narrow};
51
+ --cq-compact: #{$cq-compact};
52
+ --cq-medium: #{$cq-medium};
53
+ --cq-wide: #{$cq-wide};
54
+ }
55
+
56
+ // -----------------------------------------------------------------------
57
+ // Unified breakpoint map — resolved by mq-*/cq-* mixins.
58
+ // Keeps both scales looking up the same way; call-site mixin choice
59
+ // (mq vs cq) decides media vs container emission.
60
+ // -----------------------------------------------------------------------
61
+ $breakpoints: (
62
+ sm: $bp-sm,
63
+ md: $bp-md,
64
+ lg: $bp-lg,
65
+ xl: $bp-xl,
66
+ 2xl: $bp-2xl,
67
+ 3xl: $bp-3xl,
68
+ narrow: $cq-narrow,
69
+ compact: $cq-compact,
70
+ medium: $cq-medium,
71
+ wide: $cq-wide,
72
+ );
@@ -0,0 +1,117 @@
1
+ // ==========================================================================
2
+ // Density — ln-ashlar v1.2
3
+ // ==========================================================================
4
+ // Global spacing compression toggle. Flip one class, the entire UI
5
+ // tightens. Tables show more rows, forms pack denser, cards shrink
6
+ // padding, headings scale down. Same components, same markup, same
7
+ // selectors — the `.density-compact` class re-tunes base design tokens
8
+ // (spacing, typography) and every consumer reacts via the cascade.
9
+ //
10
+ // This file contains NO parallel `--density-*` token scale. Density
11
+ // is an override of base tokens at a region root, exactly like theme
12
+ // colors. Read `docs/css/density.md` for the full spec and rationale.
13
+ //
14
+ // Activation:
15
+ // <html class="density-compact"> ← global
16
+ // <main class="density-compact"> ← scoped to a region
17
+ //
18
+ // Density is an explicit user choice (consumer's settings toggle).
19
+ // It is NEVER auto-switched by viewport — viewport breakpoints handle
20
+ // layout, density handles information density inside that layout.
21
+ //
22
+ // What reacts: everything that reads `--size-*`, `--text-body-*`,
23
+ // `--text-label-*`, `--text-title-*`, `--text-heading-*`,
24
+ // `--text-display-sm`, or `--density-row-h`. That is the majority of
25
+ // the library (tables, forms, cards, stat-card, nav, breadcrumbs,
26
+ // alerts, banners, tabs, prose, headings, page content).
27
+ //
28
+ // What does NOT react: buttons and pill-controls — their padding and
29
+ // font are hardcoded rem/raw-scale values in `_btn.scss`, `_form.scss`
30
+ // (pill), and `_global.scss` (native <button>). This is deliberate —
31
+ // WCAG 2.5.5 hit-target size floor (~44px) must not be shrunk by a
32
+ // visual density toggle.
33
+ // ==========================================================================
34
+
35
+ :root {
36
+
37
+ // -----------------------------------------------------------------------
38
+ // Density — Row height
39
+ // Minimum row height for table rows. Padding alone determines visual
40
+ // height in comfortable mode; compact uses this as a min-height floor
41
+ // so rows stay scannable when content is short. Kept density-named
42
+ // because it has no analogue in the base token scale.
43
+ // -----------------------------------------------------------------------
44
+ --density-row-h: 2.75rem; // 44px — comfortable input/row min
45
+ }
46
+
47
+ // ---------------------------------------------------------------------------
48
+ // Compact override
49
+ // Activated by the `.density-compact` class. Re-tunes base spacing and
50
+ // typography tokens to tighter values. The cascade does the rest — every
51
+ // component referencing these tokens shrinks automatically.
52
+ //
53
+ // Anti-pattern this avoids: writing
54
+ // .density-compact table td { padding: ...; }
55
+ // for every component. That explodes specificity and duplicates
56
+ // rules. The token-override route keeps the compact surface to one
57
+ // place — this block.
58
+ // ---------------------------------------------------------------------------
59
+ .density-compact {
60
+
61
+ // -- Spacing — structural compression ---------------------------------
62
+ --padding-y: var(--size-xs-up); // 4px (compact) — was 12px (normal)
63
+ --size-xs: 0.125rem; // 2px
64
+ --size-xs-up: 0.25rem; // 4px
65
+ --size-sm: 0.375rem; // 6px
66
+ --size-sm-up: 0.5rem; // 8px
67
+ --size-md: 0.625rem; // 10px
68
+ --size-md-up: 0.8125rem; // 13px
69
+ --size-lg: 1rem; // 16px
70
+
71
+ // -- Body text --------------------------------------------------------
72
+ --text-body-md: 0.875rem;
73
+ --lh-body-md: 1.5;
74
+
75
+ --text-body-sm: 0.8125rem;
76
+ --lh-body-sm: 1.45;
77
+
78
+ // Explicit rebind — `--font-size` is defined at `:root` as
79
+ // `var(--text-body-md)`. Lazy resolution SHOULD cascade, but
80
+ // form inputs (font-size: var(--font-size)) don't shrink in
81
+ // practice. Explicit rebind here forces the compact value to
82
+ // reach every consumer of --font-size.
83
+ --font-size: var(--text-body-md);
84
+ --line-height: var(--lh-body-md);
85
+
86
+ // -- Labels -----------------------------------------------------------
87
+ --text-label-md: 0.8125rem;
88
+ --lh-label-md: 1.4;
89
+
90
+ --text-label-sm: 0.6875rem;
91
+ --lh-label-sm: 1.4;
92
+
93
+ // -- Titles -----------------------------------------------------------
94
+ --text-title-md: 1rem;
95
+ --lh-title-md: 1.3;
96
+
97
+ --text-title-sm: 0.875rem;
98
+ --lh-title-sm: 1.3;
99
+
100
+ // -- Headings — user opted in; see docs/css/density.md §stat-card ----
101
+ // heading-lg is the stat-card value. Intentionally a GENTLE reduction
102
+ // (1.875rem → 1.75rem, only 0.125rem) so the "big number" stays
103
+ // visually dominant — 2x body text, 0.5rem above heading-md.
104
+ // See plan D1 for the hierarchy math and rejected alternatives.
105
+ --text-heading-sm: 1.125rem; --lh-heading-sm: 1.25;
106
+ --text-heading-md: 1.25rem; --lh-heading-md: 1.2;
107
+ --text-heading-lg: 1.75rem; --lh-heading-lg: 1.15;
108
+
109
+ // -- Display ---------------------------------------------------------
110
+ // Only display-sm shrinks — that's what page h1 uses. lg/md kept
111
+ // at their comfortable values because they're marketing-page scale
112
+ // that shouldn't appear in dense data contexts anyway.
113
+ --text-display-sm: 1.875rem; --lh-display-sm: 1.1;
114
+
115
+ // -- Row height — density-specific (no base-token analogue) ---------
116
+ --density-row-h: 2.25rem;
117
+ }
@@ -0,0 +1,37 @@
1
+ // ==========================================================================
2
+ // Icons — SVG sprite system
3
+ // ==========================================================================
4
+ // Icons are rendered via an SVG sprite injected by ln-icons.js.
5
+ // Color is inherited from the parent's `color` property (currentColor).
6
+ //
7
+ // Usage:
8
+ // <svg class="ln-icon" aria-hidden="true"><use href="#ln-home"></use></svg>
9
+ // <svg class="ln-icon ln-icon--sm" aria-hidden="true"><use href="#ln-close"></use></svg>
10
+ //
11
+ // Available IDs: #ln-{name} where name = filename in js/ln-icons/icons/
12
+ // home, close, menu, users, settings, logout, books, lodges
13
+ // plus, edit, delete, view, save, search, check, copy, link
14
+ // upload, download, refresh, print, lock, star, filter, calendar
15
+ // arrow-up, arrow-down, chart, clock, envelope, book, globe, list
16
+ // box, building, badge, warning, info-circle, check-circle, error-circle
17
+ // sort-both, user, mail, phone, square-compass
18
+ // file, file-pdf, file-doc, file-epub ← these have embedded stroke colors
19
+ //
20
+ // Change color via CSS:
21
+ // .sidebar a { color: hsl(var(--color-primary)); } /* icon follows */
22
+ // button { color: hsl(var(--color-error)); } /* icon follows */
23
+ // ==========================================================================
24
+
25
+ svg.ln-icon {
26
+ display: inline-block;
27
+ width: 1.25rem;
28
+ height: 1.25rem;
29
+ flex-shrink: 0;
30
+ vertical-align: middle;
31
+ // fill/stroke are set per icon via the SVG source
32
+ // currentColor is applied directly in each <symbol>
33
+ }
34
+
35
+ svg.ln-icon.ln-icon--sm { width: 1rem; height: 1rem; }
36
+ svg.ln-icon.ln-icon--lg { width: 1.5rem; height: 1.5rem; }
37
+ svg.ln-icon.ln-icon--xl { width: 4rem; height: 4rem; }
@@ -0,0 +1,13 @@
1
+ // ==========================================================================
2
+ // Mixins — ln-ashlar
3
+ // ==========================================================================
4
+ // Tailwind-like utility mixins. Instead of utility classes in HTML,
5
+ // @include them in SCSS components.
6
+ //
7
+ // ALL mixins reference CSS variables from _tokens.scss.
8
+ // Nothing is hardcoded — change the token, change it everywhere.
9
+ //
10
+ // See mixins/_index.scss for the full list of @forward entries.
11
+ // ==========================================================================
12
+
13
+ @forward 'mixins/index';