App shell
The shell of an application screen: a sidebar of sections that collapses to its icons on a desktop and opens as a drawer on a phone, a sticky header with the screen's title and actions, the content.
Web only — React, from @krizaka/ui/app-shell. Beta: its API may still change in a minor version.
When to use
- Every signed-in screen of a product: a studio, a console, an administration.
- When the app has more than four destinations — fewer fit a NavBar.
When not to use
- For a public page of a site.Use instead: Marketing layout
- For a mobile app's tabs: React Native has its own tab bar.
Installation
Install
npm install @krizaka/ui @krizaka/tailwind @krizaka/tokens tailwindcssStyles
@import "tailwindcss";
@import "@krizaka/tailwind";
@import "@krizaka/ui/tailwind.css";Import
import { AppShell } from "@krizaka/ui/app-shell";Examples
Orochia studio
Elena's home in the creator studio: the shell around this week's figures, the payout, the auction and the sales.
Studio
This week
Good morning, Elena
Three sales since yesterday — your auction ends tonight.
Your week
Views
12.4k
+8 %7 days
Supporters
318
+217 days
Earned
€902
+14 %after the 10 % fee
Unlocks
146
±07 days
Next payout
Every Monday, from €20
€902 will reach your bank on Monday.
Auction
“Backstage cut”
€68
7 bids · ends tonight at 21:00
Latest sales
- Unlock · “Night shoot, part 2”Léa M.€4.50
- TipSamir K.€9.00
- Auction won · “Backstage cut”Inès B.€61.20
Administration console
A review queue in a console: sections, counts and a sortable table with bulk actions (cards on a phone).
Verification
Requests to review
Oldest first. A decision is logged with your name.
Pending
identity and payout
2
Oldest wait
40 min
Queue
| Request | Status | Waiting | ||
|---|---|---|---|---|
The shell alone
Sidebar with a group and a count, header with an action, the content.
Home
The screen's content.
Props
AppShellRoot
The shell: holds the collapse (desktop) and the drawer (phone) state. Children: Sidebar, then Body.
| Prop | Type | Default | Description |
|---|---|---|---|
collapsed | boolean | — | Controlled collapse (desktop): pair with onCollapsedChange to persist the choice. |
defaultCollapsed | boolean | false | The sidebar starts collapsed to its icons (desktop). |
onCollapsedChange | ((collapsed: boolean) => void) | — | Called when the sidebar collapses or expands. |
AppShellSidebar
The sidebar: on a desktop a column that collapses to its icons; on a phone the same content in a drawer.
| Prop | Type | Default | Description |
|---|---|---|---|
childrenrequired | ReactNode | — | The sections: AppShell.Group and AppShell.Item. |
closeLabelrequired | string | — | The drawer's close button words (phone). |
labelrequired | string | — | The navigation's accessible name (Studio, Administration). |
brand | ReactNode | — | The brand at the top: the product's mark and name (a link home through asChild of your router, or plain). |
collapseLabels | readonly [string, string] | — | The collapse button's words, [collapse, expand] (desktop only). Without it the sidebar cannot collapse. |
footer | ReactNode | — | At the bottom, above the collapse button: the account, a plan, the version. |
AppShellItem
A destination of the sidebar: icon, words, a count.
| Prop | Type | Default | Description |
|---|---|---|---|
labelrequired | string | — | Its words: the accessible name, hidden visually when collapsed (the icon carries a tooltip through title). |
asChild | boolean | — | Renders your link (Next's Link) with the item's look: pass it as the only child. |
badge | ReactNode | — | A count beside it (unread, pending): a number or a few characters. |
children | ReactElement<unknown, string | JSXElementConstructor<any>> | — | Your link element when asChild. |
current | boolean | — | The screen it opens is the current one: aria-current="page". |
icon | ReactNode | — | The item's icon (a signature icon): it stays when the sidebar collapses. |
AppShellHeader
The top of the screen: the drawer's button (phone), the title, the actions. Sticky.
| Prop | Type | Default | Description |
|---|---|---|---|
menuLabelrequired | string | — | The button that opens the drawer on a phone: its words. |
actions | ReactNode | — | The screen's actions, on the right. |
title | ReactNode | — | The screen's title (an h1). |
Accessibility
- The sidebar is a
navnamed bylabel; the current item carriesaria-current="page". - On a phone the drawer is a modal dialog (Radix): focus trapped inside, Escape and the overlay close it, the focus returns to the button.
- The header's title is the screen's
h1; nested layouts useheadingAs="h2".
Keyboard
| Keys | Action |
|---|---|
| Tab | Moves through the sidebar's items, the collapse button and the header's actions. |
| Esc | Closes the drawer on a phone and returns the focus to the menu button. |
Best practices
- Five to nine items, grouped by what the user does (
AppShell.Group), the current one marked withcurrent. - Give every item an icon: it is all that remains when the sidebar collapses (its words become a tooltip).
- Persist the collapse with
collapsed+onCollapsedChange; put the account in the sidebar'sfooter. - Render your router's links with
AppShell.Item asChild.
Related components
Generated from the code of @krizaka/ui 2.10.0: its meta.ts, its examples and its types.Edit this documentation on GitHub
Table of contents
The sections of a reading page: sticky beside the content on a wide screen, a row of chips that scrolls sideways on a phone, the section being read marked — with TocLayout to place it.
Auth layout
An entry screen — sign in, sign up, verify, onboarding: the product's brand panel (its gradient, a promise, a quote) beside a calm form; one column on a phone with the mark above the form.