Not affiliated with official shadcn/ui. Visit ui.shadcn.com for official docs.
Unlock this block—Get Pro at 60% offReact Dialog Block Assign Task
Assign task dialog with team member picker, due date selection, priority level, and task details
Looking to implement shadcn/ui blocks?
Join our Discord community for help from other developers.
Assign tasks to team members with full context. This React assign task dialog provides searchable team member dropdown for assignee selection, due date picker with quick date options, priority level selector from low to urgent, and optional notes field for instructions. Built with shadcn/ui Dialog, Command, Calendar, Select, Button, and Avatar components using Tailwind CSS, users delegate work efficiently. Pick assignee, set deadline, choose priority—perfect for project management, task boards, team collaboration, or any Next.js application requiring task assignment with clear ownership and deadlines.
"use client";import { useState } from "react";import { UserPlus, Calendar as CalendarIcon, Flag, AlertCircle, Check, Loader2, Search, Clock,} from "lucide-react";import { Button } from "@/components/ui/button";import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger,} from "@/components/ui/dialog";import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList,} from "@/components/ui/command";import { Popover, PopoverContent, PopoverTrigger,} from "@/components/ui/popover";import { Calendar } from "@/components/ui/calendar";import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue,} from "@/components/ui/select";import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";import { Label } from "@/components/ui/label";import { Textarea } from "@/components/ui/textarea";import { Badge } from "@/components/ui/badge";import { cn } from "@/lib/utils";type TeamMember = { id: string; name: string; email: string; avatar?: string; initials: string; taskCount: number;};const teamMembers: TeamMember[] = [ { id: "1", name: "Alice Johnson", email: "[email protected]", initials: "AJ", taskCount: 5 }, { id: "2", name: "Bob Smith", email: "[email protected]", initials: "BS", taskCount: 3 }, { id: "3", name: "Carol Williams", email: "[email protected]", initials: "CW", taskCount: 8 }, { id: "4", name: "David Brown", email: "[email protected]", initials: "DB", taskCount: 2 }, { id: "5", name: "Emma Davis", email: "[email protected]", initials: "ED", taskCount: 6 },];const priorities = [ { value: "low", label: "Low", color: "text-muted-foreground" }, { value: "medium", label: "Medium", color: "text-blue-600" }, { value: "high", label: "High", color: "text-orange-600" }, { value: "urgent", label: "Urgent", color: "text-destructive" },];const quickDates = [ { label: "Today", days: 0 }, { label: "Tomorrow", days: 1 }, { label: "Next Week", days: 7 }, { label: "In 2 Weeks", days: 14 },];export const title = "React Dialog Block Assign Task";export default function DialogAssignTask() { const [open, setOpen] = useState(false); const [assigneeOpen, setAssigneeOpen] = useState(false); const [calendarOpen, setCalendarOpen] = useState(false); const [selectedMember, setSelectedMember] = useState<TeamMember | null>(null); const [dueDate, setDueDate] = useState<Date | undefined>(); const [priority, setPriority] = useState("medium"); const [notes, setNotes] = useState(""); const [isAssigning, setIsAssigning] = useState(false); const handleQuickDate = (days: number) => { const date = new Date(); date.setDate(date.getDate() + days); setDueDate(date); setCalendarOpen(false); }; const handleAssign = async () => { if (!selectedMember) return; setIsAssigning(true); await new Promise((resolve) => setTimeout(resolve, 1000)); setIsAssigning(false); setOpen(false); // Reset form setSelectedMember(null); setDueDate(undefined); setPriority("medium"); setNotes(""); }; const selectedPriority = priorities.find((p) => p.value === priority); return ( <Dialog open={open} onOpenChange={setOpen}> <div className="flex min-h-[350px] items-center justify-center"> <DialogTrigger asChild> <Button variant="outline"> <UserPlus className="mr-2 h-4 w-4" /> Assign Task </Button> </DialogTrigger> </div> <DialogContent className="sm:max-w-md"> <DialogHeader> <DialogTitle className="flex items-center gap-2"> <UserPlus className="h-5 w-5" /> Assign Task </DialogTitle> <DialogDescription> Assign this task to a team member with a deadline. </DialogDescription> </DialogHeader> <div className="space-y-4 py-4"> {/* Assignee Picker */} <div className="space-y-2"> <Label>Assignee</Label> <Popover open={assigneeOpen} onOpenChange={setAssigneeOpen}> <PopoverTrigger asChild> <Button variant="outline" role="combobox" className="w-full justify-start" > {selectedMember ? ( <div className="flex items-center gap-2"> <Avatar className="h-6 w-6"> <AvatarImage src={selectedMember.avatar} /> <AvatarFallback className="text-xs"> {selectedMember.initials} </AvatarFallback> </Avatar> <span>{selectedMember.name}</span> </div> ) : ( <span className="text-muted-foreground">Select team member...</span> )} </Button> </PopoverTrigger> <PopoverContent className="w-[300px] p-0" align="start"> <Command> <CommandInput placeholder="Search team..." /> <CommandList> <CommandEmpty>No member found.</CommandEmpty> <CommandGroup> {teamMembers.map((member) => ( <CommandItem key={member.id} onSelect={() => { setSelectedMember(member); setAssigneeOpen(false); }} className="cursor-pointer" > <Avatar className="h-8 w-8 mr-2"> <AvatarImage src={member.avatar} /> <AvatarFallback className="text-xs"> {member.initials} </AvatarFallback> </Avatar> <div className="flex-1"> <p className="text-sm font-medium">{member.name}</p> <p className="text-xs text-muted-foreground"> {member.taskCount} active tasks </p> </div> {selectedMember?.id === member.id && ( <Check className="h-4 w-4 text-primary" /> )} </CommandItem> ))} </CommandGroup> </CommandList> </Command> </PopoverContent> </Popover> </div> {/* Due Date */} <div className="space-y-2"> <Label>Due Date</Label> <Popover open={calendarOpen} onOpenChange={setCalendarOpen}> <PopoverTrigger asChild> <Button variant="outline" className={cn( "w-full justify-start text-left", !dueDate && "text-muted-foreground" )} > <CalendarIcon className="mr-2 h-4 w-4" /> {dueDate ? dueDate.toLocaleDateString() : "Select due date..."} </Button> </PopoverTrigger> <PopoverContent className="w-auto p-0" align="start"> <div className="flex gap-1 p-2 border-b"> {quickDates.map((qd) => ( <Button key={qd.label} variant="ghost" size="sm" className="text-xs" onClick={() => handleQuickDate(qd.days)} > {qd.label} </Button> ))} </div> <Calendar mode="single" selected={dueDate} onSelect={(date) => { setDueDate(date); setCalendarOpen(false); }} disabled={(date) => date < new Date()} initialFocus /> </PopoverContent> </Popover> </div> {/* Priority */} <div className="space-y-2"> <Label>Priority</Label> <Select value={priority} onValueChange={setPriority}> <SelectTrigger> <SelectValue> <div className="flex items-center gap-2"> <Flag className={cn("h-4 w-4", selectedPriority?.color)} /> <span>{selectedPriority?.label}</span> </div> </SelectValue> </SelectTrigger> <SelectContent> {priorities.map((p) => ( <SelectItem key={p.value} value={p.value}> <div className="flex items-center gap-2"> <Flag className={cn("h-4 w-4", p.color)} /> <span>{p.label}</span> </div> </SelectItem> ))} </SelectContent> </Select> </div> {/* Notes */} <div className="space-y-2"> <Label htmlFor="notes">Notes (optional)</Label> <Textarea id="notes" placeholder="Add any instructions or context..." value={notes} onChange={(e) => setNotes(e.target.value)} rows={3} /> </div> {/* Summary */} {selectedMember && ( <div className="rounded-lg border p-3 space-y-2"> <p className="text-sm font-medium">Assignment Summary</p> <div className="flex items-center gap-2 text-sm text-muted-foreground"> <Avatar className="h-5 w-5"> <AvatarFallback className="text-[10px]"> {selectedMember.initials} </AvatarFallback> </Avatar> <span>{selectedMember.name}</span> {dueDate && ( <> <span>•</span> <Clock className="h-3 w-3" /> <span>{dueDate.toLocaleDateString()}</span> </> )} <span>•</span> <Badge variant="outline" className="text-xs"> {selectedPriority?.label} </Badge> </div> </div> )} </div> <DialogFooter> <Button variant="outline" onClick={() => setOpen(false)} disabled={isAssigning} > Cancel </Button> <Button onClick={handleAssign} disabled={!selectedMember || isAssigning} > {isAssigning ? ( <> <Loader2 className="mr-2 h-4 w-4 animate-spin" /> Assigning... </> ) : ( <> <Check className="mr-2 h-4 w-4" /> Assign Task </> )} </Button> </DialogFooter> </DialogContent> </Dialog> );}Installation
npx shadcn@latest add https://www.shadcn.io/registry/dialog-assign-task.jsonnpx shadcn@latest add https://www.shadcn.io/registry/dialog-assign-task.jsonpnpm dlx shadcn@latest add https://www.shadcn.io/registry/dialog-assign-task.jsonbunx shadcn@latest add https://www.shadcn.io/registry/dialog-assign-task.jsonRelated blocks you will also like
React Dialog Block Schedule Meeting
Meeting scheduling
React Dialog Block Contact Picker
Team selection
React Dialog Block Date Range Picker
Date selection
React Dialog Block Set Reminder
Reminders
React Dialog Block Team Roles
Team management
React Dialog Block Quick Note
Task notes