chrome

<tc-drawer>

Side sheet that slides in from any edge, backed by `<dialog>`. Backdrop, Esc, focus management — same primitives as the modal.

import "@ra9/tan-compose-kit/drawer"

Props

NameTypeDefaultDescription
openbooleanfalseWhether the drawer is showing. Reflects to the `open` attribute.
side"left" | "right" | "top" | "bottom""right"Which edge the drawer slides in from.
sizestring"min(420px, 92vw)"Drawer width for left / right; height for top / bottom. Any CSS length.
dismissiblebooleantrueBackdrop click and Esc dismiss.
titlestring""Optional header title.

Events

EventDetailWhen
tc-close{ reason: "backdrop" | "escape" | "button" | "api" }Fires when the drawer closes. `reason` reports what dismissed it.

Slots

SlotDescription
(default)Drawer body content.
footerOptional action footer (buttons, etc.).

CSS variables

VariableDefaultDescription
--tc-drawer-bgvar(--tc-color-surface, #ffffff)Drawer background.
--tc-drawer-inkvar(--tc-color-ink, #14171f)Body text color.
--tc-drawer-rulevar(--tc-color-rule, #ece5d3)Divider color.
--tc-drawer-shadowvar(--tc-shadow-lg, …)Outer shadow.
--tc-drawer-backdroprgba(20, 23, 31, 0.5)Backdrop dim color.
--tc-drawer-duration260msSlide-in / out duration.

Examples

Right (default)

Open drawer →
Cancel Apply
<tc-button id="trigger">Filters</tc-button> <tc-drawer id="drawer" title="Filters"> <div>…body…</div> <div slot="footer"> <tc-button variant="ghost">Cancel</tc-button> <tc-button>Apply</tc-button> </div> </tc-drawer> <script> document.getElementById("trigger").onclick = () => document.getElementById("drawer").open = true; </script>

Left

Open from left
<tc-drawer side="left" title="Navigation"> <nav>…</nav> </tc-drawer>

Bottom

Open from bottom

This pattern works well on mobile for action sheets and quick forms.

<tc-drawer side="bottom" size="min(360px, 60vh)"> <p>…</p> </tc-drawer>

Programmatic

const d = document.querySelector("tc-drawer"); d.open = true; d.addEventListener("tc-close", (e) => { console.log("drawer closed because:", e.detail.reason); });

Accessibility

  • Built on the native <dialog> element with showModal() — focus is trapped and Esc dismisses for free.
  • Backdrop click closes when dismissible is true. Disable for confirmation flows.
  • The body region scrolls independently; the header and footer stay pinned.
  • Drawers respect prefers-reduced-motion: reduce and skip the slide transition.

Theming

<tc-drawer style=" --tc-drawer-bg: #0b0c10; --tc-drawer-ink: #f3f3f3; --tc-drawer-rule: #1c1f26; --tc-drawer-backdrop: rgba(0, 0, 0, 0.7); " > <p>Dark drawer</p> </tc-drawer>