@biem/ui

Sidebar

A panel at the edge of the screen that holds the navigation and that users collapse and expand.

A sidebar holds the navigation of an app in a panel at the left or the right edge of the screen. Users collapse and expand it with the trigger, the rail or the keyboard shortcut Ctrl+B or Command+B, and the page content takes the width that the sidebar frees. In a viewport narrower than 768 pixels, the sidebar opens as a sheet over the page instead. SidebarProvider is at least as tall as the viewport, and Sidebar is fixed to an edge of the viewport, so an app places both at the root of its layout.

Retail
Support

Usage

sidebar-default.tsx
import { Card } from "@biem/ui/components/ui/card";
import {
	Sidebar,
	SidebarContent,
	SidebarGroup,
	SidebarGroupContent,
	SidebarGroupLabel,
	SidebarMenu,
	SidebarMenuButton,
	SidebarMenuItem,
	SidebarProvider,
	SidebarSeparator,
} from "@biem/ui/components/ui/sidebar";
import {
	IconBook,
	IconBuildingStore,
	IconChartBar,
	IconHelp,
	IconMessage,
	IconPackage,
	IconReceipt,
	IconUsers,
} from "@tabler/icons-react";

export function SidebarDefault() {
	return (
		<div className="w-full max-w-sm">
			<Card className="overflow-hidden py-0">
				<SidebarProvider className="min-h-0">
					<Sidebar collapsible="none" className="w-full bg-transparent">
						<SidebarContent className="gap-0">
							<SidebarGroup className="pb-1">
								<SidebarGroupLabel>Retail</SidebarGroupLabel>
								<SidebarGroupContent>
									<SidebarMenu>
										<SidebarMenuItem><SidebarMenuButton isActive><IconChartBar stroke={1.5}/>Overview</SidebarMenuButton></SidebarMenuItem>
										<SidebarMenuItem><SidebarMenuButton><IconReceipt stroke={1.5}/>Sales</SidebarMenuButton></SidebarMenuItem>
										<SidebarMenuItem><SidebarMenuButton disabled><IconBuildingStore stroke={1.5}/>Stores</SidebarMenuButton></SidebarMenuItem>
										<SidebarMenuItem><SidebarMenuButton><IconPackage stroke={1.5}/>Products</SidebarMenuButton></SidebarMenuItem>
										<SidebarMenuItem><SidebarMenuButton><IconUsers stroke={1.5}/>Customers</SidebarMenuButton></SidebarMenuItem>
									</SidebarMenu>
								</SidebarGroupContent>
							</SidebarGroup>
							<SidebarSeparator className="w-auto!"/>
							<SidebarGroup className="pt-1">
								<SidebarGroupLabel>Support</SidebarGroupLabel>
								<SidebarGroupContent>
									<SidebarMenu>
										<SidebarMenuItem><SidebarMenuButton><IconHelp stroke={1.5}/>Help center</SidebarMenuButton></SidebarMenuItem>
										<SidebarMenuItem><SidebarMenuButton><IconMessage stroke={1.5}/>Contact us</SidebarMenuButton></SidebarMenuItem>
										<SidebarMenuItem><SidebarMenuButton><IconBook stroke={1.5}/>Documentation</SidebarMenuButton></SidebarMenuItem>
									</SidebarMenu>
								</SidebarGroupContent>
							</SidebarGroup>
						</SidebarContent>
					</Sidebar>
				</SidebarProvider>
			</Card>
		</div>
	);
}

Examples

With Menu Badge

Some areas of an app collect work that waits for users, such as orders to pick or returns to process. Through SidebarMenuBadge, a menu item shows how much is waiting, so users see where to begin before they open an area, and a press on the count works like a press on the entry itself.

Store operations · ZH-1084
  • 6
  • 3
  • 2
Team

With Submenu

Larger areas often break down into views of their own, such as an assortment by category. A SidebarMenuSub lists these views as a second level of the menu item they belong to, so the first level stays short and users reach each view in one step. Every entry is a SidebarMenuSubButton, a real link that users can open in a new tab, and isActive marks the view they are on.

Campaigns
Reports

API Reference

SidebarProvider

PropdefaultOpen
Typeboolean
Defaulttrue
DescriptionSets whether the sidebar is expanded at first render. The provider then tracks the open state itself and writes every change to the cookie sidebar_state, which a server can read to pass the last state to defaultOpen.
Propopen
Typeboolean
Default–
DescriptionSets whether the sidebar is expanded and makes it controlled. Update it in onOpenChange. It has no effect on the sheet of a narrow viewport, which tracks its own open state.
ProponOpenChange
Type(open: boolean) => void
Default–
DescriptionRuns when users expand or collapse the sidebar with the trigger, the rail or the keyboard shortcut. It receives the open state that follows. It doesn't run when users open or close the sheet of a narrow viewport.
Propside
Type"left" | "right"
Default"left"
DescriptionSets the edge of the viewport that the sidebar is fixed to, and the edge that the sheet of a narrow viewport slides in from. The place of the sidebar in the markup decides where the page content leaves room for it, so a right sidebar follows the page content.
Propvariant
Type"sidebar" | "floating" | "inset"
Default"sidebar"
DescriptionSets the look of the sidebar. "sidebar" attaches it to the edge and draws a border toward the page content. "floating" sets it apart from the edge as a rounded panel with a ring and a shadow. "inset" leaves out the border, extends the sidebar background behind the page content and turns SidebarInset into a rounded panel on it.
Propcollapsible
Type"offcanvas" | "icon" | "none"
Default"offcanvas"
DescriptionSets how the sidebar collapses. With "offcanvas", it slides out of view. With "icon", it narrows to a strip that keeps the icons of the menu buttons and hides group labels, actions, badges and submenus. With "none", it stays expanded: it renders as a plain div in the layout, in a narrow viewport as well, and ignores side and variant.

