@livenetworks/ashlar 1.5.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/README.md +189 -177
  2. package/js/COMPONENTS.md +55 -49
  3. package/js/index.js +22 -5
  4. package/js/ln-accordion/README.md +186 -137
  5. package/js/ln-accordion/ln-accordion.js +1 -1
  6. package/js/ln-ajax/README.md +73 -4
  7. package/js/ln-ajax/ln-ajax.js +1 -1
  8. package/js/ln-ajax/src/ln-ajax.js +13 -13
  9. package/js/ln-api-connector/README.md +261 -150
  10. package/js/ln-api-connector/ln-api-connector.js +1 -1
  11. package/js/ln-api-connector/src/ln-api-connector.js +368 -265
  12. package/js/ln-api-queue/README.md +219 -0
  13. package/js/ln-api-queue/ln-api-queue.js +1 -0
  14. package/js/ln-api-queue/src/ln-api-queue.js +320 -0
  15. package/js/ln-api-queue/src/queue-storage.js +455 -0
  16. package/js/ln-autoresize/README.md +47 -0
  17. package/js/ln-autoresize/ln-autoresize.js +1 -1
  18. package/js/ln-autosave/README.md +33 -1
  19. package/js/ln-autosave/ln-autosave.js +1 -1
  20. package/js/ln-autosave/src/ln-autosave.js +4 -4
  21. package/js/ln-circular-progress/README.md +27 -13
  22. package/js/ln-circular-progress/ln-circular-progress.js +1 -1
  23. package/js/ln-circular-progress/src/ln-circular-progress.js +18 -5
  24. package/js/ln-confirm/README.md +162 -86
  25. package/js/ln-confirm/_ln-confirm.scss +11 -0
  26. package/js/ln-confirm/ln-confirm.js +1 -1
  27. package/js/ln-confirm/src/ln-confirm.js +77 -41
  28. package/js/ln-core/README.md +896 -0
  29. package/js/ln-core/hash.js +92 -0
  30. package/js/ln-core/helpers.js +337 -8
  31. package/js/ln-core/index.js +4 -2
  32. package/js/ln-core/persist.js +29 -3
  33. package/js/ln-core/positioning.js +1 -35
  34. package/js/ln-core/window-cache.js +213 -0
  35. package/js/ln-couchdb-connector/README.md +177 -156
  36. package/js/ln-couchdb-connector/ln-couchdb-connector.js +1 -1
  37. package/js/ln-couchdb-connector/src/ln-couchdb-connector.js +398 -348
  38. package/js/ln-data-coordinator/README.md +536 -165
  39. package/js/ln-data-coordinator/ln-data-coordinator.js +1 -1
  40. package/js/ln-data-coordinator/src/data-read-policy.js +18 -0
  41. package/js/ln-data-coordinator/src/ln-data-coordinator.js +1042 -249
  42. package/js/ln-data-coordinator/src/mutation-receipts.js +46 -0
  43. package/js/ln-data-store/README.md +241 -94
  44. package/js/ln-data-store/ln-data-store.js +1 -1
  45. package/js/ln-data-store/src/ln-data-store.js +694 -699
  46. package/js/ln-date/README.md +39 -1
  47. package/js/ln-date/ln-date-dev.scss +14 -0
  48. package/js/ln-date/ln-date.js +1 -1
  49. package/js/ln-date/src/ln-date.js +236 -178
  50. package/js/ln-debug/README.md +58 -0
  51. package/js/ln-debug/ln-debug.js +1 -0
  52. package/js/ln-debug/src/ln-debug.js +19 -0
  53. package/js/ln-dropdown/README.md +31 -8
  54. package/js/ln-dropdown/ln-dropdown.js +1 -1
  55. package/js/ln-dropdown/src/ln-dropdown.js +30 -13
  56. package/js/ln-editor/README.md +274 -0
  57. package/js/ln-editor/ln-editor.js +1 -0
  58. package/js/ln-editor/ln-editor.scss +43 -0
  59. package/js/ln-editor/src/ln-editor.js +619 -0
  60. package/js/ln-external-links/README.md +44 -5
  61. package/js/ln-external-links/ln-external-links.js +1 -1
  62. package/js/ln-fill/README.md +199 -0
  63. package/js/ln-fill/ln-fill.js +1 -0
  64. package/js/ln-fill/src/ln-fill.js +87 -0
  65. package/js/ln-filter/README.md +92 -2
  66. package/js/ln-filter/ln-filter-dev.scss +8 -0
  67. package/js/ln-filter/ln-filter.js +1 -1
  68. package/js/ln-filter/src/ln-filter.js +22 -7
  69. package/js/ln-form/README.md +212 -49
  70. package/js/ln-form/ln-form.js +1 -1
  71. package/js/ln-form/src/ln-form.js +99 -199
  72. package/js/ln-http/README.md +125 -89
  73. package/js/ln-http/ln-http.js +1 -1
  74. package/js/ln-http/src/ln-http.js +32 -13
  75. package/js/ln-icon/README.md +130 -0
  76. package/js/ln-icon/ln-icon.js +1 -0
  77. package/js/{ln-icons/src/ln-icons.js → ln-icon/src/ln-icon.js} +20 -15
  78. package/js/ln-link/README.md +47 -9
  79. package/js/ln-link/ln-link.js +1 -1
  80. package/js/ln-link/src/ln-link.js +22 -6
  81. package/js/ln-list/README.md +129 -0
  82. package/js/ln-list/ln-list.js +1 -0
  83. package/js/ln-list/ln-list.scss +28 -0
  84. package/js/ln-list/src/ln-list.js +1216 -0
  85. package/js/ln-modal/README.md +185 -154
  86. package/js/ln-modal/ln-modal-dev.scss +13 -0
  87. package/js/ln-modal/ln-modal.js +1 -1
  88. package/js/ln-modal/ln-modal.scss +28 -4
  89. package/js/ln-modal/src/ln-modal.js +137 -201
  90. package/js/ln-modal-coordinator/README.md +99 -0
  91. package/js/ln-modal-coordinator/ln-modal-coordinator-dev.scss +8 -0
  92. package/js/ln-modal-coordinator/ln-modal-coordinator.js +1 -0
  93. package/js/ln-modal-coordinator/src/ln-modal-coordinator.js +345 -0
  94. package/js/ln-nav/README.md +46 -3
  95. package/js/ln-nav/ln-nav.js +1 -1
  96. package/js/ln-nav/src/ln-nav.js +92 -127
  97. package/js/ln-number/README.md +28 -1
  98. package/js/ln-number/ln-number-dev.scss +13 -0
  99. package/js/ln-number/ln-number.js +1 -1
  100. package/js/ln-number/src/ln-number.js +443 -350
  101. package/js/ln-options/README.md +66 -0
  102. package/js/ln-options/ln-options.js +1 -0
  103. package/js/ln-options/src/ln-options.js +74 -0
  104. package/js/ln-popover/README.md +40 -5
  105. package/js/ln-popover/ln-popover.js +1 -1
  106. package/js/ln-popover/src/ln-popover.js +38 -11
  107. package/js/ln-progress/README.md +413 -442
  108. package/js/ln-progress/ln-progress.js +1 -1
  109. package/js/ln-progress/src/ln-progress.js +98 -150
  110. package/js/ln-router/README.md +432 -0
  111. package/js/ln-router/ln-router.js +1 -0
  112. package/js/ln-router/src/ln-router.js +539 -0
  113. package/js/ln-search/README.md +158 -83
  114. package/js/ln-search/ln-search-dev.scss +8 -0
  115. package/js/ln-search/ln-search.js +1 -1
  116. package/js/ln-search/src/ln-search.js +12 -9
  117. package/js/ln-slug/README.md +110 -0
  118. package/js/ln-slug/ln-slug.js +1 -0
  119. package/js/ln-slug/src/ln-slug.js +74 -0
  120. package/js/ln-sort/README.md +170 -0
  121. package/js/ln-sort/ln-sort-dev.scss +8 -0
  122. package/js/ln-sort/ln-sort.js +1 -0
  123. package/js/ln-sort/src/ln-sort.js +178 -0
  124. package/js/ln-sortable/README.md +133 -95
  125. package/js/ln-sortable/ln-sortable.js +1 -1
  126. package/js/ln-stat/README.md +55 -0
  127. package/js/ln-stat/ln-stat.js +1 -0
  128. package/js/ln-stat/src/ln-stat.js +55 -0
  129. package/js/ln-table/README.md +285 -101
  130. package/js/ln-table/ln-table-dev.scss +17 -0
  131. package/js/ln-table/ln-table.js +1 -1
  132. package/js/ln-table/ln-table.scss +1 -1
  133. package/js/ln-table/src/ln-table.js +1493 -473
  134. package/js/ln-table-coordinator/README.md +73 -0
  135. package/js/ln-table-coordinator/ln-table-coordinator.js +1 -0
  136. package/js/ln-table-coordinator/src/ln-table-coordinator.js +160 -0
  137. package/js/ln-tabs/README.md +221 -137
  138. package/js/ln-tabs/ln-tabs-dev.scss +18 -0
  139. package/js/ln-tabs/ln-tabs.js +1 -1
  140. package/js/ln-tabs/src/ln-tabs.js +41 -24
  141. package/js/ln-time/README.md +14 -0
  142. package/js/ln-time/ln-time.js +1 -1
  143. package/js/ln-time/src/ln-time.js +223 -192
  144. package/js/ln-toast/README.md +178 -122
  145. package/js/ln-toast/ln-toast.js +1 -15
  146. package/js/ln-toast/src/ln-toast.js +232 -210
  147. package/js/ln-toast/template.html +16 -12
  148. package/js/ln-toggle/README.md +61 -2
  149. package/js/ln-toggle/ln-toggle-dev.scss +13 -0
  150. package/js/ln-toggle/ln-toggle.js +1 -1
  151. package/js/ln-toggle/src/ln-toggle.js +56 -43
  152. package/js/ln-tooltip/README.md +95 -58
  153. package/js/ln-tooltip/ln-tooltip-dev.scss +9 -0
  154. package/js/ln-tooltip/ln-tooltip.js +1 -1
  155. package/js/ln-tooltip/src/ln-tooltip.js +45 -6
  156. package/js/ln-translations/README.md +118 -96
  157. package/js/ln-translations/ln-translations.js +1 -1
  158. package/js/ln-translations/src/ln-translations.js +10 -5
  159. package/js/ln-upload/README.md +85 -10
  160. package/js/ln-upload/ln-upload.js +1 -1
  161. package/js/ln-upload/src/ln-upload.js +26 -10
  162. package/js/ln-validate/README.md +72 -0
  163. package/js/ln-validate/ln-validate-dev.scss +15 -0
  164. package/js/ln-validate/ln-validate.js +1 -1
  165. package/js/ln-validate/src/ln-validate.js +64 -0
  166. package/package.json +61 -56
  167. package/scss/base/_global.scss +2 -2
  168. package/scss/base/_typography.scss +1 -2
  169. package/scss/components/_date.scss +1 -0
  170. package/scss/components/_dropdown.scss +0 -5
  171. package/scss/components/_editor.scss +5 -0
  172. package/scss/components/_filter.scss +26 -25
  173. package/scss/components/_form.scss +7 -0
  174. package/scss/components/_ln-table.scss +13 -3
  175. package/scss/components/_sort.scss +10 -0
  176. package/scss/components/_table.scss +36 -23
  177. package/scss/components/_toast.scss +68 -41
  178. package/scss/components/_toggle.scss +16 -0
  179. package/scss/config/_density.scss +205 -117
  180. package/scss/config/_icons.scss +10 -9
  181. package/scss/config/_tokens.scss +69 -47
  182. package/scss/config/mixins/_accordion.scss +2 -7
  183. package/scss/config/mixins/_alert.scss +4 -4
  184. package/scss/config/mixins/_breadcrumbs.scss +2 -2
  185. package/scss/config/mixins/_btn.scss +1 -1
  186. package/scss/config/mixins/_card.scss +89 -14
  187. package/scss/config/mixins/_collapsible.scss +3 -0
  188. package/scss/config/mixins/_colors.scss +1 -1
  189. package/scss/config/mixins/_diagnostics.scss +11 -0
  190. package/scss/config/mixins/_display.scss +1 -0
  191. package/scss/config/mixins/_dropdown.scss +3 -5
  192. package/scss/config/mixins/_editor.scss +124 -0
  193. package/scss/config/mixins/_empty-state.scss +7 -0
  194. package/scss/config/mixins/_filter.scss +3 -5
  195. package/scss/config/mixins/_footer.scss +1 -2
  196. package/scss/config/mixins/_form.scss +207 -21
  197. package/scss/config/mixins/_index.scss +2 -0
  198. package/scss/config/mixins/_ln-table.scss +41 -2
  199. package/scss/config/mixins/_modal.scss +149 -66
  200. package/scss/config/mixins/_nav.scss +3 -4
  201. package/scss/config/mixins/_popover.scss +39 -0
  202. package/scss/config/mixins/_sidebar.scss +1 -1
  203. package/scss/config/mixins/_sort.scss +42 -0
  204. package/scss/config/mixins/_table.scss +85 -60
  205. package/scss/config/mixins/_toast.scss +179 -152
  206. package/scss/config/mixins/_tooltip.scss +17 -7
  207. package/scss/config/mixins/_typography.scss +4 -2
  208. package/scss/ln-ashlar-dev.scss +27 -9
  209. package/scss/ln-ashlar.scss +7 -1
  210. package/js/ln-data-table/README.md +0 -110
  211. package/js/ln-data-table/ln-data-table.js +0 -1
  212. package/js/ln-data-table/ln-data-table.scss +0 -10
  213. package/js/ln-data-table/src/ln-data-table.js +0 -1087
  214. package/js/ln-icons/README.md +0 -88
  215. package/js/ln-icons/ln-icons.js +0 -1
  216. package/js/ln-table/ln-table-sort.js +0 -1
  217. package/js/ln-table/src/ln-table-sort.js +0 -156
