Post Poll
deso-ui/post-pollFreeBlock
A component for displaying and voting on polls within a post.
Install it
npx shadcn@latest add https://ui.deso.com/r/post-poll.jsonSource
1'use client';23import React, { useState, useEffect } from 'react';4import { cn } from '@/lib/utils/deso';5import { CheckCircle } from 'lucide-react';6import NumberFlow, { continuous } from '@number-flow/react'; // Import NumberFlow78export interface PollOption {9 text: string;10}1112export interface PostPollProps {13 options: PollOption[];14 votes: number[];15 totalVotes: number;16 userVotedIndex: number | null;17 onVote: (index: number) => void;18}1920export const PostPoll: React.FC<PostPollProps> = ({21 options,22 votes,23 totalVotes,24 userVotedIndex,25 onVote,26}) => {27 const [animatedPercentages, setAnimatedPercentages] = useState<number[]>(28 Array(options.length).fill(0)29 );3031 useEffect(() => {32 if (userVotedIndex !== null) {33 const newPercentages = options.map((_, index) =>34 totalVotes > 0 ? (votes[index] / totalVotes) * 100 : 035 );36 // A timeout to ensure the transition is applied after the component has rendered.37 const timer = setTimeout(() => {38 setAnimatedPercentages(newPercentages);39 }, 100);40 return () => clearTimeout(timer);41 }42 }, [userVotedIndex, options, votes, totalVotes]);4344 const handleVote = (index: number) => {45 if (userVotedIndex === null) {46 onVote(index);47 }48 };4950 return (51 <div className="mt-4 space-y-2">52 {options.map((option, index) => {53 if (userVotedIndex !== null) {54 // Voted state55 const percentage =56 totalVotes > 0 ? (votes[index] / totalVotes) * 100 : 0;57 const isUserChoice = userVotedIndex === index;5859 return (60 <div61 key={index}62 className="relative flex items-center justify-between overflow-hidden rounded-lg border border-border bg-background p-3 text-foreground"63 >64 <div65 className="absolute left-0 top-0 h-full bg-muted transition-all duration-700 ease-out"66 style={{ width: `${animatedPercentages[index] || 0}%` }}67 />68 <div className="relative z-10 flex w-full items-center justify-between">69 <div className="flex items-center gap-2">70 <span>{option.text}</span>71 {isUserChoice && (72 <CheckCircle className="h-5 w-5 text-green-500" />73 )}74 </div>75 <span className="font-semibold">76// … truncated
Files it writes
More from deso-ui
All 47 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Action Menuaction-menu | deso-ui | Blocks | Free | no deps | |
| Confirmation Dialogconfirmation-dialog | deso-ui | Blocks | Free | no deps | |
| Copy Buttoncopy-button | deso-ui | Blocks | Free | no deps | |
| Editoreditor | deso-ui | Blocks | Free | no deps | |
| Editor Emoji Pickereditor-emoji-picker | deso-ui | Blocks | Free | no deps | |
| Editor Markdowneditor-markdown | deso-ui | Blocks | Free | no deps | |
| Editor Uploadeditor-upload | deso-ui | Blocks | Free | no deps | |
| Feed Listfeed-list | deso-ui | Blocks | Free | no deps |