SidebarTrigger

Propvariant
Type"default" | "outline" | "secondary" | "ghost" | "destructive" | "link"
Default"ghost"
DescriptionControls the visual emphasis of the trigger.
Propsize
Type"default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg"
Default"icon-sm"
DescriptionControls the dimensions of the trigger.
Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the trigger with another component.
PropnativeButton
Typeboolean
Defaulttrue
DescriptionDeclares whether the rendered element is a native button. Set it to false when render returns a different element.
Propdisabled
Typeboolean
Defaultfalse
DescriptionPrevents users from collapsing or expanding the sidebar with the trigger and exposes the disabled state to assistive technology.
PropfocusableWhenDisabled
Typeboolean
Defaultfalse
DescriptionKeeps the trigger focusable while it is disabled.

SidebarRail

SidebarRail adds a narrow strip along the edge of the sidebar that faces the page content. Users press it to collapse or expand the sidebar. It renders a button that the Tab key skips, and it has no props of its own.

SidebarInset

SidebarInset holds the page content beside the sidebar and takes the width that the sidebar leaves. It renders a main and has no props of its own.

SidebarInput

SidebarInput is an Input for the sidebar, such as a search field in SidebarHeader. It renders an input and has no props of its own.

SidebarHeader

SidebarHeader holds the content at the top of the sidebar and stays in place while SidebarContent scrolls. It renders a div and has no props of its own.

SidebarFooter

SidebarFooter holds the content at the bottom of the sidebar and stays in place while SidebarContent scrolls. It renders a div and has no props of its own.

SidebarSeparator

Proporientation
Type"horizontal" | "vertical"
Default"horizontal"
DescriptionSets the direction of the line and the orientation that the separator reports to assistive technology. Horizontal divides the parts that the sidebar stacks.
Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the separator with another component.

SidebarContent

SidebarContent holds the groups and takes the height between the header and the footer. It scrolls when the groups don't fit. It renders a div and has no props of its own.

SidebarGroup

SidebarGroup holds one section of the sidebar: its label, its action and its content. It renders a div and has no props of its own.

SidebarGroupLabel

Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the label with another component.

SidebarGroupAction

Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the action with another component.

SidebarGroupContent

SidebarGroupContent holds the content of a group, such as a SidebarMenu. It renders a div and has no props of its own.

SidebarMenu

SidebarMenu stacks the items of a menu. It renders a ul and has no props of its own.

SidebarMenuItem

SidebarMenuItem holds one entry of the menu: its button and, with it, an action, a badge or a submenu. It renders an li and has no props of its own.

SidebarMenuButton

Propvariant
Type"default" | "outline"
Default"default"
DescriptionControls the surface of the button. With "default", the button has no background until users hover or press it. With "outline", it has the page background and an outline.
Propsize
Type"default" | "sm" | "lg"
Default"default"
DescriptionControls the height of the button and the size of its text. With "sm", the button is lower and its text smaller. With "lg", the button is higher and keeps the text size of "default".
PropisActive
Typeboolean
Defaultfalse
DescriptionMarks the button as the entry that users are on and highlights it with the accent background and a medium font weight. It sets no aria-current, so a link sets that attribute itself.
Proptooltip
Typestring | ComponentProps<typeof TooltipContent>
Default–
DescriptionShows a tooltip to the right of the button while the sidebar is collapsed, where the button shows only its icon. A string sets the text. An object passes props to TooltipContent, such as children, side and align.
Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the button with another component, such as a link.
Propdisabled
Typeboolean
Defaultfalse
DescriptionPrevents interaction, dims the button and exposes the disabled state to assistive technology.

SidebarMenuAction

PropshowOnHover
Typeboolean
Defaultfalse
DescriptionHides the action in a viewport of 768 pixels or wider until users hover the menu item, move the focus into it or open a menu from the action.
Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the action with another component.

SidebarMenuBadge

SidebarMenuBadge shows a short value at the end of a menu item, such as a count. A press on it reaches the button behind it. It renders a div and has no props of its own.

SidebarMenuSkeleton

PropshowIcon
Typeboolean
Defaultfalse
DescriptionAdds a square placeholder for an icon before the placeholder for the label.

SidebarMenuSub

SidebarMenuSub holds a second level of entries below a menu button. It indents them and draws a line along their left edge. It renders a ul and has no props of its own.

SidebarMenuSubItem

SidebarMenuSubItem holds one entry of the submenu. It renders an li and has no props of its own.

SidebarMenuSubButton

Prophref
Typestring
Default–
DescriptionSets the address that the button opens. The button renders a link and needs it, unless render replaces the link with another element.
Propsize
Type"sm" | "md"
Default"md"
DescriptionControls the size of the text. With "sm", the text is smaller.
PropisActive
Typeboolean
Defaultfalse
DescriptionMarks the button as the entry that users are on and highlights it with the accent background. It sets no aria-current, so the link sets that attribute itself.
Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the button with another component.

useSidebar

useSidebar returns the state of the nearest SidebarProvider and the functions that change it. state is "expanded" or "collapsed", and open holds the same as a boolean. setOpen expands or collapses the sidebar. openMobile and setOpenMobile read and set the sheet of a narrow viewport, and isMobile tells whether the viewport is narrower than 768 pixels. toggleSidebar toggles the sheet in a narrow viewport and the sidebar otherwise. Outside a SidebarProvider, the hook throws an error. It is a hook, so it takes no arguments, renders no element and has no props of its own.