Skip to content

Commit 7efa27e

Browse files
author
DavidQ
committed
Unify fullscreen side panels across tools: replace single open/close popouts with per-section +/- toggles, remove X buttons, allow multi-open accordions, hide top toggle buttons while sidebars are expanded, and add +/- indicators to in-panel accordion headers for Vector Map Editor, Parallax Scene Studio, and Sprite Editor.
1 parent d03c061 commit 7efa27e

9 files changed

Lines changed: 865 additions & 390 deletions

File tree

tools/Parallax Scene Studio/index.html

Lines changed: 177 additions & 135 deletions
Large diffs are not rendered by default.

tools/Parallax Scene Studio/main.js

Lines changed: 93 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -458,10 +458,9 @@ class ParallaxEditorApp {
458458
this.refs.appShell = rootDocument.querySelector(".app-shell");
459459
this.refs.leftSidebar = rootDocument.getElementById("leftSidebar");
460460
this.refs.rightSidebar = rootDocument.getElementById("rightSidebar");
461-
this.refs.showLeftPanelButton = rootDocument.getElementById("showLeftPanelButton");
462-
this.refs.showRightPanelButton = rootDocument.getElementById("showRightPanelButton");
463-
this.refs.closeLeftOverlayButton = rootDocument.getElementById("closeLeftOverlayButton");
464-
this.refs.closeRightOverlayButton = rootDocument.getElementById("closeRightOverlayButton");
461+
this.refs.leftPanelAccordions = Array.from(rootDocument.querySelectorAll("#leftSidebar .panel-accordion"));
462+
this.refs.rightPanelAccordions = Array.from(rootDocument.querySelectorAll("#rightSidebar .panel-accordion"));
463+
this.refs.overlayToggleButtons = Array.from(rootDocument.querySelectorAll("[data-overlay-toggle]"));
465464
this.refs.previewWrap = rootDocument.querySelector(".preview-wrap");
466465
this.refs.previewCanvas = rootDocument.getElementById("previewCanvas");
467466
this.refs.previewContext = this.refs.previewCanvas.getContext("2d", { alpha: false });
@@ -487,21 +486,18 @@ class ParallaxEditorApp {
487486
this.refs.inspectRemediationButton.addEventListener("click", () => this.inspectRemediationActions());
488487
this.refs.jumpToProblemButton.addEventListener("click", () => this.jumpToRemediationProblem());
489488
this.refs.applyRemediationButton.addEventListener("click", () => this.applyRemediationAction());
490-
this.refs.showLeftPanelButton?.addEventListener("click", () => {
491-
this.refs.leftSidebar?.classList.toggle("visible-overlay");
492-
this.syncOverlayToggleButtons();
489+
this.refs.overlayToggleButtons.forEach((button) => {
490+
button.addEventListener("click", () => {
491+
const side = button.dataset.overlaySide === "left" ? "left" : "right";
492+
const targetId = button.dataset.overlayTarget || "";
493+
this.toggleOverlayPanel(side, targetId);
494+
});
493495
});
494-
this.refs.showRightPanelButton?.addEventListener("click", () => {
495-
this.refs.rightSidebar?.classList.toggle("visible-overlay");
496-
this.syncOverlayToggleButtons();
496+
this.refs.leftPanelAccordions.forEach((panel) => {
497+
panel.addEventListener("toggle", () => this.handleOverlayAccordionToggle("left", panel));
497498
});
498-
this.refs.closeLeftOverlayButton?.addEventListener("click", () => {
499-
this.refs.leftSidebar?.classList.remove("visible-overlay");
500-
this.syncOverlayToggleButtons();
501-
});
502-
this.refs.closeRightOverlayButton?.addEventListener("click", () => {
503-
this.refs.rightSidebar?.classList.remove("visible-overlay");
504-
this.syncOverlayToggleButtons();
499+
this.refs.rightPanelAccordions.forEach((panel) => {
500+
panel.addEventListener("toggle", () => this.handleOverlayAccordionToggle("right", panel));
505501
});
506502
document.addEventListener("fullscreenchange", () => {
507503
this.syncFullscreenState();
@@ -551,14 +547,88 @@ class ParallaxEditorApp {
551547
}
552548

553549
syncOverlayToggleButtons() {
554-
const leftVisible = this.refs.leftSidebar?.classList.contains("visible-overlay") === true;
555-
const rightVisible = this.refs.rightSidebar?.classList.contains("visible-overlay") === true;
556-
if (this.refs.showLeftPanelButton instanceof HTMLElement) {
557-
this.refs.showLeftPanelButton.style.display = leftVisible ? "none" : "";
550+
const fullscreenActive = Boolean(document.fullscreenElement);
551+
this.refs.overlayToggleButtons.forEach((button) => {
552+
const side = button.dataset.overlaySide === "left" ? "left" : "right";
553+
const targetId = button.dataset.overlayTarget || "";
554+
const sidebar = this.getOverlaySidebar(side);
555+
const target = targetId ? document.getElementById(targetId) : null;
556+
const active = Boolean(
557+
fullscreenActive
558+
&& sidebar instanceof HTMLElement
559+
&& sidebar.classList.contains("visible-overlay")
560+
&& target instanceof HTMLElement
561+
&& target.open
562+
);
563+
button.setAttribute("aria-expanded", active ? "true" : "false");
564+
const symbol = button.querySelector(".overlay-toggle-symbol");
565+
if (symbol) {
566+
symbol.textContent = active ? "-" : "+";
567+
}
568+
const hideWhileOverlayOpen = Boolean(
569+
fullscreenActive
570+
&& sidebar instanceof HTMLElement
571+
&& sidebar.classList.contains("visible-overlay")
572+
);
573+
button.classList.toggle("is-hidden-while-overlay-open", hideWhileOverlayOpen);
574+
});
575+
}
576+
577+
getOverlaySidebar(side) {
578+
return side === "left" ? this.refs.leftSidebar : this.refs.rightSidebar;
579+
}
580+
581+
getOverlayPanels(side) {
582+
return side === "left" ? this.refs.leftPanelAccordions : this.refs.rightPanelAccordions;
583+
}
584+
585+
toggleOverlayPanel(side, targetId) {
586+
const sidebar = this.getOverlaySidebar(side);
587+
const panels = this.getOverlayPanels(side);
588+
if (!(sidebar instanceof HTMLElement) || !Array.isArray(panels) || panels.length === 0) {
589+
return;
590+
}
591+
const target = panels.find((panel) => panel.id === targetId);
592+
if (!(target instanceof HTMLElement)) {
593+
return;
594+
}
595+
596+
const fullscreenActive = Boolean(document.fullscreenElement);
597+
if (!fullscreenActive) {
598+
target.open = !target.open;
599+
this.syncOverlayToggleButtons();
600+
return;
601+
}
602+
603+
const overlayVisible = sidebar.classList.contains("visible-overlay");
604+
if (!overlayVisible) {
605+
sidebar.classList.add("visible-overlay");
606+
target.open = true;
607+
} else {
608+
target.open = !target.open;
609+
}
610+
if (!panels.some((panel) => panel.open)) {
611+
sidebar.classList.remove("visible-overlay");
558612
}
559-
if (this.refs.showRightPanelButton instanceof HTMLElement) {
560-
this.refs.showRightPanelButton.style.display = rightVisible ? "none" : "";
613+
614+
this.syncOverlayToggleButtons();
615+
}
616+
617+
handleOverlayAccordionToggle(side, panel) {
618+
if (!document.fullscreenElement) {
619+
return;
561620
}
621+
const sidebar = this.getOverlaySidebar(side);
622+
const panels = this.getOverlayPanels(side);
623+
if (!(sidebar instanceof HTMLElement) || !Array.isArray(panels)) {
624+
return;
625+
}
626+
if (panel.open) {
627+
sidebar.classList.add("visible-overlay");
628+
} else if (!panels.some((entry) => entry.open)) {
629+
sidebar.classList.remove("visible-overlay");
630+
}
631+
this.syncOverlayToggleButtons();
562632
}
563633

564634
getSelectedLayer() {

tools/Parallax Scene Studio/parallaxEditor.css

Lines changed: 80 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,38 @@ button:hover,
127127
font-size: 14px;
128128
}
129129

130+
.panel-accordion {
131+
margin: 0 0 10px;
132+
border: 1px solid var(--parallax-border);
133+
border-radius: 8px;
134+
background: linear-gradient(180deg, var(--panel, rgba(76, 29, 149, 0.88)) 0%, var(--panel2, rgba(49, 17, 102, 0.94)) 100%);
135+
overflow: hidden;
136+
}
137+
138+
.panel-accordion__summary {
139+
list-style: none;
140+
cursor: pointer;
141+
padding: 8px;
142+
border-bottom: 1px solid transparent;
143+
}
144+
145+
.panel-accordion__summary::-webkit-details-marker {
146+
display: none;
147+
}
148+
149+
.panel-accordion__summary h3 {
150+
margin: 0;
151+
font-size: 14px;
152+
}
153+
154+
.panel-accordion[open] .panel-accordion__summary {
155+
border-bottom-color: var(--parallax-border);
156+
}
157+
158+
.panel-accordion__body {
159+
padding: 8px;
160+
}
161+
130162
.preview-panel {
131163
display: flex;
132164
flex-direction: column;
@@ -240,24 +272,39 @@ button:hover,
240272
}
241273

242274
.parallax-editor-page .fullscreen-overlay-button {
243-
position: absolute;
244-
top: 10px;
245-
z-index: 20;
275+
position: relative;
276+
z-index: 80;
246277
display: none;
247278
min-height: 32px;
248279
padding: 0 10px;
249280
}
250281

251-
.parallax-editor-page .overlay-close-button {
282+
.parallax-editor-page .fullscreen-overlay-toggle-group {
252283
display: none;
284+
position: fixed;
285+
top: 96px;
286+
z-index: 80;
287+
gap: 8px;
288+
flex-direction: column;
253289
}
254290

255-
.parallax-editor-page #showLeftPanelButton {
291+
.parallax-editor-page .fullscreen-overlay-toggle-group--left {
256292
left: 10px;
293+
align-items: flex-start;
257294
}
258295

259-
.parallax-editor-page #showRightPanelButton {
296+
.parallax-editor-page .fullscreen-overlay-toggle-group--right {
260297
right: 10px;
298+
align-items: flex-end;
299+
}
300+
301+
.parallax-editor-page .overlay-toggle-symbol {
302+
display: inline-flex;
303+
align-items: center;
304+
justify-content: center;
305+
width: 14px;
306+
font-weight: 900;
307+
line-height: 1;
261308
}
262309

263310
body.parallax-editor-page.fullscreen-mode .app-shell {
@@ -296,29 +343,7 @@ body.parallax-editor-page.fullscreen-mode .sidebar.visible-overlay {
296343
width: min(360px, calc(100vw - 24px));
297344
z-index: 50;
298345
overflow: auto;
299-
padding-top: 48px;
300-
}
301-
302-
body.parallax-editor-page.fullscreen-mode .sidebar.visible-overlay .overlay-close-button {
303-
position: absolute;
304-
top: 13px;
305-
right: 13px;
306-
z-index: 80;
307-
display: inline-flex;
308-
align-items: center;
309-
justify-content: center;
310-
width: 34px;
311-
height: 34px;
312-
min-height: 34px;
313-
padding: 0;
314-
border-radius: 999px;
315-
font-size: 16px;
316-
font-weight: 900;
317-
line-height: 1;
318-
border: 2px solid #ffffff;
319-
background: #ed9700;
320-
color: #ffffff;
321-
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.45);
346+
padding-top: 10px;
322347
}
323348

324349
body.parallax-editor-page.fullscreen-mode .left-sidebar.visible-overlay {
@@ -349,19 +374,38 @@ body.parallax-editor-page.fullscreen-mode #previewCanvas {
349374

350375
body.parallax-editor-page.fullscreen-mode .fullscreen-overlay-button {
351376
display: inline-flex;
352-
position: fixed;
353377
align-items: center;
354378
justify-content: center;
355-
top: 96px;
356-
z-index: 60;
379+
gap: 6px;
357380
}
358381

359-
body.parallax-editor-page.fullscreen-mode #showLeftPanelButton {
360-
left: 10px;
382+
body.parallax-editor-page.fullscreen-mode .fullscreen-overlay-toggle-group {
383+
display: flex;
361384
}
362385

363-
body.parallax-editor-page.fullscreen-mode #showRightPanelButton {
364-
right: 10px;
386+
body.parallax-editor-page.fullscreen-mode .fullscreen-overlay-button.is-hidden-while-overlay-open {
387+
visibility: hidden;
388+
pointer-events: none;
389+
}
390+
391+
body.parallax-editor-page.fullscreen-mode .sidebar.visible-overlay .panel-accordion__summary {
392+
display: flex;
393+
align-items: center;
394+
gap: 8px;
395+
}
396+
397+
body.parallax-editor-page.fullscreen-mode .sidebar.visible-overlay .panel-accordion__summary::before {
398+
content: "+";
399+
display: inline-flex;
400+
align-items: center;
401+
justify-content: center;
402+
width: 14px;
403+
font-weight: 900;
404+
line-height: 1;
405+
}
406+
407+
body.parallax-editor-page.fullscreen-mode .sidebar.visible-overlay .panel-accordion[open] > .panel-accordion__summary::before {
408+
content: "-";
365409
}
366410

367411
body.parallax-editor-page.fullscreen-mode .preview-details-text {

0 commit comments

Comments
 (0)