layered-ui-rails 0.1.2 → 0.1.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/CHANGELOG.md +22 -0
- data/CLA.md +3 -3
- data/LICENSE +1 -1
- data/NOTICE +3 -3
- data/README.md +4 -1
- data/TRADEMARK.md +2 -2
- data/app/assets/tailwind/layered/ui/styles.css +57 -27
- data/app/javascript/layered_ui/controllers/l_ui/panel_controller.js +19 -2
- data/app/views/devise/sessions/new.html.erb +1 -1
- data/app/views/layouts/layered_ui/_panel.html.erb +1 -1
- data/lib/layered/ui/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 417904020be6218b684bb12df4c6089c04d79334ec1cd65a207de6b21e3cda15
|
|
4
|
+
data.tar.gz: 67b5030949e4b2722d2fc341d7fed3dcfd3f8d48dc4b90e6905e651dc6ecc6b8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '05296252d95be8c3a4971351ba9a23b9481d026e27bd931ff4b69a0c53a53574d30174162c69895a6ecc4294e0bf8db5b84e3478b7b44ed3c9e6d9329efda56c'
|
|
7
|
+
data.tar.gz: cd87a0ef43243f98ddcb19d05cbe7d0d1f79ed52f0156e00924725eac9619ddc2c4a27bbb951d1b07df7c8e865cf8b74f93f80e5ef96ae36311e96686fa99b82
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,28 @@ All notable changes to this project will be documented in this file. This projec
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.1.3] - 2026-03-14
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- `l-ui-utility--mt-4` and `l-ui-utility--mt-8` margin-top utilities
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- Panel closes when navigating to a new page on mobile
|
|
16
|
+
- Panel button is now draggable on mobile
|
|
17
|
+
- Better Safari support for panel
|
|
18
|
+
- Cleaner link styles
|
|
19
|
+
- Updated message bubble avatar background
|
|
20
|
+
- Updated conversation rounding
|
|
21
|
+
- Removed top padding from panel conversations
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- Panel scrolling on mobile no longer scrolls the page behind it
|
|
26
|
+
- Panel not working on devise based controllers
|
|
27
|
+
- Issue with conversation container height
|
|
28
|
+
|
|
7
29
|
## [0.1.2] - 2026-02-27
|
|
8
30
|
|
|
9
31
|
### Added
|
data/CLA.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Contributor License Agreement
|
|
2
2
|
|
|
3
|
-
This agreement allows
|
|
4
|
-
open source and commercial offerings.
|
|
3
|
+
This agreement allows LAYERED AI LIMITED (UK company number: 17056830) to
|
|
4
|
+
use your contributions in both open source and commercial offerings.
|
|
5
5
|
|
|
6
6
|
- You retain copyright
|
|
7
|
-
- You grant
|
|
7
|
+
- You grant LAYERED AI LIMITED a perpetual, worldwide license to use,
|
|
8
8
|
modify, sublicense, and distribute your contribution
|
|
9
9
|
|
|
10
10
|
This agreement does not restrict your own use of the contribution.
|
data/LICENSE
CHANGED
|
@@ -186,7 +186,7 @@
|
|
|
186
186
|
same "printed page" as the copyright notice for easier
|
|
187
187
|
identification within third-party archives.
|
|
188
188
|
|
|
189
|
-
Copyright 2026
|
|
189
|
+
Copyright 2026 LAYERED AI LIMITED (UK company number: 17056830)
|
|
190
190
|
|
|
191
191
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
192
|
you may not use this file except in compliance with the License.
|
data/NOTICE
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
layered
|
|
1
|
+
layered-ui-rails
|
|
2
2
|
|
|
3
|
-
Copyright 2026
|
|
3
|
+
Copyright 2026 LAYERED AI LIMITED (UK company number: 17056830).
|
|
4
4
|
|
|
5
|
-
This product includes software developed by
|
|
5
|
+
This product includes software developed by LAYERED AI LIMITED and contributors.
|
|
6
6
|
|
|
7
7
|
Licensed under the Apache License, Version 2.0.
|
data/README.md
CHANGED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
[](https://github.com/layered-ai-public/layered-ui-rails/actions/workflows/ci.yml)
|
|
4
4
|
[](https://www.w3.org/WAI/WCAG22/quickref/)
|
|
5
5
|
[](https://opensource.org/licenses/Apache-2.0)
|
|
6
|
+
[](https://www.layered.ai/)
|
|
7
|
+
[](https://github.com/layered-ai-public/layered-ui-rails)
|
|
8
|
+
[](https://discord.gg/aCGqz9Bx)
|
|
6
9
|
|
|
7
10
|
An open source, Rails 8+ engine that provides WCAG 2.2 AA compliant design tokens, Tailwind CSS utilities, and Stimulus controllers for theme switching, mobile navigation, slide-out panels, modals, and tabs. Ships as pure frontend with no server-side dependencies beyond Rails and Tailwind CSS. See the [live demo](https://layered-ui-rails.layered.ai).
|
|
8
11
|
|
|
@@ -97,7 +100,7 @@ This project is still in its early days. We welcome issues, feedback, and ideas
|
|
|
97
100
|
|
|
98
101
|
## License
|
|
99
102
|
|
|
100
|
-
Released under the [Apache 2.0 License](LICENSE). The source code is fully open, but the layered.ai name and brand are trademarks of
|
|
103
|
+
Released under the [Apache 2.0 License](LICENSE). The source code is fully open, but the layered.ai name and brand are trademarks of LAYERED AI LIMITED (UK company number: 17056830).
|
|
101
104
|
|
|
102
105
|
- [TRADEMARK.md](TRADEMARK.md) - trademark and brand policy
|
|
103
106
|
- [CLA.md](CLA.md) - contributor license agreement
|
data/TRADEMARK.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# layered.ai Trademark and Brand Policy
|
|
2
2
|
|
|
3
3
|
The layered.ai name, logo, domain names, and related brand assets are
|
|
4
|
-
trademarks of
|
|
4
|
+
trademarks of LAYERED AI LIMITED (UK company number: 17056830).
|
|
5
5
|
|
|
6
6
|
## Scope
|
|
7
7
|
|
|
@@ -11,7 +11,7 @@ but does not grant rights to use the layered.ai name, logo, or branding.
|
|
|
11
11
|
|
|
12
12
|
## Restrictions
|
|
13
13
|
|
|
14
|
-
Without a separate written brand license from
|
|
14
|
+
Without a separate written brand license from LAYERED AI LIMITED, you may not:
|
|
15
15
|
|
|
16
16
|
- Use the name "layered.ai" to identify a fork, derivative work, or hosted service
|
|
17
17
|
- Use the layered.ai logo or visual identity
|
|
@@ -107,11 +107,6 @@
|
|
|
107
107
|
text-sm text-foreground-muted leading-relaxed;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
p a,
|
|
111
|
-
td a {
|
|
112
|
-
@apply link;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
110
|
ul, ol {
|
|
116
111
|
@apply mt-0
|
|
117
112
|
text-sm text-foreground-muted;
|
|
@@ -225,16 +220,18 @@
|
|
|
225
220
|
transition-[margin] duration-300;
|
|
226
221
|
}
|
|
227
222
|
|
|
228
|
-
@utility link {
|
|
229
|
-
@apply underline
|
|
230
|
-
text-foreground hover:text-foreground-muted
|
|
231
|
-
focus-ring rounded-sm;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
223
|
.l-ui-utility--mt-0 {
|
|
235
224
|
@apply !mt-0 md:!mt-0;
|
|
236
225
|
}
|
|
237
226
|
|
|
227
|
+
.l-ui-utility--mt-4 {
|
|
228
|
+
@apply !mt-4 md:!mt-4;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.l-ui-utility--mt-8 {
|
|
232
|
+
@apply !mt-8 md:!mt-8;
|
|
233
|
+
}
|
|
234
|
+
|
|
238
235
|
.l-ui-utility---mr-2 {
|
|
239
236
|
@apply !-mr-2 md:!-mr-2;
|
|
240
237
|
}
|
|
@@ -320,10 +317,6 @@
|
|
|
320
317
|
@apply line-through;
|
|
321
318
|
}
|
|
322
319
|
|
|
323
|
-
.l-ui-markdown a {
|
|
324
|
-
@apply link;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
320
|
.l-ui-markdown ul {
|
|
328
321
|
@apply my-3 pl-5
|
|
329
322
|
text-sm
|
|
@@ -437,6 +430,12 @@
|
|
|
437
430
|
@apply page;
|
|
438
431
|
}
|
|
439
432
|
|
|
433
|
+
.l-ui-page a:not([class*="l-ui-button"]) {
|
|
434
|
+
@apply underline
|
|
435
|
+
text-foreground hover:text-foreground-muted
|
|
436
|
+
focus-ring rounded-sm;
|
|
437
|
+
}
|
|
438
|
+
|
|
440
439
|
.l-ui-page--with-navigation {
|
|
441
440
|
@apply page md:ml-[240px];
|
|
442
441
|
}
|
|
@@ -668,7 +667,7 @@
|
|
|
668
667
|
/* Buttons */
|
|
669
668
|
|
|
670
669
|
@utility button {
|
|
671
|
-
@apply flex items-center justify-center
|
|
670
|
+
@apply flex items-center justify-center gap-2
|
|
672
671
|
px-4 min-h-[44px]
|
|
673
672
|
text-sm font-medium
|
|
674
673
|
cursor-pointer
|
|
@@ -1039,10 +1038,6 @@
|
|
|
1039
1038
|
.l-ui-table__cell--primary {
|
|
1040
1039
|
@apply table-cell-padding
|
|
1041
1040
|
text-left text-sm font-medium whitespace-nowrap;
|
|
1042
|
-
|
|
1043
|
-
& a {
|
|
1044
|
-
@apply link;
|
|
1045
|
-
}
|
|
1046
1041
|
}
|
|
1047
1042
|
|
|
1048
1043
|
.l-ui-table__cell--action {
|
|
@@ -1312,6 +1307,10 @@
|
|
|
1312
1307
|
@apply flex-1;
|
|
1313
1308
|
}
|
|
1314
1309
|
|
|
1310
|
+
.l-ui-panel__header-heading .l-ui-select {
|
|
1311
|
+
@apply mb-2;
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1315
1314
|
.l-ui-panel__header-actions {
|
|
1316
1315
|
@apply flex items-center
|
|
1317
1316
|
gap-2;
|
|
@@ -1324,7 +1323,18 @@
|
|
|
1324
1323
|
.l-ui-panel__body {
|
|
1325
1324
|
@apply flex-1
|
|
1326
1325
|
p-4 space-y-4
|
|
1327
|
-
overflow-y-auto
|
|
1326
|
+
overflow-y-auto
|
|
1327
|
+
overscroll-contain;
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
.l-ui-panel__body:has(.l-ui-conversation__container) {
|
|
1331
|
+
@apply relative
|
|
1332
|
+
overflow-hidden;
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
.l-ui-panel__body .l-ui-conversation__container {
|
|
1336
|
+
@apply absolute inset-0
|
|
1337
|
+
p-4 pt-0;
|
|
1328
1338
|
}
|
|
1329
1339
|
|
|
1330
1340
|
.l-ui-panel__input {
|
|
@@ -1342,14 +1352,16 @@
|
|
|
1342
1352
|
.l-ui-conversation__container {
|
|
1343
1353
|
@apply flex flex-col
|
|
1344
1354
|
gap-4
|
|
1345
|
-
h-
|
|
1355
|
+
flex-1 min-h-0
|
|
1346
1356
|
bg-background;
|
|
1347
1357
|
}
|
|
1348
1358
|
|
|
1359
|
+
.l-ui-page:has(.l-ui-conversation__container) {
|
|
1360
|
+
@apply max-h-dvh overflow-hidden;
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1349
1363
|
.l-ui-conversation__messages {
|
|
1350
1364
|
@apply flex-1
|
|
1351
|
-
py-4
|
|
1352
|
-
border-b border-border
|
|
1353
1365
|
overflow-y-auto;
|
|
1354
1366
|
}
|
|
1355
1367
|
|
|
@@ -1394,7 +1406,7 @@
|
|
|
1394
1406
|
@apply flex items-center justify-center shrink-0
|
|
1395
1407
|
w-7 h-7
|
|
1396
1408
|
text-xs font-bold
|
|
1397
|
-
bg-surface
|
|
1409
|
+
bg-surface
|
|
1398
1410
|
text-foreground
|
|
1399
1411
|
rounded-full;
|
|
1400
1412
|
}
|
|
@@ -1405,7 +1417,7 @@
|
|
|
1405
1417
|
w-full min-w-0
|
|
1406
1418
|
bg-surface
|
|
1407
1419
|
text-foreground
|
|
1408
|
-
rounded-
|
|
1420
|
+
rounded-md;
|
|
1409
1421
|
}
|
|
1410
1422
|
|
|
1411
1423
|
.l-ui-message--sent .l-ui-message__bubble {
|
|
@@ -1527,7 +1539,7 @@
|
|
|
1527
1539
|
border-0 md:border md:border-border
|
|
1528
1540
|
bg-background
|
|
1529
1541
|
text-foreground
|
|
1530
|
-
rounded-none md:rounded-
|
|
1542
|
+
rounded-none md:rounded-sm;
|
|
1531
1543
|
}
|
|
1532
1544
|
|
|
1533
1545
|
.l-ui-modal::backdrop {
|
|
@@ -1544,3 +1556,21 @@
|
|
|
1544
1556
|
@apply px-5 py-4
|
|
1545
1557
|
overflow-y-auto;
|
|
1546
1558
|
}
|
|
1559
|
+
|
|
1560
|
+
/* Safari */
|
|
1561
|
+
@media (max-width: 767px) {
|
|
1562
|
+
/* Prevent Safari auto-zoom on input focus */
|
|
1563
|
+
input,
|
|
1564
|
+
textarea,
|
|
1565
|
+
select {
|
|
1566
|
+
font-size: 16px !important;
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
/* iOS Safari ignores overflow:hidden on body; position:fixed is required */
|
|
1570
|
+
.l-ui-scroll-lock {
|
|
1571
|
+
position: fixed;
|
|
1572
|
+
left: 0;
|
|
1573
|
+
right: 0;
|
|
1574
|
+
overflow: hidden;
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
@@ -10,7 +10,7 @@ export default class extends Controller {
|
|
|
10
10
|
this.previousActiveElement = null
|
|
11
11
|
this.isOpen = false
|
|
12
12
|
this.boundKeyboardShortcut = this.handleKeyboardShortcut.bind(this)
|
|
13
|
-
|
|
13
|
+
this.boundCloseOnNavigate = this.closeOnMobileNavigate.bind(this)
|
|
14
14
|
const page = document.querySelector(".l-ui-page")
|
|
15
15
|
if (page) page.style.transition = "none"
|
|
16
16
|
this.containerTarget.style.transition = "none"
|
|
@@ -27,11 +27,13 @@ export default class extends Controller {
|
|
|
27
27
|
})
|
|
28
28
|
|
|
29
29
|
document.addEventListener('keydown', this.boundKeyboardShortcut)
|
|
30
|
+
document.addEventListener('turbo:visit', this.boundCloseOnNavigate)
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
disconnect() {
|
|
33
34
|
clearAnnounceTimeout(this)
|
|
34
35
|
document.removeEventListener('keydown', this.boundKeyboardShortcut)
|
|
36
|
+
document.removeEventListener('turbo:visit', this.boundCloseOnNavigate)
|
|
35
37
|
this.previousActiveElement = null
|
|
36
38
|
}
|
|
37
39
|
|
|
@@ -84,10 +86,13 @@ export default class extends Controller {
|
|
|
84
86
|
this.containerTarget.setAttribute("aria-hidden", "false")
|
|
85
87
|
this.containerTarget.removeAttribute("inert")
|
|
86
88
|
|
|
87
|
-
// On mobile, prevent background content from being tabbable
|
|
89
|
+
// On mobile, prevent background content from being tabbable and scrollable
|
|
88
90
|
if (isMobile()) {
|
|
89
91
|
const main = document.querySelector("main")
|
|
90
92
|
if (main) main.setAttribute("inert", "")
|
|
93
|
+
this.savedScrollY = window.scrollY
|
|
94
|
+
document.body.style.top = `-${this.savedScrollY}px`
|
|
95
|
+
document.body.classList.add("l-ui-scroll-lock")
|
|
91
96
|
}
|
|
92
97
|
|
|
93
98
|
storageSet("panelOpen", "true")
|
|
@@ -119,6 +124,11 @@ export default class extends Controller {
|
|
|
119
124
|
|
|
120
125
|
const main = document.querySelector("main")
|
|
121
126
|
if (main) main.removeAttribute("inert")
|
|
127
|
+
document.body.classList.remove("l-ui-scroll-lock")
|
|
128
|
+
document.body.style.top = ""
|
|
129
|
+
if (this.savedScrollY !== undefined) {
|
|
130
|
+
window.scrollTo(0, this.savedScrollY)
|
|
131
|
+
}
|
|
122
132
|
|
|
123
133
|
storageSet("panelOpen", "false")
|
|
124
134
|
this.updatePageMargin()
|
|
@@ -133,6 +143,13 @@ export default class extends Controller {
|
|
|
133
143
|
}
|
|
134
144
|
}
|
|
135
145
|
|
|
146
|
+
// Close the panel on mobile when navigating to a new page
|
|
147
|
+
closeOnMobileNavigate() {
|
|
148
|
+
if (this.isOpen && isMobile()) {
|
|
149
|
+
this.close(false)
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
136
153
|
// Update the page margin to accommodate the open panel on desktop
|
|
137
154
|
updatePageMargin() {
|
|
138
155
|
const page = document.querySelector(".l-ui-page")
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
</div>
|
|
19
19
|
|
|
20
20
|
<% if devise_mapping.rememberable? %>
|
|
21
|
-
<div class="l-ui-form__group l-ui-container--checkbox l-ui-utility--mt-
|
|
21
|
+
<div class="l-ui-form__group l-ui-container--checkbox l-ui-utility--mt-8">
|
|
22
22
|
<%= f.check_box :remember_me %>
|
|
23
23
|
<%= f.label :remember_me, class: "l-ui-label--checkbox" %>
|
|
24
24
|
</div>
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
tabindex="-1"
|
|
63
63
|
title="Toggle panel (Ctrl/⌘+i). Move to corners (Ctrl/⌘ + Alt/⌥ + 1/2/3/4), double-click, or drag."
|
|
64
64
|
data-controller="l-ui--panel-button"
|
|
65
|
-
data-action="click->l-ui--panel-button#queueToggle dblclick->l-ui--panel-button#cycleCorner mousedown->l-ui--panel-button#startDrag touchstart
|
|
65
|
+
data-action="click->l-ui--panel-button#queueToggle dblclick->l-ui--panel-button#cycleCorner mousedown->l-ui--panel-button#startDrag touchstart->l-ui--panel-button#startDrag"
|
|
66
66
|
data-l-ui--panel-target="actionButton"
|
|
67
67
|
>
|
|
68
68
|
<%= image_tag("layered_ui/panel_icon_light.svg", alt: "", class: "l-ui-icon--lg l-ui-panel__icon--light", aria: { hidden: true }) %>
|
data/lib/layered/ui/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: layered-ui-rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- layered.ai
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-03-14 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -236,6 +236,8 @@ metadata:
|
|
|
236
236
|
source_code_uri: https://github.com/layered-ai-public/layered-ui-rails
|
|
237
237
|
bug_tracker_uri: https://github.com/layered-ai-public/layered-ui-rails/issues
|
|
238
238
|
changelog_uri: https://github.com/layered-ai-public/layered-ui-rails/blob/main/CHANGELOG.md
|
|
239
|
+
documentation_uri: https://www.layered.ai
|
|
240
|
+
discord_uri: https://discord.gg/aCGqz9Bx
|
|
239
241
|
rubygems_mfa_required: 'true'
|
|
240
242
|
post_install_message: |
|
|
241
243
|
To complete installation, run:
|