Not affiliated with official shadcn/ui. Visit ui.shadcn.com for official docs.
Unlock this block—Get Pro at 60% offReact Dialog Block Emergency Contact
Emergency contact dialog with contact details form, relationship selector, priority order, and medical information fields
Looking to implement shadcn/ui blocks?
Join our Discord community for help from other developers.
Safety starts with preparation. This React emergency contact dialog enables users to add and manage emergency contacts with name, phone, email fields, relationship type selector, priority ordering, and optional medical notes. Built with shadcn/ui Dialog, Input, Select, Textarea, Button, and Checkbox components using Tailwind CSS, users maintain critical contact information with clear relationship context and priority levels. Contact details, relationship type, medical notes—perfect for healthcare apps, travel booking platforms, HR systems, or any Next.js application where emergency preparedness protects users and ensures rapid response.
"use client";import { useState } from "react";import { Heart, Phone, Mail, User, Check, AlertTriangle, Shield,} from "lucide-react";import { Button } from "@/components/ui/button";import { Checkbox } from "@/components/ui/checkbox";import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger,} from "@/components/ui/dialog";import { Input } from "@/components/ui/input";import { Label } from "@/components/ui/label";import { Textarea } from "@/components/ui/textarea";import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue,} from "@/components/ui/select";import { Alert, AlertDescription } from "@/components/ui/alert";import { cn } from "@/lib/utils";const relationships = [ { value: "spouse", label: "Spouse / Partner" }, { value: "parent", label: "Parent" }, { value: "sibling", label: "Sibling" }, { value: "child", label: "Child" }, { value: "friend", label: "Friend" }, { value: "relative", label: "Other Relative" }, { value: "doctor", label: "Doctor / Physician" }, { value: "other", label: "Other" },];const priorities = [ { value: "primary", label: "Primary Contact", description: "Called first in emergencies" }, { value: "secondary", label: "Secondary Contact", description: "Called if primary unavailable" }, { value: "tertiary", label: "Additional Contact", description: "Backup contact option" },];export const title = "React Dialog Block Emergency Contact";export default function DialogEmergencyContact() { const [open, setOpen] = useState(false); const [saved, setSaved] = useState(false); const [fullName, setFullName] = useState(""); const [phone, setPhone] = useState(""); const [email, setEmail] = useState(""); const [relationship, setRelationship] = useState(""); const [priority, setPriority] = useState("primary"); const [medicalNotes, setMedicalNotes] = useState(""); const [canMakeDecisions, setCanMakeDecisions] = useState(false); const formatPhoneNumber = (value: string) => { const cleaned = value.replace(/\D/g, ""); if (cleaned.length <= 3) return cleaned; if (cleaned.length <= 6) return `(${cleaned.slice(0, 3)}) ${cleaned.slice(3)}`; return `(${cleaned.slice(0, 3)}) ${cleaned.slice(3, 6)}-${cleaned.slice(6, 10)}`; }; const handlePhoneChange = (value: string) => { const formatted = formatPhoneNumber(value); if (formatted.length <= 14) { setPhone(formatted); } }; const handleSave = () => { console.log({ fullName, phone, email, relationship, priority, medicalNotes, canMakeDecisions, }); setSaved(true); }; const handleClose = () => { setOpen(false); setTimeout(() => { setSaved(false); setFullName(""); setPhone(""); setEmail(""); setRelationship(""); setPriority("primary"); setMedicalNotes(""); setCanMakeDecisions(false); }, 200); }; const isValidPhone = phone.replace(/\D/g, "").length >= 10; const isValidEmail = !email || (email.includes("@") && email.includes(".")); const isValid = fullName.trim() && isValidPhone && relationship && isValidEmail; const getRelationshipLabel = () => { return relationships.find((r) => r.value === relationship)?.label || ""; }; const getPriorityLabel = () => { return priorities.find((p) => p.value === priority)?.label || ""; }; return ( <Dialog open={open} onOpenChange={setOpen}> <div className="flex min-h-[350px] items-center justify-center"> <DialogTrigger asChild> <Button variant="outline"> <Heart className="mr-2 h-4 w-4" /> Add Emergency Contact </Button> </DialogTrigger> </div> <DialogContent className="sm:max-w-md"> {saved ? ( <> <DialogHeader className="text-center"> <div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-primary/10 mb-4"> <Check className="h-6 w-6 text-primary" /> </div> <DialogTitle>Contact Added</DialogTitle> <DialogDescription> {fullName} has been added as your {getPriorityLabel().toLowerCase()} ({getRelationshipLabel().toLowerCase()}). </DialogDescription> </DialogHeader> <div className="py-4"> <div className="rounded-lg border p-4 space-y-2"> <div className="flex items-center gap-2"> <User className="h-4 w-4 text-muted-foreground" /> <span className="font-medium">{fullName}</span> </div> <div className="flex items-center gap-2 text-sm text-muted-foreground"> <Phone className="h-4 w-4" /> <span>{phone}</span> </div> {email && ( <div className="flex items-center gap-2 text-sm text-muted-foreground"> <Mail className="h-4 w-4" /> <span>{email}</span> </div> )} {canMakeDecisions && ( <div className="flex items-center gap-2 text-sm text-primary"> <Shield className="h-4 w-4" /> <span>Authorized for medical decisions</span> </div> )} </div> </div> <DialogFooter> <Button onClick={handleClose} className="w-full"> Done </Button> </DialogFooter> </> ) : ( <> <DialogHeader> <DialogTitle className="flex items-center gap-2"> <Heart className="h-5 w-5" /> Emergency Contact </DialogTitle> <DialogDescription> Add someone who can be contacted in case of emergency. </DialogDescription> </DialogHeader> <div className="space-y-4 py-4"> <Alert> <AlertTriangle className="h-4 w-4" /> <AlertDescription> This information may be shared with emergency services if needed. </AlertDescription> </Alert> <div className="space-y-2"> <Label htmlFor="fullName">Full Name *</Label> <div className="relative"> <User className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" /> <Input id="fullName" placeholder="Contact's full name" value={fullName} onChange={(e) => setFullName(e.target.value)} className="pl-9" /> </div> </div> <div className="grid grid-cols-2 gap-3"> <div className="space-y-2"> <Label htmlFor="relationship">Relationship *</Label> <Select value={relationship} onValueChange={setRelationship}> <SelectTrigger id="relationship"> <SelectValue placeholder="Select" /> </SelectTrigger> <SelectContent> {relationships.map((rel) => ( <SelectItem key={rel.value} value={rel.value}> {rel.label} </SelectItem> ))} </SelectContent> </Select> </div> <div className="space-y-2"> <Label htmlFor="priority">Priority *</Label> <Select value={priority} onValueChange={setPriority}> <SelectTrigger id="priority"> <SelectValue /> </SelectTrigger> <SelectContent> {priorities.map((p) => ( <SelectItem key={p.value} value={p.value}> {p.label} </SelectItem> ))} </SelectContent> </Select> </div> </div> <div className="space-y-2"> <Label htmlFor="phone">Phone Number *</Label> <div className="relative"> <Phone className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" /> <Input id="phone" type="tel" placeholder="(555) 123-4567" value={phone} onChange={(e) => handlePhoneChange(e.target.value)} className="pl-9" /> </div> </div> <div className="space-y-2"> <Label htmlFor="email">Email (optional)</Label> <div className="relative"> <Mail className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" /> <Input id="email" type="email" placeholder="[email protected]" value={email} onChange={(e) => setEmail(e.target.value)} className="pl-9" /> </div> </div> <div className="space-y-2"> <Label htmlFor="medicalNotes">Medical Notes (optional)</Label> <Textarea id="medicalNotes" placeholder="Allergies, conditions, medications..." value={medicalNotes} onChange={(e) => setMedicalNotes(e.target.value)} className="h-16 resize-none" /> </div> <div className="flex items-start space-x-3 pt-2"> <Checkbox id="canMakeDecisions" checked={canMakeDecisions} onCheckedChange={(checked) => setCanMakeDecisions(checked as boolean)} /> <div className="space-y-1"> <Label htmlFor="canMakeDecisions" className="text-sm font-normal cursor-pointer" > Authorize for medical decisions </Label> <p className="text-xs text-muted-foreground"> This person can make medical decisions on your behalf if you're unable to. </p> </div> </div> </div> <DialogFooter className="gap-2 sm:gap-0"> <Button variant="outline" onClick={handleClose}> Cancel </Button> <Button onClick={handleSave} disabled={!isValid}> Save Contact </Button> </DialogFooter> </> )} </DialogContent> </Dialog> );}Installation
npx shadcn@latest add https://www.shadcn.io/registry/dialog-emergency-contact.jsonnpx shadcn@latest add https://www.shadcn.io/registry/dialog-emergency-contact.jsonpnpm dlx shadcn@latest add https://www.shadcn.io/registry/dialog-emergency-contact.jsonbunx shadcn@latest add https://www.shadcn.io/registry/dialog-emergency-contact.jsonRelated blocks you will also like
React Dialog Block Contact Card
Contact display card
React Dialog Block Edit Profile Form
Profile information form
React Dialog Block Billing Address
Address input form
React Dialog Block Add Writer Profile
Profile creation form
React Dialog Block Destructive Warning
Important alerts
React Dialog Block Success Confirmation
Save confirmation