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">
|
<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>">
|
<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>
|
<title>${escapeHtml(title)}</title>
|
||||||
<link rel="stylesheet" href="/shell.css?v=4">
|
<link rel="stylesheet" href="/shell.css?v=5">
|
||||||
<style>
|
<style>
|
||||||
/* When loaded inside an iframe (e.g. standalone domain redirecting back),
|
/* When loaded inside an iframe (e.g. standalone domain redirecting back),
|
||||||
hide the shell chrome — the parent rSpace page already provides it. */
|
hide the shell chrome — the parent rSpace page already provides it. */
|
||||||
|
|
@ -94,7 +94,7 @@ export function renderShell(opts: ShellOptions): string {
|
||||||
${renderWelcomeOverlay()}
|
${renderWelcomeOverlay()}
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import '/shell.js?v=4';
|
import '/shell.js?v=5';
|
||||||
// Provide module list to app switcher
|
// Provide module list to app switcher
|
||||||
document.querySelector('rstack-app-switcher')?.setModules(${moduleListJSON});
|
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">
|
<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>">
|
<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>
|
<title>${escapeHtml(title)}</title>
|
||||||
<link rel="stylesheet" href="/shell.css?v=4">
|
<link rel="stylesheet" href="/shell.css?v=5">
|
||||||
<style>
|
<style>
|
||||||
html.rspace-embedded .rstack-header { display: none !important; }
|
html.rspace-embedded .rstack-header { display: none !important; }
|
||||||
html.rspace-embedded .rstack-tab-row { display: none !important; }
|
html.rspace-embedded .rstack-tab-row { display: none !important; }
|
||||||
|
|
@ -398,7 +398,7 @@ export function renderExternalAppShell(opts: ExternalAppShellOptions): string {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import '/shell.js?v=4';
|
import '/shell.js?v=5';
|
||||||
document.querySelector('rstack-app-switcher')?.setModules(${moduleListJSON});
|
document.querySelector('rstack-app-switcher')?.setModules(${moduleListJSON});
|
||||||
|
|
||||||
const tabBar = document.querySelector('rstack-tab-bar');
|
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">
|
<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>">
|
<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>
|
<title>${escapeHtml(mod.name)} — rSpace</title>
|
||||||
<link rel="stylesheet" href="/shell.css?v=4">
|
<link rel="stylesheet" href="/shell.css?v=5">
|
||||||
${cssBlock}
|
${cssBlock}
|
||||||
<script defer src="https://rdata.online/collect.js" data-website-id="6ee7917b-0ed7-44cb-a4c8-91037638526b"></script>
|
<script defer src="https://rdata.online/collect.js" data-website-id="6ee7917b-0ed7-44cb-a4c8-91037638526b"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
@ -601,7 +601,7 @@ export function renderModuleLanding(opts: ModuleLandingOptions): string {
|
||||||
</header>
|
</header>
|
||||||
${bodyContent}
|
${bodyContent}
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import '/shell.js?v=4';
|
import '/shell.js?v=5';
|
||||||
document.querySelector('rstack-app-switcher')?.setModules(${moduleListJSON});
|
document.querySelector('rstack-app-switcher')?.setModules(${moduleListJSON});
|
||||||
try {
|
try {
|
||||||
var raw = localStorage.getItem('encryptid_session');
|
var raw = localStorage.getItem('encryptid_session');
|
||||||
|
|
|
||||||
|
|
@ -241,7 +241,12 @@ export class RStackAppSwitcher extends HTMLElement {
|
||||||
|
|
||||||
trigger.addEventListener("click", (e) => {
|
trigger.addEventListener("click", (e) => {
|
||||||
e.stopPropagation();
|
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
|
// Prevent external links from closing the menu prematurely
|
||||||
|
|
@ -298,10 +303,10 @@ const STYLES = `
|
||||||
.caret { font-size: 0.7em; opacity: 0.6; }
|
.caret { font-size: 0.7em; opacity: 0.6; }
|
||||||
|
|
||||||
.menu {
|
.menu {
|
||||||
position: absolute; top: 100%; left: 0; margin-top: 6px;
|
position: fixed; margin-top: 0;
|
||||||
min-width: 300px; border-radius: 12px; overflow: hidden;
|
min-width: 300px; border-radius: 12px; overflow: hidden;
|
||||||
overflow-y: auto; max-height: 70vh;
|
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; }
|
.menu.open { display: block; }
|
||||||
:host-context([data-theme="light"]) .menu {
|
:host-context([data-theme="light"]) .menu {
|
||||||
|
|
|
||||||
|
|
@ -100,9 +100,14 @@ export class RStackSpaceSwitcher extends HTMLElement {
|
||||||
trigger.addEventListener("click", async (e) => {
|
trigger.addEventListener("click", async (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
const isOpen = menu.classList.toggle("open");
|
const isOpen = menu.classList.toggle("open");
|
||||||
if (isOpen && !this.#loaded) {
|
if (isOpen) {
|
||||||
await this.#loadSpaces();
|
const rect = trigger.getBoundingClientRect();
|
||||||
this.#renderMenu(menu, current);
|
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; }
|
.caret { font-size: 0.7em; opacity: 0.6; }
|
||||||
|
|
||||||
.menu {
|
.menu {
|
||||||
position: absolute; top: 100%; left: 0; margin-top: 6px;
|
position: fixed; margin-top: 0;
|
||||||
min-width: 260px; max-height: 400px; overflow-y: auto;
|
min-width: 260px; max-height: 400px; overflow-y: auto;
|
||||||
border-radius: 12px; box-shadow: 0 8px 30px rgba(0,0,0,0.25);
|
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; }
|
.menu.open { display: block; }
|
||||||
:host-context([data-theme="light"]) .menu { background: white; border: 1px solid rgba(0,0,0,0.1); }
|
:host-context([data-theme="light"]) .menu { background: white; border: 1px solid rgba(0,0,0,0.1); }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue