Redesign navbar with avatar dropdown and mobile drawer
Stream C from docs/information-architecture.md. The navbar's account
cluster (<username> + Settings + Logout) was three controls for the
same concept; the cluster now collapses behind an avatar dropdown.
On mobile, all primary nav and account controls move into a
hamburger drawer so the top bar stays at logo + bell + hamburger
without wrapping at small viewports.
- New apps/journal/app/components/Avatar.tsx — initials-only avatar
(no image-upload story yet; the component is the single place to
add image fallback when one lands).
- New apps/journal/app/components/AccountDropdown.tsx — click the
avatar trigger to reveal Profile / Settings / Log Out menuitems.
Click-outside + Escape-to-close. role="menu" + role="menuitem" for
a11y.
- New apps/journal/app/components/MobileNavMenu.tsx — hamburger
trigger + slide-out drawer at md and below. Contains all primary
nav (Feed, Explore, Routes, Activities, Notifications) plus the
account cluster (Profile, Settings, Log Out). Auto-closes on
navigation; locks body scroll while open.
- apps/journal/app/root.tsx — refactor NavBar:
* Brand + primary nav links hide at md and below (drawer covers
them).
* Right cluster: bell on every viewport; avatar dropdown on
desktop, hamburger on mobile.
* Loader exposes user.displayName so Avatar can compute initials.
* Drops the now-unused Form import; Form moved into the
dropdown/drawer components.
E2E tests updated:
- e2e/auth.test.ts — logout helper opens the avatar dropdown via
aria-label = displayName||username, then clicks the Log Out
menuitem. Username assertions in nav switch from getByText to
getByRole("button", {name: username}) (the avatar button).
- e2e/settings.test.ts — "settings link visible in nav" opens the
avatar dropdown first, then asserts the Settings menuitem.
i18n: nav.openMenu, nav.closeMenu keys for the hamburger trigger
labels (EN + DE).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
65e6699dc4
commit
4e2bfb0bbe
8 changed files with 372 additions and 66 deletions
|
|
@ -139,18 +139,22 @@ test.describe("Account Settings", () => {
|
|||
await removeVirtualAuthenticator(cdp, authenticatorId);
|
||||
});
|
||||
|
||||
test("settings link visible in nav when logged in", async ({ page }) => {
|
||||
test("settings link reachable from nav when logged in", async ({ page }) => {
|
||||
const cdp = await page.context().newCDPSession(page);
|
||||
const authenticatorId = await setupVirtualAuthenticator(cdp);
|
||||
await registerAndLogin(page, cdp);
|
||||
const { username } = await registerAndLogin(page, cdp);
|
||||
|
||||
await expect(page.getByRole("navigation").getByRole("link", { name: "Settings" })).toBeVisible();
|
||||
// Settings now lives inside the avatar dropdown; opening the
|
||||
// dropdown reveals the menuitem.
|
||||
await page.getByRole("navigation").getByRole("button", { name: username }).click();
|
||||
await expect(page.getByRole("menuitem", { name: "Settings" })).toBeVisible();
|
||||
|
||||
await removeVirtualAuthenticator(cdp, authenticatorId);
|
||||
});
|
||||
|
||||
test("settings link not visible when logged out", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
// Anonymous navbar has neither the avatar nor the Settings link.
|
||||
await expect(page.getByRole("navigation").getByRole("link", { name: "Settings" })).not.toBeVisible();
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue