Linear Modal

Feature cards that grow into a modal: the card frame, its image and its title travel to their place in the dialog, and return to the card when it closes.

Examples

Feature grid

Each card opens its feature, with a description and the points that make it up.

Release notes

One column, and no list of points: the modal shows the description alone.

Installation

npx shadcn@latest add https://ui.ndekocode.dev/r/motion-linear-modal.json

Component API

LinearModal

Renders the grid of cards and the one modal they share.

PropTypeDefaultDescription
featuresLinearModalFeature[]One card per feature.
closeLabelstring'Close'The accessible name of the close button.
classNamestringClasses for the grid. It starts as grid gap-3 sm:grid-cols-2.

LinearModalFeature

FieldTypeDescription
idstringA stable id for the feature.
titlestringThe title on the card and in the modal.
summarystringOne line under the title on the card.
descriptionstringThe paragraph in the modal.
image{ src: string; alt: string }The image on the card and at the top of the modal.
pointsLinearModalPoint[]The list in the modal: title, description and an optional icon.

How it differs from Morphing Dialog

Morphing Dialog gives you the parts to build any card that opens into a dialog. Linear Modal is the finished section: a grid of cards, one modal and the content layout, on the Base UI dialog for its keyboard and focus handling.

Accessibility and motion

  • Each card is a button. The modal moves focus to its close button, keeps it inside, closes with Escape or a click on the backdrop, and returns focus to the card that opened it. The page behind does not scroll.
  • The frame, image and title travel on a spring with no bounce, in 360ms to open and 280ms to close. The text of the modal fades in once the frame has nearly arrived.
  • With reduced motion, the modal appears in place with a fade and nothing travels.

Credits

Inspired by the Linear modal of UI Layouts, rebuilt on the Base UI dialog and motion.