Skip to content
RefineUI

Sidebar

Collapsible vertical navigation drawer/sidebar.

SidebarTrigger is the button that opens and closes the sidebar. Put it anywhere inside SidebarProvider — this page places it at the start of the content. Closing removes the sidebar. Hover the edge to peek it, or press the trigger to open it again.

Overview

Machine-readable contract from Component Spec.

component: sidebarexport: Sidebarversion: 1attributes: data-refineui=sidebar

Anatomy

Partdata-refineui
rootsidebar
brandsidebar-brand
contentsidebar-content
footersidebar-footer
groupsidebar-group
group_labelsidebar-group-label
headersidebar-header
linksidebar-link
navsidebar-nav
peeksidebar-peek
peek_edgesidebar-peek-edge
peek_insetsidebar-peek-inset
peek_panelsidebar-peek-panel
peek_pinsidebar-peek-pin
peek_surfacesidebar-peek-surface
providersidebar-provider
triggerbutton

States

ScopeCategoryValues
componentpseudofocus-visible
componentenvironmentforced-colors, dir

Focus

SectionPropertyValue
visualrequiredtrue
visualselector:focus-visible

Layout

PropertyValue
directionlogical
rtltrue
npm install @refineui/react @refineui/tokens
import {
Sidebar,
SidebarHeader,
SidebarBrand,
SidebarContent,
SidebarNav,
SidebarGroup,
SidebarGroupLabel,
SidebarLink,
SidebarFooter
} from "@refineui/react";
<Sidebar>
<SidebarHeader>
<SidebarBrand>
<Logo />
My App
</SidebarBrand>
</SidebarHeader>
<SidebarContent>
<SidebarNav>
<SidebarGroup>
<SidebarGroupLabel>Main</SidebarGroupLabel>
<SidebarLink href="/" active>Dashboard</SidebarLink>
<SidebarLink href="/projects">Projects</SidebarLink>
<SidebarLink href="/tasks">Tasks</SidebarLink>
</SidebarGroup>
<SidebarGroup>
<SidebarGroupLabel>Settings</SidebarGroupLabel>
<SidebarLink href="/settings">Preferences</SidebarLink>
<SidebarLink href="/profile">Profile</SidebarLink>
</SidebarGroup>
</SidebarNav>
</SidebarContent>
<SidebarFooter>
<p>© 2024</p>
</SidebarFooter>
</Sidebar>

Root sidebar container (<aside> element).

Header section.

Brand/logo area.

Main content area. Scrolls through a built-in ScrollArea — overlay scrollbar on hover, and links and group labels take the edge blur. Do not wrap it in another ScrollArea; content in SidebarFooter stays outside the scroll.

Navigation container (<nav> element).

Groups related links.

Label for a group.

PropDefaultTypeDescription
activefalsebooleanMarks the current page (`aria-current="page"`).

Footer section.

Owns whether the sidebar is expanded. Wrap both the docked Sidebar and the trigger so the trigger can sit outside the sidebar.

PropDefaultTypeDescription
open—booleanExpanded state. Omit to let the provider own it.
defaultOpentruebooleanInitial expanded state when `open` is omitted.
onOpenChange—(open: boolean) => voidCalled when the trigger toggles.
id—stringId of the docked sidebar. The trigger sets `aria-controls` to this id.

Button that toggles the provider. Where you render it is the position. Default variant is secondary.

<SidebarProvider id="app-sidebar" open={open} onOpenChange={setOpen}>
<SidebarTrigger layout="icon" size="sm" aria-label={open ? "Close sidebar" : "Open sidebar"}>
<PanelIcon />
</SidebarTrigger>
<Sidebar id="app-sidebar">{/* nav */}</Sidebar>
</SidebarProvider>

Composable flyout when the docked sidebar is collapsed — edge hover reveals a floating panel over the main area (content does not reflow).

<SidebarPeek enabled={collapsed} widthPercent={28} mode="contained" onPin={expand}>
<SidebarPeekEdge />
<SidebarPeekPanel>
<SidebarPeekPin>{/* pin control */}</SidebarPeekPin>
<Sidebar>...</Sidebar>
</SidebarPeekPanel>
<SidebarPeekInset>{/* main + toggle */}</SidebarPeekInset>
</SidebarPeek>

Use mode="viewport" with --refineui-sidebar-peek-viewport-offset when the peek layer should align below a fixed app header.