import { useState } from "react";
import { AppHeader, RadioGroup, type Session } from "@meowerse/ui";
const SESSIONS: Record<string, Session> = {
loading: { loading: true, authenticated: false },
guest: { loading: false, authenticated: false },
"signed-in": { loading: false, authenticated: true, username: "alxnko", verified: true },
error: { loading: false, authenticated: false, error: "timeout" },
};
// AppHeader's default links point at the auth app (/login, /signup, /account, …), which 404 on
// meow.alxnko.dev: the strict link check has no exemptions, so this demo passes links that resolve
// on this site instead (same pattern as the static preview on this component's own page).
const DEMO_LINKS = {
guest: [
{ label: "about", href: "/ui/" },
{ label: "developers", href: "/ui/components/" },
{ label: "docs", href: "/ui/" },
],
guestActions: [
{ label: "log in", href: "/#projects" },
{ label: "sign up", href: "/#projects" },
],
signedIn: [
{ label: "account", href: "/" },
{ label: "developers", href: "/ui/components/" },
{ label: "docs", href: "/ui/" },
],
};
export default function Demo() {
const [k, setK] = useState("guest");
return (
<div className="demo">
<RadioGroup name="demo-session" legend="session" value={k} onChange={setK} options={[
{ label: "checking", value: "loading" }, { label: "signed out", value: "guest" },
{ label: "signed in", value: "signed-in" }, { label: "check failed", value: "error" },
]} />
<div className="demo__frame"><AppHeader session={SESSIONS[k]!} links={DEMO_LINKS} /></div>
</div>
);
}
props
prop
type
default
required
session
Session the current session, from useSession(); its loading/authenticated state decides which links show.
—
yes
className
string extra class names to append.
—
no
links
AppHeaderLinks the nav links per session state; defaults to the auth app's set. A docs preview passes links that resolve on its own site.
DEFAULT_LINKS
no
css custom properties
variable
dark
light
--c-accent
#00ff82
#0a6e3c
--c-bg
#0a0a0b
#e9e8e4
--c-fg
#ededeb
#1a1a1c
--c-fg-muted
#b3b3af
#46464a
--c-line
#232326
#cfcec8
--c-surface
#151517
#dfded9
--c-surface-raised
#1a1a1d
#f7f6f3
--control-height
44px
same
--d-fast
120ms
same
--ease
cubic-bezier(.16,1,.3,1)
same
--font-mark
"VT323 Mark", var(--font-mono)
same
--fs-2
0.8125rem
same
--fs-4
1rem
same
--r-m
4px
same
--shadow-md
0 8px 24px rgb(0 0 0 / 0.25) (legacy alias)
—
--sp-1
4px
same
--sp-2
8px
same
--sp-3
12px
same
--sp-4
16px
same
--z-chrome
10
same
Classes: .mw-brand-auth, .mw-brand-meow, .mw-header. Set any of these variables on an ancestor (or wrap a subtree in .mw-theme--dark / .mw-theme--light) to restyle just that part of a page.
The phone menu button reports aria-expanded; the navigation opens below the header.
While the session is loading or failed, the header never offers "log in" to someone who may already be signed in (B9).
key
does
Tab
moves through the links, the theme toggle and the menu button
Enter or Space
opens or closes the phone menu
do and don't
[ ok ] do
Pass the session from useSession(base), so every island on the page shares one request.
Pass your own links prop; the live preview above points at this docs site's own pages, not the auth app's real destinations (see the props table's default column for those).
[fail] don't
Don't use it outside meowerse accounts yet: its brand is fixed. A configurable header comes with the accounts redesign (sub-project 3).