suiss/ui · Pattern
Flyout
A non-modal panel anchored to a trigger on desktop that becomes a bottom drawer on mobile.
Flyout is an open-source pattern from suiss/ui for React. The @esuiss/ui CLI copies its source into your project, so you own the code.
Flyout shows supplementary content, such as a small form or a share link, next to the control that opened it. On desktop it renders a Popover positioned against the trigger. Below the 48rem breakpoint it renders a bottom Drawer with a swipe handle, and each part switches to its drawer counterpart: FlyoutHeader, FlyoutTitle and FlyoutDescription map to the drawer's header, title and description, and FlyoutBody gains padding.
Use it for quick settings or filters that do not need a full modal.
Installation
CLI
Works in any project with a components.json. See Installation for the one-line registry setup. Or use the suiss/ui CLI:
Manual
- Install the dependencies and add the
cnhelper:
-
Copy the source into
components/patterns/flyout.tsx:
- Update the import paths to match your project.
Usage
The flyout is uncontrolled with defaultOpen, or controlled with open and onOpenChange. align, alignOffset, side and sideOffset on FlyoutContent position the desktop popover and are ignored on mobile. Put interactive content in FlyoutBody, and use FlyoutClose for a button that closes the flyout after an action.
Examples
With close button
Adds an icon close button to the mobile drawer with showCloseButton.
With close label
Adds a text close button labelled Done to the mobile drawer with closeLabel.
With close
Uses FlyoutClose on a Copy link button so the action also closes the flyout.
Floating
Insets the mobile drawer from the screen edges with floating.
API Reference
Flyout
The root that renders a Popover on desktop and a Drawer on mobile.
| Prop | Type | Default | Description |
|---|---|---|---|
onOpenChange | (open: boolean) => void | - | Called when the flyout opens or closes. |
floating | boolean | - | Insets the mobile drawer from the screen edges with fully rounded corners. |
Also accepts the props of React.ComponentProps<typeof Popover>.
FlyoutTrigger
The button that opens the flyout.
| Prop | Type | Default | Description |
|---|---|---|---|
render | React.ReactElement | - | Replaces the default button element with your own element, such as a Button. |
Also accepts the props of React.ButtonHTMLAttributes<HTMLButtonElement>.
On the radix base, set asChild and pass your element as the child instead of render.
FlyoutContent
The popup; a PopoverContent on desktop and a DrawerContent on mobile.
| Prop | Type | Default | Description |
|---|---|---|---|
showCloseButton | boolean | - | Shows a close button in the mobile drawer. |
closeLabel | string | - | Replaces the drawer's close icon with this text; requires showCloseButton. |
Also accepts the props of React.HTMLAttributes<HTMLElement>, React.ComponentProps<typeof PopoverContent>.
FlyoutHeader
Groups the title and description.
Also accepts the props of React.ComponentProps<"div">.
FlyoutTitle
The flyout's title, used as its accessible name.
Also accepts the props of React.HTMLAttributes<HTMLHeadingElement>.
FlyoutDescription
Supporting text, used as the flyout's accessible description.
Also accepts the props of React.HTMLAttributes<HTMLParagraphElement>.
FlyoutBody
The main content area, padded on mobile.
Also accepts the props of React.ComponentProps<"div">.
FlyoutClose
A button that closes the flyout.
| Prop | Type | Default | Description |
|---|---|---|---|
render | React.ReactElement | - | Replaces the default button element with your own element, such as a Button. |
Also accepts the props of React.ButtonHTMLAttributes<HTMLButtonElement>.
On the radix base, set asChild and pass your element as the child instead of render.
Accessibility
- The popup has the
dialogrole, named byFlyoutTitleand described byFlyoutDescription. - Opening moves focus into the flyout.
Escapecloses it and returns focus to the trigger; pressing outside also closes it.
Notes
Parts carry data-slot values from flyout through flyout-close. showCloseButton and closeLabel only affect the mobile drawer; on desktop, add a FlyoutClose if the popover needs an explicit close control.