Julien Thibeaut

Morphing Dialog

Cards 105

About

A dialog that uses layout animations to transition content into a focused view. It supports click-outside and escape key functionalities for closing.

Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds Morphing Dialog to your project and fits it to your theme.

Code

How Morphing Dialog is used: the demo's code. The component's own source comes with a free account.

Usage.tsx

"use client"

import React from "react"
import { XIcon } from "lucide-react"
import {
  MorphingDialog,
  MorphingDialogTrigger,
  MorphingDialogContainer,
  MorphingDialogContent,
  MorphingDialogClose,
} from "@/components/ui/morphing-dialog"

type Project = {
  name: string
  description: string
  link: string
  video: string
  id: string
}

const PROJECTS: Project[] = [
  {
    name: 'Motion Primitives Pro',
    description:
      'Advanced components and templates to craft beautiful websites.',
    link: 'https://pro.motion-primitives.com/',
    video:
      'https://res.cloudinary.com/read-cv/video/upload/t_v_b/v1/1/profileItems/W2azTw5BVbMXfj7F53G92hMVIn32/newProfileItem/d898be8a-7037-4c71-af0c-8997239b050d.mp4?_a=DATAdtAAZAA0',
    id: 'project1',
  },
  {
    name: 'Motion Primitives',
    description: 'UI kit to make beautiful, animated interfaces.',
    link: 'https://motion-primitives.com/',
    video:
      'https://res.cloudinary.com/read-cv/video/upload/t_v_b/v1/1/profileItems/W2azTw5BVbMXfj7F53G92hMVIn32/XSfIvT7BUWbPRXhrbLed/ee6871c9-8400-49d2-8be9-e32675eabf7e.mp4?_a=DATAdtAAZAA0',
    id: 'project2',
  },
]

function ProjectVideo({ src }: { src: string }) {
  return (
    <MorphingDialog
      transition={{
        type: "spring",
        bounce: 0,
        duration: 0.3,
      }}
    >
      <MorphingDialogTrigger>
        <video
          src={src}
          autoPlay
          loop
          muted
          playsInline
          className="aspect-video w-full cursor-zoom-in rounded-xl"
        />
      </MorphingDialogTrigger>
      <MorphingDialogContainer>
        <MorphingDialogContent className="relative aspect-video rounded-2xl bg-zinc-50 p-1 ring-1 ring-zinc-200/50 ring-inset dark:bg-zinc-950 dark:ring-zinc-800/50">
          <video
            src={src}
            autoPlay
            loop
            muted
            playsInline
            className="aspect-video h-[50vh] w-full rounded-xl md:h-[70vh]"
          />
        </MorphingDialogContent>
        <MorphingDialogClose
          className="fixed top-6 right-6 h-fit w-fit rounded-full bg-white p-1"
          variants={{
            initial: { opacity: 0 },
            animate: {
              opacity: 1,
              transition: { delay: 0.3, duration: 0.1 },
            },
            exit: { opacity: 0, transition: { duration: 0 } },
          }}
        >
          <XIcon className="h-5 w-5 text-zinc-500" />
        </MorphingDialogClose>
      </MorphingDialogContainer>
    </MorphingDialog>
  )
}

function MorphingDialogDemo() {
  return (
    <div className="flex min-h-[400px] w-full items-center justify-center bg-white p-8 dark:bg-zinc-950">
      <div className="grid w-full max-w-5xl grid-cols-1 gap-6 sm:grid-cols-2">
        {PROJECTS.map((project) => (
          <div key={project.name} className="space-y-2">
            <div className="relative rounded-2xl bg-zinc-50/40 p-1 ring-1 ring-zinc-200/50 ring-inset dark:bg-zinc-950/40 dark:ring-zinc-800/50">
              <ProjectVideo src={project.video} />
            </div>
            <div className="px-1">
              <a
                className="font-base group relative inline-block font-[450] text-zinc-900 dark:text-zinc-50"
                href={project.link}
                target="_blank"
                rel="noopener noreferrer"
              >
                {project.name}
                <span className="absolute bottom-0.5 left-0 block h-[1px] w-full max-w-0 bg-zinc-900 transition-all duration-200 group-hover:max-w-full dark:bg-zinc-50"></span>
              </a>
              <p className="text-base text-zinc-600 dark:text-zinc-400">
                {project.description}
              </p>
            </div>
          </div>
        ))}
      </div>
    </div>
  )
}

export { MorphingDialogDemo }

Dependencies

More by Julien Thibeaut

View all
  • Dock

    Dock

    3.1K
  • Text Effect

    Text Effect

    1.6K
  • Infinite Slider

    Infinite Slider

    1.5K
  • Text Shimmer

    Text Shimmer

    1.3K
  • Text Scramble

    Text Scramble

    1.1K
  • Progressive blur

    Progressive blur

    683
  • Glow Effect

    Glow Effect

    608
  • Tailwind CSS Background Snippet

    Tailwind CSS Background Snippet

    533

More in Cards

View all
  • Course Design Cards

    Course Design Cards

    1.1K
  • Stats cards with links

    Stats cards with links

    79
  • Statistics Card 2

    Statistics Card 2

    259
  • Card

    Card

    56
  • Card Studio

    Card Studio

    9
  • The Item one

    The Item one

    3
  • Statistics Card 7

    Statistics Card 7

    289
  • Weather Card

    Weather Card

    54