Not affiliated with official shadcn/ui. Visit ui.shadcn.com for official docs.
Unlock this block—Get Pro at 60% offReact Dialog Block Poll Create
Poll creation dialog with question input, multiple choice options, voting settings, duration picker, and preview
Looking to implement shadcn/ui blocks?
Join our Discord community for help from other developers.
Gather opinions with ease. This React poll creation dialog enables users to craft engaging polls with question input, dynamic answer options, voting configuration (single/multiple choice), duration settings, and live preview. Built with shadcn/ui Dialog, Input, Button, Switch, Select, and RadioGroup components using Tailwind CSS, creators publish polls with customizable options and clear voting rules. Add options, set duration, configure voting—perfect for social platforms, community forums, team decision tools, or any Next.js application where user engagement through polls and surveys drives community participation and data-driven decisions.
"use client";import { useState } from "react";import { BarChart3, Plus, X, GripVertical, Clock, Users, Eye, Check,} from "lucide-react";import { Button } from "@/components/ui/button";import { Badge } from "@/components/ui/badge";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 { Select, SelectContent, SelectItem, SelectTrigger, SelectValue,} from "@/components/ui/select";import { Switch } from "@/components/ui/switch";import { Separator } from "@/components/ui/separator";import { cn } from "@/lib/utils";type PollOption = { id: string; text: string;};const durations = [ { value: "1h", label: "1 hour" }, { value: "6h", label: "6 hours" }, { value: "1d", label: "1 day" }, { value: "3d", label: "3 days" }, { value: "7d", label: "1 week" }, { value: "custom", label: "Custom" },];export const title = "React Dialog Block Poll Create";export default function DialogPollCreate() { const [open, setOpen] = useState(false); const [question, setQuestion] = useState(""); const [options, setOptions] = useState<PollOption[]>([ { id: "1", text: "" }, { id: "2", text: "" }, ]); const [duration, setDuration] = useState("1d"); const [allowMultiple, setAllowMultiple] = useState(false); const [showResults, setShowResults] = useState(true); const [isCreating, setIsCreating] = useState(false); const [created, setCreated] = useState(false); const addOption = () => { if (options.length >= 6) return; setOptions([ ...options, { id: Math.random().toString(36).substr(2, 9), text: "" }, ]); }; const removeOption = (optionId: string) => { if (options.length <= 2) return; setOptions(options.filter((o) => o.id !== optionId)); }; const updateOption = (optionId: string, text: string) => { setOptions(options.map((o) => (o.id === optionId ? { ...o, text } : o))); }; const handleCreate = async () => { setIsCreating(true); await new Promise((resolve) => setTimeout(resolve, 1000)); console.log("Creating poll:", { question, options: options.map((o) => o.text), duration, allowMultiple, showResults, }); setIsCreating(false); setCreated(true); }; const handleClose = () => { setOpen(false); setTimeout(() => { setQuestion(""); setOptions([ { id: "1", text: "" }, { id: "2", text: "" }, ]); setDuration("1d"); setAllowMultiple(false); setShowResults(true); setIsCreating(false); setCreated(false); }, 200); }; const filledOptions = options.filter((o) => o.text.trim()); const isValid = question.trim() && filledOptions.length >= 2; const selectedDuration = durations.find((d) => d.value === duration); return ( <Dialog open={open} onOpenChange={setOpen}> <div className="flex min-h-[350px] items-center justify-center"> <DialogTrigger asChild> <Button variant="outline"> <BarChart3 className="mr-2 h-4 w-4" /> Create Poll </Button> </DialogTrigger> </div> <DialogContent className="sm:max-w-md"> {created ? ( <> <DialogHeader className="text-center"> <div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-primary/10 mb-2"> <Check className="h-6 w-6 text-primary" /> </div> <DialogTitle>Poll Created!</DialogTitle> <DialogDescription> Your poll is now live and ready for responses. </DialogDescription> </DialogHeader> <div className="py-4"> <div className="rounded-lg border p-4 space-y-3"> <p className="font-medium">{question}</p> <div className="space-y-2"> {filledOptions.map((option, index) => ( <div key={option.id} className="flex items-center gap-2 text-sm" > <div className="h-4 w-4 rounded-full border flex items-center justify-center"> <span className="text-xs text-muted-foreground"> {index + 1} </span> </div> <span>{option.text}</span> </div> ))} </div> <Separator /> <div className="flex items-center justify-between text-xs text-muted-foreground"> <span className="flex items-center gap-1"> <Clock className="h-3 w-3" /> {selectedDuration?.label} </span> <span className="flex items-center gap-1"> <Users className="h-3 w-3" /> {allowMultiple ? "Multiple choice" : "Single choice"} </span> </div> </div> </div> <DialogFooter className="gap-2 sm:gap-0"> <Button variant="outline" onClick={handleClose}> Create Another </Button> <Button onClick={handleClose}>Done</Button> </DialogFooter> </> ) : ( <> <DialogHeader> <DialogTitle className="flex items-center gap-2"> <BarChart3 className="h-5 w-5" /> Create Poll </DialogTitle> <DialogDescription> Ask a question and let people vote on options. </DialogDescription> </DialogHeader> <div className="space-y-4 py-4"> <div className="space-y-2"> <Label htmlFor="question">Question</Label> <Input id="question" placeholder="What would you like to ask?" value={question} onChange={(e) => setQuestion(e.target.value)} maxLength={280} /> <p className="text-xs text-muted-foreground text-right"> {question.length}/280 </p> </div> <div className="space-y-2"> <div className="flex items-center justify-between"> <Label>Options</Label> <span className="text-xs text-muted-foreground"> {options.length}/6 </span> </div> <div className="space-y-2"> {options.map((option, index) => ( <div key={option.id} className="flex items-center gap-2"> <GripVertical className="h-4 w-4 text-muted-foreground shrink-0 cursor-grab" /> <Input placeholder={`Option ${index + 1}`} value={option.text} onChange={(e) => updateOption(option.id, e.target.value)} maxLength={100} /> {options.length > 2 && ( <Button variant="ghost" size="icon" className="h-8 w-8 shrink-0" onClick={() => removeOption(option.id)} > <X className="h-4 w-4" /> </Button> )} </div> ))} </div> {options.length < 6 && ( <Button variant="outline" size="sm" className="w-full" onClick={addOption} > <Plus className="mr-2 h-4 w-4" /> Add Option </Button> )} </div> <Separator /> <div className="space-y-3"> <div className="flex items-center justify-between"> <Label htmlFor="duration">Poll Duration</Label> <Select value={duration} onValueChange={setDuration}> <SelectTrigger className="w-[120px]"> <SelectValue /> </SelectTrigger> <SelectContent> {durations.map((d) => ( <SelectItem key={d.value} value={d.value}> {d.label} </SelectItem> ))} </SelectContent> </Select> </div> <div className="flex items-center justify-between"> <div className="space-y-0.5"> <Label htmlFor="multiple">Allow multiple choices</Label> <p className="text-xs text-muted-foreground"> Voters can select more than one option </p> </div> <Switch id="multiple" checked={allowMultiple} onCheckedChange={setAllowMultiple} /> </div> <div className="flex items-center justify-between"> <div className="space-y-0.5"> <Label htmlFor="results">Show results</Label> <p className="text-xs text-muted-foreground"> Display votes before poll ends </p> </div> <Switch id="results" checked={showResults} onCheckedChange={setShowResults} /> </div> </div> {isValid && ( <> <Separator /> <div className="rounded-lg border bg-muted/30 p-3"> <div className="flex items-center gap-2 mb-2"> <Eye className="h-4 w-4 text-muted-foreground" /> <span className="text-sm font-medium">Preview</span> </div> <p className="text-sm mb-2">{question}</p> <div className="space-y-1.5"> {filledOptions.map((option) => ( <div key={option.id} className="flex items-center gap-2 text-sm" > <div className={cn( "h-4 w-4 border", allowMultiple ? "rounded" : "rounded-full" )} /> <span className="text-muted-foreground"> {option.text} </span> </div> ))} </div> <div className="flex items-center gap-2 mt-2"> <Badge variant="secondary" className="text-xs"> <Clock className="mr-1 h-3 w-3" /> {selectedDuration?.label} </Badge> <Badge variant="secondary" className="text-xs"> {allowMultiple ? "Multiple" : "Single"} choice </Badge> </div> </div> </> )} </div> <DialogFooter className="gap-2 sm:gap-0"> <Button variant="outline" onClick={handleClose}> Cancel </Button> <Button onClick={handleCreate} disabled={!isValid || isCreating}> {isCreating ? "Creating..." : "Create Poll"} </Button> </DialogFooter> </> )} </DialogContent> </Dialog> );}Installation
npx shadcn@latest add https://www.shadcn.io/registry/dialog-poll-create.jsonnpx shadcn@latest add https://www.shadcn.io/registry/dialog-poll-create.jsonpnpm dlx shadcn@latest add https://www.shadcn.io/registry/dialog-poll-create.jsonbunx shadcn@latest add https://www.shadcn.io/registry/dialog-poll-create.jsonRelated blocks you will also like
React Dialog Block Feedback Rating
User feedback collection
React Dialog Block Quick Note
Quick content capture
React Dialog Block Content Scheduler
Scheduled publishing
React Dialog Block Share Link
Share poll results
React Dialog Block Success Confirmation
Poll created confirmation
React Dialog Block Destructive Warning
Delete poll confirmation