studio-engine 0.32.2 → 0.32.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 +34 -0
- data/app/views/components/_sidebar_panel.html.erb +13 -2
- data/app/views/layouts/studio/_head.html.erb +45 -6
- data/lib/studio/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e56dfd4be2d6f429f329626c4aebb8b22aa9e0069cfdf8905a02fab4bc47ab4c
|
|
4
|
+
data.tar.gz: 71b6a6d3dafa57d3b25e9cb791049ae9b4a975efa7d14b08b961492b2b870d6f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ea74d63cf741530df52e0fbe490a3fe48817845235f12aa911e094d67fe6012e3b9f1d139f95d8f5240d467fa079a2746f6a3985c256a3daee948136752e3c9c
|
|
7
|
+
data.tar.gz: 75146aa7893ca074ada0c58b5ecfb20641615432c63090d3d8bd39bd0b6f6e480a6d7e558bbf45ac8003144a6fd224222fd7eeaac297571b522e255e43343472
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,40 @@
|
|
|
2
2
|
|
|
3
3
|
The format is [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). This project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html) — `MAJOR.MINOR.PATCH`. Consumer Rails apps install the released RubyGems package with `gem "studio-engine", "~> 0.6"`; bumping the gem version and updating consumer lockfiles is a release.
|
|
4
4
|
|
|
5
|
+
## 0.32.3 — 2026-08-09
|
|
6
|
+
|
|
7
|
+
**New public CSS custom property: `--nav-bottom`.** `_head.html.erb` now
|
|
8
|
+
publishes the page header's **bottom edge** in viewport coordinates alongside
|
|
9
|
+
the existing `--nav-h`, which stays the header's **height**. Use them for
|
|
10
|
+
different jobs:
|
|
11
|
+
|
|
12
|
+
- `var(--nav-h)` — to size something as tall as the header.
|
|
13
|
+
- `var(--nav-bottom)` — to **start** something underneath it.
|
|
14
|
+
|
|
15
|
+
They are equal only when the header sits at the top of the viewport, which is
|
|
16
|
+
why one was long used for the other. An app that renders chrome **above** the
|
|
17
|
+
navbar — an environment banner before the `<header>` — pushes the header down,
|
|
18
|
+
and a `fixed` overlay offset by `--nav-h` then rides up over the header by
|
|
19
|
+
exactly the height of that chrome.
|
|
20
|
+
|
|
21
|
+
**Fix — `components/_sidebar_panel` offsets from `--nav-bottom`.** The open
|
|
22
|
+
sidebar panel overlapped the header by 47px on `mcritchie-industries`, covering
|
|
23
|
+
the Log in button. Falls back to `var(--nav-h)` (then `6rem`), so a host that
|
|
24
|
+
overrides `layouts/studio/_head` keeps today's geometry rather than collapsing.
|
|
25
|
+
**No change for a consumer whose header already starts at the viewport top** —
|
|
26
|
+
the two values converge there.
|
|
27
|
+
|
|
28
|
+
Unlike `--nav-h`, `--nav-bottom` is **scroll-dependent**: chrome above the
|
|
29
|
+
header scrolls away while a panel is open, and nothing locks body scroll. It
|
|
30
|
+
republishes on a passive `scroll` listener behind a `requestAnimationFrame`
|
|
31
|
+
throttle, bound once at script eval rather than per Turbo visit. A page with no
|
|
32
|
+
`<header>` now releases the observed node, so a Turbo visit to a headerless page
|
|
33
|
+
can no longer publish an all-zero rect from a detached element.
|
|
34
|
+
|
|
35
|
+
**Note for hosts that override `components/_sidebar_panel`** — an app copy of
|
|
36
|
+
that partial shadows the engine's, so it keeps the old `top:var(--nav-h, 6rem)`
|
|
37
|
+
until updated. `mcritchie-studio` and `turf-monster` both carry such an override.
|
|
38
|
+
|
|
5
39
|
## 0.32.2 — 2026-08-09
|
|
6
40
|
|
|
7
41
|
**Two public-page navigation fixes** (found by the industries sidebar-adoption
|
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
<%# Shared fixed right-sidebar shell (lifted from the mcritchie-studio hub).
|
|
2
2
|
Alpine-driven: `open` is an Alpine expression; the panel slides in from
|
|
3
3
|
off-screen right under x-transition and positions beneath the sticky
|
|
4
|
-
header via the --nav-
|
|
4
|
+
header via the --nav-bottom custom property _head.html.erb publishes.
|
|
5
|
+
--nav-bottom is the header's BOTTOM EDGE, not its height: the two differ
|
|
6
|
+
the moment an app renders chrome above the navbar (an environment banner
|
|
7
|
+
before the header), and positioning off the height put this panel over the
|
|
8
|
+
header by exactly that much.
|
|
9
|
+
|
|
10
|
+
The --nav-h fallback is NOT for a host pinning an older gem — an older gem
|
|
11
|
+
ships the old _head and the old panel together, so that path never runs.
|
|
12
|
+
It is reachable only when a host OVERRIDES layouts/studio/_head, in which
|
|
13
|
+
case --nav-bottom is never published and this degrades to the previous,
|
|
14
|
+
BUGGY geometry. That is a deliberate floor, not a safe default: it keeps an
|
|
15
|
+
overriding host at today's behaviour instead of collapsing to 6rem. %>
|
|
5
16
|
<% id = local_assigns.fetch(:id, nil) %>
|
|
6
17
|
<% title = local_assigns.fetch(:title, nil) %>
|
|
7
18
|
<% open = local_assigns.fetch(:open) %>
|
|
@@ -33,7 +44,7 @@
|
|
|
33
44
|
x-transition:leave-start="translate-x-0"
|
|
34
45
|
x-transition:leave-end="translate-x-full"
|
|
35
46
|
class="<%= display_class %> fixed right-0 <%= width_class %> bg-surface border-l border-subtle shadow-2xl <%= z_class %> flex-col <%= panel_class %>"
|
|
36
|
-
style="top:var(--nav-h, 6rem);height:calc(100% - var(--nav-h, 6rem))"
|
|
47
|
+
style="top:var(--nav-bottom, var(--nav-h, 6rem));height:calc(100% - var(--nav-bottom, var(--nav-h, 6rem)))"
|
|
37
48
|
role="<%= role %>"
|
|
38
49
|
<% if labelledby %>aria-labelledby="<%= labelledby %>"<% elsif aria_label.present? %>aria-label="<%= aria_label %>"<% end %>>
|
|
39
50
|
<div class="flex flex-col h-full">
|
|
@@ -96,19 +96,54 @@
|
|
|
96
96
|
body { overflow-anchor: none; }
|
|
97
97
|
</style>
|
|
98
98
|
<script>
|
|
99
|
-
// studio-engine: publish the sticky header's live
|
|
100
|
-
//
|
|
101
|
-
//
|
|
102
|
-
//
|
|
99
|
+
// studio-engine: publish the sticky header's live geometry as CSS custom
|
|
100
|
+
// properties so fixed/sticky elements can position off it without hardcoded
|
|
101
|
+
// px. Tracks every resize, including scroll-collapse animations, and
|
|
102
|
+
// re-attaches after Turbo nav.
|
|
103
|
+
//
|
|
104
|
+
// --nav-h the header's HEIGHT
|
|
105
|
+
// --nav-bottom the header's BOTTOM EDGE, in viewport coordinates
|
|
106
|
+
//
|
|
107
|
+
// They are equal only when the header sits at the top of the viewport, which
|
|
108
|
+
// is why one was long mistaken for the other. An app that stacks chrome ABOVE
|
|
109
|
+
// the header — an environment banner rendered before the navbar, as
|
|
110
|
+
// mcritchie-industries does — pushes the header down, and a `fixed` overlay
|
|
111
|
+
// positioned at --nav-h then rides UP over the header by exactly the height of
|
|
112
|
+
// that chrome. Use --nav-h to size something as tall as the header; use
|
|
113
|
+
// --nav-bottom to start something underneath it.
|
|
103
114
|
(function () {
|
|
104
115
|
if (!window.ResizeObserver) return;
|
|
105
116
|
var ro = null;
|
|
117
|
+
var current = null;
|
|
118
|
+
var queued = false;
|
|
106
119
|
function publish(header) {
|
|
107
|
-
document.documentElement.style
|
|
120
|
+
var style = document.documentElement.style;
|
|
121
|
+
style.setProperty('--nav-h', header.offsetHeight + 'px');
|
|
122
|
+
// Scroll-dependent where --nav-h is not: chrome above the header scrolls
|
|
123
|
+
// away while an overlay is open (nothing here locks body scroll), so this
|
|
124
|
+
// is republished on scroll. Clamped at 0 — once the sticky header is
|
|
125
|
+
// pinned at top:0 the two values converge, which is why a consumer whose
|
|
126
|
+
// header already starts at the viewport top sees no change at all.
|
|
127
|
+
style.setProperty('--nav-bottom', Math.max(0, header.getBoundingClientRect().bottom) + 'px');
|
|
128
|
+
}
|
|
129
|
+
function schedule() {
|
|
130
|
+
if (queued || !current) return;
|
|
131
|
+
queued = true;
|
|
132
|
+
window.requestAnimationFrame(function () { queued = false; if (current) publish(current); });
|
|
108
133
|
}
|
|
109
134
|
function attach() {
|
|
110
135
|
var header = document.querySelector('header');
|
|
111
|
-
if (!header)
|
|
136
|
+
if (!header) {
|
|
137
|
+
// A page with no <header> — a bare error page, a print view. RELEASE the
|
|
138
|
+
// old node instead of returning: the scroll listener outlives the visit,
|
|
139
|
+
// and publishing from a DETACHED element yields an all-zero rect, which
|
|
140
|
+
// would drive --nav-h to 0px. Before this listener existed nothing ran
|
|
141
|
+
// after detach, so --nav-h simply kept its last value; keep that promise.
|
|
142
|
+
if (ro) { ro.disconnect(); ro = null; }
|
|
143
|
+
current = null;
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
current = header;
|
|
112
147
|
if (ro) ro.disconnect();
|
|
113
148
|
ro = new ResizeObserver(function () { publish(header); });
|
|
114
149
|
ro.observe(header);
|
|
@@ -116,6 +151,10 @@
|
|
|
116
151
|
}
|
|
117
152
|
document.addEventListener('DOMContentLoaded', attach);
|
|
118
153
|
document.addEventListener('turbo:load', attach);
|
|
154
|
+
// Registered ONCE at script eval, not inside attach(), so a Turbo nav
|
|
155
|
+
// re-points `current` instead of stacking another listener per visit.
|
|
156
|
+
window.addEventListener('scroll', schedule, { passive: true });
|
|
157
|
+
window.addEventListener('resize', schedule, { passive: true });
|
|
119
158
|
})();
|
|
120
159
|
</script>
|
|
121
160
|
|
data/lib/studio/version.rb
CHANGED