@@ -14,32 +14,30 @@ table {
14
14
 
15
15
  @container table (max-width: 640px) {
16
16
  table { @include table-responsive; }
17
+
18
+ .table-row-actions {
19
+ position: static !important;
20
+ opacity: 1 !important;
21
+ visibility: visible !important;
22
+ pointer-events: auto !important;
23
+ transform: none !important;
24
+ background: transparent !important;
25
+ padding-left: 0 !important;
26
+ justify-content: flex-end;
27
+ margin-top: var(--size-xs);
28
+
29
+ &::before {
30
+ display: none !important;
31
+ }
32
+ }
17
33
  }
18
34
  }
19
35
 
20
- // ─── Shared Column Sort & Filter Buttons ────────────────────────
36
+ // ─── Shared Column Filter Button ─────────────────────────────────
21
37
  // CSS targets the unprefixed structural helper class on the button, NOT the data-ln-* JS
22
- // hook. .table-sort / .table-filter are thin bindings that mirror the mixins; a consumer
23
- // may instead @include table-sort / table-filter on their own selector (the class is a
24
- // convenience, not a mandate — see "Naming & class architecture"). Behavior hooks
25
- // (data-ln-col-sort / data-ln-table-sort / data-ln-popover-for / data-ln-col-filter) are
26
- // the per-system functional layer and intentionally differ.
27
-
28
- .table-sort { @include table-sort; }
29
- th:hover .table-sort { opacity: 0.7; }
30
-
31
- // Active sort — JS-state class on the <th>, set by sort JS (client) or server.
32
- .ln-sort-asc .table-sort,
33
- .ln-sort-desc .table-sort { @include table-sort-active; }
34
-
35
- .ln-sort-asc .table-sort {
36
- [data-ln-sort-icon="none"] { display: none; }
37
- [data-ln-sort-icon="asc"] { display: inline-block; }
38
- }
39
- .ln-sort-desc .table-sort {
40
- [data-ln-sort-icon="none"] { display: none; }
41
- [data-ln-sort-icon="desc"] { display: inline-block; }
42
- }
38
+ // hook. .table-filter is a thin binding that mirrors the mixin; a consumer may instead
39
+ // @include table-filter on their own selector (the class is a convenience, not a mandate).
40
+ // Sort lives in scss/components/_sort.scss — see [data-ln-sort].
43
41
 
