layered-ui-rails 0.18.1 → 0.18.3
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.
- checksums.yaml +4 -4
- data/.claude/skills/layered-ui-rails/SKILL.md +3 -1
- data/.claude/skills/layered-ui-rails/references/CSS.md +9 -3
- data/AGENTS.md +1 -0
- data/CHANGELOG.md +18 -0
- data/app/assets/tailwind/layered_ui/engine.css +43 -2
- data/lib/layered/ui/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2fd8c671e3944ef7729ed3b06323c413e8e6b514bb41399063abab390216b874
|
|
4
|
+
data.tar.gz: fed13e167f82d2765c5152cd86bed58eb424c4e95205111b74fe21cfd5e2dfb0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6e78e1b237b6f7319e1de46c4fe569578b1f29c0d271b5d149d6578280991dd5912508c46cbb9c4de8ce2a96886e6494f2b0abcbc1421b1343680cee16770ee2
|
|
7
|
+
data.tar.gz: c781405282f383c5f6c4921521e745ce10af3746e6eace6f68ae85b1053faf0ec78d2d5c3e40ca1f483e6fa04cf8d3683346af269c9c919e5fbc3977f74dc8ce
|
|
@@ -132,6 +132,8 @@ Populate layout regions with `content_for` (always above the render call):
|
|
|
132
132
|
Body class modifiers:
|
|
133
133
|
- `l-ui-body--always-show-navigation` - pins navigation as a sidebar on desktop
|
|
134
134
|
- `l-ui-body--hide-header` - hides the header and collapses its space
|
|
135
|
+
- `l-ui-body--glass-header` - glass header (translucent + blur); content scrolls under it
|
|
136
|
+
- `l-ui-body--flush-top` - zeroes the page's top gutter so a hero sits flush at the top, behind the header (pair with `--glass-header` or `--hide-header`)
|
|
135
137
|
|
|
136
138
|
### Controller instance variables
|
|
137
139
|
|
|
@@ -178,7 +180,7 @@ Key components:
|
|
|
178
180
|
|
|
179
181
|
| Component | Key classes |
|
|
180
182
|
|---|---|
|
|
181
|
-
| Page layout | `.l-ui-page`, `--with-navigation`, `__vertically-centered`, `__narrow` (narrow ~384px column, md:max-w-sm) |
|
|
183
|
+
| Page layout | `.l-ui-page`, `--with-navigation`, `__vertically-centered`, `__narrow` (narrow ~384px column, md:max-w-sm), `__contained` (wide column capped at `--l-ui-contained-width`) |
|
|
182
184
|
| Buttons | `.l-ui-button`, `--primary`, `--outline`, `--outline-danger`, `--full`, `--icon` |
|
|
183
185
|
| Surfaces | `.l-ui-surface`, `--highlighted`, `--sm`, `--collapsible`, `--collapsible-highlighted` |
|
|
184
186
|
| Forms | `.l-ui-form`, `.l-ui-form__group`, `.l-ui-form__field`, `.l-ui-label`, `.l-ui-select` |
|
|
@@ -24,7 +24,9 @@ Applied to `<body>` via the `:l_ui_body_class` yield to toggle layout-level beha
|
|
|
24
24
|
```
|
|
25
25
|
.l-ui-body--always-show-navigation Pin sidebar navigation open on desktop
|
|
26
26
|
.l-ui-body--hide-header Hide the header and collapse its reserved space
|
|
27
|
-
.l-ui-body--header-contained Constrain the header's inner row to
|
|
27
|
+
.l-ui-body--header-contained Constrain the header's inner row to --l-ui-contained-width (landing pages)
|
|
28
|
+
.l-ui-body--glass-header Glass header (translucent + backdrop blur); content scrolls under it
|
|
29
|
+
.l-ui-body--flush-top Zero the page's top gutter so the first section sits flush at the top, behind the header
|
|
28
30
|
```
|
|
29
31
|
|
|
30
32
|
## Page layout
|
|
@@ -34,12 +36,14 @@ Applied to `<body>` via the `:l_ui_body_class` yield to toggle layout-level beha
|
|
|
34
36
|
.l-ui-page--with-navigation Left margin for sidebar on desktop
|
|
35
37
|
.l-ui-page__vertically-centered Centred layout element (e.g. login pages)
|
|
36
38
|
.l-ui-page__narrow Narrow column (md:max-w-sm, ~384px) for any compact, centred content
|
|
39
|
+
.l-ui-page__contained Centred column capped at --l-ui-contained-width; aligns with the contained header
|
|
40
|
+
.l-ui-page__contained--no-gutter Contained column flush to the page edge until the cap, then centred
|
|
37
41
|
.l-ui-bleed Breaks a child out to the page edge (full-bleed hero etc.)
|
|
38
42
|
```
|
|
39
43
|
|
|
40
|
-
`.l-ui-page` (and `--with-navigation`) is applied by the engine layout around your view's `yield` - you do not add it yourself. Wrapping your view content in another `.l-ui-page` nests two containers. The `__vertically-centered` and `__narrow` elements are used *inside* views for centred, compact content (the Devise auth pages are one example, but they are general-purpose). `__narrow` caps width at `md:max-w-sm` (~384px). For a wider content area,
|
|
44
|
+
`.l-ui-page` (and `--with-navigation`) is applied by the engine layout around your view's `yield` - you do not add it yourself. Wrapping your view content in another `.l-ui-page` nests two containers. The `__vertically-centered` and `__narrow` elements are used *inside* views for centred, compact content (the Devise auth pages are one example, but they are general-purpose). `__narrow` caps width at `md:max-w-sm` (~384px). For a wider content area, wrap your content in `.l-ui-page__contained`: it caps width at the `--l-ui-contained-width` token (default `80rem`) and centres with `mx-auto`. Because the contained header (`.l-ui-body--header-contained`) reads the same token, the two line up automatically - override `--l-ui-contained-width` once to move both. Left to itself, `.l-ui-page` holds content to the full available width. By default `.l-ui-page__contained` keeps the page gutter; add `.l-ui-page__contained--no-gutter` to opt out, so the column runs flush to the page edge until it reaches `--l-ui-contained-width`, then centres and caps (useful for tables, media, or full-width cards that should run edge-to-edge on small screens without losing the cap on large ones).
|
|
41
45
|
|
|
42
|
-
The page gutter (horizontal and bottom padding) is the `--l-ui-gutter` custom property (default `1rem`),
|
|
46
|
+
The page gutter (horizontal and bottom padding) is the `--l-ui-gutter` custom property (default `1rem`), owned by the `.l-ui-page` and `.l-ui-header-container` shells - the contained header and `.l-ui-page__contained` then cap their inner content within that gutter the same way, so they always align by construction. Override it on a container to change the gutter in one place rather than reverse-engineering padding values. To take a single child edge-to-edge (a full-bleed hero, a banner), add `.l-ui-bleed` to it - it cancels exactly the current gutter, so no negative-margin guesswork. Note `.l-ui-bleed` only handles the horizontal edges; content still sits below the page's top padding (header offset + gutter). To take the *top* edge too - a hero that starts at the very top of the viewport, behind the header - add `.l-ui-body--flush-top`, which zeroes the page's top padding. On its own over the opaque header that would hide content, so pair it with `.l-ui-body--glass-header` (the header turns translucent and content shows through the blur) or `.l-ui-body--hide-header`. Give the hero its own internal top padding (at least `--header-height`) so its content clears the floating header.
|
|
43
47
|
|
|
44
48
|
`.l-ui-page` is a flex column (`flex flex-1 flex-col`) and uses `overflow-x-clip` to hold its content to the available width: intrinsically wide content (tables, code blocks, long unbroken strings) is clipped rather than expanding the page or adding a horizontal page scrollbar. So make such content scroll internally (e.g. wrap a table in an `overflow-x-auto` element) instead of expecting the page to grow.
|
|
45
49
|
|
|
@@ -392,6 +396,8 @@ Tier 2 - Full palette (override individually as needed):
|
|
|
392
396
|
--error-bg Error background
|
|
393
397
|
--error-text Error text
|
|
394
398
|
--header-height Header height (default 63px)
|
|
399
|
+
--l-ui-gutter Page/header horizontal + bottom padding (default 1rem)
|
|
400
|
+
--l-ui-contained-width Max width of contained content - header + .l-ui-page__contained (default 80rem)
|
|
395
401
|
```
|
|
396
402
|
|
|
397
403
|
Override --button-primary-text when your accent color needs a different text/icon color on buttons (e.g. a pink accent with white button text in dark mode). Override --button-primary-icon instead when only the icon color should change.
|
data/AGENTS.md
CHANGED
|
@@ -29,6 +29,7 @@ Guidance for AI agents working in this repository.
|
|
|
29
29
|
- Importmap for JS (no bundler)
|
|
30
30
|
- Put new changes on a branch with a meaningful name, but do not commit; the user will ask when ready to commit
|
|
31
31
|
- We are currently in pre-release, so breaking changes may be introduced. Flag any expected breaking changes clearly before making them, but do not avoid necessary improvements solely to preserve backwards compatibility
|
|
32
|
+
- Do not overthink basic tasks. Match the effort to the request: a one-line change is a one-line change. Avoid unnecessary investigation, refactoring, or generalisation beyond what was asked.
|
|
32
33
|
- CRITICAL: Retain WCAG 2.2 AA compliance. Do not be too pedantic though as this introduces audit loops which are undesirable.
|
|
33
34
|
- A WCAG 2.2 AA table looks like this:
|
|
34
35
|
```
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. This project follows [Semantic Versioning](https://semver.org/).
|
|
4
4
|
|
|
5
|
+
## [0.18.3] - 2026-06-08
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- `l-ui-page__contained--no-gutter`: opts the contained column out of the page gutter. The column runs flush to the page edge while narrower than `--l-ui-contained-width`, then centres and caps once there is room - useful for tables, media, or full-width cards that should run edge-to-edge on small screens without losing the cap on large ones.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- The page gutter is now owned by the `.l-ui-page` and `.l-ui-header-container` shells, with the contained header and `.l-ui-page__contained` capping their inner content within that gutter the same way. Header and contained page content now align by construction at every width. The horizontal padding moved from `.l-ui-header` to `.l-ui-header-container`; the header's bottom border still spans edge to edge.
|
|
14
|
+
|
|
15
|
+
## [0.18.2] - 2026-06-08
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- `--l-ui-contained-width` token (default `80rem`) and `l-ui-page__contained`, a centred content column capped at that width. The contained header (`l-ui-body--header-contained`) now reads the same token, so header and page content align and can be moved together with a single override.
|
|
20
|
+
- `l-ui-body--glass-header`: glass header (translucent background plus backdrop blur, dropping the solid bottom border) so page content scrolls beneath it.
|
|
21
|
+
- `l-ui-body--flush-top`: zeroes the page's top padding so the first section sits flush at the top of the viewport, behind the header. Pair with `l-ui-body--glass-header` (content shows through the frosted header) or `l-ui-body--hide-header` for full-bleed heroes.
|
|
22
|
+
|
|
5
23
|
## [0.18.1] - 2026-06-07
|
|
6
24
|
|
|
7
25
|
### Added
|
|
@@ -81,6 +81,7 @@
|
|
|
81
81
|
--error-text: oklch(0.2248 0.0874 28.11);
|
|
82
82
|
--header-height: 63px;
|
|
83
83
|
--l-ui-gutter: 1rem;
|
|
84
|
+
--l-ui-contained-width: 80rem;
|
|
84
85
|
}
|
|
85
86
|
|
|
86
87
|
.dark {
|
|
@@ -466,6 +467,13 @@
|
|
|
466
467
|
@apply md:ml-[256px];
|
|
467
468
|
}
|
|
468
469
|
|
|
470
|
+
/* Zero the page's top gutter so the first section sits flush at the viewport top, behind the
|
|
471
|
+
header. Intended with .l-ui-body--glass-header (content shows through the glass header) or
|
|
472
|
+
.l-ui-body--hide-header; over an opaque header it would tuck content out of sight. */
|
|
473
|
+
.l-ui-body--flush-top .l-ui-page {
|
|
474
|
+
@apply pt-0;
|
|
475
|
+
}
|
|
476
|
+
|
|
469
477
|
.l-ui-page__vertically-centered {
|
|
470
478
|
@apply flex flex-1 flex-col items-center justify-center;
|
|
471
479
|
}
|
|
@@ -477,11 +485,36 @@
|
|
|
477
485
|
my-auto;
|
|
478
486
|
}
|
|
479
487
|
|
|
488
|
+
/* Centred content column capped at --l-ui-contained-width. The page owns the gutter (px on
|
|
489
|
+
.l-ui-page), so the gutter sits OUTSIDE this cap and the column's content spans the full
|
|
490
|
+
--l-ui-contained-width. The contained header mirrors this exactly (gutter on its container, cap
|
|
491
|
+
on the child), so the two align by construction at every width. */
|
|
492
|
+
.l-ui-page__contained {
|
|
493
|
+
@apply w-full max-w-[var(--l-ui-contained-width)]
|
|
494
|
+
mx-auto;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/* Opt out of the page gutter: reclaim it (as .l-ui-bleed does) so the column can reach the page
|
|
498
|
+
edge, then re-cap and re-centre the content with padding. Flush to the edge while narrower than
|
|
499
|
+
--l-ui-contained-width; centred and capped once there is room. */
|
|
500
|
+
.l-ui-page__contained--no-gutter {
|
|
501
|
+
@apply w-auto max-w-none
|
|
502
|
+
mx-[calc(var(--l-ui-gutter)*-1)];
|
|
503
|
+
/* +gutter cancels the negative margin's effect on the % basis, so this nets to
|
|
504
|
+
max(0, (page - contained) / 2): centred when there's room, flush when not. */
|
|
505
|
+
padding-inline: max(0px, calc((100% - var(--l-ui-contained-width)) / 2 + var(--l-ui-gutter)));
|
|
506
|
+
}
|
|
507
|
+
|
|
480
508
|
/* Header */
|
|
481
509
|
|
|
510
|
+
/* The container owns the gutter (mirroring .l-ui-page), so .l-ui-header fills the gutter-inset
|
|
511
|
+
content box by default and the contained header re-centres within the same frame as
|
|
512
|
+
.l-ui-page__contained. The bottom border still spans edge to edge (border sits outside the
|
|
513
|
+
padding). */
|
|
482
514
|
.l-ui-header-container {
|
|
483
515
|
@apply fixed top-0 left-0 right-0
|
|
484
516
|
z-50
|
|
517
|
+
px-[var(--l-ui-gutter)]
|
|
485
518
|
bg-background
|
|
486
519
|
border-b border-border;
|
|
487
520
|
}
|
|
@@ -490,14 +523,22 @@
|
|
|
490
523
|
@apply hidden;
|
|
491
524
|
}
|
|
492
525
|
|
|
526
|
+
.l-ui-body--glass-header .l-ui-header-container {
|
|
527
|
+
@apply bg-background/60
|
|
528
|
+
border-b-transparent
|
|
529
|
+
backdrop-blur-xl;
|
|
530
|
+
}
|
|
531
|
+
|
|
493
532
|
.l-ui-header {
|
|
494
533
|
@apply flex items-center justify-between
|
|
495
534
|
h-[var(--header-height)]
|
|
496
|
-
|
|
535
|
+
py-3;
|
|
497
536
|
}
|
|
498
537
|
|
|
538
|
+
/* Mirror of .l-ui-page__contained: the gutter lives on the container, the cap lives here. Same
|
|
539
|
+
formula, same reference frame, so header and contained page content share the same edges. */
|
|
499
540
|
.l-ui-body--header-contained .l-ui-header {
|
|
500
|
-
@apply w-full max-w-
|
|
541
|
+
@apply w-full max-w-[var(--l-ui-contained-width)]
|
|
501
542
|
mx-auto;
|
|
502
543
|
}
|
|
503
544
|
|
data/lib/layered/ui/version.rb
CHANGED