From eebd6a43498163ae7eda80f43fec3fcb4fd4d352 Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Thu, 5 Feb 2026 19:11:11 +0000 Subject: [PATCH] Redesign demo page with Reddit-style voting UX and improve ELI5 section Demo page changes: - Reddit-style vote arrows on left (orange upvote, blue downvote) - More realistic governance proposals (treasury, moderation, research, security, town halls) - Prominent color-coded vote states and confirmation flow - Cleaner card layout with progress bars Homepage ELI5 section: - Three distinct colored cards (orange/blue/purple) for each mechanism - Icon badges for visual hierarchy - Clearer explanations with emphasized takeaways Co-Authored-By: Claude Opus 4.5 --- src/app/demo/page.tsx | 512 +++++++++++++++++++++++------------------- src/app/page.tsx | 93 +++++--- 2 files changed, 342 insertions(+), 263 deletions(-) diff --git a/src/app/demo/page.tsx b/src/app/demo/page.tsx index 501faef..6868e3c 100644 --- a/src/app/demo/page.tsx +++ b/src/app/demo/page.tsx @@ -34,9 +34,9 @@ interface DemoProposal { const initialProposals: DemoProposal[] = [ { id: 1, - title: "Add dark mode to the dashboard", - description: "Implement a dark theme option for better nighttime usage", - score: 45, + title: "Allocate 15% of treasury to ecosystem grants program", + description: "Fund community developers building tools and integrations for the ecosystem over the next 6 months", + score: 72, userVote: 0, pendingVote: 0, stage: "ranking", @@ -45,9 +45,9 @@ const initialProposals: DemoProposal[] = [ }, { id: 2, - title: "Weekly community calls", - description: "Host weekly video calls to discuss proposals and progress", - score: 43, + title: "Establish a community moderation council", + description: "Elect 7 members to handle disputes, enforce guidelines, and maintain community standards", + score: 58, userVote: 0, pendingVote: 0, stage: "ranking", @@ -56,9 +56,31 @@ const initialProposals: DemoProposal[] = [ }, { id: 3, - title: "Create a mobile app", - description: "Build native iOS and Android apps for on-the-go voting", - score: 44, + title: "Partner with University research lab for governance study", + description: "Collaborate with academic researchers to analyze and improve our decision-making processes", + score: 41, + userVote: 0, + pendingVote: 0, + stage: "ranking", + yesVotes: 0, + noVotes: 0, + }, + { + id: 4, + title: "Create bounty program for security audits", + description: "Reward external security researchers who identify vulnerabilities in our smart contracts", + score: 35, + userVote: 0, + pendingVote: 0, + stage: "ranking", + yesVotes: 0, + noVotes: 0, + }, + { + id: 5, + title: "Host quarterly virtual town halls", + description: "Regular video conferences for community updates, Q&A sessions, and open discussion", + score: 23, userVote: 0, pendingVote: 0, stage: "ranking", @@ -173,7 +195,7 @@ export default function DemoPage() { const rankingProposals = proposals .filter((p) => p.stage === "ranking") - .sort((a, b) => b.score - a.score); // Sort by score descending + .sort((a, b) => b.score - a.score); const votingProposals = proposals.filter((p) => p.stage === "voting"); return ( @@ -184,25 +206,26 @@ export default function DemoPage() {

Try Quadratic Proposal Ranking

- Experience how rVote works without creating an account. Click the arrows - to add votes and see the quadratic cost increase in real-time. + Experience how rVote works without creating an account. Click the vote + arrows to rank proposals—watch how quadratic costs scale in real-time.

{/* Credits display */} - +
- - {credits} credits + + {credits} + credits
- - Max vote weight: {maxWeight} - + + Max vote: ±{maxWeight} +
- @@ -211,14 +234,14 @@ export default function DemoPage() { {/* Quadratic cost explainer */} - - + + - - Quadratic Ranking Cost + + Quadratic Voting Cost - Click the arrows to add votes. Each additional vote costs more! + Each additional vote costs exponentially more credits @@ -226,174 +249,203 @@ export default function DemoPage() { {[1, 2, 3, 4, 5].map((w) => (
-
{w}
-
vote{w > 1 ? "s" : ""}
-
{w * w} credits
+
{w > 0 ? "+" : ""}{w}
+
vote{w > 1 ? "s" : ""}
+
{w * w}¢
))}
-

- This prevents wealthy voters from dominating. Spreading votes across - proposals is more efficient than concentrating them. -

{/* Ranking stage */} -
-
- Stage 1 -

Ranking

+
+
+ Stage 1 +

Quadratic Ranking

- Proposals need +100 to advance + Score +100 to advance →
- {rankingProposals.map((proposal, index) => { - const hasPending = proposal.pendingVote !== 0; - const hasVoted = proposal.userVote !== 0; - const pendingCost = proposal.pendingVote * proposal.pendingVote; - const previewScore = proposal.score + proposal.pendingVote; - const rank = index + 1; +
+ {rankingProposals.map((proposal) => { + const hasPending = proposal.pendingVote !== 0; + const hasVoted = proposal.userVote !== 0; + const pendingCost = proposal.pendingVote * proposal.pendingVote; + const previewScore = proposal.score + proposal.pendingVote; + const progressPercent = Math.min((proposal.score / 100) * 100, 100); + const previewPercent = Math.min((previewScore / 100) * 100, 100); - return ( - -
- {/* Rank indicator */} -
- #{rank} -
-
- {/* Up arrow */} - + return ( + 0 + ? "ring-2 ring-orange-500/50 bg-orange-500/5" + : "ring-2 ring-blue-500/50 bg-blue-500/5" + : hasVoted + ? proposal.userVote > 0 + ? "bg-orange-500/5" + : "bg-blue-500/5" + : "" + }`} + > +
+ {/* Reddit-style vote column */} +
+ {/* Upvote button */} + - {/* Score display */} - 0 - ? "bg-primary text-primary-foreground" - : "bg-destructive text-destructive-foreground" - : "" - }`} - > - {hasPending ? ( - - {proposal.score} - - {previewScore} - - ) : ( - proposal.score - )} - + ? "text-orange-500" + : "text-blue-500" + : hasVoted + ? proposal.userVote > 0 + ? "text-orange-500" + : "text-blue-500" + : "text-foreground" + }`}> + {hasPending ? previewScore : proposal.score} +
- {/* Down arrow */} - + {/* Downvote button */} + +
- {/* Pending vote info */} - {hasPending && ( -
- - {proposal.pendingVote > 0 ? "+" : ""}{proposal.pendingVote} vote{Math.abs(proposal.pendingVote) !== 1 ? "s" : ""} - - - {pendingCost} credit{pendingCost !== 1 ? "s" : ""} - -
- - + {/* Proposal content */} +
+

{proposal.title}

+

+ {proposal.description} +

+ + {/* Progress bar */} +
+
+ Progress to voting stage + 0 ? "text-orange-500" : "text-blue-500") : ""}> + {hasPending ? previewScore : proposal.score}/100 + +
+
+
0 + ? "bg-orange-500" + : "bg-blue-500" + : "bg-primary" + }`} + style={{ width: `${hasPending ? previewPercent : progressPercent}%` }} + />
- )} - {/* Existing vote display */} - {hasVoted && !hasPending && ( - - Your vote: {proposal.userVote > 0 ? "+" : ""}{proposal.userVote} - - )} -
- -
-

{proposal.title}

-

- {proposal.description} -

-
-
- Progress to voting - {hasPending ? previewScore : proposal.score}/100 -
- + {/* Vote status / pending confirmation */} + {(hasPending || hasVoted) && ( +
+ {hasPending ? ( + <> + 0 + ? "border-orange-500/50 text-orange-600 bg-orange-500/10" + : "border-blue-500/50 text-blue-600 bg-blue-500/10" + } + > + {proposal.pendingVote > 0 ? "+" : ""}{proposal.pendingVote} vote = {pendingCost} credits + + + + + ) : hasVoted && ( + 0 + ? "bg-orange-500/20 text-orange-600 border-orange-500/30" + : "bg-blue-500/20 text-blue-600 border-blue-500/30" + } + > + You voted: {proposal.userVote > 0 ? "+" : ""}{proposal.userVote} + + )} +
+ )}
-
- - ); - })} + + ); + })} +
- {/* Voting stage - only show if proposals have been promoted */} + {/* Voting stage */} {votingProposals.length > 0 && ( -
-
- Stage 2 +
+
+ Stage 2

Pass/Fail Voting

One member = one vote @@ -401,79 +453,79 @@ export default function DemoPage() {
{votingProposals.map((proposal) => { - const total = proposal.yesVotes + proposal.noVotes; - const yesPercent = total > 0 ? (proposal.yesVotes / total) * 100 : 50; - return ( - - -
- {proposal.title} -
- - 6 days left + const total = proposal.yesVotes + proposal.noVotes; + const yesPercent = total > 0 ? (proposal.yesVotes / total) * 100 : 50; + return ( + + +
+ {proposal.title} +
+ + 6 days left +
-
- {proposal.description} - - - {/* Vote bar */} -
-
-
-
+ {proposal.description} + + + {/* Vote bar */} +
+
+
+
+
+
+ + {proposal.yesVotes} Yes ({Math.round(yesPercent)}%) + + + {proposal.noVotes} No ({Math.round(100 - yesPercent)}%) + +
-
- - {proposal.yesVotes} Yes ({Math.round(yesPercent)}%) - - - {proposal.noVotes} No ({Math.round(100 - yesPercent)}%) - -
-
- {/* Vote buttons */} -
- - - -
- - - ); + {/* Vote buttons */} +
+ + + +
+ + + ); })}
)} {/* CTA */} - +

Ready to try it for real?

@@ -481,7 +533,7 @@ export default function DemoPage() { You'll get 50 credits to start and earn 10 more each day.

-