44
42
  .table-filter { @include table-filter; }
45
43
  th:hover .table-filter { opacity: 0.7; }
@@ -67,7 +65,22 @@ th:hover .table-filter { opacity: 0.7; }
67
65
  }
68
66
 
69
67
  // Virtual-scroll spacer
70
- .ln-data-table__spacer {
68
+ .ln-table__spacer {
71
69
  @include table-spacer-row;
72
70
  }
73
71
 
72
+ // ─── Table Row Actions ──────────────────────────────────────────
73
+ td:has(.table-row-actions) {
74
+ position: relative;
75
+ }
76
+
77
+ .table-row-actions {
78
+ @include table-row-actions;
79
+ }
80
+
81
+ tr:hover .table-row-actions {
82
+ opacity: 1;
83
+ pointer-events: auto;
84
+ visibility: visible;
85
+ }
86
+
@@ -1,41 +1,68 @@
1
- @use '../config/mixins' as *;
2
-
3
- [data-ln-toast] {
4
- @include toast-container;
5
- }
6
-
7
- [data-ln-toast] > .ln-toast__item {
8
- @include toast-item;
9
- }
10
-
11
- [data-ln-toast] > .ln-toast__item--in {
12
- @include toast-item-in;
13
- }
14
-
15
- .ln-toast__item--out {
16
- @include toast-item-out;
17
- }
18
-
19
- .ln-toast__card {
20
- @include toast-card;
21
- }
22
-
23
- .ln-toast__side {
24
- @include toast-side;
25
- }
26
-
27
- .ln-toast__content {
28
- @include toast-content;
29
- }
30
-
31
- .ln-toast__head {
32
- @include toast-head;
33
- }
34
-
35
- .ln-toast__title {
36
- @include toast-title;
37
- }
38
-
39
- .ln-toast__body {
40
- @include toast-body;
41
- }
1
+ @use '../config/mixins' as *;
2
+
3
+ [data-ln-toast] {
4
+ @include toast-container;
5
+ }
6
+
7
+ // The <li> IS the card: structural (item) + visual (card) styling both bind
8
+ // here, contextually — the <li> carries no static class (no-BEM), only the
9
+ // filled/authored type class.
10
+ [data-ln-toast] > li {
11
+ @include toast-item;
12
+ @include toast-card;
13
+ }
14
+
15
+ [data-ln-toast] > li.ln-enter {
16
+ @include toast-item-enter;
17
+ }
18
+
19
+ [data-ln-toast] > li.ln-out {
20
+ @include toast-item-out;
21
+ }
22
+
23
+ // Type → tone. The status→tone map lives here (one place): warn maps to the
24
+ // warning family. SSR authors the class; the dynamic path fills it verbatim.
25
+ [data-ln-toast] > li.success { @include semantic-color(success); }
26
+ [data-ln-toast] > li.error { @include semantic-color(error); }
27
+ [data-ln-toast] > li.warn { @include semantic-color(warning); }
28
+ [data-ln-toast] > li.info { @include semantic-color(info); }
29
+
30
+ [data-ln-toast] .icon {
31
+ @include toast-icon;
32
+ }
33
+
34
+ [data-ln-toast] .icon ul {
35
+ @include toast-icon-list;
36
+ }
37
+
38
+ // When-toggle — dynamic template ships all 4 icon variants; CSS shows the
39
+ // one matching the card's type class. Unknown/absent type → no matching
40
+ // class → no icon (documented degradation, see js/ln-toast/README.md).
41
+ [data-ln-toast] > li.success .icon li[data-ln-toast-when="success"],
42
+ [data-ln-toast] > li.error .icon li[data-ln-toast-when="error"],
43
+ [data-ln-toast] > li.warn .icon li[data-ln-toast-when="warn"],
44
+ [data-ln-toast] > li.info .icon li[data-ln-toast-when="info"] {
45
+ @include block;
46
+ }
47
+
48
+ [data-ln-toast] .content {
49
+ @include toast-content;
50
+ }
51
+
52
+ [data-ln-toast] .title {
53
+ @include toast-title;
54
+ }
55
+
56
+ // No default titles are ever filled by JS — an empty title collapses.
57
+ [data-ln-toast] .title:empty {
58
+ @include hidden;
59
+ }
60
+
61
+ [data-ln-toast] .body {
62
+ @include toast-body;
63
+ }
64
+
65
+ // No hasBody flag — an unfilled body collapses via :empty.
66
+ [data-ln-toast] .body:empty {
67
+ @include hidden;
68
+ }
@@ -35,6 +35,22 @@
35
35
  }
36
36
  }
37
37
 
38
+ // Default internal spacing for EVERY collapsible panel — plain toggle and
39
+ // accordion alike — so no consumer has to re-solve it.
40
+ //
41
+ // Spacing lives on the body's CHILDREN, never on .collapsible-body itself:
42
+ // that element is the overflow:hidden grid-track child, so any padding/border
43
+ // on it feeds its automatic min-height and stops the panel collapsing to 0px
44
+ // (a sliver of the first line leaks through when "closed"). Padding the
45
+ // children — and zeroing their margins — keeps .collapsible-body's own min
46
+ // at 0. Rebind --padding-x / --padding-y on the body to retune per context.
47
+ .collapsible-body > * {
48
+ --padding-y: var(--size-sm-up);
49
+ --padding-x: var(--size-md);
50
+ padding: var(--padding-y) var(--padding-x);
51
+ margin: 0;
52
+ }
53
+
38
54
  // ──────────────────────────────────────────────────────────────────────
39
55
  // Chevron — generic toggle behavior
40
56
  // ──────────────────────────────────────────────────────────────────────
@@ -1,117 +1,205 @@
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
- }
1
+ // ==========================================================================
2
+ // Density — ln-ashlar v2.0
3
+ // ==========================================================================
4
+ // Inverted density system. The :root default is DENSE (DocuFlow scale:
5
+ // 14px body, 52px header, 232px sidebar). Density goes UP via the
6
+ // [data-density] attribute, mirroring how [data-theme] works.
7
+ //
8
+ // Activation:
9
+ // <html> ← default: dense (DocuFlow look)
10
+ // <html data-density="compact"> ← explicit dense handle (same as base)
11
+ // <html data-density="comfortable"> ← pre-v2 default (16px / roomier)
12
+ // <html data-density="spacious"> ← large type, generous padding
13
+ // <main data-density="compact"> ← scope dense within comfortable page
14
+ //
15
+ // Density is an explicit user choice (settings toggle).
16
+ // It is NEVER auto-switched by viewport — viewport breakpoints handle
17
+ // layout, density handles information density inside that layout.
18
+ //
19
+ // What reacts: everything reading --padding-y, --gap, --text-body-*,
20
+ // --text-label-*, --text-title-*, --text-heading-*, --text-display-sm,
21
+ // --lh-*, --app-header-height, --app-sidebar-width, --density-row-h,
22
+ // --btn-padding-y, --input-padding-y.
23
+ //
24
+ // Interactive controls (buttons, inputs, pills): density-reactive UPWARD.
25
+ // Base (~38px) = WCAG AA. Comfortable (≥46px) and Spacious (≥54px) = AAA.
26
+ // Controls rebind --btn-padding-y and --input-padding-y in up-tier scopes.
27
+ // See docs/css/density.md §wcag for the height math.
28
+ //
29
+ // No parallel --density-* token scale. Density overrides existing base
30
+ // tokens at the scope root, exactly like theme color overrides.
31
+ // ==========================================================================
32
+
33
+ :root {
34
+
35
+ // -----------------------------------------------------------------------
36
+ // Density — Row height
37
+ // Minimum row height for table rows and data lists. Kept density-named
38
+ // because it has no analogue in the base token scale.
39
+ // -----------------------------------------------------------------------
40
+ --density-row-h: 2.25rem; // 36px — dense base
41
+ }
42
+
43
+ // ---------------------------------------------------------------------------
44
+ // [data-density="compact"] — explicit handle for the dense base.
45
+ //
46
+ // Identical to :root. Exists so:
47
+ // (a) a switcher can write a single attribute across all tiers including
48
+ // returning to base (rather than removing the attribute)
49
+ // (b) a region inside a comfortable page can be scoped dense:
50
+ // <table data-density="compact">
51
+ //
52
+ // Rebinds --density-row-h so a compact-scoped region keeps the dense row
53
+ // floor inside a comfortable/spacious page. NOTE: only row-h is restored —
54
+ // full dense region-scoping (type, padding) would re-declare the base
55
+ // surface; deferred. The global switcher returns to base via :root (dense).
56
+ // ---------------------------------------------------------------------------
57
+ [data-density="compact"] {
58
+ --density-row-h: 2.25rem; // 36px — restore dense base in scoped context
59
+ }
60
+
61
+ // ---------------------------------------------------------------------------
62
+ // [data-density="comfortable"] — pre-v2 default, now an explicit opt-in.
63
+ //
64
+ // Restores the roomy 16px / lh 1.6 scale that was the :root default before
65
+ // design-v2. WCAG 2.5.5 AAA: buttons 46px, inputs/pills ≥44px.
66
+ //
67
+ // <html data-density="comfortable"> ← global comfortable
68
+ // <aside data-density="comfortable"> ← scoped comfortable sidebar
69
+ // ---------------------------------------------------------------------------
70
+ [data-density="comfortable"] {
71
+
72
+ // -- Logical rhythm --------------------------------------------------
73
+ --padding-y: var(--size-sm); // 8px (was dense 6px)
74
+ --gap: var(--size-sm); // 8px (was dense 6px)
75
+
76
+ // -- Body text (restore 16px / 1.6 scale) ----------------------------
77
+ --text-body-md: 1rem;
78
+ --lh-body-md: 1.6;
79
+
80
+ --text-body-sm: 0.875rem;
81
+ --lh-body-sm: 1.5;
82
+
83
+ // Explicit rebind — form inputs consume --font-size and don't always
84
+ // cascade lazy var(--text-body-md) resolutions under a scope.
85
+ --font-size: var(--text-body-md);
86
+ --line-height: var(--lh-body-md);
87
+
88
+ // -- Labels ----------------------------------------------------------
89
+ --text-label-md: 0.875rem;
90
+ --lh-label-md: 1.4;
91
+
92
+ --text-label-sm: 0.8125rem; // 13px (was dense 12px) — form-label, table th
93
+ --lh-label-sm: 1.4;
94
+
95
+ // -- Caption ---------------------------------------------------------
96
+ --text-caption: 0.8125rem; // 13px — modal subtitle, validation errors
97
+ --lh-caption: 1.4;
98
+
99
+ // -- Titles ----------------------------------------------------------
100
+ --text-title-md: 1.125rem;
101
+ --lh-title-md: 1.4;
102
+
103
+ --text-title-sm: 1rem;
104
+ --lh-title-sm: 1.4;
105
+
106
+ // -- Headings --------------------------------------------------------
107
+ --text-heading-sm: 1.25rem; --lh-heading-sm: 1.3;
108
+ --text-heading-md: 1.5rem; --lh-heading-md: 1.25;
109
+ --text-heading-lg: 1.875rem; --lh-heading-lg: 1.2;
110
+
111
+ // -- Display ---------------------------------------------------------
112
+ --text-display-sm: 2.25rem; --lh-display-sm: 1.15;
113
+
114
+ // -- App shell -------------------------------------------------------
115
+ --app-header-height: 3.5rem; // 56px (was dense 3.25rem)
116
+ --app-sidebar-width: 16rem; // 256px (was dense 14.5rem)
117
+
118
+ // -- Row height ------------------------------------------------------
119
+ --density-row-h: 2.75rem; // 44px (was dense 2.25rem)
120
+
121
+ // -- Interactive controls — WCAG 2.5.5 AAA ≥44px --------------------
122
+ // btn-padding-y: 2×12px + 20px line-height + 2px borders = 46px
123
+ // input-padding-y: indirection token read by form-input + pill-outline
124
+ --btn-padding-y: var(--size-sm-up); // 12px → buttons 46px
125
+ --btn-padding-x: var(--size-md); // 16px — restore roomy width
126
+ --input-padding-y: var(--size-sm-up); // 12px → inputs/pills ≥44px
127
+
128
+ // -- Card and table padding — roomier at comfortable/spacious --------
129
+ --card-padding-y: var(--size-md); // 16px
130
+ --card-padding-x: var(--size-lg); // 24px
131
+ --table-cell-padding-y: var(--size-sm-up); // 12px
132
+ --table-cell-padding-x: var(--size-lg); // 24px
133
+ }
134
+
135
+ // ---------------------------------------------------------------------------
136
+ // [data-density="spacious"] — NEW tier above comfortable.
137
+ //
138
+ // For low-vision, touch-primary, or presentation contexts.
139
+ // Body 18px, generous padding, larger shell. WCAG 2.5.5 AAA:
140
+ // buttons 54px, inputs/pills ≥48px.
141
+ //
142
+ // <html data-density="spacious">
143
+ // ---------------------------------------------------------------------------
144
+ [data-density="spacious"] {
145
+
146
+ // -- Logical rhythm --------------------------------------------------
147
+ --padding-y: var(--size-md); // 16px
148
+ --gap: var(--size-md); // 16px
149
+
150
+ // -- Body text -------------------------------------------------------
151
+ --text-body-md: 1.125rem; // 18px
152
+ --lh-body-md: 1.75;
153
+
154
+ --text-body-sm: 1rem;
155
+ --lh-body-sm: 1.6;
156
+
157
+ --font-size: var(--text-body-md);
158
+ --line-height: var(--lh-body-md);
159
+
160
+ // -- Labels ----------------------------------------------------------
161
+ --text-label-md: 1rem;
162
+ --lh-label-md: 1.5;
163
+
164
+ --text-label-sm: 0.9375rem; // 15px (was dense 12px) — form-label, table th
165
+ --lh-label-sm: 1.45;
166
+
167
+ // -- Caption ---------------------------------------------------------
168
+ --text-caption: 0.9375rem; // 15px — modal subtitle, validation errors
169
+ --lh-caption: 1.45;
170
+
171
+ // -- Titles ----------------------------------------------------------
172
+ --text-title-md: 1.25rem;
173
+ --lh-title-md: 1.5;
174
+
175
+ --text-title-sm: 1.125rem;
176
+ --lh-title-sm: 1.45;
177
+
178
+ // -- Headings --------------------------------------------------------
179
+ --text-heading-sm: 1.5rem; --lh-heading-sm: 1.35;
180
+ --text-heading-md: 1.875rem; --lh-heading-md: 1.3;
181
+ --text-heading-lg: 2.25rem; --lh-heading-lg: 1.25;
182
+
183
+ // -- Display ---------------------------------------------------------
184
+ --text-display-sm: 2.75rem; --lh-display-sm: 1.2;
185
+
186
+ // -- App shell -------------------------------------------------------
187
+ --app-header-height: 4rem; // 64px
188
+ --app-sidebar-width: 17.5rem; // 280px
189
+
190
+ // -- Row height ------------------------------------------------------
191
+ --density-row-h: 3rem; // 48px
192
+
193
+ // -- Interactive controls — WCAG 2.5.5 AAA ≥48px --------------------
194
+ // btn-padding-y: 2×16px + 20px line-height + 2px borders = 54px
195
+ // input-padding-y: indirection token read by form-input + pill-outline
196
+ --btn-padding-y: var(--size-md); // 16px → buttons 54px
197
+ --btn-padding-x: var(--size-lg); // 24px — spacious width
198
+ --input-padding-y: var(--size-md); // 16px → inputs/pills ≥48px
199
+
200
+ // -- Card and table padding ------------------------------------------
201
+ --card-padding-y: var(--size-lg); // 24px
202
+ --card-padding-x: var(--size-xl); // 32px
203
+ --table-cell-padding-y: var(--size-md); // 16px
204
+ --table-cell-padding-x: var(--size-xl); // 32px
205
+ }
@@ -1,14 +1,14 @@
1
1
  // ==========================================================================
