--- // VoteWidget — the "which draft would you ship?" reader poll. // // Static markup only. The fetch to vote-service, the localStorage voter id, // and the click handler are task 16's job. The button toggle state lives // here so the layout matches the legacy page at first render. // // CSS hooks asserted by scripts/verify.mjs that must survive in the new // architecture: // .vote-widget — the outer wrapper // .vote-buttons — the button row // [aria-pressed=true] — the selected state // // The aria-label / role="group" on the inner cluster carries the state to // assistive tech — colour alone is not enough. This is asserted in the // task brief and lives in the same hook surface. interface VoteTally { original: number; improved: number; } interface Props { /** Skill id this widget votes for. */ skillId: string; /** Current vote tallies. Zeros render as "0 · 0%". */ tally: VoteTally; /** The current visitor's vote, if any. */ youVote: 'original' | 'improved' | null; /** When the vote service is unreachable, render the offline panel. */ unavailable?: boolean; } const { skillId, tally, youVote, unavailable = false } = Astro.props; const total = (tally.original || 0) + (tally.improved || 0); const share = (count: number) => (total ? Math.round((count / total) * 100) : 0); --- { unavailable ? (
READER VOTE

Voting is offline right now — the vote service is not configured or unreachable.

) : (
WHICH DRAFT WOULD YOU SHIP?

{youVote ? `You voted ${youVote === 'original' ? 'original' : 'improved draft'}. Pick the other option to change it.` : 'One vote per visitor, tracked by network source.'}

) }