fix: dropdown menus use fixed positioning to escape overflow clipping
Dropdown menus in app-switcher and space-switcher were clipped by overflow:hidden on .rstack-header__left (mobile). Changed from position:absolute to position:fixed with dynamic getBoundingClientRect positioning. Bumped shell asset versions to v=5 to bypass CF cache. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
08928a9f8e
commit
d9bd7557fa
|
|
@ -54,7 +54,7 @@ export function renderShell(opts: ShellOptions): string {
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🌌</text></svg>">
|
||||
<title>${escapeHtml(title)}</title>
|
||||
<link rel="stylesheet" href="/shell.css?v=4">
|
||||
<link rel="stylesheet" href="/shell.css?v=5">
|
||||
<style>
|
||||
/* When loaded inside an iframe (e.g. standalone domain redirecting back),
|
||||
hide the shell chrome — the parent rSpace page already provides it. */
|
||||
|
|
@ -94,7 +94,7 @@ export function renderShell(opts: ShellOptions): string {
|
|||
${renderWelcomeOverlay()}
|
||||
|
||||
<script type="module">
|
||||
import '/shell.js?v=4';
|
||||
import '/shell.js?v=5';
|
||||
// Provide module list to app switcher
|
||||
document.querySelector('rstack-app-switcher')?.setModules(${moduleListJSON});
|
||||
|
||||
|
|
@ -355,7 +355,7 @@ export function renderExternalAppShell(opts: ExternalAppShellOptions): string {
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🌌</text></svg>">
|
||||
<title>${escapeHtml(title)}</title>
|
||||
<link rel="stylesheet" href="/shell.css?v=4">
|
||||
<link rel="stylesheet" href="/shell.css?v=5">
|
||||
<style>
|
||||
html.rspace-embedded .rstack-header { display: none !important; }
|
||||
html.rspace-embedded .rstack-tab-row { display: none !important; }
|
||||
|
|
@ -398,7 +398,7 @@ export function renderExternalAppShell(opts: ExternalAppShellOptions): string {
|
|||
</div>
|
||||
|
||||
<script type="module">
|
||||
import '/shell.js?v=4';
|
||||
import '/shell.js?v=5';
|
||||
document.querySelector('rstack-app-switcher')?.setModules(${moduleListJSON});
|
||||
|
||||
const tabBar = document.querySelector('rstack-tab-bar');
|
||||
|
|
@ -581,7 +581,7 @@ export function renderModuleLanding(opts: ModuleLandingOptions): string {
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>${mod.icon}</text></svg>">
|
||||
<title>${escapeHtml(mod.name)} — rSpace</title>
|
||||
<link rel="stylesheet" href="/shell.css?v=4">
|
||||
<link rel="stylesheet" href="/shell.css?v=5">
|
||||
${cssBlock}
|
||||
<script defer src="https://rdata.online/collect.js" data-website-id="6ee7917b-0ed7-44cb-a4c8-91037638526b"></script>
|
||||
</head>
|
||||
|
|
@ -601,7 +601,7 @@ export function renderModuleLanding(opts: ModuleLandingOptions): string {
|
|||
</header>
|
||||
${bodyContent}
|
||||
<script type="module">
|
||||
import '/shell.js?v=4';
|
||||
import '/shell.js?v=5';
|
||||
document.querySelector('rstack-app-switcher')?.setModules(${moduleListJSON});
|
||||
try {
|
||||
var raw = localStorage.getItem('encryptid_session');
|
||||
|
|
|
|||
|
|
@ -241,7 +241,12 @@ export class RStackAppSwitcher extends HTMLElement {
|
|||
|
||||
trigger.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
menu.classList.toggle("open");
|
||||
const isOpen = menu.classList.toggle("open");
|
||||
if (isOpen) {
|
||||
const rect = trigger.getBoundingClientRect();
|
||||
menu.style.top = `${rect.bottom + 6}px`;
|
||||
menu.style.left = `${Math.max(4, rect.left)}px`;
|
||||
}
|
||||
});
|
||||
|
||||
// Prevent external links from closing the menu prematurely
|
||||
|
|
@ -298,10 +303,10 @@ const STYLES = `
|
|||
.caret { font-size: 0.7em; opacity: 0.6; }
|
||||
|
||||
.menu {
|
||||
position: absolute; top: 100%; left: 0; margin-top: 6px;
|
||||
position: fixed; margin-top: 0;
|
||||
min-width: 300px; border-radius: 12px; overflow: hidden;
|
||||
overflow-y: auto; max-height: 70vh;
|
||||
box-shadow: 0 8px 30px rgba(0,0,0,0.25); display: none; z-index: 200;
|
||||
box-shadow: 0 8px 30px rgba(0,0,0,0.25); display: none; z-index: 10001;
|
||||
}
|
||||
.menu.open { display: block; }
|
||||
:host-context([data-theme="light"]) .menu {
|
||||
|
|
|
|||
|
|
@ -100,9 +100,14 @@ export class RStackSpaceSwitcher extends HTMLElement {
|
|||
trigger.addEventListener("click", async (e) => {
|
||||
e.stopPropagation();
|
||||
const isOpen = menu.classList.toggle("open");
|
||||
if (isOpen && !this.#loaded) {
|
||||
await this.#loadSpaces();
|
||||
this.#renderMenu(menu, current);
|
||||
if (isOpen) {
|
||||
const rect = trigger.getBoundingClientRect();
|
||||
menu.style.top = `${rect.bottom + 6}px`;
|
||||
menu.style.left = `${Math.max(4, rect.left)}px`;
|
||||
if (!this.#loaded) {
|
||||
await this.#loadSpaces();
|
||||
this.#renderMenu(menu, current);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -689,10 +694,10 @@ const STYLES = `
|
|||
.caret { font-size: 0.7em; opacity: 0.6; }
|
||||
|
||||
.menu {
|
||||
position: absolute; top: 100%; left: 0; margin-top: 6px;
|
||||
position: fixed; margin-top: 0;
|
||||
min-width: 260px; max-height: 400px; overflow-y: auto;
|
||||
border-radius: 12px; box-shadow: 0 8px 30px rgba(0,0,0,0.25);
|
||||
display: none; z-index: 200;
|
||||
display: none; z-index: 10001;
|
||||
}
|
||||
.menu.open { display: block; }
|
||||
:host-context([data-theme="light"]) .menu { background: white; border: 1px solid rgba(0,0,0,0.1); }
|
||||
|
|
|
|||
Loading…
Reference in New Issue