App chrome (shell)
The frame that wraps every page: a top header bar (brand wordmark + a few nav links + a primary action + a notification count), a left nav rail of grouped, icon'd links with an active you-are-here state, and a footer — plus an 'example portal' card showing PageTabs over a content area. Everything below is a STATIC MOCK: it rebuilds the look of the real Header / PortalShell with plain markup and the shared UI primitives rather than importing the originals (which are client components bound to auth + live data). Each piece reads its colours from the Save the Dogs semantic tokens, so flip the theme in the top bar to confirm the whole frame re-skins in light and dark.
- what this is
- A presentational reference for the app frame — header bar, left rail, footer, and a portal content card. Static markup + shared primitives; no auth, no data, no navigation.
- why a mock
- The real chrome (Header.tsx, PortalShell.tsx, PortalSidebar.tsx) is "use client" and pulls session + notification counts. This page reproduces their exact class treatments instead, so it stays public and theme-only.
- real primitives used
- Button (the header CTA), NotificationBadge (the count chip), Badge, and PageTabs (the portal card sub-nav) are the genuine @/components/ui components — only the layout chrome around them is mocked.
- active state
- Header links use a border-accent underline (border-b-2); rail links use a soft accent wash (bg-indigo-50 dark:bg-indigo-900/20) + text-accent. Both also set aria-current="page" — never colour alone.
- theme-aware
- Surfaces (bg-surface / -2 / -3), borders (--color-border), text (--color-text / muted / faint) and the accent are all semantic tokens, so the frame re-skins with the theme switch with no per-element edits.
The full frame — header + rail + content + footer
The whole chrome assembled at once, exactly as a page wears it: a sticky-style header bar across the top, the left nav rail down the side, a content well in the middle (here holding the example portal card), and the footer pinned beneath. Resize / theme-flip to see every surface tier respond. This is a self-contained mock — it does not nest a second <main> or sidebar inside the styleguide's own layout; it's a bordered preview of the frame.
Your dashboard
Everything you need to get involved in your community.
Downtown organizing team
Your hub for this community — agreements, reports and updates.
This panel is a static stand-in for the routed content behind the active tab — in the real portal each PageTab is its own URL, so the panel is whatever that page renders.
- header bar
- border-b border-[--color-border] over bg-surface; left = wordmark + nav links, right (ml-auto) = a notification bell carrying a NotificationBadge + the primary accent Button. In production it's sticky (sticky top-0 z-30).
- left rail
- w-56 aside, border-r, bg-surface, hidden below md (a slide-over drawer takes over on mobile). Holds the grouped <nav> of icon'd links.
- content well
- min-w-0 flex-1 over bg-[--color-bg] — the page's reading column. In the real shell this is where PageContainer (the <main>) + the page body render.
- footer
- border-t bg-surface, text-faint; a copyright line + a small link nav. Stacks on mobile, splits left/right from sm up.
Header bar — wordmark, nav links, actions
The top chrome on its own, with each part labelled. The wordmark sits in the Fraunces display face; the nav links use a 2px underline for the active page (border-accent) and a muted-with-hover treatment otherwise; the right cluster carries a notification bell with the real NotificationBadge count chip and the primary accent Button. Every nav link also sets aria-current on the active one, so the you-are-here cue is never colour alone.
brand wordmark (font-display)
NotificationBadge — tones & clamping (count=0 renders nothing)
header primary action — Button variant="primary" (size sm)
- wordmark
- font-display text-base font-bold tracking-tight, in --color-text. Links home. The styleguide sets it in Fraunces; reproduce that for the Save the Dogs brand.
- nav link — active
- h-11 px-3 border-b-2 border-accent, text-[--color-text], font-medium, aria-current="page". The 2px accent underline is the primary you-are-here cue.
- nav link — idle
- border-transparent, text-muted, hover:text-[--color-text]. No underline until active. Keep these as real links (or buttons for menus).
- NotificationBadge
- The real count chip: count<=0 renders null; clamps to max+ (default 99); tone red (default) / accent / gray; pass a label fn for the aria-label. Position it -top-0.5 -right-0.5 over the bell.
- primary action
- A Button variant="primary" size="sm" — the accent CTA for the whole app (e.g. Create). Pair an icon (h-4 w-4) before the label.
Example portal card — PageTabs over a content area
A small portal surface that shows the canonical in-page sub-nav pattern: a header band, PageTabs (Overview / Agreements / Reports) as the secondary nav, and the content area beneath. PageTabs is the real primitive — a links-based nav (not a WAI-ARIA tablist), so the active tab carries an accent underline + aria-current="page" and each tab is a real URL. The demo uses anchor (#…) hrefs so nothing navigates; the panel below simply reflects what the "Overview" tab would show.
Downtown organizing team
Your hub for this community — agreements, reports and updates.
This panel is a static stand-in for the routed content behind the active tab — in the real portal each PageTab is its own URL, so the panel is whatever that page renders.
Downtown organizing team
Your hub for this community — agreements, reports and updates.
This panel is a static stand-in for the routed content behind the active tab — in the real portal each PageTab is its own URL, so the panel is whatever that page renders.
- header band
- A bordered top strip (px-5 py-4) with the card title in the display face + a short muted sub-line. Sits flush above the tab bar.
- PageTabs
- The real @/components/ui PageTabs: tabs = [{ label, href, active? }]. The active tab gets a 2px accent underline + text-accent + aria-current="page"; the others are muted with a hover underline. It is link nav, NOT role="tablist".
- content area
- The panel below the tabs (p-5). In production this is the routed page body for the active tab's URL; here it's a static stand-in for the Overview view.
- not a tablist
- Because each tab is a separate URL (bookmarkable, back-button friendly), this is a <nav aria-label> + aria-current pattern — there is no client-toggled tabpanel or arrow-key roving focus to justify role=tablist.