layered-ui-rails 0.8.0 → 0.9.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 -0
- data/.claude/skills/layered-ui-rails/references/CONTROLLERS.md +1 -0
- data/.claude/skills/layered-ui-rails/references/CSS.md +10 -0
- data/.claude/skills/layered-ui-rails/references/HELPERS.md +23 -0
- data/CHANGELOG.md +14 -1
- data/app/assets/tailwind/layered/ui/styles.css +36 -4
- data/app/helpers/layered/ui/title_bar_helper.rb +52 -0
- data/app/javascript/layered_ui/controllers/l_ui/navigation_controller.js +29 -0
- data/app/javascript/layered_ui/controllers/l_ui/panel_controller.js +19 -8
- data/app/javascript/layered_ui/utilities/scroll_lock.js +29 -0
- data/app/views/layered/ui/managed_resource/_form.html.erb +1 -1
- data/config/importmap.rb +1 -0
- data/lib/layered/ui/engine.rb +1 -0
- data/lib/layered/ui/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ff66e126597c535133ec15b8fa13fd0efeecfe319b9a60d383b051ce111234e1
|
|
4
|
+
data.tar.gz: 25872e652c050f87c8752a43b8f9184ee3f98f888a7b30086efa4531c329ed1a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 22e3a324fb57843766fc6b243071b305508d88dc8ca00dd428cce23eebb7f965cab8be974fcaeef365e74ba142bff59d28f2b8b9680ff50ab3853c94d1806079
|
|
7
|
+
data.tar.gz: d0e60d24e524aad6516e2e070db67e31d7eb049d63334f36d99463d2cd2cb392ce8e863070f1952d5387096f5bc5ec06c172346ba57c3fe2b4a78ceeb6cbe4fc
|
|
@@ -106,6 +106,7 @@ Quick reference:
|
|
|
106
106
|
| `l_ui_navigation_item(label, path, active: nil, &block)` | Sidebar nav link with optional nesting |
|
|
107
107
|
| `l_ui_breadcrumbs(&block)` | Breadcrumb nav wrapper |
|
|
108
108
|
| `l_ui_breadcrumb_item(label, path = nil)` | Individual breadcrumb |
|
|
109
|
+
| `l_ui_title_bar(title:, breadcrumbs: [], actions: nil, &block)` | Responsive page title bar with breadcrumbs and actions |
|
|
109
110
|
| `l_ui_pagy(pagy)` | Styled pagination (requires pagy gem) |
|
|
110
111
|
| `l_ui_search_form(query, url:, fields:, ...)` | Search form (requires ransack gem) |
|
|
111
112
|
| `l_ui_sort_link(query, attribute, label = nil, ...)` | Sortable table header (requires ransack gem) |
|
|
@@ -28,6 +28,7 @@ Responsive sidebar navigation with backdrop overlay on mobile.
|
|
|
28
28
|
**Targets:** `navigation`, `backdrop`, `toggleButton`, `openIcon`, `closeIcon`
|
|
29
29
|
**Actions:** `toggle`, `close`
|
|
30
30
|
**Keyboard:** Escape to close
|
|
31
|
+
**Behaviour:** Locks body scroll while the mobile overlay is open
|
|
31
32
|
|
|
32
33
|
The layout wires this up automatically. Navigation items are populated via `content_for :l_ui_navigation_items`.
|
|
33
34
|
|
|
@@ -170,6 +170,15 @@ WCAG 2.2 AA table pattern:
|
|
|
170
170
|
.l-ui-breadcrumbs__link Breadcrumb link
|
|
171
171
|
```
|
|
172
172
|
|
|
173
|
+
## Title bar
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
.l-ui-title-bar Title bar wrapper used with .l-ui-container--spread
|
|
177
|
+
.l-ui-title-bar__content Breadcrumbs and title column
|
|
178
|
+
.l-ui-title-bar__title Page title
|
|
179
|
+
.l-ui-title-bar__actions Action area
|
|
180
|
+
```
|
|
181
|
+
|
|
173
182
|
## Pagination
|
|
174
183
|
|
|
175
184
|
```
|
|
@@ -275,6 +284,7 @@ WCAG 2.2 AA table pattern:
|
|
|
275
284
|
.l-ui-sr-only Visually hidden, screen reader only
|
|
276
285
|
.l-ui-skip-link Accessibility skip link
|
|
277
286
|
.l-ui-list Styled list
|
|
287
|
+
.l-ui-hr Horizontal rule with theme border and vertical spacing
|
|
278
288
|
.l-ui-container--grid 1-col mobile, 2-col desktop grid
|
|
279
289
|
.l-ui-container--spread Flex row with space-between
|
|
280
290
|
.l-ui-container--pagy Pagination wrapper
|
|
@@ -41,6 +41,29 @@ l_ui_breadcrumb_item(label, path = nil)
|
|
|
41
41
|
<% end %>
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
+
## Title bar
|
|
45
|
+
|
|
46
|
+
```ruby
|
|
47
|
+
l_ui_title_bar(title:, breadcrumbs: [], actions: nil, &block)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
- `title` (String) - page title rendered as the `<h1>`
|
|
51
|
+
- `breadcrumbs` (Array, optional) - breadcrumb items as `[label, path]` arrays or `{ label:, path: }` hashes
|
|
52
|
+
- `actions` (String|Array, optional) - HTML-safe action content; omit when using a block
|
|
53
|
+
- `&block` - optional action markup, usually buttons or links
|
|
54
|
+
|
|
55
|
+
```erb
|
|
56
|
+
<%= l_ui_title_bar(
|
|
57
|
+
title: "Users",
|
|
58
|
+
breadcrumbs: [
|
|
59
|
+
["Home", root_path],
|
|
60
|
+
["Admin", admin_path]
|
|
61
|
+
]
|
|
62
|
+
) do %>
|
|
63
|
+
<%= link_to "New user", new_user_path, class: "l-ui-button--primary" %>
|
|
64
|
+
<% end %>
|
|
65
|
+
```
|
|
66
|
+
|
|
44
67
|
## Pagination (requires pagy gem)
|
|
45
68
|
|
|
46
69
|
```ruby
|
data/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,20 @@
|
|
|
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
|
-
## [
|
|
5
|
+
## [0.9.0] - 2026-04-26
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- `l_ui_title_bar` helper for page title bars with optional actions
|
|
10
|
+
- `l-ui-hr` class for styled horizontal rules
|
|
11
|
+
- `color-scheme` CSS property set to match the active theme so native form controls (date pickers, scrollbars, etc.) render with matching light/dark styling
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- Navigation and panel controllers share an extracted `scroll_lock` utility module
|
|
16
|
+
- Checkbox and radio inputs use a pointer cursor
|
|
17
|
+
- Scroll-to-bottom button is centred and has a faint shadow
|
|
18
|
+
- Form submit label shortened from "Save changes" to "Save"
|
|
6
19
|
|
|
7
20
|
## [0.8.0] - 2026-04-24
|
|
8
21
|
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
|
|
48
48
|
@layer base {
|
|
49
49
|
:root {
|
|
50
|
+
color-scheme: light;
|
|
50
51
|
/* Tier 1 - Accent */
|
|
51
52
|
--accent: oklch(0.2044 0 0);
|
|
52
53
|
--accent-foreground: oklch(1 0 0);
|
|
@@ -76,6 +77,7 @@
|
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
.dark {
|
|
80
|
+
color-scheme: dark;
|
|
79
81
|
/* Tier 1 - Accent */
|
|
80
82
|
--accent: oklch(1 0 0);
|
|
81
83
|
--accent-foreground: oklch(0.2044 0 0);
|
|
@@ -294,6 +296,13 @@
|
|
|
294
296
|
space-y-1;
|
|
295
297
|
}
|
|
296
298
|
|
|
299
|
+
/* Horizontal rule */
|
|
300
|
+
|
|
301
|
+
.l-ui-hr {
|
|
302
|
+
@apply my-4
|
|
303
|
+
border-0 border-t border-border;
|
|
304
|
+
}
|
|
305
|
+
|
|
297
306
|
/* Markdown */
|
|
298
307
|
|
|
299
308
|
.l-ui-markdown > *:first-child {
|
|
@@ -740,6 +749,26 @@
|
|
|
740
749
|
focus-ring rounded-sm;
|
|
741
750
|
}
|
|
742
751
|
|
|
752
|
+
/* Title bar */
|
|
753
|
+
|
|
754
|
+
.l-ui-title-bar {
|
|
755
|
+
@apply w-full;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
.l-ui-title-bar__content {
|
|
759
|
+
@apply min-w-0;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
.l-ui-title-bar__title {
|
|
763
|
+
@apply mt-0;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
.l-ui-title-bar__actions {
|
|
767
|
+
@apply flex flex-wrap items-center justify-end
|
|
768
|
+
gap-2
|
|
769
|
+
shrink-0;
|
|
770
|
+
}
|
|
771
|
+
|
|
743
772
|
/* Buttons */
|
|
744
773
|
|
|
745
774
|
@utility button {
|
|
@@ -1017,7 +1046,8 @@ pre.l-ui-surface {
|
|
|
1017
1046
|
@apply w-6 h-6
|
|
1018
1047
|
accent-foreground
|
|
1019
1048
|
focus-ring
|
|
1020
|
-
rounded-sm
|
|
1049
|
+
rounded-sm
|
|
1050
|
+
cursor-pointer;
|
|
1021
1051
|
}
|
|
1022
1052
|
|
|
1023
1053
|
/* Search */
|
|
@@ -1124,11 +1154,12 @@ pre.l-ui-surface {
|
|
|
1124
1154
|
@apply w-6 h-6
|
|
1125
1155
|
mr-2
|
|
1126
1156
|
accent-foreground
|
|
1127
|
-
focus-ring
|
|
1157
|
+
focus-ring
|
|
1158
|
+
cursor-pointer;
|
|
1128
1159
|
}
|
|
1129
1160
|
|
|
1130
1161
|
.l-ui-radio__label {
|
|
1131
|
-
@apply text-sm;
|
|
1162
|
+
@apply text-sm cursor-pointer;
|
|
1132
1163
|
}
|
|
1133
1164
|
|
|
1134
1165
|
/* Tabs */
|
|
@@ -1659,10 +1690,11 @@ pre.l-ui-surface {
|
|
|
1659
1690
|
.l-ui-scroll-to-bottom {
|
|
1660
1691
|
@apply
|
|
1661
1692
|
sticky bottom-2 flex items-center justify-center
|
|
1662
|
-
|
|
1693
|
+
mx-auto -mt-9 h-9 w-9
|
|
1663
1694
|
rounded-full
|
|
1664
1695
|
cursor-pointer
|
|
1665
1696
|
bg-button-primary-bg text-button-primary-icon
|
|
1697
|
+
shadow-sm
|
|
1666
1698
|
focus-ring
|
|
1667
1699
|
opacity-0 pointer-events-none
|
|
1668
1700
|
transition-opacity duration-200;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module Layered
|
|
2
|
+
module Ui
|
|
3
|
+
module TitleBarHelper
|
|
4
|
+
include Layered::Ui::BreadcrumbsHelper
|
|
5
|
+
|
|
6
|
+
def l_ui_title_bar(title:, breadcrumbs: [], actions: nil, &block)
|
|
7
|
+
action_content = block_given? ? capture(&block) : actions
|
|
8
|
+
|
|
9
|
+
content_tag(:header, class: "l-ui-title-bar l-ui-container--spread") do
|
|
10
|
+
safe_join([
|
|
11
|
+
content_tag(:div, class: "l-ui-title-bar__content") do
|
|
12
|
+
safe_join([
|
|
13
|
+
l_ui_title_bar_breadcrumbs(breadcrumbs),
|
|
14
|
+
content_tag(:h1, title, class: "l-ui-title-bar__title")
|
|
15
|
+
].compact)
|
|
16
|
+
end,
|
|
17
|
+
l_ui_title_bar_actions(action_content)
|
|
18
|
+
].compact)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def l_ui_title_bar_breadcrumbs(breadcrumbs)
|
|
25
|
+
return if breadcrumbs.blank?
|
|
26
|
+
|
|
27
|
+
l_ui_breadcrumbs do
|
|
28
|
+
safe_join(breadcrumbs.map { |breadcrumb| l_ui_title_bar_breadcrumb_item(breadcrumb) })
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def l_ui_title_bar_breadcrumb_item(breadcrumb)
|
|
33
|
+
case breadcrumb
|
|
34
|
+
when Hash
|
|
35
|
+
l_ui_breadcrumb_item(breadcrumb.fetch(:label), breadcrumb[:path])
|
|
36
|
+
when Array
|
|
37
|
+
l_ui_breadcrumb_item(breadcrumb[0], breadcrumb[1])
|
|
38
|
+
else
|
|
39
|
+
l_ui_breadcrumb_item(breadcrumb)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def l_ui_title_bar_actions(action_content)
|
|
44
|
+
return if action_content.blank?
|
|
45
|
+
|
|
46
|
+
content = action_content.is_a?(Array) ? safe_join(action_content) : action_content
|
|
47
|
+
|
|
48
|
+
content_tag(:div, content, class: "l-ui-title-bar__actions")
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Controller } from "@hotwired/stimulus"
|
|
2
2
|
import { announce, clearAnnounceTimeout } from "layered_ui/utilities/announce"
|
|
3
3
|
import { isMobile } from "layered_ui/utilities/layout"
|
|
4
|
+
import { lockBodyScroll, unlockBodyScroll } from "layered_ui/utilities/scroll_lock"
|
|
4
5
|
|
|
5
6
|
export default class extends Controller {
|
|
6
7
|
static targets = ["navigation", "backdrop", "toggleButton", "openIcon", "closeIcon"]
|
|
@@ -8,6 +9,7 @@ export default class extends Controller {
|
|
|
8
9
|
connect() {
|
|
9
10
|
this.previousActiveElement = null
|
|
10
11
|
this.isOpen = false
|
|
12
|
+
this.isScrollLocked = false
|
|
11
13
|
this._resizeFrame = null
|
|
12
14
|
this.boundHandleResize = () => {
|
|
13
15
|
if (this._resizeFrame) return
|
|
@@ -54,6 +56,7 @@ export default class extends Controller {
|
|
|
54
56
|
this.navigationTarget.classList.add("open")
|
|
55
57
|
this.backdropTarget.classList.add("open")
|
|
56
58
|
this.setNavigationInteractivity(true)
|
|
59
|
+
this.updateScrollLock()
|
|
57
60
|
|
|
58
61
|
// Update ARIA attributes and swap icons
|
|
59
62
|
if (this.hasToggleButtonTarget) {
|
|
@@ -89,6 +92,7 @@ export default class extends Controller {
|
|
|
89
92
|
this.navigationTarget.classList.remove("open")
|
|
90
93
|
this.backdropTarget.classList.remove("open")
|
|
91
94
|
this.setNavigationInteractivity(false)
|
|
95
|
+
this.unlockScroll()
|
|
92
96
|
|
|
93
97
|
// Update ARIA attributes and swap icons
|
|
94
98
|
if (this.hasToggleButtonTarget) {
|
|
@@ -116,6 +120,7 @@ export default class extends Controller {
|
|
|
116
120
|
clearAnnounceTimeout(this)
|
|
117
121
|
cancelAnimationFrame(this._resizeFrame)
|
|
118
122
|
window.removeEventListener("resize", this.boundHandleResize)
|
|
123
|
+
this.unlockScroll()
|
|
119
124
|
this.previousActiveElement = null
|
|
120
125
|
}
|
|
121
126
|
|
|
@@ -125,6 +130,7 @@ export default class extends Controller {
|
|
|
125
130
|
// In overlay mode (default), always respect isOpen state regardless of viewport
|
|
126
131
|
if (isMobile() || !this.alwaysShow) {
|
|
127
132
|
this.setNavigationInteractivity(this.isOpen)
|
|
133
|
+
this.updateScrollLock()
|
|
128
134
|
return
|
|
129
135
|
}
|
|
130
136
|
|
|
@@ -133,6 +139,7 @@ export default class extends Controller {
|
|
|
133
139
|
this.navigationTarget.classList.remove("open")
|
|
134
140
|
this.backdropTarget.classList.remove("open")
|
|
135
141
|
this.setNavigationInteractivity(true)
|
|
142
|
+
this.unlockScroll()
|
|
136
143
|
|
|
137
144
|
if (this.hasToggleButtonTarget) {
|
|
138
145
|
this.toggleButtonTarget.setAttribute("aria-expanded", "false")
|
|
@@ -157,6 +164,28 @@ export default class extends Controller {
|
|
|
157
164
|
this.navigationTarget.removeAttribute("aria-hidden")
|
|
158
165
|
}
|
|
159
166
|
|
|
167
|
+
updateScrollLock() {
|
|
168
|
+
if (this.isOpen && isMobile()) {
|
|
169
|
+
this.lockScroll()
|
|
170
|
+
} else {
|
|
171
|
+
this.unlockScroll()
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
lockScroll() {
|
|
176
|
+
if (this.isScrollLocked) return
|
|
177
|
+
|
|
178
|
+
lockBodyScroll()
|
|
179
|
+
this.isScrollLocked = true
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
unlockScroll() {
|
|
183
|
+
if (!this.isScrollLocked) return
|
|
184
|
+
|
|
185
|
+
unlockBodyScroll()
|
|
186
|
+
this.isScrollLocked = false
|
|
187
|
+
}
|
|
188
|
+
|
|
160
189
|
get alwaysShow() {
|
|
161
190
|
return this.element.classList.contains("l-ui-body--always-show-navigation")
|
|
162
191
|
}
|
|
@@ -2,6 +2,7 @@ import { Controller } from "@hotwired/stimulus"
|
|
|
2
2
|
import { announce, clearAnnounceTimeout } from "layered_ui/utilities/announce"
|
|
3
3
|
import { storageGet, storageSet } from "layered_ui/utilities/storage"
|
|
4
4
|
import { isMobile } from "layered_ui/utilities/layout"
|
|
5
|
+
import { lockBodyScroll, unlockBodyScroll } from "layered_ui/utilities/scroll_lock"
|
|
5
6
|
|
|
6
7
|
export default class extends Controller {
|
|
7
8
|
static targets = ["container", "hideButton", "actionButton"]
|
|
@@ -9,6 +10,7 @@ export default class extends Controller {
|
|
|
9
10
|
connect() {
|
|
10
11
|
this.previousActiveElement = null
|
|
11
12
|
this.isOpen = false
|
|
13
|
+
this.isScrollLocked = false
|
|
12
14
|
this.boundKeyboardShortcut = this.handleKeyboardShortcut.bind(this)
|
|
13
15
|
this.boundCloseOnNavigate = this.closeOnMobileNavigate.bind(this)
|
|
14
16
|
const page = document.querySelector(".l-ui-page")
|
|
@@ -34,6 +36,7 @@ export default class extends Controller {
|
|
|
34
36
|
clearAnnounceTimeout(this)
|
|
35
37
|
document.removeEventListener('keydown', this.boundKeyboardShortcut)
|
|
36
38
|
document.removeEventListener('turbo:visit', this.boundCloseOnNavigate)
|
|
39
|
+
this.unlockScroll()
|
|
37
40
|
this.previousActiveElement = null
|
|
38
41
|
}
|
|
39
42
|
|
|
@@ -90,9 +93,7 @@ export default class extends Controller {
|
|
|
90
93
|
if (isMobile()) {
|
|
91
94
|
const main = document.querySelector("main")
|
|
92
95
|
if (main) main.setAttribute("inert", "")
|
|
93
|
-
this.
|
|
94
|
-
document.body.style.top = `-${this.savedScrollY}px`
|
|
95
|
-
document.body.classList.add("l-ui-scroll-lock")
|
|
96
|
+
this.lockScroll()
|
|
96
97
|
}
|
|
97
98
|
|
|
98
99
|
storageSet("panelOpen", "true")
|
|
@@ -124,11 +125,7 @@ export default class extends Controller {
|
|
|
124
125
|
|
|
125
126
|
const main = document.querySelector("main")
|
|
126
127
|
if (main) main.removeAttribute("inert")
|
|
127
|
-
|
|
128
|
-
document.body.style.top = ""
|
|
129
|
-
if (this.savedScrollY !== undefined) {
|
|
130
|
-
window.scrollTo(0, this.savedScrollY)
|
|
131
|
-
}
|
|
128
|
+
this.unlockScroll()
|
|
132
129
|
|
|
133
130
|
storageSet("panelOpen", "false")
|
|
134
131
|
this.updatePageMargin()
|
|
@@ -161,4 +158,18 @@ export default class extends Controller {
|
|
|
161
158
|
page.style.marginRight = ""
|
|
162
159
|
}
|
|
163
160
|
}
|
|
161
|
+
|
|
162
|
+
lockScroll() {
|
|
163
|
+
if (this.isScrollLocked) return
|
|
164
|
+
|
|
165
|
+
lockBodyScroll()
|
|
166
|
+
this.isScrollLocked = true
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
unlockScroll() {
|
|
170
|
+
if (!this.isScrollLocked) return
|
|
171
|
+
|
|
172
|
+
unlockBodyScroll()
|
|
173
|
+
this.isScrollLocked = false
|
|
174
|
+
}
|
|
164
175
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
let lockCount = 0
|
|
2
|
+
let savedScrollY = null
|
|
3
|
+
|
|
4
|
+
export function lockBodyScroll() {
|
|
5
|
+
if (lockCount === 0) {
|
|
6
|
+
savedScrollY = window.scrollY
|
|
7
|
+
document.body.style.top = `-${savedScrollY}px`
|
|
8
|
+
document.body.classList.add("l-ui-scroll-lock")
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
lockCount++
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function unlockBodyScroll() {
|
|
15
|
+
if (lockCount === 0) return
|
|
16
|
+
|
|
17
|
+
lockCount--
|
|
18
|
+
|
|
19
|
+
if (lockCount === 0) {
|
|
20
|
+
document.body.classList.remove("l-ui-scroll-lock")
|
|
21
|
+
document.body.style.top = ""
|
|
22
|
+
|
|
23
|
+
if (savedScrollY !== null) {
|
|
24
|
+
window.scrollTo(0, savedScrollY)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
savedScrollY = null
|
|
28
|
+
}
|
|
29
|
+
}
|
data/config/importmap.rb
CHANGED
|
@@ -3,6 +3,7 @@ pin "layered_ui", to: "layered_ui/index.js"
|
|
|
3
3
|
# Utilities
|
|
4
4
|
pin "layered_ui/utilities/announce", to: "layered_ui/utilities/announce.js"
|
|
5
5
|
pin "layered_ui/utilities/layout", to: "layered_ui/utilities/layout.js"
|
|
6
|
+
pin "layered_ui/utilities/scroll_lock", to: "layered_ui/utilities/scroll_lock.js"
|
|
6
7
|
pin "layered_ui/utilities/storage", to: "layered_ui/utilities/storage.js"
|
|
7
8
|
|
|
8
9
|
# Controllers
|
data/lib/layered/ui/engine.rb
CHANGED
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.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- layered.ai
|
|
@@ -215,6 +215,7 @@ files:
|
|
|
215
215
|
- app/helpers/layered/ui/pagy_helper.rb
|
|
216
216
|
- app/helpers/layered/ui/ransack_helper.rb
|
|
217
217
|
- app/helpers/layered/ui/table_helper.rb
|
|
218
|
+
- app/helpers/layered/ui/title_bar_helper.rb
|
|
218
219
|
- app/javascript/layered_ui/controllers/l_ui/modal_controller.js
|
|
219
220
|
- app/javascript/layered_ui/controllers/l_ui/navigation_controller.js
|
|
220
221
|
- app/javascript/layered_ui/controllers/l_ui/panel_button_controller.js
|
|
@@ -226,6 +227,7 @@ files:
|
|
|
226
227
|
- app/javascript/layered_ui/index.js
|
|
227
228
|
- app/javascript/layered_ui/utilities/announce.js
|
|
228
229
|
- app/javascript/layered_ui/utilities/layout.js
|
|
230
|
+
- app/javascript/layered_ui/utilities/scroll_lock.js
|
|
229
231
|
- app/javascript/layered_ui/utilities/storage.js
|
|
230
232
|
- app/views/devise/confirmations/new.html.erb
|
|
231
233
|
- app/views/devise/mailer/confirmation_instructions.html.erb
|