mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 22:01:09 +02:00
feat(shared): Phase 6 — update app URLs and navigation for unified app
mana-apps.ts: - Change all APP_URLS from subdomains to internal paths (e.g., https://todo.mana.how → https://mana.how/todo) - Keep separate subdomains only for games (arcade) and matrix PillNavigation, AppDrawer, GlobalSpotlight: - Detect internal URLs and navigate directly instead of window.open - External URLs (games, matrix) still open in new tab Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8fe16b20f4
commit
59e1e8e833
4 changed files with 72 additions and 88 deletions
|
|
@ -76,7 +76,14 @@
|
|||
} else if (app.isCurrent) {
|
||||
window.location.href = '/';
|
||||
} else if (app.url) {
|
||||
window.open(app.url, '_blank', 'noopener,noreferrer');
|
||||
const isInternal =
|
||||
app.url.startsWith('/') ||
|
||||
new URL(app.url, window.location.origin).origin === window.location.origin;
|
||||
if (isInternal) {
|
||||
window.location.href = app.url;
|
||||
} else {
|
||||
window.open(app.url, '_blank', 'noopener,noreferrer');
|
||||
}
|
||||
}
|
||||
|
||||
close();
|
||||
|
|
|
|||
|
|
@ -152,7 +152,14 @@
|
|||
if (app.isCurrent) {
|
||||
window.location.href = '/';
|
||||
} else if (app.url) {
|
||||
window.open(app.url, '_blank', 'noopener,noreferrer');
|
||||
const isInternal =
|
||||
app.url.startsWith('/') ||
|
||||
new URL(app.url, window.location.origin).origin === window.location.origin;
|
||||
if (isInternal) {
|
||||
window.location.href = app.url;
|
||||
} else {
|
||||
window.open(app.url, '_blank', 'noopener,noreferrer');
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -170,7 +170,15 @@
|
|||
// Navigate to home route for current app
|
||||
window.location.href = '/';
|
||||
} else if (app.url) {
|
||||
window.open(app.url, '_blank', 'noopener,noreferrer');
|
||||
// Internal paths (same-origin) navigate directly, external URLs open in new tab
|
||||
const isInternal =
|
||||
app.url.startsWith('/') ||
|
||||
new URL(app.url, window.location.origin).origin === window.location.origin;
|
||||
if (isInternal) {
|
||||
window.location.href = app.url;
|
||||
} else {
|
||||
window.open(app.url, '_blank', 'noopener,noreferrer');
|
||||
}
|
||||
}
|
||||
},
|
||||
active: app.isCurrent,
|
||||
|
|
@ -292,6 +300,8 @@
|
|||
spiralHref?: string;
|
||||
/** Help page href (shown in user dropdown). Set to empty string to hide. */
|
||||
helpHref?: string;
|
||||
/** Bottom offset from viewport bottom (default: '0px'). Use to position above other fixed bars. */
|
||||
bottomOffset?: string;
|
||||
}
|
||||
|
||||
let {
|
||||
|
|
@ -340,6 +350,7 @@
|
|||
themesHref,
|
||||
spiralHref,
|
||||
helpHref,
|
||||
bottomOffset = '0px',
|
||||
}: Props = $props();
|
||||
|
||||
// Type guards for elements
|
||||
|
|
@ -369,14 +380,6 @@
|
|||
return localPart.substring(0, maxLength) + '…';
|
||||
}
|
||||
|
||||
// Local state for uncontrolled mode
|
||||
let internalCollapsed = $state(false);
|
||||
|
||||
// Use external or internal state
|
||||
const isCollapsed = $derived(
|
||||
onCollapsedChange !== undefined ? (externalCollapsed ?? false) : internalCollapsed
|
||||
);
|
||||
|
||||
// Dropdown direction: always up since nav is always at bottom
|
||||
const dropdownDirection = 'up' as const;
|
||||
|
||||
|
|
@ -386,31 +389,17 @@
|
|||
// Global spotlight (Cmd+K) — only active when spotlightActions are provided
|
||||
const spotlight = spotlightActions ? createGlobalSpotlightState() : null;
|
||||
|
||||
function collapseNav() {
|
||||
if (onCollapsedChange) {
|
||||
onCollapsedChange(true);
|
||||
} else {
|
||||
internalCollapsed = true;
|
||||
}
|
||||
}
|
||||
|
||||
function expandNav() {
|
||||
if (onCollapsedChange) {
|
||||
onCollapsedChange(false);
|
||||
} else {
|
||||
internalCollapsed = false;
|
||||
}
|
||||
}
|
||||
|
||||
function isActive(path: string) {
|
||||
return currentPath === path;
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if !isCollapsed}
|
||||
{#if !(externalCollapsed ?? false)}
|
||||
<nav
|
||||
class="pill-nav"
|
||||
style={primaryColor ? `--pill-primary-color: ${primaryColor}` : ''}
|
||||
style="{primaryColor
|
||||
? `--pill-primary-color: ${primaryColor};`
|
||||
: ''}--pill-nav-bottom: {bottomOffset}"
|
||||
aria-label={ariaLabel}
|
||||
>
|
||||
<div class="pill-nav-container">
|
||||
|
|
@ -803,22 +792,10 @@
|
|||
<span class="pill-label">Anmelden</span>
|
||||
</a>
|
||||
{/if}
|
||||
|
||||
<!-- Collapse Button -->
|
||||
<button onclick={collapseNav} class="pill glass-pill" title="Navigation minimieren">
|
||||
<CaretRight size={18} class="pill-icon" />
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
{/if}
|
||||
|
||||
<!-- FAB for collapsed state -->
|
||||
{#if isCollapsed}
|
||||
<button onclick={expandNav} class="nav-fab glass-pill" title="Expand navigation">
|
||||
<List size={18} class="pill-icon" />
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
<!-- Global Spotlight (Cmd+K) -->
|
||||
{#if spotlight && spotlightActions}
|
||||
<GlobalSpotlight
|
||||
|
|
@ -833,7 +810,7 @@
|
|||
<style>
|
||||
.pill-nav {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
bottom: var(--pill-nav-bottom, 0px);
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
|
|
@ -991,22 +968,6 @@
|
|||
display: inline;
|
||||
}
|
||||
|
||||
/* FAB for collapsed state - positioned at bottom right */
|
||||
.nav-fab {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
z-index: 1001;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0.875rem;
|
||||
padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 0.875rem);
|
||||
border-radius: 1rem 0 0 0;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Transitions */
|
||||
.pill-nav {
|
||||
transition: all 0.3s ease;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue