update styles and ui-chrome

This commit is contained in:
2026-03-15 12:23:57 -07:00
parent 843c2fe96f
commit dfc0027c31
3 changed files with 170 additions and 50 deletions

View File

@@ -58,6 +58,34 @@
line-height: 1; line-height: 1;
flex: 0 0 auto; flex: 0 0 auto;
} }
.topbar-panel-toggle {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 7px 12px;
border-radius: 999px;
border: 1px solid #3f3f46;
background: #27272a;
color: #f4f4f5;
cursor: pointer;
font-size: 13px;
font-weight: 600;
line-height: 1;
flex: 0 0 auto;
margin-left: auto;
}
.topbar-panel-toggle:hover {
background: #3f3f46;
}
.topbar-panel-toggle[hidden] {
display: none;
}
.topbar-panel-toggle[hidden] + .topbar-menu-toggle {
margin-left: auto;
}
.topbar-panel-toggle:not([hidden]) + .topbar-menu-toggle {
margin-left: 0;
}
.topbar-menu-toggle:hover { .topbar-menu-toggle:hover {
background: #3f3f46; background: #3f3f46;
} }
@@ -158,7 +186,9 @@
} }
.topbar-menu-toggle { .topbar-menu-toggle {
min-height: 38px; min-height: 38px;
margin-left: auto; }
.topbar-panel-toggle {
min-height: 38px;
} }
.topbar.is-menu-open { .topbar.is-menu-open {
flex-wrap: nowrap; flex-wrap: nowrap;
@@ -2123,13 +2153,6 @@
pointer-events: auto; pointer-events: auto;
} }
.sidebar-popout-open {
position: absolute;
top: 10px;
right: 10px;
z-index: 5;
}
.detail-popout-open { .detail-popout-open {
position: absolute; position: absolute;
top: 10px; top: 10px;
@@ -5960,7 +5983,6 @@
min-height: 38px; min-height: 38px;
padding: 8px 10px; padding: 8px 10px;
} }
.sidebar-popout-open,
.detail-popout-open { .detail-popout-open {
position: fixed; position: fixed;
top: auto; top: auto;
@@ -5976,9 +5998,6 @@
-webkit-backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px); backdrop-filter: blur(10px);
} }
.sidebar-popout-open {
right: 14px;
}
.detail-popout-open { .detail-popout-open {
left: 14px; left: 14px;
} }

View File

