fix: app-switcher routes through tab system + canvas fills viewport in tab pane
- App-switcher now dispatches module-select event instead of full page navigation for same-origin links; shell routes through TabCache for instant tab switching - Tab pane gets height:100% in canvas-layout mode so #canvas fills the viewport (fixes pan/zoom not working on empty canvas background) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
be271de7fb
commit
a402caacd8
|
|
@ -324,6 +324,36 @@ export function renderShell(opts: ShellOptions): string {
|
|||
document.dispatchEvent(new CustomEvent('layer-view-mode', { detail: { mode } }));
|
||||
});
|
||||
|
||||
// ── App-switcher → tab system integration ──
|
||||
// When user picks a module from the app-switcher, route through tabs
|
||||
// instead of doing a full page navigation.
|
||||
const appSwitcher = document.querySelector('rstack-app-switcher');
|
||||
if (appSwitcher) {
|
||||
appSwitcher.addEventListener('module-select', (e) => {
|
||||
const { moduleId } = e.detail;
|
||||
// Already on this module? No-op.
|
||||
if (moduleId === currentModuleId && !tabCache) return;
|
||||
if (moduleId === currentModuleId && tabCache) {
|
||||
tabCache.switchTo(moduleId);
|
||||
return;
|
||||
}
|
||||
// Add tab if not already open
|
||||
if (!layers.find(l => l.moduleId === moduleId)) {
|
||||
layers.push(makeLayer(moduleId, layers.length));
|
||||
}
|
||||
saveTabs();
|
||||
tabBar.setLayers(layers);
|
||||
tabBar.setAttribute('active', 'layer-' + moduleId);
|
||||
if (tabCache) {
|
||||
tabCache.switchTo(moduleId).then(ok => {
|
||||
if (!ok) window.location.href = window.__rspaceNavUrl(spaceSlug, moduleId);
|
||||
});
|
||||
} else {
|
||||
window.location.href = window.__rspaceNavUrl(spaceSlug, moduleId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Expose tabBar for CommunitySync integration
|
||||
window.__rspaceTabBar = tabBar;
|
||||
|
||||
|
|
|
|||
|
|
@ -254,6 +254,27 @@ export class RStackAppSwitcher extends HTMLElement {
|
|||
el.addEventListener("click", (e) => e.stopPropagation());
|
||||
});
|
||||
|
||||
// Intercept same-origin module links → dispatch event for tab system
|
||||
this.#shadow.querySelectorAll("a.item").forEach((el) => {
|
||||
el.addEventListener("click", (e) => {
|
||||
const moduleId = (el as HTMLElement).dataset.id;
|
||||
if (!moduleId) return;
|
||||
// Only intercept same-origin links (skip bare-domain landing pages)
|
||||
const href = (el as HTMLAnchorElement).href;
|
||||
try {
|
||||
const url = new URL(href, window.location.href);
|
||||
if (url.origin !== window.location.origin) return;
|
||||
} catch { return; }
|
||||
e.preventDefault();
|
||||
menu.classList.remove("open");
|
||||
this.dispatchEvent(new CustomEvent("module-select", {
|
||||
detail: { moduleId },
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener("click", () => menu.classList.remove("open"));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -392,6 +392,11 @@ body[data-theme="light"] {
|
|||
display: block;
|
||||
}
|
||||
|
||||
/* When canvas is active, the tab pane must fill the viewport so #canvas height:100% works */
|
||||
#app.canvas-layout > .rspace-tab-pane--active {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.rspace-tab-loading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
|
|||
Loading…
Reference in New Issue