Efferd

Modal

Forms 90

About

This smart Modal component auto-switches between a Dialog and Drawer based on screen size using context. It gives you a seamless, unified API for building mobile-friendly popups, side panels, or modals with full Radix/vaul support—super handy for responsive UIs.

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

Code

How Modal 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 {
	Modal,
	ModalBody,
	ModalClose,
	ModalContent,
	ModalDescription,
	ModalFooter,
	ModalHeader,
	ModalTitle,
	ModalTrigger,
} from '@/components/ui/modal';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { useIsMobile } from '@/hooks/use-media-query';

function Preview() {
	const [open, setOpen] = React.useState(false);

	return (
		<Modal open={open} onOpenChange={setOpen}>
			<ModalTrigger>
				<Button variant="outline">Open Modal</Button>
			</ModalTrigger>
			<ModalContent>
				<form
					onSubmit={(e) => {
						e.preventDefault();
						alert('Form submitted!');
					}}
				>
					<ModalHeader>
						<ModalTitle>Edit Profile</ModalTitle>
						<ModalDescription>Update your name and username.</ModalDescription>
					</ModalHeader>
					<ModalBody className="grid gap-4 py-4">
						<div className="grid gap-2">
							<Label htmlFor="name">Name</Label>
							<Input id="name" defaultValue="Pedro Duarte" />
						</div>
						<div className="grid gap-2">
							<Label htmlFor="username">Username</Label>
							<Input id="username" defaultValue="@peduarte" />
						</div>
					</ModalBody>
					<ModalFooter>
						<ModalClose asChild>
							<Button type="button" variant="outline">
								Cancel
							</Button>
						</ModalClose>
						<Button type="submit">Save</Button>
					</ModalFooter>
				</form>
			</ModalContent>
		</Modal>
	);
}

export default function Default() {
	return (
		<div className="flex min-h-screen flex-col items-center space-y-12 py-24">
			<DeviceIndicator />
			<div className="space-y-3 text-center">
				<h1 className="text-6xl font-extrabold tracking-tight">
					Responsive Modal
				</h1>
				<p className="text-xl font-medium">
					This modal automatically adapts to your device:
				</p>
				<div className="flex justify-center gap-8 text-sm">
					<div className="flex items-center gap-2 rounded-md border p-1">
						<div className="h-3 w-3 rounded-full bg-blue-500" />
						<span className="flex items-center gap-2">
							<strong className="font-semibold">Desktop:</strong>{' '}
							<code>
								<pre>{`<Dialog />`}</pre>
							</code>
						</span>
					</div>
					<div className="flex items-center gap-2 rounded-md border p-1">
						<div className="h-3 w-3 rounded-full bg-green-500" />
						<span className="flex items-center gap-2">
							<strong className="font-semibold">Mobile:</strong>{' '}
							<code>
								<pre>{`<Drawer />`}</pre>
							</code>
						</span>
					</div>
				</div>
			</div>
			<Preview />
			<p className="text-muted-foreground text-sm">
				*Try resizing your browser window or opening this on different devices!
			</p>
		</div>
	);
}

function DeviceIndicator() {
	const isMobile = useIsMobile();

	return (
		<div className="fixed top-4 left-4 z-50">
			<div
				className={`bg-muted rounded-full border px-3 py-2 text-sm font-medium`}
			>
				<div className="flex items-center gap-2">
					<div
						className={`h-2 w-2 rounded-full ${isMobile ? 'bg-green-500' : 'bg-blue-500'}`}
					/>
					{isMobile ? 'Mobile' : 'Desktop'}
				</div>
			</div>
		</div>
	);
}

More by Efferd

View all
  • Testimonials Columns

    Testimonials Columns

    7.1K
  • Zoom Parallax

    Zoom Parallax

    5.2K
  • Dotted Surface

    Dotted Surface

    3.5K
  • Footer Section

    Footer Section

    2.7K
  • Grid Feature Cards

    Grid Feature Cards

    1.9K
  • Logo Cloud 2

    Logo Cloud 2

    1.6K
  • Header 3

    Header 3

    1.6K
  • Logo Cloud 3

    Logo Cloud 3

    1.5K

More in Forms

View all
  • Premium Auth

    Premium Auth

    500
  • Login 2

    Login 2

    7
  • Authentication Card

    Authentication Card

    47
  • Login 1

    Login 1

    52
  • Contact Card

    Contact Card

    1K
  • Login Form

    Login Form

    6
  • Form

    Form

    16
  • Book A Demo 3

    Book A Demo 3

    83

Explore more

Part of Efferd UI — browse the full library on 21st.dev.