tray apparatus scales w. fluid rem; sig-select 9×2 middling breakpoint — $handle-exposed was 48px fixed while #id_tray_btn is 3rem, so on big-rem viewports (clamp(14px, 2.4vmin, 22px) → up to 22px on tall screens, btn=66) the btn's flex parent (#id_tray_handle) shrank the btn from 66×66 → 48×66 via default flex-shrink:1 in portrait (elongated tall ellipse), and in landscape the btn overflowed the 48px-tall handle vertically (extending 9px past viewport top in closed state); fix: $handle-exposed: 3rem matches the btn so it fills the exposed area at every rem; $handle-rect-h: 4.5rem (was 72px) gives the visible rail thickness a touch of breathing room around the btn at every scale; landscape rules in the same partial that hard-coded 48px / 72px (#id_tray_handle { height: 48px }, #id_tray_grip { bottom: calc(48px/2 - 0.125rem); width: 72px }) now reference the variables so they track in sync — tray.js _computeBounds() swapped from _btn.offsetWidth/Height → _handle.offsetWidth/Height for the same reason: even with the SCSS fix, measuring the btn would re-introduce the offset when btn and handle drift (which they shouldn't now, but the handle is the layout-defining element so measure it directly); id_kit_btn added as fallback for id_gear_btn (which no longer renders on the room page) so the open-state landscape wrap height anchors to the bottom-right kit btn instead of the full viewport — id_tray_handle cached on the module via _handle ref alongside _btn and cleared in reset() ; sig-select grid jumped straight from 6 cols (narrow landscape) → 18 cols × 3rem at min-width: 900px, but 18×3rem + 7rem modal margins needs ~1376px to clear at rem=22 so the cards spilled off the sides on common 1280-wide laptops + the previous-era 9×2 middling layout had simply been dropped; new cascade in _card-deck.scss mirrors the comment's documented intent: 6 cols default landscape (row layout, stage beside grid) → 9 cols × 3rem at min-width: 900px (column layout, stage above grid) → 18 cols × 3rem at min-width: 1400px → 18 × 5rem at min-width: 1800px (unchanged) — verified in Claudezilla across iphone-14 portrait (rem=14, btn=42 square, handle right edge at viewport right), 816×826 portrait near-landscape (rem=19.6, btn=58.75 square no longer elongated), 1149×751 landscape mid (rem=18, btn=54 square at viewport top, 9×2 grid), 1789×1111 desktop XL (rem=22, btn=66 square at viewport top, 18×1 grid)
Code architected by Disco DeDisco <discodedisco@outlook.com> Git commit message Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ var Tray = (function () {
|
||||
var _dragHandled = false;
|
||||
|
||||
var _wrap = null;
|
||||
var _handle = null;
|
||||
var _btn = null;
|
||||
var _tray = null;
|
||||
var _grid = null;
|
||||
@@ -99,12 +100,20 @@ var Tray = (function () {
|
||||
// meets the gear button when open. Tray is flex:1 and fills the rest.
|
||||
// Open: wrap top = 0 (pinned to viewport top).
|
||||
// Closed: wrap top = -(gearBtnTop - handleH) = tray fully above viewport.
|
||||
var gearBtn = document.getElementById('id_gear_btn');
|
||||
// Anchor: id_gear_btn historically; id_kit_btn is the live fallback so
|
||||
// the open-state handle bottom lands at the bottom-right anchor instead
|
||||
// of overlapping it (no id_gear_btn renders on the room page today).
|
||||
var gearBtn = document.getElementById('id_gear_btn')
|
||||
|| document.getElementById('id_kit_btn');
|
||||
var gearBtnTop = window.innerHeight;
|
||||
if (gearBtn) {
|
||||
gearBtnTop = Math.round(gearBtn.getBoundingClientRect().top);
|
||||
}
|
||||
var handleH = (_btn && _btn.offsetHeight) || 48;
|
||||
// handleH = #id_tray_handle's height (48px CSS), NOT _btn.offsetHeight.
|
||||
// The 3rem btn can be larger than the 48px handle on big-rem viewports
|
||||
// (clamp(14px, 2.4vmin, 22px) → btn=66 at rem=22); using btn here would
|
||||
// push the handle's bottom that far below y=0 in closed state.
|
||||
var handleH = (_handle && _handle.offsetHeight) || 48;
|
||||
|
||||
// Pin wrap height so handle bottom = gear btn top when open.
|
||||
if (_wrap) _wrap.style.height = gearBtnTop + 'px';
|
||||
@@ -116,7 +125,11 @@ var Tray = (function () {
|
||||
_maxTop = -(gearBtnTop - handleH);
|
||||
} else {
|
||||
// Portrait: wrap width = full viewport; handle parks at right edge.
|
||||
var handleW = _btn.offsetWidth || 48;
|
||||
// handleW = #id_tray_handle's width (48px CSS), NOT _btn.offsetWidth —
|
||||
// same rationale as landscape: btn can be wider than handle on big-rem
|
||||
// viewports, which would leave a visible gap between the handle's right
|
||||
// edge and the viewport right edge in closed state.
|
||||
var handleW = (_handle && _handle.offsetWidth) || 48;
|
||||
if (_wrap) _wrap.style.width = window.innerWidth + 'px';
|
||||
_minLeft = 0;
|
||||
_maxLeft = window.innerWidth - handleW;
|
||||
@@ -399,6 +412,7 @@ var Tray = (function () {
|
||||
|
||||
function init() {
|
||||
_wrap = document.getElementById('id_tray_wrap');
|
||||
_handle = document.getElementById('id_tray_handle');
|
||||
_btn = document.getElementById('id_tray_btn');
|
||||
_tray = document.getElementById('id_tray');
|
||||
_grid = document.getElementById('id_tray_grid');
|
||||
@@ -573,6 +587,7 @@ var Tray = (function () {
|
||||
});
|
||||
}
|
||||
_wrap = null;
|
||||
_handle = null;
|
||||
_btn = null;
|
||||
_tray = null;
|
||||
_grid = null;
|
||||
|
||||
@@ -868,10 +868,12 @@ html:has(.sig-backdrop) {
|
||||
}
|
||||
|
||||
// ─── Sig select: landscape overrides ─────────────────────────────────────────
|
||||
// Landscape base: 9×2 grid of 3rem cards. At ≥992px (wide enough for 18 cards
|
||||
// at 3rem + 4rem left + ~4rem right): collapse to a single 18×1 row so the
|
||||
// stage preview gets maximum vertical real-estate.
|
||||
// padding-left clears the fixed left navbar (JS sets right/bottom but not left).
|
||||
// Cascade (each step is a SUPERSET of the prior):
|
||||
// narrow landscape → 6 cols × 2.5rem, row layout (stage beside grid)
|
||||
// ≥ 900px → 9×2 grid of 3rem cards, column layout (stage above)
|
||||
// ≥ 1400px → 18×1 row of 3rem cards (wide enough that 18×3rem
|
||||
// + ~7rem modal margins clears even at rem=22)
|
||||
// ≥ 1800px → 18×1 row of 5rem cards + doubled sidebar padding
|
||||
// Grid margins reset to 0 — overlay padding handles all edge clearance.
|
||||
|
||||
@media (orientation: landscape) {
|
||||
@@ -892,7 +894,7 @@ html:has(.sig-backdrop) {
|
||||
}
|
||||
|
||||
@media (orientation: landscape) and (min-width: 900px) {
|
||||
// Wide landscape: revert to stacked layout (stage top, 18-card row grid bottom).
|
||||
// Middling landscape: stacked layout (stage top, 9×2 grid bottom).
|
||||
.sig-modal {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
@@ -903,11 +905,19 @@ html:has(.sig-backdrop) {
|
||||
margin-left: 3rem;
|
||||
}
|
||||
.sig-deck-grid {
|
||||
grid-template-columns: repeat(18, 3rem);
|
||||
grid-template-columns: repeat(9, 3rem);
|
||||
align-self: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media (orientation: landscape) and (min-width: 1400px) {
|
||||
// Wide landscape: 18-card single-row grid. 18×3rem + ~7rem modal margins
|
||||
// clears the viewport here even at the fluid-rem ceiling (rem=22 → ~1376px).
|
||||
.sig-deck-grid {
|
||||
grid-template-columns: repeat(18, 3rem);
|
||||
}
|
||||
}
|
||||
|
||||
@media (orientation: landscape) and (min-width: 1800px) {
|
||||
// Sig overlay: clear doubled sidebars (8rem each instead of 4rem/6rem)
|
||||
.sig-overlay { padding-left: 8rem; padding-right: 8rem; }
|
||||
|
||||
@@ -20,8 +20,9 @@
|
||||
|
||||
$tray-w: 280px;
|
||||
$handle-rect-w: 10000px;
|
||||
$handle-rect-h: 72px;
|
||||
$handle-exposed: 48px;
|
||||
$handle-rect-h: 4.5rem; // visible rail thickness — scales w. rem; ≈ btn (3rem) + breathing room
|
||||
$handle-exposed: 3rem; // matches #id_tray_btn so the btn fills the exposed handle area
|
||||
// (previously 48px → flex-shrink squished the btn on rem > 16px viewports)
|
||||
$handle-r: 1rem;
|
||||
$tray-bevel: 0.3rem; // inner bevel ring; grid must sit inside this
|
||||
|
||||
@@ -305,19 +306,19 @@ $tray-bevel: 0.3rem; // inner bevel ring; grid must sit inside this
|
||||
|
||||
#id_tray_handle {
|
||||
width: auto; // full width of wrap
|
||||
height: 48px; // $handle-exposed — same exposed dimension as portrait
|
||||
height: $handle-exposed; // same exposed dimension as portrait — scales w. rem
|
||||
}
|
||||
|
||||
#id_tray_grip {
|
||||
// Rotate 90°: centred horizontally, extends vertically.
|
||||
// bottom mirrors portrait's left: grip starts at handle centre and extends
|
||||
// toward the tray (upward in column-reverse layout).
|
||||
bottom: calc(48px / 2 - 0.125rem); // $handle-exposed / 2 from handle bottom
|
||||
bottom: calc(#{$handle-exposed} / 2 - 0.125rem); // $handle-exposed / 2 from handle bottom
|
||||
top: auto;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 72px; // $handle-rect-h — narrow visible dimension
|
||||
height: 10000px; // $handle-rect-w — extends upward into tray area
|
||||
width: $handle-rect-h; // narrow visible dimension — scales w. rem
|
||||
height: $handle-rect-w; // extends upward into tray area
|
||||
}
|
||||
|
||||
#id_tray {
|
||||
|
||||
Reference in New Issue
Block a user