layered-ui-rails 0.14.0 → 0.15.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.
- checksums.yaml +4 -4
- data/.claude/skills/layered-ui-rails/SKILL.md +1 -1
- data/.claude/skills/layered-ui-rails/references/CONTROLLERS.md +1 -1
- data/.claude/skills/layered-ui-rails/references/CSS.md +0 -1
- data/AGENTS.md +1 -1
- data/CHANGELOG.md +20 -0
- data/app/assets/images/layered_ui/icon_panel_close.svg +4 -0
- data/app/assets/tailwind/layered/ui/styles.css +12 -19
- data/app/javascript/layered_ui/controllers/l_ui/modal_controller.js +13 -2
- data/app/javascript/layered_ui/controllers/l_ui/panel_resize_controller.js +1 -1
- data/app/javascript/layered_ui/utilities/layout.js +1 -1
- data/app/views/layouts/layered_ui/_panel.html.erb +3 -3
- data/lib/layered/ui/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 21924f2cc31a2154c80002c22b304b3061eee7af0c6a6b80221932c62f17c0cd
|
|
4
|
+
data.tar.gz: 74c95e1eae950256dd07ab02a426ba77c3e213087709f92e9256e94b52eba987
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 23b89112299368d834cc3c6d6a2599c529dd9d6152a4cdb91e68822d7c3042d896011f2fa7bef9635caa082ce233302f74f431a65179e97245d432c0fe73e834
|
|
7
|
+
data.tar.gz: 2e4973efa5a08199438d2d420cfbe42c253c6d4aaedfdd61962ff3ccf34d93c40dd227b6e5d191c506d2cbf5786214883280a1c78ab21df4a90697d6f19cc373
|
|
@@ -37,7 +37,7 @@ Then render the engine layout from your application layout. Place all `content_f
|
|
|
37
37
|
|
|
38
38
|
## Layout structure
|
|
39
39
|
|
|
40
|
-
The engine layout provides a fixed header (63px), optional sidebar navigation (
|
|
40
|
+
The engine layout provides a fixed header (63px), optional sidebar navigation (256px wide), optional resizable panel (320px default), and a main content area. Dark mode is built in with a toggle and localStorage persistence.
|
|
41
41
|
|
|
42
42
|
### Content blocks
|
|
43
43
|
|
|
@@ -140,7 +140,7 @@ Drag handle for resizing the panel width on desktop.
|
|
|
140
140
|
**Keyboard:** Arrow Left/Right (10px), Shift+Arrow (50px), Home/End
|
|
141
141
|
**Storage key:** `panelWidth` (pixel value)
|
|
142
142
|
|
|
143
|
-
- Min width:
|
|
143
|
+
- Min width: 256px
|
|
144
144
|
- Default width: 480px
|
|
145
145
|
- Double-click handle to reset to default
|
|
146
146
|
|
|
@@ -271,7 +271,6 @@ Always combine the base block with a modifier, e.g. `<span class="l-ui-badge l-u
|
|
|
271
271
|
.l-ui-panel__button--dragging During drag
|
|
272
272
|
.l-ui-panel__button--snapping Snapping to edge
|
|
273
273
|
.l-ui-panel__button--hidden Hidden when panel is open (toggled by Stimulus)
|
|
274
|
-
.l-ui-panel__close-button Panel close button (combine with l-ui-button l-ui-button--icon)
|
|
275
274
|
.l-ui-panel__icon Panel button inline SVG icon
|
|
276
275
|
.l-ui-panel__icon--light Panel button icon (light, for custom image override)
|
|
277
276
|
.l-ui-panel__icon--dark Panel button icon (dark, for custom image override)
|
data/AGENTS.md
CHANGED
|
@@ -6,7 +6,7 @@ Guidance for AI agents working in this repository.
|
|
|
6
6
|
|
|
7
7
|
- **Entry:** `require "layered-ui-rails"` → `lib/layered/ui.rb` → `lib/layered/ui/engine.rb`
|
|
8
8
|
- **Engine:** importmap, assets, Pagy helpers when present; helpers: `AuthenticationHelper`, `NavigationHelper`, `PagyHelper`
|
|
9
|
-
- **CSS** `app/assets/tailwind/layered/ui/styles.css`: OKLCH tokens, `.dark` on `<html>`, `@theme` utilities (`bg-background`, etc.), BEM components (`.l-ui-button--primary`, etc.). Layout: 63px header,
|
|
9
|
+
- **CSS** `app/assets/tailwind/layered/ui/styles.css`: OKLCH tokens, `.dark` on `<html>`, `@theme` utilities (`bg-background`, etc.), BEM components (`.l-ui-button--primary`, etc.). Layout: 63px header, 256px sidebar, 320px panel. WCAG 2.2 AA.
|
|
10
10
|
- **CSS `@apply`:** Multi-line with grouping, following the Prettier Tailwind plugin order: layout → sizing → spacing → typography → backgrounds → borders → effects → transitions → interactivity. Within each group, follow Tailwind's own ordering (not alphabetical). State variants (`hover:`, `focus:`, `active:`, `disabled:`) and responsive prefixes (`sm:`, `md:`, `lg:`) are grouped with their base utility. Single utilities may stay on one line.
|
|
11
11
|
- **Generators:** `bin/rails generate layered:ui:install` (copy CSS, import CSS, import JS)
|
|
12
12
|
- **JS** `app/javascript/layered_ui/`: Stimulus controllers registered as `l-ui--theme`, `l-ui--navigation`, `l-ui--panel`, `l-ui--modal`, `l-ui--tabs`
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
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.15.0] - 2026-05-11
|
|
6
|
+
|
|
7
|
+
### Breaking
|
|
8
|
+
|
|
9
|
+
- `l-ui-panel__close-button` modifier removed; the panel close button is now an `l-ui-button--outline l-ui-button--icon`
|
|
10
|
+
- Navigation width increased from 240px to 256px (affects `NAV_WIDTH` consumers and the panel resize minimum width)
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `icon_panel_close.svg` asset for the panel close button
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- Borders removed from navigation container (right and top), navigation user block, panel container (left edge), and panel header
|
|
19
|
+
- `h2` elements now have a bottom border for stronger visual separation
|
|
20
|
+
- Table cell padding evened out to `p-2`
|
|
21
|
+
- Panel header padding adjusted (`p-4 pb-0`) and header button gap increased to `gap-4`
|
|
22
|
+
- Modal backdrop click detection now uses the dialog's bounding rect, so clicks on the dialog's own padding no longer close it
|
|
23
|
+
- Navigation item corners rounded on the left only (`rounded-l-sm`)
|
|
24
|
+
|
|
5
25
|
## [0.14.0] - 2026-05-10
|
|
6
26
|
|
|
7
27
|
### Breaking
|
|
@@ -118,7 +118,8 @@
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
h2 {
|
|
121
|
-
@apply heading text-lg
|
|
121
|
+
@apply heading text-lg
|
|
122
|
+
border-b border-border pb-2;
|
|
122
123
|
}
|
|
123
124
|
|
|
124
125
|
h3 {
|
|
@@ -456,7 +457,7 @@
|
|
|
456
457
|
}
|
|
457
458
|
|
|
458
459
|
.l-ui-body--always-show-navigation .l-ui-page--with-navigation {
|
|
459
|
-
@apply md:ml-[
|
|
460
|
+
@apply md:ml-[256px];
|
|
460
461
|
}
|
|
461
462
|
|
|
462
463
|
.l-ui-page__vertically-centered {
|
|
@@ -585,11 +586,10 @@
|
|
|
585
586
|
/* Navigation */
|
|
586
587
|
|
|
587
588
|
.l-ui-navigation-container {
|
|
588
|
-
@apply fixed top-[var(--header-height)] left-0 bottom-0
|
|
589
|
+
@apply fixed top-[calc(var(--header-height)+1px)] left-0 bottom-0
|
|
589
590
|
z-50
|
|
590
|
-
w-[
|
|
591
|
+
w-[256px]
|
|
591
592
|
bg-background
|
|
592
|
-
border-t border-border
|
|
593
593
|
-translate-x-full
|
|
594
594
|
transition-transform duration-300;
|
|
595
595
|
}
|
|
@@ -632,7 +632,7 @@
|
|
|
632
632
|
w-full min-h-[40px]
|
|
633
633
|
gap-3 px-3
|
|
634
634
|
text-sm font-medium text-foreground-muted
|
|
635
|
-
rounded-sm
|
|
635
|
+
rounded-l-sm
|
|
636
636
|
focus-ring
|
|
637
637
|
transition-colors;
|
|
638
638
|
}
|
|
@@ -726,13 +726,12 @@
|
|
|
726
726
|
.l-ui-navigation__links {
|
|
727
727
|
@apply flex flex-col flex-1 overflow-y-auto
|
|
728
728
|
min-h-0
|
|
729
|
-
gap-0.5 px-3
|
|
729
|
+
gap-0.5 px-3 py-3;
|
|
730
730
|
}
|
|
731
731
|
|
|
732
732
|
.l-ui-navigation__user {
|
|
733
733
|
@apply shrink-0
|
|
734
|
-
p-4
|
|
735
|
-
border-t border-border;
|
|
734
|
+
p-4;
|
|
736
735
|
}
|
|
737
736
|
|
|
738
737
|
.l-ui-navigation__user-name-and-email {
|
|
@@ -1268,7 +1267,7 @@ pre.l-ui-surface {
|
|
|
1268
1267
|
}
|
|
1269
1268
|
|
|
1270
1269
|
.l-ui-table__cell {
|
|
1271
|
-
@apply
|
|
1270
|
+
@apply p-2
|
|
1272
1271
|
text-sm whitespace-nowrap text-foreground-muted;
|
|
1273
1272
|
}
|
|
1274
1273
|
|
|
@@ -1486,7 +1485,6 @@ pre.l-ui-surface {
|
|
|
1486
1485
|
z-40
|
|
1487
1486
|
w-full md:w-[480px]
|
|
1488
1487
|
bg-background
|
|
1489
|
-
md:border-l md:border-border
|
|
1490
1488
|
transform translate-x-full
|
|
1491
1489
|
transition-transform duration-300;
|
|
1492
1490
|
}
|
|
@@ -1523,19 +1521,18 @@ pre.l-ui-surface {
|
|
|
1523
1521
|
}
|
|
1524
1522
|
|
|
1525
1523
|
.l-ui-panel__header {
|
|
1526
|
-
@apply flex flex-col
|
|
1527
|
-
border-b border-border;
|
|
1524
|
+
@apply flex flex-col;
|
|
1528
1525
|
}
|
|
1529
1526
|
|
|
1530
1527
|
.l-ui-panel__header-content {
|
|
1531
1528
|
@apply flex items-center
|
|
1532
|
-
|
|
1529
|
+
p-4 pb-0;
|
|
1533
1530
|
}
|
|
1534
1531
|
|
|
1535
1532
|
.l-ui-panel__header-buttons {
|
|
1536
1533
|
@apply flex items-center
|
|
1537
1534
|
w-full
|
|
1538
|
-
gap-
|
|
1535
|
+
gap-4;
|
|
1539
1536
|
}
|
|
1540
1537
|
|
|
1541
1538
|
.l-ui-panel__header-heading {
|
|
@@ -1551,10 +1548,6 @@ pre.l-ui-surface {
|
|
|
1551
1548
|
gap-2;
|
|
1552
1549
|
}
|
|
1553
1550
|
|
|
1554
|
-
.l-ui-panel__close-button {
|
|
1555
|
-
@apply -mr-4;
|
|
1556
|
-
}
|
|
1557
|
-
|
|
1558
1551
|
.l-ui-panel__body {
|
|
1559
1552
|
@apply flex-1 overflow-y-auto overscroll-contain
|
|
1560
1553
|
p-4 space-y-4;
|
|
@@ -39,9 +39,20 @@ export default class extends Controller {
|
|
|
39
39
|
this.dialogTarget.close()
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
// Close the modal when clicking outside the dialog
|
|
42
|
+
// Close the modal when clicking outside the dialog rect (on the backdrop).
|
|
43
|
+
// Comparing against event.target alone is unreliable: clicks on the dialog's
|
|
44
|
+
// own padding/empty space also have target === dialog, which would close it.
|
|
43
45
|
closeOnBackdrop(event) {
|
|
44
|
-
if (event.target
|
|
46
|
+
if (event.target !== this.dialogTarget) return
|
|
47
|
+
|
|
48
|
+
const rect = this.dialogTarget.getBoundingClientRect()
|
|
49
|
+
const insideDialog =
|
|
50
|
+
event.clientX >= rect.left &&
|
|
51
|
+
event.clientX <= rect.right &&
|
|
52
|
+
event.clientY >= rect.top &&
|
|
53
|
+
event.clientY <= rect.bottom
|
|
54
|
+
|
|
55
|
+
if (!insideDialog) {
|
|
45
56
|
this.close()
|
|
46
57
|
}
|
|
47
58
|
}
|
|
@@ -2,7 +2,7 @@ import { Controller } from "@hotwired/stimulus"
|
|
|
2
2
|
import { storageGet, storageSet, storageRemove } from "layered_ui/utilities/storage"
|
|
3
3
|
import { isMobile, hasNavigation, NAV_WIDTH } from "layered_ui/utilities/layout"
|
|
4
4
|
|
|
5
|
-
const MIN_WIDTH =
|
|
5
|
+
const MIN_WIDTH = 256
|
|
6
6
|
const DEFAULT_WIDTH = 480
|
|
7
7
|
|
|
8
8
|
export default class extends Controller {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
aria-label="Resize panel"
|
|
18
18
|
aria-orientation="vertical"
|
|
19
19
|
aria-valuenow="480"
|
|
20
|
-
aria-valuemin="
|
|
20
|
+
aria-valuemin="256"
|
|
21
21
|
aria-valuemax="1200"
|
|
22
22
|
aria-valuetext="Panel width: 480 pixels"
|
|
23
23
|
tabindex="0"
|
|
@@ -35,13 +35,13 @@
|
|
|
35
35
|
|
|
36
36
|
<div class="l-ui-panel__header-actions">
|
|
37
37
|
<button type="button"
|
|
38
|
-
class="l-ui-button l-ui-button--
|
|
38
|
+
class="l-ui-button l-ui-button--outline l-ui-button--icon"
|
|
39
39
|
aria-label="Hide panel"
|
|
40
40
|
aria-controls="panel"
|
|
41
41
|
title="Toggle panel (Ctrl+i / ⌘i)"
|
|
42
42
|
data-action="click->l-ui--panel#toggle"
|
|
43
43
|
data-l-ui--panel-target="hideButton">
|
|
44
|
-
<%= image_tag "layered_ui/
|
|
44
|
+
<%= image_tag "layered_ui/icon_panel_close.svg", alt: "", class: "l-ui-icon l-ui-icon--sm", aria: { hidden: true } %>
|
|
45
45
|
</button>
|
|
46
46
|
</div>
|
|
47
47
|
</div>
|
data/lib/layered/ui/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: layered-ui-rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.15.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- layered.ai
|
|
@@ -201,6 +201,7 @@ files:
|
|
|
201
201
|
- app/assets/images/layered_ui/icon_linkedin.svg
|
|
202
202
|
- app/assets/images/layered_ui/icon_mail.svg
|
|
203
203
|
- app/assets/images/layered_ui/icon_moon.svg
|
|
204
|
+
- app/assets/images/layered_ui/icon_panel_close.svg
|
|
204
205
|
- app/assets/images/layered_ui/icon_sun.svg
|
|
205
206
|
- app/assets/images/layered_ui/icon_x.svg
|
|
206
207
|
- app/assets/images/layered_ui/icon_youtube.svg
|