Skip to content
EspañolEnglish
All components (204)

Resizable panels

Management · ResizablePanels · .amset-panels

What it is and when to use it

Two or more panels with a draggable divider. The usual case: the list on one side, the detail on the other, and whoever looks decides how much each thing takes up. The divider is not only draggable: it also moves with the keyboard.

When to use it

  • List and detail, an editor with its preview, a three-column catalog.
  • shipping to start in proportions ([2, 1]: the first, twice the second); sizes with onChange to save and restore it (in percentages that add up to one hundred).
  • orientation="vertical" to stack them one on top of another.
  • The container takes the height it is given: none is invented here, because it lives inside a screen that already knows how tall it is.

When not to

  • A detail that opens on top and closes: Drawer.
  • Sections that fold one below another: Accordion.

Keyboard: Tab reaches each divider. In horizontal, Left and Right Arrow move it one step (2% by default), and in a right-to-left language the arrow still moves it in the direction it points; in vertical, Up and Down. Page Up and Page Down jump five steps, and Home and End take it to the limits. What one panel gains, the neighboring one loses, never the others. A panel with more content than fits also receives focus, so it can be scrolled with the keyboard.

Accessibility: the group is named after label and each panel is a region with its name. The divider is a focusable separator that says what it adjusts ("Resize Orders and Detail") and where it stands in words ("45% for Orders"). Each panel has its min (10% by default): there is no way to leave one at two pixels. With a finger, the divider widens so it can be grabbed.

Fine-tuning: CSS variables --amset-panels-*: -extra, -handle, -handle-hover, -separator, -target. The size changes the gap between panels and the handle. The divider is SEEN in -separator and grabbed in -target, with the extra area placed over the panels.

What it looks like

The folders.

What gets edited.

<ResizablePanels
  label="Editor"
  panels={[
    { key: 'lista', label: 'List', content: <Lista /> },
    { key: 'detalle', label: 'Details', content: <Detalle /> },
  ]}
/>

Props

Import it with import { ResizablePanels } from '@amset/ui'. Required props are marked.

PropTypeWhat it does
labelrequiredstringRequired: the group is announced with it.
panelsrequiredreadonly ResizablePanel[]—
classNamestringMerged with the library classes; it does not replace them.
onChange(sizes: readonly number[]) => void—
orientationPanelsOrientation—
shippingreadonly number[]Initial proportions. `[2, 1]` is "the first twice the second".
size"sm" | "md" | "lg"—
sizesreadonly number[]Controlled: percentages that add up to one hundred.
stepnumberHow much each arrow moves, as a percentage. 2 by default.

It also accepts the attributes of the element it renders: className, style, data-*, aria-* and its events.

CSS variables

These CSS variables are how you adapt it. Declare them on the component's selector, not on :root: the stylesheet redeclares them in the rule itself, and a declaration on the same element always wins.

VariableDefault
--amset-panels-separatorvar(--amset-space-3)
--amset-panels-handle1.75rem
--amset-panels-handle-hover2.5rem
--amset-panels-target1.5rem
--amset-panels-extracalc((var(--amset-panels-target) - var(--amset-panels-separator)) / 2)

How to change it

.amset-panels {
  --amset-panels-separator: ...;
  --amset-panels-handle: ...;
}

In the test bench

Every state and variant, to try one at a time, on its page at ui.amset.tech: