Dashral Pro is on the wayGet 30% off at launch

Dashral

Dialog

Dialog with motion: it grows out of the button that opened it, shrinks back into it as it closes, glides to a new height when its content changes, and swipes down to close on a phone.

$ pnpm dlx shadcn@latest add https://dashral.com/r/motion-dialog.json

Installation

$ pnpm dlx shadcn@latest add https://dashral.com/r/motion-dialog.json

Adds components/dashral/motion/dialog.tsx, the Dialog it builds on (in components/dashral/), motion and the motion files every motion component shares. With the registry in your components.json:

$ pnpm dlx shadcn@latest add @dashral/motion-dialog

Usage

The same as Dialog, imported from components/dashral/motion/: swap the import and it moves.

example.tsx
import { Dialog, DialogClose } from "@/components/dashral/motion/dialog"

<Dialog
  trigger={<Button>Edit profile</Button>}
  title="Edit profile"
  footer={<DialogClose asChild><Button>Done</Button></DialogClose>}
>
  <ProfileForm />
</Dialog>

Examples

Delete from a list

Each dialog grows out of its row's button. Delete shows Deleting…, the dialog shrinks back, the row folds away, and Undo brings it back.

Marketing site

Updated 2 hours ago

Customer portal

Updated Yesterday

Billing API

Updated Oct 28

Help center

Updated Oct 12

Swipe down to close

On a phone, or in your browser's device mode: swipe the panel down and it follows your finger as the backdrop clears, slides away closed far or fast enough, and springs back short of it.

On a phone, or in your browser's device mode, swipe the panel down to close it.

Steps of different heights

Name, template, done: the panel glides between steps, Create shows it's working, and the new project slides into the list.

Projects

  • Q3 review

    Sales template

  • Helpdesk

    Support template

Compared with Default

Default

Fades and zooms in from 95% in the middle of the screen. A new step's height jumps.

Motion

Grows out of the button that opened it on a spring and shrinks back into it; glides to a new height when what's inside changes; on a phone, swipe it down to close.

How the two editions differ in general, and which to use where: Motion.

API reference

Every prop of Dialog, and every attribute of the element it renders. What the Motion edition adds is marked Motion.

Dialog

Also takes every prop of Radix Dialog(opens in a new tab).

PropTypeDefault
swipeToCloseboolean

Motion On a touch screen, swipe the panel down to close it.

true
triggerReactElement

What opens it. Leave it out to open it with open / onOpenChange.

—
titleReactNode

Required: it names the dialog. Hide it with classNames.title "sr-only" if the design has none.

—
descriptionReactNode

Under the title; it describes the dialog.

—
childrenReactNode

The body.

—
footerReactNode

Buttons at the bottom.

—
formComponentProps<"form">

Makes the body and footer one form, e.g. { onSubmit } or { action }.

—
size"sm" | "md" | "lg" | "xl"

The window's width.

"md"
showCloseButtonboolean

The × in the corner.

true
open / defaultOpen / onOpenChange

Controlled or initial state.

—
classNames{ header, title, description, footer }

Classes for each part.

—
classNamestring

The window's classes.

—

DialogClose

Closes the dialog: wrap a Cancel button in the footer.

Also takes every prop of Radix Dialog(opens in a new tab).

PropTypeDefault
asChildboolean

Render the child element instead (e.g. a Next.js Link), passing these styles and props to it.

false

DialogClose is the default edition's, re-exported, so a footer works the same with either.

Motion

  • It grows from 60% on a quick spring (--duration-standard, a hint of overshoot), from the middle of the button that opened it.
  • Closing, it shrinks back toward that button and fades (--duration-fast, --ease-exit) while the backdrop clears; the backdrop's blur stays put and only fades, so it never costs frames.
  • When what's inside changes (a form's next step, an error appearing) the panel glides to its new height with no overshoot; it's clipped only while it glides.
  • On a touch screen, a swipe down on the panel (not in a field) moves it with your finger while the backdrop clears; past 110px, or flicked, it slides off the bottom closed and the phone buzzes; short of it it springs back. Upward it barely gives. A small handle at the top says so.
  • Opened without a trigger (open and onOpenChange alone), it grows from the middle. With reduced motion it only fades, and doesn't swipe.