Synchronize UX stack handling and search header
This commit is contained in:
parent
0450ec9e1c
commit
fc85729374
2 changed files with 49 additions and 32 deletions
59
script.js
59
script.js
|
@ -64,9 +64,24 @@
|
|||
function ensureViewEl(view) {
|
||||
if (!view || !view.el) throw new Error('Invalid view');
|
||||
view.el.classList.add('ux-view');
|
||||
if (view.kind) view.el.dataset.uxKind = view.kind;
|
||||
return view.el;
|
||||
}
|
||||
|
||||
function assertKind(view, expected) {
|
||||
if (!view) throw new Error('Missing view');
|
||||
if (view.kind && view.kind !== expected) {
|
||||
throw new Error(`Expected view kind "${expected}" but received "${view.kind}"`);
|
||||
}
|
||||
}
|
||||
|
||||
async function closeAllOverlays({ restoreFocus = false } = {}) {
|
||||
while (overlayStack.length) {
|
||||
const shouldRestore = restoreFocus && overlayStack.length === 1;
|
||||
await closeTop({ restoreFocus: shouldRestore });
|
||||
}
|
||||
}
|
||||
|
||||
function syncOverlayVisibility() {
|
||||
const topIndex = overlayStack.length - 1;
|
||||
overlayStack.forEach((entry, idx) => {
|
||||
|
@ -104,6 +119,8 @@
|
|||
}
|
||||
|
||||
async function replace(view) {
|
||||
assertKind(view, 'base');
|
||||
await closeAllOverlays({ restoreFocus: false });
|
||||
const el = ensureViewEl(view);
|
||||
const prev = currentBase;
|
||||
if (prev) {
|
||||
|
@ -122,6 +139,7 @@
|
|||
}
|
||||
|
||||
async function openOverlay(view) {
|
||||
assertKind(view, 'overlay');
|
||||
const el = ensureViewEl(view);
|
||||
el.classList.add('ux-view--overlay');
|
||||
const lastFocus = document.activeElement;
|
||||
|
@ -134,7 +152,7 @@
|
|||
if (typeof view.onShow === 'function') view.onShow();
|
||||
}
|
||||
|
||||
async function closeTop() {
|
||||
async function closeTop({ restoreFocus = true } = {}) {
|
||||
const top = overlayStack[overlayStack.length - 1];
|
||||
if (!top) return;
|
||||
if (top.isClosing) return;
|
||||
|
@ -146,7 +164,9 @@
|
|||
if (typeof view.destroy === 'function') view.destroy();
|
||||
overlayStack.pop();
|
||||
syncOverlayVisibility();
|
||||
if (lastFocus && typeof lastFocus.focus === 'function') lastFocus.focus();
|
||||
if (restoreFocus && lastFocus && typeof lastFocus.focus === 'function') {
|
||||
lastFocus.focus();
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('keydown', (e) => {
|
||||
|
@ -156,7 +176,7 @@
|
|||
}
|
||||
});
|
||||
|
||||
return { replace, openOverlay, closeTop };
|
||||
return { replace, openOverlay, closeTop, closeAllOverlays };
|
||||
})();
|
||||
|
||||
// --- IndexedDB helpers (minimal, no external deps) ---
|
||||
|
@ -722,35 +742,8 @@
|
|||
const $form = el.querySelector('[data-ref="form"]');
|
||||
const $q = el.querySelector('[data-ref="q"]');
|
||||
const $results = el.querySelector('[data-ref="results"]');
|
||||
|
||||
// Back + sort toolbar keeps controls grouped for accessibility.
|
||||
const $toolbar = document.createElement('div');
|
||||
$toolbar.className = 'level mb-4 is-mobile';
|
||||
const $toolbarLeft = document.createElement('div');
|
||||
$toolbarLeft.className = 'level-left';
|
||||
const $toolbarLeftItem = document.createElement('div');
|
||||
$toolbarLeftItem.className = 'level-item';
|
||||
const $backBtn = document.createElement('button');
|
||||
$backBtn.type = 'button';
|
||||
$backBtn.className = 'button is-small is-text';
|
||||
$backBtn.textContent = 'Back to menu';
|
||||
$toolbarLeftItem.appendChild($backBtn);
|
||||
$toolbarLeft.appendChild($toolbarLeftItem);
|
||||
const $toolbarRight = document.createElement('div');
|
||||
$toolbarRight.className = 'level-right';
|
||||
const $toolbarRightItem = document.createElement('div');
|
||||
$toolbarRightItem.className = 'level-item';
|
||||
const $sortLabel = document.createElement('span');
|
||||
$sortLabel.className = 'is-size-7 has-text-grey mr-2';
|
||||
$sortLabel.textContent = 'Sort';
|
||||
const $sortButtons = document.createElement('div');
|
||||
$sortButtons.className = 'buttons has-addons is-small';
|
||||
$toolbarRightItem.appendChild($sortLabel);
|
||||
$toolbarRightItem.appendChild($sortButtons);
|
||||
$toolbarRight.appendChild($toolbarRightItem);
|
||||
$toolbar.appendChild($toolbarLeft);
|
||||
$toolbar.appendChild($toolbarRight);
|
||||
$form.insertAdjacentElement('afterend', $toolbar);
|
||||
const $backBtn = el.querySelector('[data-action="back"]');
|
||||
const $sortButtons = el.querySelector('[data-ref="sort-buttons"]');
|
||||
|
||||
const $status = document.createElement('p');
|
||||
$status.className = 'has-text-grey';
|
||||
|
@ -796,6 +789,8 @@
|
|||
{ key: 'alpha', label: 'A–Z' },
|
||||
];
|
||||
|
||||
if (!$backBtn) throw new Error('Missing back button');
|
||||
if (!$sortButtons) throw new Error('Missing sort container');
|
||||
sortOptions.forEach((opt) => {
|
||||
const btn = document.createElement('button');
|
||||
btn.type = 'button';
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue