update styles and ui-chrome
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
173
app/ui-chrome.js
173
app/ui-chrome.js
@@ -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,
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user