Optimize navigation links

This commit is contained in:
dtonon 2026-05-20 23:29:02 +01:00
parent 346a5a0005
commit fb8a8b2224
4 changed files with 50 additions and 14 deletions

View file

@ -8,9 +8,11 @@
type Props = { type Props = {
mode: "simple" | "full"; mode: "simple" | "full";
activeRoom?: string; activeRoom?: string;
activeResource?: string;
contactsActive?: boolean;
}; };
let { mode, activeRoom }: Props = $props(); let { mode, activeRoom, activeResource, contactsActive }: Props = $props();
// The description of the room currently being viewed (full mode). // The description of the room currently being viewed (full mode).
const activeAbout = $derived( const activeAbout = $derived(
@ -26,7 +28,7 @@
href="/" href="/"
class="flex items-center gap-2 py-1 hover:bg-neutral-100 text-neutral-700" class="flex items-center gap-2 py-1 hover:bg-neutral-100 text-neutral-700"
> >
Home {mode === "simple" ? "Discussions" : "Home"}
</a> </a>
{#if mode === "simple"} {#if mode === "simple"}
@ -74,13 +76,17 @@
{#each resourcesStore.list as r (r.slug)} {#each resourcesStore.list as r (r.slug)}
<a <a
href="/resource/{r.slug}" href="/resource/{r.slug}"
class="block py-1 text-neutral-500 hover:text-neutral-900" aria-current={activeResource === r.slug ? "page" : undefined}
class="block py-1 hover:text-neutral-900
{activeResource === r.slug ? 'text-brand' : 'text-neutral-500'}"
>{r.title}</a >{r.title}</a
> >
{/each} {/each}
<a <a
href="/contacts" href="/contacts"
class="block py-1 text-neutral-500 hover:text-neutral-900">Contacts</a aria-current={contactsActive ? "page" : undefined}
class="block py-1 hover:text-neutral-900
{contactsActive ? 'text-brand' : 'text-neutral-500'}">Contacts</a
> >
</nav> </nav>
</div> </div>

View file

@ -10,9 +10,18 @@
onClose: () => void; onClose: () => void;
mode: "simple" | "full"; mode: "simple" | "full";
activeRoom?: string; activeRoom?: string;
activeResource?: string;
contactsActive?: boolean;
}; };
let { open, onClose, mode, activeRoom }: Props = $props(); let {
open,
onClose,
mode,
activeRoom,
activeResource,
contactsActive,
}: Props = $props();
function onLogin() { function onLogin() {
onClose(); onClose();
@ -110,7 +119,8 @@
<a <a
href="/" href="/"
onclick={onClose} onclick={onClose}
class="py-2 text-xl text-neutral-700 hover:text-brand">Home</a class="py-2 text-xl text-neutral-700 hover:text-brand"
>{mode === "simple" ? "Discussions" : "Home"}</a
> >
{#if mode === "full"} {#if mode === "full"}
@ -146,14 +156,18 @@
<a <a
href="/resource/{r.slug}" href="/resource/{r.slug}"
onclick={onClose} onclick={onClose}
class="block py-1.5 text-xl text-neutral-700 hover:text-brand" aria-current={activeResource === r.slug ? "page" : undefined}
class="block py-1.5 text-xl hover:text-brand
{activeResource === r.slug ? 'text-brand' : 'text-neutral-700'}"
>{r.title}</a >{r.title}</a
> >
{/each} {/each}
<a <a
href="/contacts" href="/contacts"
onclick={onClose} onclick={onClose}
class="block py-1.5 text-lg text-neutral-700 hover:text-brand" aria-current={contactsActive ? "page" : undefined}
class="block py-1.5 text-lg hover:text-brand
{contactsActive ? 'text-brand' : 'text-neutral-700'}"
>Contacts</a >Contacts</a
> >
</nav> </nav>

View file

@ -15,7 +15,11 @@
<header <header
class="sticky top-0 z-20 flex h-16 shrink-0 items-center justify-between gap-2 bg-neutral-100 px-4 md:static md:px-8" class="sticky top-0 z-20 flex h-16 shrink-0 items-center justify-between gap-2 bg-neutral-100 px-4 md:static md:px-8"
> >
<div class="flex min-w-0 items-center gap-2"> <a
href="/"
class="flex min-w-0 items-center gap-2 hover:opacity-90"
aria-label="{name} — home"
>
{#if groupStore.data?.picture} {#if groupStore.data?.picture}
<img <img
src={groupStore.data.picture} src={groupStore.data.picture}
@ -32,7 +36,7 @@
<span class="truncate text-2xl font-medium text-neutral-900 md:text-[1.7rem]" <span class="truncate text-2xl font-medium text-neutral-900 md:text-[1.7rem]"
>{name}</span >{name}</span
> >
</div> </a>
<button <button
type="button" type="button"
onclick={onMenuToggle} onclick={onMenuToggle}

View file

@ -53,12 +53,22 @@
let mobileView = $state<"forum" | "chat">("forum"); let mobileView = $state<"forum" | "chat">("forum");
// Room pages highlight via their slug; thread pages highlight the room the // Room pages highlight via their slug; thread pages highlight the room the
// thread belongs to (tracked in activeGroup). // thread belongs to (tracked in activeGroup). Scoped to those routes so a
// resource slug (same [slug] param name) never highlights a room.
const activeRoom = $derived( const activeRoom = $derived(
page.params.slug ?? page.url.pathname.startsWith("/room/")
(page.url.pathname.startsWith("/thread/") ? activeGroup.id : ""), ? (page.params.slug ?? "")
: page.url.pathname.startsWith("/thread/")
? activeGroup.id
: "",
); );
// Resource pages highlight the open article in the Resources menu.
const activeResource = $derived(
page.url.pathname.startsWith("/resource/") ? (page.params.slug ?? "") : "",
);
const contactsActive = $derived(page.url.pathname === "/contacts");
// Article pages (both modes) and the full-mode landing have no single room to // Article pages (both modes) and the full-mode landing have no single room to
// chat in, so they render the latest-discussions panel instead of room chat. // chat in, so they render the latest-discussions panel instead of room chat.
// The simple-mode home keeps its room chat, like every full-mode room. // The simple-mode home keeps its room chat, like every full-mode room.
@ -93,7 +103,7 @@
? 'flex flex-1 overflow-hidden' ? 'flex flex-1 overflow-hidden'
: ''}" : ''}"
> >
<LeftSidebar {mode} {activeRoom} /> <LeftSidebar {mode} {activeRoom} {activeResource} {contactsActive} />
<main <main
class="min-h-[calc(100dvh_-_4rem)] bg-white px-6 pt-8 pb-20 shadow-lg md:min-h-0 md:overflow-y-auto md:rounded-t-xl md:px-10 md:pt-6 {showDiscussions class="min-h-[calc(100dvh_-_4rem)] bg-white px-6 pt-8 pb-20 shadow-lg md:min-h-0 md:overflow-y-auto md:rounded-t-xl md:px-10 md:pt-6 {showDiscussions
? 'md:flex-[3]' ? 'md:flex-[3]'
@ -181,6 +191,8 @@
onClose={() => (menuOpen = false)} onClose={() => (menuOpen = false)}
{mode} {mode}
{activeRoom} {activeRoom}
{activeResource}
{contactsActive}
/> />
<LoginModal /> <LoginModal />