NRVM

Back to Discover
ModalsIntermediate

Minimal Modal

A fully functional, animated dialog powered by Framer Motion.

Live Preview
"use client";
import { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { X } from "lucide-react";

export function MinimalModal() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <div className="flex items-center justify-center h-full w-full relative">
      <button 
        onClick={() => setIsOpen(true)}
        className="rounded-md bg-foreground text-background px-4 py-2 text-sm font-medium hover:bg-[#e0e0e0] transition-colors z-0"
      >
        Open Dialog
      </button>

      <AnimatePresence>
        {isOpen && (
          <div className="absolute inset-0 z-50 flex items-center justify-center p-4">
            <motion.div 
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              exit={{ opacity: 0 }}
              className="absolute inset-0 bg-background/80 backdrop-blur-sm" 
              onClick={() => setIsOpen(false)} 
            />
            <motion.div 
              initial={{ opacity: 0, scale: 0.95, y: 10 }}
              animate={{ opacity: 1, scale: 1, y: 0 }}
              exit={{ opacity: 0, scale: 0.95, y: 10 }}
              transition={{ type: "spring", damping: 25, stiffness: 300 }}
              className="relative w-full max-w-lg rounded-xl border border-border bg-[#050505] p-6 shadow-2xl"
            >
              <button 
                onClick={() => setIsOpen(false)}
                className="absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none"
              >
                <X className="h-4 w-4 text-muted-foreground hover:text-foreground" />
                <span className="sr-only">Close</span>
              </button>
              <div className="flex flex-col space-y-1.5 mb-4 text-left">
                <h2 className="text-lg font-semibold leading-none tracking-tight text-foreground">Edit Profile</h2>
                <p className="text-sm text-muted-foreground">Make changes to your profile here. Click save when you're done.</p>
              </div>
              <div className="space-y-4 py-4 text-left">
                <div className="grid grid-cols-4 items-center gap-4">
                  <label className="text-right text-sm font-medium text-foreground">Name</label>
                  <input className="col-span-3 rounded-md border border-border bg-transparent px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-foreground" defaultValue="Pedro Duarte" />
                </div>
                <div className="grid grid-cols-4 items-center gap-4">
                  <label className="text-right text-sm font-medium text-foreground">Username</label>
                  <input className="col-span-3 rounded-md border border-border bg-transparent px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-foreground" defaultValue="@peduarte" />
                </div>
              </div>
              <div className="flex justify-end mt-4">
                <button 
                  onClick={() => setIsOpen(false)}
                  className="rounded-md bg-foreground text-background px-4 py-2 text-sm font-medium hover:bg-[#e0e0e0] transition-colors"
                >
                  Save changes
                </button>
              </div>
            </motion.div>
          </div>
        )}
      </AnimatePresence>
    </div>
  );
}