plutonium 0.58.0 → 0.58.1
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 +5 -0
- data/app/assets/plutonium.css +1 -1
- data/app/assets/plutonium.js +7 -2
- data/app/assets/plutonium.js.map +2 -2
- data/app/assets/plutonium.min.js +1 -1
- data/app/assets/plutonium.min.js.map +2 -2
- data/lib/plutonium/ui/layout/base.rb +10 -11
- data/lib/plutonium/ui/layout/resource_layout.rb +18 -0
- data/lib/plutonium/version.rb +1 -1
- data/package.json +1 -1
- data/src/css/components.css +11 -11
- data/src/js/controllers/icon_rail_controller.js +11 -2
- metadata +1 -1
|
@@ -44,12 +44,10 @@ module Plutonium
|
|
|
44
44
|
# preferences read from localStorage:
|
|
45
45
|
# - Color mode: applies `dark` class on <html> so dark theme renders
|
|
46
46
|
# from the first frame instead of flashing light.
|
|
47
|
-
# - Rail-pin:
|
|
48
|
-
#
|
|
49
|
-
#
|
|
50
|
-
#
|
|
51
|
-
# after a form submit) doesn't flash the rail into its collapsed
|
|
52
|
-
# state before the icon-rail Stimulus controller can restore it.
|
|
47
|
+
# - Rail-pin: a turbo:before-render listener adds/removes `pu-rail-pinned`
|
|
48
|
+
# on <html> based on whether the incoming body contains an icon-rail,
|
|
49
|
+
# preventing layout shift on Turbo navigations between rail and non-rail
|
|
50
|
+
# pages. Initial-load rail-pinned is handled by ResourceLayout.
|
|
53
51
|
def render_pre_paint_scripts
|
|
54
52
|
script do
|
|
55
53
|
raw(safe(<<~JS))
|
|
@@ -63,11 +61,12 @@ module Plutonium
|
|
|
63
61
|
} catch (e) {}
|
|
64
62
|
|
|
65
63
|
try {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
64
|
+
document.addEventListener("turbo:before-render", function (e) {
|
|
65
|
+
var hasRail = !!e.detail.newBody.querySelector('[data-controller~="icon-rail"]');
|
|
66
|
+
if (hasRail && localStorage.getItem("pu_rail_pinned") !== "false") {
|
|
67
|
+
document.documentElement.classList.add("pu-rail-pinned");
|
|
68
|
+
} else {
|
|
69
|
+
document.documentElement.classList.remove("pu-rail-pinned");
|
|
71
70
|
}
|
|
72
71
|
});
|
|
73
72
|
} catch (e) {}
|
|
@@ -4,6 +4,24 @@ module Plutonium
|
|
|
4
4
|
class ResourceLayout < Base
|
|
5
5
|
private
|
|
6
6
|
|
|
7
|
+
# Sets pu-rail-pinned immediately on initial page load so the rail
|
|
8
|
+
# renders in its pinned state from the first frame. Turbo navigations
|
|
9
|
+
# are handled by the turbo:before-render listener in Base.
|
|
10
|
+
def render_pre_paint_scripts
|
|
11
|
+
super
|
|
12
|
+
script do
|
|
13
|
+
raw(safe(<<~JS))
|
|
14
|
+
(function () {
|
|
15
|
+
try {
|
|
16
|
+
if (localStorage.getItem("pu_rail_pinned") !== "false") {
|
|
17
|
+
document.documentElement.classList.add("pu-rail-pinned");
|
|
18
|
+
}
|
|
19
|
+
} catch (e) {}
|
|
20
|
+
})();
|
|
21
|
+
JS
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
7
25
|
def main_attributes
|
|
8
26
|
classes = case Plutonium.configuration.shell
|
|
9
27
|
when :modern
|
data/lib/plutonium/version.rb
CHANGED
data/package.json
CHANGED
data/src/css/components.css
CHANGED
|
@@ -689,16 +689,16 @@ aside[data-controller~="icon-rail"] {
|
|
|
689
689
|
}
|
|
690
690
|
|
|
691
691
|
/* Pinned mode: rail expands, labels appear */
|
|
692
|
-
|
|
692
|
+
html.pu-rail-pinned aside[data-controller~="icon-rail"] {
|
|
693
693
|
width: 14rem !important; /* 224px */
|
|
694
694
|
}
|
|
695
695
|
|
|
696
|
-
|
|
696
|
+
html.pu-rail-pinned .icon-rail-label {
|
|
697
697
|
display: inline-flex !important;
|
|
698
698
|
}
|
|
699
699
|
|
|
700
|
-
|
|
701
|
-
|
|
700
|
+
html.pu-rail-pinned .icon-rail-leaf,
|
|
701
|
+
html.pu-rail-pinned .icon-rail-parent-trigger {
|
|
702
702
|
width: 100%;
|
|
703
703
|
justify-content: flex-start;
|
|
704
704
|
gap: 8px;
|
|
@@ -707,7 +707,7 @@ body.pu-rail-pinned .icon-rail-parent-trigger {
|
|
|
707
707
|
|
|
708
708
|
/* When pinned, chevron flows inline after the label (right-aligned)
|
|
709
709
|
and rotates to point down — mirrors a typical disclosure caret. */
|
|
710
|
-
|
|
710
|
+
html.pu-rail-pinned .icon-rail-chevron {
|
|
711
711
|
position: static;
|
|
712
712
|
background: transparent;
|
|
713
713
|
box-shadow: none;
|
|
@@ -720,7 +720,7 @@ body.pu-rail-pinned .icon-rail-chevron {
|
|
|
720
720
|
}
|
|
721
721
|
|
|
722
722
|
/* When pinned, items stretch full width so labels read left-to-right */
|
|
723
|
-
|
|
723
|
+
html.pu-rail-pinned #sidebar-navigation-content {
|
|
724
724
|
align-items: stretch;
|
|
725
725
|
padding-left: 8px;
|
|
726
726
|
padding-right: 8px;
|
|
@@ -728,31 +728,31 @@ body.pu-rail-pinned #sidebar-navigation-content {
|
|
|
728
728
|
|
|
729
729
|
/* When pinned, brand area aligns to the start so it reads as part of the
|
|
730
730
|
left-aligned column instead of staying centered while items go left. */
|
|
731
|
-
|
|
731
|
+
html.pu-rail-pinned aside[data-controller~="icon-rail"] > div:first-child {
|
|
732
732
|
justify-content: flex-start;
|
|
733
733
|
padding-left: 14px;
|
|
734
734
|
}
|
|
735
735
|
|
|
736
736
|
/* When pinned, pin button right-aligns to anchor the collapse affordance
|
|
737
737
|
to the rail edge it'll snap toward. */
|
|
738
|
-
|
|
738
|
+
html.pu-rail-pinned aside[data-controller~="icon-rail"] > div:last-child {
|
|
739
739
|
justify-content: flex-end;
|
|
740
740
|
padding-right: 8px;
|
|
741
741
|
}
|
|
742
742
|
|
|
743
743
|
/* Pin button icon swap */
|
|
744
|
-
|
|
744
|
+
html.pu-rail-pinned .icon-rail-pin-collapse {
|
|
745
745
|
display: inline-flex !important;
|
|
746
746
|
}
|
|
747
747
|
|
|
748
|
-
|
|
748
|
+
html.pu-rail-pinned .icon-rail-pin-expand {
|
|
749
749
|
display: none !important;
|
|
750
750
|
}
|
|
751
751
|
|
|
752
752
|
/* Main content padding when pinned: rail width + 1.5rem breathing room
|
|
753
753
|
(matches the collapsed-state lg:pl-20 = rail 3.5rem + 1.5rem gap). */
|
|
754
754
|
@media (min-width: 1024px) {
|
|
755
|
-
|
|
755
|
+
html.pu-rail-pinned main {
|
|
756
756
|
padding-left: 15.5rem !important;
|
|
757
757
|
}
|
|
758
758
|
}
|
|
@@ -11,11 +11,20 @@ export default class extends Controller {
|
|
|
11
11
|
connect() {
|
|
12
12
|
// Pinned is the default; only an explicit "false" collapses the rail.
|
|
13
13
|
const pinned = localStorage.getItem(this.storageKeyValue) !== "false"
|
|
14
|
-
document.
|
|
14
|
+
document.documentElement.classList.toggle("pu-rail-pinned", pinned)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
disconnect() {
|
|
18
|
+
// Guard: if another icon-rail is already in the DOM (Turbo swapped to a
|
|
19
|
+
// page that also has a rail), leave the class alone — the new controller's
|
|
20
|
+
// connect() will assert the correct value immediately after.
|
|
21
|
+
if (!document.querySelector('[data-controller~="icon-rail"]')) {
|
|
22
|
+
document.documentElement.classList.remove("pu-rail-pinned")
|
|
23
|
+
}
|
|
15
24
|
}
|
|
16
25
|
|
|
17
26
|
togglePin() {
|
|
18
|
-
const pinned = document.
|
|
27
|
+
const pinned = document.documentElement.classList.toggle("pu-rail-pinned")
|
|
19
28
|
localStorage.setItem(this.storageKeyValue, pinned)
|
|
20
29
|
}
|
|
21
30
|
}
|