Sidebar
Open a navigation panel beside your content.
View code
import { Sidebar } from "@stack/ui/sidebar";
export default function Example() { return ( <Sidebar.Root> <Sidebar.Trigger /> <Sidebar.Panel> <Sidebar.Header> <Sidebar.Title>Conversations</Sidebar.Title> <Sidebar.Close /> </Sidebar.Header> <Sidebar.Content> <Sidebar.Item> <Sidebar.ItemButton active>Release planning</Sidebar.ItemButton> </Sidebar.Item> </Sidebar.Content> </Sidebar.Panel> </Sidebar.Root> );}import { Sidebar } from "@stack/ui/sidebar";The basic example uses a modal panel. Use modal={false} for a panel that leaves the rest of the page interactive.
Reference
Section titled “Reference”Tables list component-specific props and inherited control options. Components that forward native props also accept the applicable React HTML attributes and event handlers, including data-* and aria-* attributes.
Sidebar.Root
Section titled “Sidebar.Root”| Prop | Type | Required | Description |
|---|---|---|---|
children |
ReactNode | PayloadChildRenderFunction<unknown> |
No | Content rendered inside the component. |
open |
boolean |
No | Controlled open state. |
defaultOpen |
boolean |
No | Whether the drawer is initially open. |
onOpenChange |
((open: boolean, eventDetails: Drawer.Root.ChangeEventDetails) => void) |
No | Event handler called when the drawer is opened or closed. |
onOpenChangeComplete |
((open: boolean) => void) |
No | Event handler called after any animations complete when the drawer is opened or closed. |
actionsRef |
RefObject<DrawerRootActions | null> |
No | A ref to imperative actions. - unmount: Ends the closing phase of the drawer after an externally controlled closing animation finishes. |
modal |
boolean | "trap-focus" |
No | Determines if the drawer enters a modal state when open. - true: user interaction is limited to just the drawer: focus is trapped, document page scroll is locked, and pointer interactions on outside elements are disabled. - false: user interaction with the rest of the document is allowed. - 'trap-focus': focus is trapped inside the drawer, but document page scroll is not locked and pointer interactions outside of it remain enabled. Default: true. |
triggerId |
string | null |
No | ID of the trigger that the drawer is associated with. |
defaultTriggerId |
string | null |
No | ID of the trigger that the drawer is associated with. |
handle |
Drawer.Handle<unknown> |
No | A handle to associate the drawer with a trigger. |
disablePointerDismissal |
boolean |
No | Whether to prevent the drawer from closing on outside presses. |
snapPoints |
DrawerSnapPoint[] |
No | Snap points used to position the drawer. |
snapToSequentialPoints |
boolean |
No | Disables velocity-based snap skipping so drag distance determines the next snap point. |
snapPoint |
DrawerSnapPoint | null |
No | The currently active snap point. |
defaultSnapPoint |
DrawerSnapPoint | null |
No | The initial snap point value when uncontrolled. |
onSnapPointChange |
((snapPoint: DrawerSnapPoint | null, eventDetails: Drawer.Root.SnapPointChangeEventDetails) => void) |
No | Callback fired when the snap point changes. |
side |
"left" | "right" |
No | Side on which the popup or panel appears. Default: "left". |
width |
number |
No | Controlled panel width in pixels. |
defaultWidth |
number |
No | Initial uncontrolled panel width in pixels. Default: 288. |
minWidth |
number |
No | Minimum panel width in pixels. Default: 200. |
maxWidth |
number |
No | Maximum panel width in pixels. Default: 480. |
onWidthChange |
((width: number) => void) |
No | Save panel width changes. |
Sidebar.Surface
Section titled “Sidebar.Surface”Also accepts native element props.
| Prop | Type | Required | Description |
|---|---|---|---|
style |
CSSProperties | ((state: DrawerSwipeAreaState) => CSSProperties | undefined) |
No | Inline styles for the underlying element. |
className |
string | ((state: DrawerSwipeAreaState) => string | undefined) |
No | Additional CSS classes for the underlying element. |
children |
ReactNode |
No | Content rendered inside the component. |
render |
ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DrawerSwipeAreaState> |
No | Replace the underlying element using render composition. |
disabled |
boolean |
No | Disable interaction. |
swipeDirection |
SwipeDirection |
No | The swipe direction that opens the drawer. |
Sidebar.Panel
Section titled “Sidebar.Panel”Also accepts native element props.
| Prop | Type | Required | Description |
|---|---|---|---|
className |
string | ((state: DrawerPopupState) => string | undefined) |
No | Additional CSS classes for the underlying element. |
children |
ReactNode |
No | Content rendered inside the component. |
initialFocus |
boolean | RefObject<HTMLElement | null> | ((openType: InteractionType) => boolean | HTMLElement | null | void) |
No | Determines the element to focus when the drawer is opened. |
finalFocus |
boolean | RefObject<HTMLElement | null> | ((closeType: InteractionType) => boolean | HTMLElement | null | void) |
No | Determines the element to focus when the drawer is closed. |
render |
ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DrawerPopupState> |
No | Replace the underlying element using render composition. |
style |
CSSProperties |
No | Inline styles for the underlying element. |
Sidebar.Trigger
Section titled “Sidebar.Trigger”Also accepts native element props.
| Prop | Type | Required | Description |
|---|---|---|---|
handle |
Drawer.Handle<unknown> |
No | A handle to associate the trigger with a drawer. |
payload |
unknown |
No | A payload to pass to the drawer when it is opened. |
id |
string |
No | Element identifier. |
nativeButton |
boolean |
No | Whether the component renders a native <button> element when replacing it via the render prop. |
children |
ReactNode |
No | Content rendered inside the component. |
className |
string | ((state: DrawerTriggerState) => string | undefined) |
No | Additional CSS classes for the underlying element. |
render |
ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DrawerTriggerState> |
No | Replace the underlying element using render composition. |
style |
CSSProperties | ((state: DrawerTriggerState) => CSSProperties | undefined) |
No | Inline styles for the underlying element. |
Sidebar.Close
Section titled “Sidebar.Close”Also accepts native element props.
| Prop | Type | Required | Description |
|---|---|---|---|
nativeButton |
boolean |
No | Whether the component renders a native <button> element when replacing it via the render prop. |
children |
ReactNode |
No | Content rendered inside the component. |
className |
string | ((state: DrawerCloseState) => string | undefined) |
No | Additional CSS classes for the underlying element. |
render |
ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DrawerCloseState> |
No | Replace the underlying element using render composition. |
style |
CSSProperties | ((state: DrawerCloseState) => CSSProperties | undefined) |
No | Inline styles for the underlying element. |
Sidebar.Header
Section titled “Sidebar.Header”Also accepts native element props.
| Prop | Type | Required | Description |
|---|---|---|---|
children |
ReactNode |
No | Content rendered inside the component. |
size |
"default" | "sm" |
No | Size variant. |
Sidebar.Title
Section titled “Sidebar.Title”Also accepts native element props.
| Prop | Type | Required | Description |
|---|---|---|---|
children |
ReactNode |
No | Content rendered inside the component. |
className |
string | ((state: DrawerTitleState) => string | undefined) |
No | Additional CSS classes for the underlying element. |
render |
ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DrawerTitleState> |
No | Replace the underlying element using render composition. |
style |
CSSProperties | ((state: DrawerTitleState) => CSSProperties | undefined) |
No | Inline styles for the underlying element. |
Sidebar.Description
Section titled “Sidebar.Description”Also accepts native element props.
| Prop | Type | Required | Description |
|---|---|---|---|
children |
ReactNode |
No | Content rendered inside the component. |
className |
string | ((state: DrawerDescriptionState) => string | undefined) |
No | Additional CSS classes for the underlying element. |
render |
ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DrawerDescriptionState> |
No | Replace the underlying element using render composition. |
style |
CSSProperties | ((state: DrawerDescriptionState) => CSSProperties | undefined) |
No | Inline styles for the underlying element. |
Sidebar.Content
Section titled “Sidebar.Content”Also accepts native element props.
| Prop | Type | Required | Description |
|---|---|---|---|
className |
string |
No | Additional CSS classes for the underlying element. |
children |
ReactNode |
No | Content rendered inside the component. |
Sidebar.Footer
Section titled “Sidebar.Footer”Also accepts native element props.
| Prop | Type | Required | Description |
|---|---|---|---|
className |
string |
No | Additional CSS classes for the underlying element. |
children |
ReactNode |
No | Content rendered inside the component. |
Sidebar.Item
Section titled “Sidebar.Item”Also accepts native element props.
| Prop | Type | Required | Description |
|---|---|---|---|
className |
string |
No | Additional CSS classes for the underlying element. |
children |
ReactNode |
No | Content rendered inside the component. |
Sidebar.ItemButton
Section titled “Sidebar.ItemButton”Also accepts native element props.
| Prop | Type | Required | Description |
|---|---|---|---|
focusableWhenDisabled |
boolean |
No | Whether the button should be focusable when disabled. |
nativeButton |
boolean |
No | Whether the component renders a native <button> element when replacing it via the render prop. |
children |
ReactNode |
No | Content rendered inside the component. |
className |
string | ((state: ButtonState) => string | undefined) |
No | Additional CSS classes for the underlying element. |
render |
ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, ButtonState> |
No | Replace the underlying element using render composition. |
style |
CSSProperties | ((state: ButtonState) => CSSProperties | undefined) |
No | Inline styles for the underlying element. |
variant |
"link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | null |
No | Appearance variant. |
size |
"default" | "sm" | "xs" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null |
No | Size variant. |
active |
boolean |
No | Mark the item as active. Default: false. |
Sidebar.ItemText
Section titled “Sidebar.ItemText”Also accepts native element props.
| Prop | Type | Required | Description |
|---|---|---|---|
className |
string |
No | Additional CSS classes for the underlying element. |
children |
ReactNode |
No | Content rendered inside the component. |
Sidebar.ResizeHandle
Section titled “Sidebar.ResizeHandle”Also accepts native element props.
| Prop | Type | Required | Description |
|---|---|---|---|
className |
string |
No | Additional CSS classes for the underlying element. |
children |
ReactNode |
No | Content rendered inside the component. |