Templates
AppShell template
The signed-in page layout; navigation, top bar, page header and content width.
This template sets up the AppShell component at page level: navigation groups, top bar, PageHeader and a content container. The dashboard, list, settings and account blocks sit inside it.
Preview
Section titled “Preview”The brand and mode switches in the page header restyle the preview too. Collapse the sidebar to icons with its button; in a narrow window the menu becomes a slide-in panel.
Regions
Section titled “Regions”| Region | Element | Note |
|---|---|---|
| Skip link | AppShell | The first tab stop; moves to main. |
| Sidebar | nav |
“General” and a collapsible “Administration” group; the current page has aria-current="page". |
| Top bar | header |
A search button, the Notification centre, the Account menu and, on narrow screens, the menu button. |
| Page header | PageHeader | The single h1, description, optional breadcrumbs and page actions. |
| Content | Container | width="lg" for dashboards and lists, md for forms and settings. |
The document <title> reads Page · Product name.
Breakpoints
Section titled “Breakpoints”| Width | Layout |
|---|---|
| Below 1024 px | Sidebar hidden; the top bar button opens a panel that slides in from the start edge (motion.drawer). |
| 1024 px and up | A 256 px sidebar; 48 px when collapsed, labels kept for screen readers. |
| 1440 px and up | Content is limited by Container, so line length stays readable. |
Accessibility
Section titled “Accessibility”- Landmarks: a named
nav,headerandmain; the skip link moves focus tomain. - On a page change, focus goes to the new page’s
h1; the routing layer does this. - The collapse button has
aria-expandedandaria-controls. - The narrow-screen menu traps focus, closes with Escape and returns focus to the menu button.
import { AppShell, Button, Container, Icon, NavGroup, NavItem, PageHeader, Stack } from '@bigbang/ui';import type { BreadcrumbItem, IconName } from '@bigbang/ui';import type { ReactNode } from 'react';import { AccountMenu } from '../../blocks/account-menu/AccountMenu';import { NotificationsCentre } from '../../blocks/notifications-centre/NotificationsCentre';import { type Lang, LangProvider } from '../../patterns/lang';
const copy = { tr: { product: 'Ürün adı', general: 'Genel', admin: 'Yönetim', search: 'Ara', pages: { home: 'Ana sayfa', projects: 'Projeler', records: 'Kayıtlar', reports: 'Raporlar', team: 'Ekip', account: 'Hesap', settings: 'Ayarlar' }, }, en: { product: 'Product name', general: 'General', admin: 'Administration', search: 'Search', pages: { home: 'Home', projects: 'Projects', records: 'Records', reports: 'Reports', team: 'Team', account: 'Account', settings: 'Settings' }, },};
export type AppPage = keyof (typeof copy)['tr']['pages'];
const general: { id: AppPage; icon: IconName; badge?: number }[] = [ { id: 'home', icon: 'home' }, { id: 'projects', icon: 'layout-grid' }, { id: 'records', icon: 'list', badge: 3 }, { id: 'reports', icon: 'file' },];const admin: { id: AppPage; icon: IconName }[] = [ { id: 'team', icon: 'user' }, { id: 'account', icon: 'user' }, { id: 'settings', icon: 'settings' },];
export type AppShellTemplateProps = { /** The current page: marks the navigation item and names the page. */ current: AppPage; /** Page title (h1); defaults to the navigation label of `current`. */ title?: string; description?: string; breadcrumbs?: readonly BreadcrumbItem[]; /** Page-level actions at the end of the header. */ actions?: ReactNode; /** Shows the header skeleton while the page loads. */ loading?: boolean; /** Content width: `lg` for dashboards and lists, `md` for forms and settings. */ width?: 'md' | 'lg' | 'full'; children: ReactNode; defaultCollapsed?: boolean; /** Opens the notifications panel or the account menu of the header on first render. */ headerOpen?: 'notifications' | 'account'; /** `empty` starts the notifications centre with no notifications. */ notifications?: 'some' | 'empty'; lang?: Lang;};
/** * The signed-in page template: AppShell navigation and a top bar with search, notifications and the * account menu, a PageHeader with the page's h1, * and the content in a Container. Blocks fill `children`. */export function AppShellTemplate({ current, title, description, breadcrumbs, actions, loading, width = 'lg', children, defaultCollapsed, headerOpen, notifications = 'some', lang = 'tr' }: AppShellTemplateProps) { const t = copy[lang]; const mainId = `main-${current}-${lang}`; return ( <LangProvider lang={lang}> <AppShell mainId={mainId} className="min-h-[44rem]" {...(defaultCollapsed === undefined ? {} : { defaultCollapsed })} brand={<strong className="type-label-md text-fg-default">{t.product}</strong>} header={ <div className="ms-auto flex items-center gap-sm"> <Button variant="secondary" size="sm" startIcon={<Icon name="search" />}> {t.search} </Button> <NotificationsCentre lang={lang} state={notifications} defaultOpen={headerOpen === 'notifications'} /> <AccountMenu lang={lang} defaultOpen={headerOpen === 'account'} /> </div> } nav={ <> <NavGroup label={t.general}> {general.map((item) => ( <NavItem key={item.id} href="#" label={t.pages[item.id]} icon={item.icon} current={item.id === current} {...(item.badge ? { badge: item.badge } : {})} /> ))} </NavGroup> <NavGroup label={t.admin} collapsible> {admin.map((item) => ( <NavItem key={item.id} href="#" label={t.pages[item.id]} icon={item.icon} current={item.id === current} /> ))} </NavGroup> </> } > <Container size={width} className="py-2xl"> <Stack gap="2xl"> <PageHeader title={title ?? t.pages[current]} {...(description ? { description } : {})} {...(breadcrumbs ? { breadcrumbs } : {})} {...(actions ? { actions } : {})} {...(loading ? { loading } : {})} /> {children} </Stack> </Container> </AppShell> </LangProvider> );}Components used
Section titled “Components used”AppShell, PageHeader, Container, Button, Breadcrumbs. Blocks built on this template: Dashboard, Empty dashboard, List and filters, Settings, Account overview.