Detached Sheet
A mobile-friendly bottom sheet that becomes a centered dialog on desktop. Built on Silk.
A responsive sheet component. Swipeable bottom sheet on mobile, centered dialog on desktop.
Usage
import { DetachedSheet, Textarea } from "@delphi/ui";
export function FeedbackSheet() {
const [open, setOpen] = useState(false);
return (
<DetachedSheet.Root presented={open} onPresentedChange={setOpen}>
<DetachedSheet.Trigger asChild>
<Button>Open Sheet</Button>
</DetachedSheet.Trigger>
<DetachedSheet.Portal>
<DetachedSheet.View>
<DetachedSheet.Backdrop />
<DetachedSheet.Content>
<DetachedSheet.Handle />
<div className="px-6 pt-0 sm:pt-6">
<DetachedSheet.Title className="text-xl font-semibold">
Title
</DetachedSheet.Title>
<DetachedSheet.Description className="text-sand-11 mt-1">
Description text
</DetachedSheet.Description>
</div>
<div className="px-6 pt-4">
<Textarea variant="tactile" autoSize minRows={3} placeholder="Type here..." />
</div>
<DetachedSheet.Footer>
<DetachedSheet.CancelButton onClick={() => setOpen(false)}>
Cancel
</DetachedSheet.CancelButton>
<DetachedSheet.SubmitButton>
Submit
</DetachedSheet.SubmitButton>
</DetachedSheet.Footer>
</DetachedSheet.Content>
</DetachedSheet.View>
</DetachedSheet.Portal>
</DetachedSheet.Root>
);
}
Parts
| Part | Description |
|---|---|
Root | Manages open/close state (presented, onPresentedChange) |
Trigger | Button that opens the sheet |
Portal | Renders sheet outside the DOM hierarchy |
View | Positions content (bottom on mobile, center on desktop) |
Backdrop | Dimmed overlay behind the sheet |
Content | The sheet panel with rounded corners and shadow |
Handle | Swipe handle bar (hidden on desktop) |
Title | Accessible sheet title |
Description | Accessible description text |
Footer | Bottom action bar with flex row layout |
CancelButton | Pre-styled cancel button |
SubmitButton | Pre-styled submit button (supports disabled) |