AppShellLayout
An app shell for dashboards and admin apps. The viewport never scrolls: the header and sidebar stay in place, and only the main region scrolls.
import { AppShellLayout } from "@glob-ui/app-shell-layout"Anatomy
Each slot declares its scroll behaviour. Switch on Anatomy to see them, and Fill with content to see which region scrolls.
import { AppShellLayout } from "@glob-ui/app-shell-layout"import { LayoutNavTrigger } from "@glob-ui/layout"import { PageLayout, PageHeader } from "@glob-ui/page-layout"const ROWS = Array.from({ length: 24 }, (_, i) => `Order ${1000 + i}`)export default function AppShellDefault() { return ( <AppShellLayout header={ <> <LayoutNavTrigger /> <strong>Acme</strong> </> } sidebar={ <> <a href="#overview" aria-current="page" className="rounded-md px-3 py-2 text-sm no-underline hover:bg-fd-accent"> Overview </a> <a href="#orders" className="rounded-md px-3 py-2 text-sm no-underline hover:bg-fd-accent"> Orders </a> <a href="#customers" className="rounded-md px-3 py-2 text-sm no-underline hover:bg-fd-accent"> Customers </a> </> } > <PageLayout header={<PageHeader title="Orders" />}> <ul className="flex flex-col gap-2"> {ROWS.map((row) => ( <li key={row} className="rounded-lg border p-3"> {row} </li> ))} </ul> </PageLayout> </AppShellLayout> )}Slots
The layout is a grid of slots. A prop fills each slot, and each slot is fixed or scroll.
| Slot | Element | Scroll | Notes |
|---|---|---|---|
header | <header> | fixed | Brand, the navigation trigger on small screens, account. |
sidebar | <nav> | fixed | Navigation. Hidden below lg, where it moves into a Sheet. Its list is the only scroller inside it. |
main | <main> | scroll | The page. The one region that scrolls. It has no padding: put a PageLayout in it. |
- fixed: the slot never scrolls. It stays in place, or sticks.
- scroll: the one region that scrolls for this part of the screen.
Mobile navigation
Put LayoutNavTrigger in the header. It hides itself at lg and up, where the sidebar is shown inline. Below lg the sidebar content opens in a Sheet from the left.
<AppShellLayout header={<><LayoutNavTrigger /><Brand /></>} sidebar={<NavLinks />}>
<Page />
</AppShellLayout>API
AppShellLayoutProps
Prop
Type
Accessibility
| Key or action | Behaviour |
|---|---|
| Skip to content | The first Tab stop. Enter moves focus to main. |
| Navigation trigger | A button named "Open navigation" with aria-expanded. It opens the navigation in a Sheet below lg. |
| Sheet | Focus moves into the navigation. Escape returns focus to the trigger. A link inside it closes the Sheet. |
ARIA. Landmarks: banner for the header, navigation named by sidebarLabel, and one main. Only the main region is a keyboard stop for scrolling.
Methodology
The methodology behind GlobUI layouts and templates: a layout owns the scroll, a template fixes part of it, and a page only fills the slots.
PageLayout
A page inside a layout: a sticky header, the content, and an optional aside that sticks from `lg`. It owns the page padding, sets no height and no overflow, and it is server-safe.