2
2
  // Icons — SVG sprite system
3
3
  // ==========================================================================
4
- // Icons are rendered via an SVG sprite injected by ln-icons.js.
4
+ // Icons are rendered via an SVG sprite injected by ln-icon.js.
5
5
  // Color is inherited from the parent's `color` property (currentColor).
6
6
  //
7
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>
8
+ // <svg class="ln-icon" aria-hidden="true"><use href="#ln-icon-home"></use></svg>
9
+ // <svg class="ln-icon ln-icon--sm" aria-hidden="true"><use href="#ln-icon-close"></use></svg>
10
10
  //
11
- // Available IDs: #ln-{name} where name = filename in js/ln-icons/icons/
11
+ // Available IDs: #ln-{name} where name = filename in js/ln-icon/icons/
12
12
  // home, close, menu, users, settings, logout, books, lodges
13
13
  // plus, edit, delete, view, save, search, check, copy, link
14
14
  // upload, download, refresh, print, lock, star, filter, calendar
@@ -24,14 +24,15 @@
24
24
 
25
25
  svg.ln-icon {
26
26
  display: inline-block;
27
- width: 1.25rem;
28
- height: 1.25rem;
27
+ --icon-size: 1.25rem; // intrinsic icon dimension (component primitive — rebind to resize)
28
+ width: var(--icon-size);
29
+ height: var(--icon-size);
29
30
  flex-shrink: 0;
30
31
  vertical-align: middle;
31
32
  // fill/stroke are set per icon via the SVG source
32
33
  // currentColor is applied directly in each <symbol>
33
34
  }
34
35
 
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; }
36
+ svg.ln-icon.ln-icon--sm { --icon-size: 1rem; }
37
+ svg.ln-icon.ln-icon--lg { --icon-size: 1.5rem; }
38
+ svg.ln-icon.ln-icon--xl { --icon-size: 4rem; }