Sheet
A side-anchored panel that slides out from any screen edge to present complementary content or forms.
import { Button } from "@glint/components/button.slint";import { Sheet } from "@glint/components/sheet.slint";import { Tokens } from "@glint/theme/tokens.slint";
export component Demo inherits Window { width: 560px; height: 360px; background: Tokens.color-background;
VerticalLayout { alignment: center; padding: 24px;
HorizontalLayout { alignment: center;
Button { text: "Edit profile"; haspopup: true; clicked => { sheet.open = true; } } } }
sheet := Sheet { width: parent.width; height: parent.height; title: "Edit profile"; description: "Make changes to your profile details here.";
VerticalLayout { spacing: 8px;
Text { text: "Full Name: Ana Silva"; color: Tokens.color-foreground; font-size: Tokens.typography-body-size; }
Text { color: Tokens.color-muted-foreground; font-size: Tokens.typography-body-sm-size; } } }}Usage
import { Sheet, SheetSide } from "@glint/components/sheet.slint";
export component AppWindow inherits Window { in-out property <bool> show-filters: false; callback apply-filters();
VerticalLayout { // your screen layout }
// Last child of the window, sized to it: Slint has no portals, so what // draws on top is what comes last. Sheet { width: parent.width; height: parent.height; side: SheetSide.right; open <=> root.show-filters; title: "Filters"; description: "Narrow down the search results."; dismissed => { root.apply-filters(); } }}A Sheet is a side-anchored drawer that slides into view over the current window.
Its body content goes between the braces via the @children slot, placed between
the header block and the bottom of the panel.
Mount it last among the window’s children, sized to width: parent.width; height: parent.height.
Examples
Sides
side attaches the sheet to any edge of the window: right (the default), left, top, or bottom. The slide animation automatically follows the chosen edge.
import { Button } from "@glint/components/button.slint";import { Sheet, SheetSide } from "@glint/components/sheet.slint";import { Tokens } from "@glint/theme/tokens.slint";
export component Demo inherits Window { width: 560px; height: 360px; background: Tokens.color-background;
VerticalLayout { alignment: center; spacing: 12px; padding: 24px;
HorizontalLayout { alignment: center; spacing: 8px;
Button { text: "Top"; haspopup: true; clicked => { top-sheet.open = true; } } Button { text: "Right"; haspopup: true; clicked => { right-sheet.open = true; } } Button { text: "Bottom"; haspopup: true; clicked => { bottom-sheet.open = true; } } Button { text: "Left"; haspopup: true; clicked => { left-sheet.open = true; } } } }
top-sheet := Sheet { width: parent.width; height: parent.height; side: SheetSide.top; panel-extent: 180px; title: "Top Sheet"; description: "Anchored to the top edge."; }
right-sheet := Sheet { width: parent.width; height: parent.height; side: SheetSide.right; title: "Right Sheet"; description: "Anchored to the right edge."; }
bottom-sheet := Sheet { width: parent.width; height: parent.height; side: SheetSide.bottom; panel-extent: 180px; title: "Bottom Sheet"; description: "Anchored to the bottom edge."; }
left-sheet := Sheet { width: parent.width; height: parent.height; side: SheetSide.left; title: "Left Sheet"; description: "Anchored to the left edge."; }}Custom panel extent
panel-extent sets the cross-axis dimension of the sheet: width for left/right sheets (default 360px) or height for top/bottom sheets.
import { Button } from "@glint/components/button.slint";import { Sheet } from "@glint/components/sheet.slint";import { Tokens } from "@glint/theme/tokens.slint";
export component Demo inherits Window { width: 560px; height: 360px; background: Tokens.color-background;
VerticalLayout { alignment: center; padding: 24px;
HorizontalLayout { alignment: center;
Button { text: "Open wide sheet"; haspopup: true; clicked => { sheet.open = true; } } } }
sheet := Sheet { width: parent.width; height: parent.height; panel-extent: 460px; title: "Workspace details"; description: "A wider panel gives extra horizontal space for multi-column layouts."; }}Backdrop dismissal
By default, clicking the scrim backdrop closes the sheet. Set dismiss-on-backdrop: false when the reader must explicitly use the close button or press Escape.
import { Button } from "@glint/components/button.slint";import { Sheet } from "@glint/components/sheet.slint";import { Tokens } from "@glint/theme/tokens.slint";
export component Demo inherits Window { width: 560px; height: 360px; background: Tokens.color-background;
VerticalLayout { alignment: center; padding: 24px;
HorizontalLayout { alignment: center;
Button { text: "Review terms"; haspopup: true; clicked => { sheet.open = true; } } } }
sheet := Sheet { width: parent.width; height: parent.height; title: "Terms of service"; description: "Clicking outside will not close this sheet."; dismiss-on-backdrop: false; }}Restoring focus
restore-focus fires whenever the sheet closes, returning keyboard focus to the trigger element.
import { Button } from "@glint/components/button.slint";import { Sheet } from "@glint/components/sheet.slint";import { Tokens } from "@glint/theme/tokens.slint";
export component Demo inherits Window { width: 560px; height: 360px; background: Tokens.color-background;
VerticalLayout { alignment: center; padding: 24px;
HorizontalLayout { alignment: center;
trigger := Button { text: "Account settings"; haspopup: true; clicked => { sheet.open = true; } } } }
sheet := Sheet { width: parent.width; height: parent.height; title: "Account settings"; description: "Closing will return keyboard focus to the trigger button."; restore-focus => { trigger.focus(); } }}API Reference
Properties
| Property | Type | Default | Description |
|---|---|---|---|
open | in-out bool | false | Two-way; consumer sets true to slide in, Glint sets false on close. |
side | in SheetSide | SheetSide.right | Edge to attach to — top, right, bottom, left. |
title | in string | no default | Heading inside the sheet. |
description | in string | no default | Body text under the title. |
close-label | in string | @tr("Close") | Accessible label for the panel's close control. |
show-close-button | in bool | true | Whether the panel carries its top-right close control. |
dismiss-on-backdrop | in bool | true | When true, clicking outside the sheet closes it. |
panel-extent | in length | 360px | Cross-axis dimension of the panel: width for left/right, height for top/bottom. |
Callbacks
| Callback | Description |
|---|---|
dismissed() | Fired when the sheet closes itself — backdrop, Escape or the close control. |
restore-focus() | Fired on EVERY close, including one the consumer drives by setting open = false, so keyboard focus always gets a new home: restore-focus => { my-button.focus(); }. Slint exposes no "previously focused element", so only the trigger's owner can name it. Same contract Drawer, Dialog and AlertDialog publish. |
Enums
| Enum | Values |
|---|---|
SheetSide | top, right, bottom, left |
Accessibility
- Role and name. The open sheet card claims a region landmark named by
titleand described bydescription. - Keyboard navigation. While open, keyboard events land in the sheet overlay so
Escape immediately dismisses the panel and fires
dismissed(). - Focus restoration. Every close path — backdrop, Escape, close button, or setting
open = false— firesrestore-focus()to hand focus back to the opening trigger. - Off-screen tree presence. When dismissed, the panel leaves the accessibility tree only when its slide-out motion completes and it has physically exited the window viewport.
- Close button. The corner close button is announced using
close-label(defaulting to@tr("Close")). It can be hidden withshow-close-button: false. - The trigger. Controls that open a sheet should declare
haspopup: true.