Drawer slot
canonNon-modal panel slot beside the page; the side is chosen away from the click and the content survives closing.
Slot rendered by AppShell; screens fill it through <ShellDrawer>. .as-drawer.full was removed on 11 September 2026 (NAV-1, acrm !3403) — it had had no consumer since P276.
Used in 11 files · 11 areas · 11× — pages/AiZamestnanciPage, pages/DochazkaPage, pages/FirmyPage, pages/LidePage, pages/MajetekPage, pages/PipelinePage …
The place in the app shell where a screen can float a panel next to its content — a record preview, a create form, the search preview. CSS apps/web/src/ds/app-shell.css (.as-drawer, .as-drawer-left); the slot is always rendered by AppShell inside the page plane, and a screen puts content into it through <ShellDrawer open side onClose> (apps/web/src/components/shell/ShellDrawer.tsx).
Two decisions are already made for the screen, and both matter:
- The slot is never unmounted. It is hidden when empty, so a panel's content — a half-written form, a scroll position — survives closing and reopening.
- The side is chosen per opening, away from where the user clicked (
useDrawerSide): the panel never covers the row that opened it.
When to use
- Reading or editing something that belongs to the list behind it, while the list stays usable: a record preview, a create form for the list, a search result preview.
- Any panel that must not block the page.
When not to use
- A task that must be finished before the screen continues — that is a Dialog.
- Content that needs the whole screen — that is a route.
- A menu anchored to a control — that is a Popover.
- A modeless window the user drags around and minimises — that is Dialog with window states.
Anatomy
- Slot
.as-drawer:position: absoluteinside the page plane,width: clamp(404px, 33.333vw, 640px),z-index: 50. The slot itself does not take clicks (pointer-events: none); its children do — so an empty slot never blocks the page under it. - Side
.as-drawer-leftmirrors the default right dock. - Entry animation is gated by
prefers-reduced-motion. - Content is whatever the screen portals in; in practice the Record drawer chrome (
.pdr) or a Drawer form. - There is no scrim and no
role="dialog"on the slot — non-modal by design. - There is no full-plane variant.
.as-drawer.fullwas a mirror of the upstream canon with no consumer since records started opening in a new tab; it was removed on 11 September 2026 (NAV-1).
Best practices
- Let the side be decided by
useDrawerSide; do not hard-code right. - Keep the panel's own chrome (head, close, footer) inside the content component — the slot only positions.
- Close on the panel's own control; the page behind must never need a click to "get back".
- Keep the listing behind it live: selection, scrolling and keyboard must keep working.
- Add a scrim or block the page — that turns a drawer into a bad dialog.
- Set a width on the content; the slot owns the width so every drawer in the app matches.
- Stack two drawers; one slot, one panel.
- Bring back a full-plane drawer; a record that needs the whole plane is a route.
Content
- The panel inside says what it is (the record's name,
Nový kontakt); the slot itself carries no text.
Related
record-drawer— the usual content of this slot.drawer-form— the create/edit variant.dialog— when the task must block.- Stories:
components--drawer-slot--default,--variants,--states,--composition.
Source: docs/app-shell/drawer-slot.usage.md · GitLab