Components
Loading preview...
This is a responsive modal component system that automatically switches between Dialog (desktop) and Drawer (mobile) using a media query. It provides reusable subcomponents like Header, Body, Footer, Trigger, and Close for consistent structure. Includes a built-in FormFooter with cancel and submit (with loader) support for common form use cases.
npx shadcn@latest add https://21st.dev/r/info-mdshakeeb/responsive-modal"use client";
import React, { useTransition } from "react";
import { Modal } from "@/components/ui/responsive-modal";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
export default function DemoOne() {
const [open, setOpen] = React.useState(false);
const [isPending, startTransition] = useTransition();
// controlled select value
const [platform, setPlatform] = React.useState<string>("");
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
startTransition(async()=>{
// fake API delay
await new Promise((res) => setTimeout(res, 3500));
setOpen(false);
})
};
return (
<>
<div>
<Button
className="h-6 px-2 mt-2"
size="sm"
onClick={() => setOpen(true)}
>
Open Modal
</Button>
</div>
<Modal.Root open={open} onOpenChange={setOpen}>
<Modal.Content>
<form id="demo-form" onSubmit={handleSubmit}>
<Modal.Header>
<Modal.Title>Example Modal</Modal.Title>
<Modal.Description>
This modal adapts between desktop (Dialog) and mobile (Drawer).
</Modal.Description>
</Modal.Header>
<Modal.Body>
<p className="text-sm text-muted-foreground">
You can put any content here — inputs, text, or custom UI.
</p>
</Modal.Body>
</form>
{/* Ready-made footer with Cancel + Submit */}
<Modal.FormFooter
formId="demo-form"
isPending={isPending}
submitLabel="Save Changes"
/>
</Modal.Content>
</Modal.Root>
</>
);
}