component

TuxSlideover

Edge-anchored drawer. Distinct from TuxModal — slides in from a viewport edge, preserves the reading context behind the scrim. Built on the native <dialog> element so focus trap + escape + scrim come from the platform. Slide animation rides Batch J's --ease-corridor curve. Three sides: right (default, row detail and filters), left (mobile nav), bottom (action sheet).

right edge

Row detail (default)

The default posture. Use for clicking a TuxRichDataGrid row to inspect its full record, or for the "details" pane of a list view. Width defaults to 28rem; override via the size prop for wider panels (e.g. a side-by-side editor).

schema

Field details

The slide animation respects prefers-reduced-motion; users with that preference see the panel appear without the slide.

Escape closes; clicking the scrim closes (unless :close-on-backdrop="false"); the close button in the header always closes.

data-tux-overlay + data-tux-elevation="overlay" wired by default

<TuxSlideover v-model="open" title="Field details" eyebrow="schema">
  <p>Body content scrolls here.</p>
  <template #footer>
    <TuxButton intent="ghost" @click="open = false">Cancel</TuxButton>
    <TuxButton intent="primary">Save</TuxButton>
  </template>
</TuxSlideover>

left edge

Mobile nav drawer

Symmetric to the right variant — slides from the left. The style-guide shell uses a similar pattern for the mobile sidebar reveal; this component packages the affordance so a consuming app doesn't reinvent the trap-focus + animation stack.

<TuxSlideover v-model="open" side="left" title="Navigation drawer">
  …mobile-style nav reveal…
</TuxSlideover>

bottom edge

Action sheet

Phone-style action sheet. Slides up from the bottom edge of the viewport; the panel takes full viewport width and the configured size (height). Use for quick actions that don't deserve a full modal — bulk row operations, "share" sheets, sort controls.

bulk

Quick actions

<TuxSlideover v-model="open" side="bottom" title="Quick actions">
  …action sheet…
</TuxSlideover>

canonical use

Filter panel

The most common posture in a real app — clicking a "Filter" button on a list view opens a right-edge panel of filter controls, with Reset / Apply at the footer. The panel preserves the catalog context behind the scrim so users can see what they're filtering against.

Selected: 2 tiers, all format

catalog

Filters

classification tier
format
metadata
<TuxSlideover v-model="filterOpen" title="Filters" eyebrow="catalog">
  <fieldset>
    <legend class="eyebrow">classification tier</legend>
    <label v-for="t in tiers" :key="t.value">
      <input type="checkbox" :value="t.value" v-model="filters.tier" />
      {{ t.label }}
    </label>
  </fieldset>
  <!-- more filter fields… -->
  <template #footer>
    <TuxButton intent="ghost" @click="filters.tier = []">Reset</TuxButton>
    <TuxButton intent="primary" @click="filterOpen = false">Apply</TuxButton>
  </template>
</TuxSlideover>

props

Props

  • v-model — open / closed. Boolean.
  • side"left" | "right" | "bottom". Defaults "right".
  • size — CSS length for the panel width (left/right) or height (bottom). Defaults 28rem (left/right) or 24rem (bottom).
  • title — header heading. Pair with eyebrow above it.
  • eyebrow — uppercase mini-label above the title.
  • showClose — top-right close button. Defaults true.
  • closeOnBackdrop — dismiss when scrim is clicked. Defaults true.
  • Slots: default (body), #header (replace eyebrow + title region), #footer (action row).
  • Exposes open() + close() via template ref.

when to reach for which

Slideover vs Modal

  • TuxSlideover — user is drilling into the page they're on. Row detail, filter panel, side-by-side editor. Context behind the scrim is still relevant.
  • TuxModal — the page below doesn't matter. Confirmation, full-attention form, fatal error. Center-screen makes the page recede.
  • Both ship the native dialog primitives — focus trap, escape, scrim. Choose based on whether the underlying page is part of the user's mental model for the current action.