Skip to content
EspañolEnglish
All components (204)

Side panel

Layers · Drawer · .amset-panel

What it is and when to use it

A panel that slides in from one side of the screen: filters, the detail of a row, a short form. Inside it is a modal dialog, so focus enters, stays inside and returns to the trigger on closing.

When to use it

  • Filters for a list, with "Apply" and "Clear" in the footer.
  • The detail of a row without losing sight of the list.
  • side: end (default) or start, which follow the language, and top or bottom.
  • actions for the footer buttons: it receives the function that closes the panel.
  • loading while the content arrives: the body shows a skeleton and the title and the buttons stay.
  • dismissable={false} (clicking outside does not close) or keyboardDismissDisabled (Escape does not close) for a half-filled form that must not be lost to an extra click.

When not to

  • A short decision in the center: Dialog.
  • A small panel attached to the button that does not block the page: Dropdown.
  • If it is a whole page with its own address, it is not a panel: it is navigation.

Keyboard: on opening, focus enters and stays inside. Escape closes and focus returns to the trigger; clicking outside also closes. If both exits are turned off, what is inside has to offer one.

Accessibility: it is a modal browser <dialog>, with the rest of the page inert while it is open. It is announced as dialog with the title as its name and description as its accessible description. The cross is on by default (withCloseButton) and is named with closeLabel ("Close the panel"). While loading, the body carries aria-busy and announces loadingText ("Loading…"). If the body scrolls, it takes focus so that it can be traversed with the keyboard.

Fine-tuning: CSS variables --amset-panel-*: -width (on the sides: 20, 28 or 40 rem depending on the size), -height (top and bottom), -padding, -background and -from, which is where it enters from. Each side brings its own: the bottom one rises, the top one drops and the side ones slide in sideways. The veil is the browser's ::backdrop. The body is the only thing that scrolls.

What it looks like

<Drawer title="Filters" trigger={<Button variant="outline">Open filters</Button>}>
  <Filtros />
</Drawer>

Props

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

PropTypeWhat it does
childrenrequiredReactNode—
titlerequiredstring—
actions(close: () => void) => ReactNodeFooter buttons. Receives `close`, like the dialog.
classNamestringMerged with the library classes; it does not replace them.
closeLabelstring—
descriptionstring—
dismissablebooleanPressing outside closes. By default yes. With `false`, the panel only goes away through its own buttons: for a half-filled form that must not be lost by one click too many.
keyboardDismissDisabledbooleanEscape closes. By default yes. Same case as the previous one, and with the same warning: if both are turned off, what is INSIDE has to offer a way out, or whoever does not use a mouse is locked in.
loadingbooleanThe content is arriving. A skeleton is shown instead of `children`, and the body is marked busy. The title and the buttons stay: whoever opened it knows what it is about and can close it without waiting.
loadingTextstringWhat is announced to the reader while loading. "Loading…" by default.
onOpenChange(open: boolean) => void—
openboolean—
sidePanelSideWhich side it enters from, and which side it slides from when appearing. `start` and `end` follow the language.
size"sm" | "md" | "lg"On the sides, 20, 28 or 40 rem wide; top and bottom, 30, 50 or 80% of the height.
triggerReactElement<unknown, string | JSXElementConstructor<any>>—
withCloseButtonboolean—

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-panel-width28rem
--amset-panel-height50vh
--amset-panel-paddingvar(--amset-space-5)
--amset-panel-backgroundvar(--amset-surface)
--amset-panel-fromtranslateX(16px)

How to change it

.amset-panel {
  --amset-panel-width: ...;
  --amset-panel-height: ...;
}

In the test bench

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