Noctis

Rail

A non-modal side panel that docks to a layout edge and reflows the content beside it. Unlike a sheet, the page stays visible and usable while the rail is open — no backdrop, no focus trap, no Escape-to-close.

Basic

A Rail.Trigger toggles the panel open. The Rail.Layout is the surrounding region — its Rail.Content is the main area and its Rail.Panel is the rail, composed from a Rail.Header (with a Rail.Title and a corner Rail.Close) and a Rail.Body. Compose the trigger from a Button through render so it inherits the button's look.

Reflow

variant on Rail.Layout sets how the content yields to the panel: squeeze shrinks the content beside the rail, while push keeps its width and slides it under. Either way the content stays visible and usable — that's the line between a rail and a sheet.

Squeeze
Push

Anatomy

Compose a rail from its parts. Rail.Root owns the open state (controlled via open / onOpenChange, or uncontrolled via defaultOpen) on Base UI's Collapsible and renders transparently (display: contents), so the Layout becomes the surrounding layout's child directly.

  • Rail.Root — owns the open state; renders no box of its own.
  • Rail.Trigger — toggles the panel. Style it directly or compose a Button through render.
  • Rail.Layout — the region that reflows. Props: variant (squeeze | push), side (start | end, RTL-aware), and size (xs | sm | md | lg).
  • Rail.Content — the main area beside the rail.
  • Rail.Panel — the rail surface itself; takes its own side / size when used standalone.
  • Rail.Header + Rail.Title — the panel's top region and its accessible name.
  • Rail.Body — the panel's scrollable content region.
  • Rail.Close — closes the rail; give it an aria-label for the accessible name.

Every rendered part carries a data-slot (noctis-rail, noctis-rail-trigger, noctis-rail-layout, noctis-rail-content, noctis-rail-panel, noctis-rail-surface, noctis-rail-close, noctis-rail-header, noctis-rail-body, noctis-rail-title) for host-side styling — pair it with the rail state attributes (data-variant, data-side, data-size, data-docking) and the Base UI Collapsible state (data-open, data-closed).

Keyboard

KeyAction
Enter / SpaceOn the trigger: toggle the rail open or closed.
Tab / Shift + TabMove through the page and into the open panel — focus is not trapped, since the rail is non-modal.

The rail is non-modal by design: there's no backdrop, no focus trap, and no Escape-to-close, so the surrounding content stays fully reachable while it's open.

Design tokens

Generated from the component's declaration — the same graph that mints the CSS, so a variable name or its resolution default can't drift. The minted tokens are the public override seam: set one on any ancestor and every rail in that region retunes — e.g. .editor { --noctis-rail-panel-width: 20rem; } widens every rail beneath it. Knobs that aren't minted are reached through the part's data-slot. See Customization for the full override ladder and Tokens for the whole graph.

Token

API reference

Generated from the component's types — every prop, type, default, and description comes straight from the source. Each part gets its own table; parts that forward to Base UI's Collapsible list just the props they pass through. Expand a row for the full type and description.

Rail.Root

Prop

Rail.Trigger

Prop

Rail.Layout

Prop

Rail.Content

Prop

Rail.Panel

Prop

Rail.Close

Prop

Rail.Header

Prop

Rail.Body

Prop

Rail.Title

Prop

AttributeDescription
data-slotThe catalog slot that anchors every `rail.css` rule and marks the part for SLOTS.md/testing.
data-variantThe reflow mode — `squeeze` | `push` — on the layout/content/panel; drives clip/slide/float.
data-sideWhich edge the rail docks to — `start` | `end`; drives the divider edge and the slide direction.
data-sizeThe rail's width — `xs` | `sm` | `md` | `lg`; the generated layer keys the width token off it.
data-dockingStandalone vs in-layout docking — `dock` | `inline`; selects the viewport-edge vs cell rules.