Skip to content

Layout

The application shell composes AppLayout, AppHeader, and an optional Sidebar. Each component page is the API reference; the code examples live here. The header and sidebar render in the Falcon font while the main content keeps the host app’s font — see Styling.

SidebarProvider
└── AppLayout
├── Sidebar (optional)
└── AppLayoutContent
├── AppHeader
└── AppLayoutMain

When including a sidebar, wrap the complete layout in SidebarProvider so the sidebar and its triggers share state. AppLayoutMain holds the page’s own header and content — see Pages.

On narrow viewports the sidebar collapses into a drawer; pair it with a SidebarTrigger in the header, which reads sidebar state from context and throws without SidebarProvider. Long breadcrumb trails scroll inside Breadcrumb itself.

Code
import {
AppHeader,
AppHeaderLeading,
AppHeaderNotifications,
AppHeaderTrailing,
AppLayout,
AppLayoutContent,
AppLayoutMain,
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
Button,
FieldIcon,
LayoutDashboardIcon,
PackageIcon,
PencilIcon,
Sidebar,
SidebarActionButton,
SidebarBrand,
SidebarContent,
SidebarFooter,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
SidebarSeparator,
SidebarTrigger,
SidebarUser,
} from "@falcon/ui-kit";
export function Example() {
return (
<SidebarProvider defaultOpen>
<AppLayout>
<Sidebar>
<SidebarBrand logo={<FieldIcon />} name="AgVend" />
<SidebarContent>
<SidebarActionButton
icon={<PencilIcon size={16} />}
tooltip="New order"
>
New order
</SidebarActionButton>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton
render={<a href="#dashboard" />}
icon={<LayoutDashboardIcon size={16} />}
tooltip="Dashboard"
>
Dashboard
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton
render={<a href="#orders" />}
isActive
icon={<PackageIcon size={16} />}
tooltip="Orders"
>
Orders
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarContent>
<SidebarFooter>
<SidebarSeparator />
<SidebarUser
name="Maria Larsen"
menuContent={
<Button variant="ghost" className="tw:w-full tw:justify-start">
Sign out
</Button>
}
/>
</SidebarFooter>
</Sidebar>
<AppLayoutContent>
<AppHeader>
<AppHeaderLeading>
<SidebarTrigger />
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="#orders">Orders</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Order #1042</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</AppHeaderLeading>
<AppHeaderTrailing>
<Button variant="outline" size="sm">
Export
</Button>
<AppHeaderNotifications aria-label="Notifications" count={3} />
</AppHeaderTrailing>
</AppHeader>
<AppLayoutMain>
<div className="tw:flex tw:flex-1 tw:items-center tw:justify-center tw:p-5 tw:text-sm tw:text-muted-foreground">
Order lines, totals, and delivery details go here.
</div>
</AppLayoutMain>
</AppLayoutContent>
</AppLayout>
</SidebarProvider>
);
}

Without a sidebar there is nothing for a SidebarTrigger to open, so omit it.

Code
import {
AppHeader,
AppHeaderLeading,
AppHeaderNotifications,
AppHeaderTrailing,
AppLayout,
AppLayoutContent,
AppLayoutMain,
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@falcon/ui-kit";
export function Example() {
return (
<AppLayout>
<AppLayoutContent>
<AppHeader>
<AppHeaderLeading>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink href="#">Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Dashboard</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</AppHeaderLeading>
<AppHeaderTrailing>
<AppHeaderNotifications aria-label="Notifications" count={3} />
</AppHeaderTrailing>
</AppHeader>
<AppLayoutMain>
<div className="tw:flex tw:flex-1 tw:items-center tw:justify-center tw:p-5 tw:text-sm tw:text-muted-foreground">
Dashboard cards and reports go here.
</div>
</AppLayoutMain>
</AppLayoutContent>
</AppLayout>
);
}

Pass isActive to the leaf item the user is on, and to the parent section button whose child route is active — the parent keeps marking the location while the section is closed or the sidebar is collapsed.

Code
import { useState } from "react";
import {
AppHeader,
AppHeaderContent,
AppHeaderLeading,
AppLayout,
AppLayoutContent,
AppLayoutMain,
MoreHorizontalIcon,
PlusIcon,
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupAction,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuAction,
SidebarMenuBadge,
SidebarMenuButton,
SidebarMenuItem,
SidebarMenuSub,
SidebarMenuSubButton,
SidebarMenuSubIndicator,
SidebarMenuSubItem,
SidebarProvider,
SidebarTrigger,
UsersIcon,
} from "@falcon/ui-kit";
export function Example() {
const [accountsOpen, setAccountsOpen] = useState(true);
return (
<SidebarProvider defaultOpen>
<AppLayout>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Accounts</SidebarGroupLabel>
<SidebarGroupAction aria-label="Add account">
<PlusIcon />
</SidebarGroupAction>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton
render={<a href="#accounts" />}
icon={<UsersIcon size={16} />}
tooltip="Accounts"
>
Accounts
</SidebarMenuButton>
<SidebarMenuBadge>12</SidebarMenuBadge>
<SidebarMenuAction showOnHover aria-label="Account actions">
<MoreHorizontalIcon />
</SidebarMenuAction>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton
isActive
icon={<UsersIcon size={16} />}
tooltip="Leads"
expanded={accountsOpen}
onClick={() => setAccountsOpen((open) => !open)}
>
Leads
</SidebarMenuButton>
<SidebarMenuSub expanded={accountsOpen}>
<SidebarMenuSubItem>
<SidebarMenuSubIndicator />
<SidebarMenuSubButton
render={<a href="#new-leads" />}
isActive
>
New leads
</SidebarMenuSubButton>
</SidebarMenuSubItem>
<SidebarMenuSubItem>
<SidebarMenuSubIndicator />
<SidebarMenuSubButton render={<a href="#qualified" />}>
Qualified
</SidebarMenuSubButton>
</SidebarMenuSubItem>
</SidebarMenuSub>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
<AppLayoutContent>
<AppHeader>
<AppHeaderLeading>
<SidebarTrigger />
</AppHeaderLeading>
<AppHeaderContent>Accounts</AppHeaderContent>
</AppHeader>
<AppLayoutMain>
<div className="tw:flex tw:flex-1 tw:items-center tw:justify-center tw:p-5 tw:text-sm tw:text-muted-foreground">
Accounts across every retailer go here.
</div>
</AppLayoutMain>
</AppLayoutContent>
</AppLayout>
</SidebarProvider>
);
}

When the sidebar is collapsed to its icon rail, a SidebarMenuButton with a flyout opens its flyout items in a popover on click instead of a tooltip.

Code
import {
AppHeader,
AppHeaderContent,
AppHeaderLeading,
AppLayout,
AppLayoutContent,
AppLayoutMain,
LayoutDashboardIcon,
Sidebar,
SidebarContent,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
SidebarTrigger,
UsersIcon,
} from "@falcon/ui-kit";
export function Example() {
return (
<SidebarProvider defaultOpen={false}>
<AppLayout>
<Sidebar>
<SidebarContent>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton
render={<a href="#dashboard" />}
isActive
icon={<LayoutDashboardIcon size={16} />}
tooltip="Dashboard"
>
Dashboard
</SidebarMenuButton>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuButton
icon={<UsersIcon size={16} />}
tooltip="Accounts"
flyout={[
{
label: "Accounts",
isActive: true,
render: <a href="#accounts" />,
},
{ label: "Leads", render: <a href="#leads" /> },
]}
>
Accounts
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarContent>
</Sidebar>
<AppLayoutContent>
<AppHeader>
<AppHeaderLeading>
<SidebarTrigger />
</AppHeaderLeading>
<AppHeaderContent>Dashboard</AppHeaderContent>
</AppHeader>
<AppLayoutMain>
<div className="tw:flex tw:flex-1 tw:items-center tw:justify-center tw:p-5 tw:text-sm tw:text-muted-foreground">
Dashboard cards and reports go here.
</div>
</AppLayoutMain>
</AppLayoutContent>
</AppLayout>
</SidebarProvider>
);
}