Slide-out

A Slide-out is a secondary surface that slides in from the edge of the screen to provide contextual space for tasks, details, or navigation without misplacing the user from their primary journey. Should be used sparingly as to not compete with a chatbot slide out (future implementation).

SlideOut is an accessible side panel built on Radix UI's Dialog primitive. It slides in from the right, supports imperative open and close via a ref, and exposes a fine-grained status lifecycle for coordination with forms and other UI.

Features

  • Compound component pattern — Compose panels with Header, Body, Footer, and Close
  • Imperative control — Call open() and close() on a ref; both return promises that resolve when the transition finishes
  • Status lifecycle — Optional onStatusChange with isClosed, isClosing, isOpening, and isOpen
  • Configurable widthpanelWidth defaults to 400px and drives the slide distance
  • Accessible — Inherits Radix Dialog focus management and ARIA behavior

Basic

Open the panel with a button that calls panelRef.current?.open(). The body scrolls when content overflows. Use SlideOut.Close around actions that should dismiss the panel (for example Cancel and OK).

  • Use useRef<SlideOutRef>(null) and await panelRef.current?.open() to open with animation
  • SlideOut.Close wraps elements that close the panel on activation

Form

Submitting valid data closes the panel via panelRef.current?.close(). The primary submit control lives in the footer with form pointing at the form id so it stays outside the Form wrapper.

  • Use onStatusChange to reset or sync state when the panel fully closes
  • Imperative close() after successful submit keeps footer actions flexible

Status

Demonstrates onStatusChange by highlighting the current status among isClosed, isClosing, isOpening, and isOpen. Useful for debugging transitions or wiring loading states.

SlideOut status:

isClosed
isClosing 300ms animation
isOpening 300ms animation
isOpen

Sub-components

  • <SlideOut.Header> — Panel title area
  • <SlideOut.Body> — Main scrollable content
  • <SlideOut.Footer> — Actions and secondary controls
  • <SlideOut.Close> — Wraps controls that close the panel

Ref API

  • open() — Opens the panel; resolves when the panel is fully open
  • close() — Runs the exit animation and resolves when fully closed

Animation behavior

Open and close use CSS transitions and overlay animation classes aligned with the design system dialog timing:

  • Duration — Transitions complete in ~300ms
  • Closing — Overlay and content animate out; the panel translates off-screen by panelWidth

Dos and don'ts

Panel Header
Content scrolls…
Content scrolls…
Content scrolls…
Content scrolls…
Cancel Save
Do

Put primary actions in a fixed footer so they are always accessible, even if the body content scrolls.

Panel A
Panel B
Stacked on top…
Don't

Stack panels on top of other panels. If a user triggers a new panel from within an existing one, either replace the content with a proper "back" navigation or navigate the user entirely.

Edit Details
Unsaved form…
Unsaved changes

Discard your changes?

Keep editing Discard
Do

Warn users if they attempt to close a panel with unsaved changes in a form.

System Error
Critical failure.
Action required.
Retry
Don't

Use a slide-out panel for critical, system-interrupting errors. Use a Modal Dialog centered on the screen instead.