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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dd3b300ca92cbb2d2bc81086f5bc641f5124ce17e9ee8bfe509bca379fea9a32
4
- data.tar.gz: 4dd8fadd0855594730d434e48dcd3eee163c0d8c3859212cfcfaa67a3856ccdb
3
+ metadata.gz: 21924f2cc31a2154c80002c22b304b3061eee7af0c6a6b80221932c62f17c0cd
4
+ data.tar.gz: 74c95e1eae950256dd07ab02a426ba77c3e213087709f92e9256e94b52eba987
5
5
  SHA512:
6
- metadata.gz: 4f55763d1411e9d97fba34b3d7cebf22642c7aed74679e9f4218bc6389145acf3f2a5503cabfa9d0157ddc7873f9b337be0d7821349e33c2283b710568a9b773
7
- data.tar.gz: 0fd9a835309c100a8a15968a55843fd7d857fc941a0e77686881fa022d244add42addd67c3c76931fea6dd2c7565dc69df3cee45ee12a11cc78215cb57bdf85a
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 (240px wide), optional resizable panel (320px default), and a main content area. Dark mode is built in with a toggle and localStorage persistence.
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: 240px
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, 240px sidebar, 320px panel. WCAG 2.2 AA.
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
@@ -0,0 +1,4 @@
1
+ <svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
2
+ <path stroke-linecap="round" stroke-linejoin="round" d="M9 8l4 4-4 4" />
3
+ <path stroke-linecap="round" stroke-linejoin="round" d="M19 4v16" />
4
+ </svg>
@@ -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-[240px];
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-[240px]
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 md:pr-0 py-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 px-2 py-2.5
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
- px-4 py-2;
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-2;
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 === this.dialogTarget) {
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 = 240
5
+ const MIN_WIDTH = 256
6
6
  const DEFAULT_WIDTH = 480
7
7
 
8
8
  export default class extends Controller {
@@ -1,5 +1,5 @@
1
1
  export const MOBILE_BREAKPOINT = 768
2
- export const NAV_WIDTH = 240
2
+ export const NAV_WIDTH = 256
3
3
 
4
4
  export function isMobile() {
5
5
  return window.innerWidth < MOBILE_BREAKPOINT
@@ -17,7 +17,7 @@
17
17
  aria-label="Resize panel"
18
18
  aria-orientation="vertical"
19
19
  aria-valuenow="480"
20
- aria-valuemin="240"
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--icon l-ui-panel__close-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/icon_chevron_right.svg", alt: "", class: "l-ui-icon l-ui-icon--sm", aria: { hidden: true } %>
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>
@@ -1,5 +1,5 @@
1
1
  module Layered
2
2
  module Ui
3
- VERSION = "0.14.0"
3
+ VERSION = "0.15.0"
4
4
  end
5
5
  end
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.14.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