@@ -6,6 +6,7 @@
const DEFAULT_DATASET_ENTRY_COLLAPSED = false; const DEFAULT_DATASET_ENTRY_COLLAPSED = false;
const DEFAULT_DATASET_DETAIL_COLLAPSED = true; const DEFAULT_DATASET_DETAIL_COLLAPSED = true;
const sidebarControllers = new WeakMap(); const sidebarControllers = new WeakMap();
const sidebarControllerRegistry = new Map();
const detailControllers = new WeakMap(); const detailControllers = new WeakMap();
const AUTO_COLLAPSE_ENTRY_SELECTOR = [ const AUTO_COLLAPSE_ENTRY_SELECTOR = [
".planet-list-item", ".planet-list-item",
@@ -162,6 +163,131 @@
return resolveLayoutTarget(panel); return resolveLayoutTarget(panel);
} }
function isLayoutVisible(layout) {
if (!(layout instanceof HTMLElement)) {
return false;
}
if (layout.hidden || layout.closest("[hidden]")) {
return false;
}
const section = layout.closest("section");
if (section instanceof HTMLElement && section.hidden) {
return false;
}
return true;
}
function getActiveVisibleSidebarController() {
for (const controller of sidebarControllerRegistry.values()) {
if (!isLayoutVisible(controller.layout)) {
continue;
}
return controller;
}
return null;
}
function getTopbarPanelToggleButton() {
const { topbarEl, menuToggleEl } = getTopbarElements();
if (!(topbarEl instanceof HTMLElement) || !(menuToggleEl instanceof HTMLButtonElement)) {
return null;
}
const existingButton = topbarEl.querySelector("#topbar-panel-toggle");
if (existingButton instanceof HTMLButtonElement) {
return existingButton;
}
const panelToggleEl = document.createElement("button");
panelToggleEl.id = "topbar-panel-toggle";
panelToggleEl.type = "button";
panelToggleEl.className = "topbar-panel-toggle sidebar-popout-open";
panelToggleEl.textContent = "Show Detail";
panelToggleEl.setAttribute("aria-label", "Show detail view");
panelToggleEl.hidden = true;
panelToggleEl.addEventListener("click", () => {
const controller = getActiveVisibleSidebarController();
if (!controller) {
return;
}
if (controller.layout.classList.contains("layout-sidebar-collapsed")) {
showSidebarOnly(controller.layout);
return;
}
if (detailControllers.has(controller.layout)) {
showDetailOnly(controller.layout);
}
});
topbarEl.insertBefore(panelToggleEl, menuToggleEl);
return panelToggleEl;
}
function syncTopbarPanelToggleButton() {
const panelToggleEl = getTopbarPanelToggleButton();
if (!(panelToggleEl instanceof HTMLButtonElement)) {
return;
}
const controller = getActiveVisibleSidebarController();
if (!controller) {
panelToggleEl.hidden = true;
panelToggleEl.removeAttribute("aria-controls");
panelToggleEl.setAttribute("aria-expanded", "false");
return;
}
const sidebarCollapsed = controller.layout.classList.contains("layout-sidebar-collapsed");
const hasDetailController = detailControllers.has(controller.layout);
if (!sidebarCollapsed && !hasDetailController) {
panelToggleEl.hidden = true;
panelToggleEl.removeAttribute("aria-controls");
panelToggleEl.setAttribute("aria-expanded", "false");
return;
}
panelToggleEl.hidden = false;
panelToggleEl.setAttribute("aria-controls", controller.panel.id);
panelToggleEl.setAttribute("aria-expanded", sidebarCollapsed ? "false" : "true");
panelToggleEl.textContent = sidebarCollapsed ? "Show Panel" : "Show Detail";
panelToggleEl.setAttribute("aria-label", sidebarCollapsed ? "Show entry panel" : "Show detail view");
}
function initializeTopbarPanelToggle() {
if (!document.body || document.body.dataset.topbarPanelToggleReady === "1") {
syncTopbarPanelToggleButton();
return;
}
document.body.dataset.topbarPanelToggleReady = "1";
getTopbarPanelToggleButton();
const observer = new MutationObserver(() => {
window.requestAnimationFrame(() => {
syncTopbarPanelToggleButton();
});
});
observer.observe(document.body, {
subtree: true,
attributes: true,
attributeFilter: ["hidden", "class"]
});
window.addEventListener("resize", () => {
syncTopbarPanelToggleButton();
});
syncTopbarPanelToggleButton();
}
function scheduleAutoCollapse(layout) { function scheduleAutoCollapse(layout) {
if (!(layout instanceof HTMLElement)) { if (!(layout instanceof HTMLElement)) {
return; return;
@@ -221,11 +347,6 @@
return; return;
} }
const header = panel.querySelector(".planet-list-header, .tarot-list-header");
if (!(header instanceof HTMLElement)) {
return;
}
panel.dataset.sidebarPopoutReady = "1"; panel.dataset.sidebarPopoutReady = "1";
const sectionId = layout.closest("section")?.id || `layout-${index + 1}`; const sectionId = layout.closest("section")?.id || `layout-${index + 1}`;
@@ -234,53 +355,30 @@
const storageKey = `${SIDEBAR_COLLAPSE_STORAGE_PREFIX}${sectionId}`; const storageKey = `${SIDEBAR_COLLAPSE_STORAGE_PREFIX}${sectionId}`;
const collapseBtn = document.createElement("button");
collapseBtn.type = "button";
collapseBtn.className = "sidebar-toggle-inline";
collapseBtn.textContent = "Hide Panel";
collapseBtn.setAttribute("aria-label", "Hide entry panel");
collapseBtn.setAttribute("aria-controls", panelId);
header.appendChild(collapseBtn);
const openBtn = document.createElement("button");
openBtn.type = "button";
openBtn.className = "sidebar-popout-open";
openBtn.textContent = "Show Panel";
openBtn.setAttribute("aria-label", "Show entry panel");
openBtn.setAttribute("aria-controls", panelId);
openBtn.hidden = true;
layout.appendChild(openBtn);
const applyCollapsedState = (collapsed, persist = true) => { const applyCollapsedState = (collapsed, persist = true) => {
layout.classList.toggle("layout-sidebar-collapsed", collapsed); layout.classList.toggle("layout-sidebar-collapsed", collapsed);
collapseBtn.setAttribute("aria-expanded", collapsed ? "false" : "true"); syncTopbarPanelToggleButton();
openBtn.setAttribute("aria-expanded", collapsed ? "false" : "true");
openBtn.hidden = !collapsed;
if (persist) { if (persist) {
saveSidebarCollapsedState(storageKey, collapsed); saveSidebarCollapsedState(storageKey, collapsed);
} }
}; };
sidebarControllers.set(layout, { const controller = {
layout,
applyCollapsedState, applyCollapsedState,
panel, panel,
collapseBtn,
openBtn,
storageKey storageKey
}); };
collapseBtn.addEventListener("click", () => { sidebarControllers.set(layout, controller);
showDetailOnly(layout); sidebarControllerRegistry.set(layout, controller);
});
openBtn.addEventListener("click", () => {
showSidebarOnly(layout);
});
const storedCollapsed = loadSidebarCollapsedState(storageKey); const storedCollapsed = loadSidebarCollapsedState(storageKey);
applyCollapsedState(storedCollapsed == null ? DEFAULT_DATASET_ENTRY_COLLAPSED : storedCollapsed, false); applyCollapsedState(storedCollapsed == null ? DEFAULT_DATASET_ENTRY_COLLAPSED : storedCollapsed, false);
}); });
syncTopbarPanelToggleButton();
} }
function initializeDetailPopouts() { function initializeDetailPopouts() {
@@ -322,6 +420,7 @@
layout.classList.toggle("layout-detail-collapsed", collapsed); layout.classList.toggle("layout-detail-collapsed", collapsed);
detailPanel.setAttribute("aria-hidden", collapsed ? "true" : "false"); detailPanel.setAttribute("aria-hidden", collapsed ? "true" : "false");
syncTopbarPanelToggleButton();
if (persist) { if (persist) {
saveSidebarCollapsedState(detailStorageKey, collapsed); saveSidebarCollapsedState(detailStorageKey, collapsed);
@@ -503,6 +602,7 @@
initializeSidebarAutoCollapse(); initializeSidebarAutoCollapse();
bindTopbarMobileMenu(); bindTopbarMobileMenu();
bindTopbarDropdownInteractions(); bindTopbarDropdownInteractions();
initializeTopbarPanelToggle();
} }
window.TarotChromeUi = { window.TarotChromeUi = {
@@ -512,6 +612,7 @@
initializeDetailPopouts, initializeDetailPopouts,
initializeSidebarAutoCollapse, initializeSidebarAutoCollapse,
bindTopbarMobileMenu, bindTopbarMobileMenu,
initializeTopbarPanelToggle,
setSidebarCollapsed, setSidebarCollapsed,
setDetailCollapsed, setDetailCollapsed,
showDetailOnly, showDetailOnly,

View File

@@ -16,7 +16,7 @@
<link rel="stylesheet" href="node_modules/@fontsource/amiri/arabic-400.css"> <link rel="stylesheet" href="node_modules/@fontsource/amiri/arabic-400.css">
<link rel="stylesheet" href="node_modules/@fontsource/amiri/arabic-700.css"> <link rel="stylesheet" href="node_modules/@fontsource/amiri/arabic-700.css">
<link rel="stylesheet" href="node_modules/@fontsource/noto-naskh-arabic/arabic-400.css"> <link rel="stylesheet" href="node_modules/@fontsource/noto-naskh-arabic/arabic-400.css">
<link rel="stylesheet" href="app/styles.css?v=20260314-audio-circle-01"> <link rel="stylesheet" href="app/styles.css?v=20260314-topbar-panel-toggle-01">
</head> </head>
<body> <body>
<div class="topbar"> <div class="topbar">
@@ -1086,7 +1086,7 @@
<script src="app/ui-numbers.js"></script> <script src="app/ui-numbers.js"></script>
<script src="app/ui-tarot-spread.js"></script> <script src="app/ui-tarot-spread.js"></script>
<script src="app/ui-settings.js?v=20260309-gate"></script> <script src="app/ui-settings.js?v=20260309-gate"></script>
<script src="app/ui-chrome.js?v=20260314-mobile-menu-overlay-01"></script> <script src="app/ui-chrome.js?v=20260314-topbar-panel-toggle-02"></script>
<script src="app/ui-navigation.js?v=20260314-audio-circle-01"></script> <script src="app/ui-navigation.js?v=20260314-audio-circle-01"></script>
<script src="app/ui-calendar-formatting.js?v=20260307b"></script> <script src="app/ui-calendar-formatting.js?v=20260307b"></script>
<script src="app/ui-calendar-visuals.js?v=20260307b"></script> <script src="app/ui-calendar-visuals.js?v=20260307b"></script>