Sheet
The Sheet component is a panel that slides in from an edge of the screen for overlaid content — settings, details, or a focused task off to the side. It’s a compound component built on Radix Dialog, composed from Sheet.Root, Sheet.Trigger, Sheet.Content, and the structural parts Sheet.Header, Sheet.Footer, Sheet.Title, and Sheet.Description.
Variations
Sides
Sheet.Content slides in from the right by default. Set side to left, top, or bottom to change the edge it appears from.
Installation
import { Sheet } from '@harnessio/ui/components'
return ( <Sheet.Root> <Sheet.Trigger asChild> <Button>Open Sheet</Button> </Sheet.Trigger> <Sheet.Content> <Sheet.Header> <Sheet.Title>Sheet Title</Sheet.Title> <Sheet.Description>This is the sheet description.</Sheet.Description> </Sheet.Header> <p>Sheet content goes here.</p> <Sheet.Footer> <Button>Footer Action</Button> </Sheet.Footer> </Sheet.Content> </Sheet.Root>)Anatomy
All parts of the Sheet component can be imported and composed as required.
<Sheet.Root> <Sheet.Trigger /> <Sheet.Content> <Sheet.Header> <Sheet.Title /> <Sheet.Description /> </Sheet.Header> {/* body content */} <Sheet.Footer /> </Sheet.Content></Sheet.Root>Sheet.Root— the Radix Dialog root that holds open state. Control it withopen/onOpenChange, or leave it uncontrolled withdefaultOpen.Sheet.Trigger— the element that opens the sheet. UseasChildto render your ownButtonas the trigger.Sheet.Content— the sliding panel. Sets theside, renders a built-in close button (unlesshideCloseButton), and portals itself above the page with an overlay.Sheet.Header/Sheet.Footer— layout regions for the title/description and for actions.Sheet.Title/Sheet.Description— the accessible name and supporting text; Radix wires them to the dialog automatically.
Best practices
Do
- Always include a
Sheet.Title— it names the dialog for assistive tech (Radix warns when it’s missing). UseSheet.Descriptionfor a short supporting line. - Put confirming/cancelling actions in
Sheet.Footerso they sit in a predictable place. - Choose
sideto match the mental model: side panels for supporting detail,bottomfor mobile-style actions.
Don’t
- Don’t stack multiple sheets on top of each other; open one focused panel at a time.
- Don’t hide the close button (
hideCloseButton) unless you provide another obvious way to dismiss the sheet.
Content
- Keep the title a short noun phrase describing what the sheet is for (“Filters”, “Pipeline settings”).
- Use the description for a single clarifying sentence — move longer guidance into the body.
Accessibility
Keyboard
- Built on Radix Dialog:
Esccloses the sheet, focus moves into the panel on open and returns to the trigger on close, and focus is trapped within the panel while it’s open.
Labeling
Sheet.TitleandSheet.Descriptionare wired to the dialog’saria-labelledby/aria-describedbyautomatically. The built-in close button carries ansr-only“Close” label.
Focus & states
- The panel opens as a
role="dialog"witharia-modal. Withmodal(the default) the rest of the page is inert behind the overlay; setmodal={false}for a non-blocking panel.
Properties
Sheet.Root
Radix Dialog root — it renders no DOM of its own, so styling props don’t apply here.
Prop | Required | Default | Type |
|---|---|---|---|
| children | true | ReactNode | |
| open | false | boolean | |
| defaultOpen | false | boolean | |
| onOpenChange | false | (open: boolean) => void | |
| modal | false | true | boolean |
Sheet.Trigger
Prop | Required | Default | Type |
|---|---|---|---|
| children | true | ReactNode | |
| asChild | false | false | boolean |
Sheet.Content
Prop | Required | Default | Type |
|---|---|---|---|
| children | true | ReactNode | |
| side | false | 'right' | 'top' | 'bottom' | 'left' | 'right' |
| hideCloseButton | false | false | boolean |
| modal | false | true | boolean |
| handleClose | false | () => void | |
| overlayClassName | false | string | |
| closeClassName | false | string | |
| className | false | string |
The content also accepts the underlying Radix Dialog Content props, such as onEscapeKeyDown, onInteractOutside, and onOpenAutoFocus.
Sheet.Header
Prop | Required | Default | Type |
|---|---|---|---|
| children | true | ReactNode | |
| className | false | string |
Sheet.Footer
Prop | Required | Default | Type |
|---|---|---|---|
| children | true | ReactNode | |
| className | false | string |
Sheet.Title
Prop | Required | Default | Type |
|---|---|---|---|
| children | true | ReactNode | |
| className | false | string |
Sheet.Description
Prop | Required | Default | Type |
|---|---|---|---|
| children | true | ReactNode | |
| className | false | string |