diff options
| author | Claude <noreply@anthropic.com> | 2026-03-19 12:06:19 +0000 |
|---|---|---|
| committer | Claude <noreply@anthropic.com> | 2026-03-19 12:06:19 +0000 |
| commit | 99ce17ec1e73d876e0c16c1a3f0dde056f77b75c (patch) | |
| tree | bb642dad61ee3911bfa825d15ee6a228372b4abe /frontend/app/pages/TournamentPage.tsx | |
| parent | 4af220e63b173ca45c3f10d70731d2c6c73002f3 (diff) | |
| download | phperkaigi-2026-albatross-99ce17ec1e73d876e0c16c1a3f0dde056f77b75c.tar.gz phperkaigi-2026-albatross-99ce17ec1e73d876e0c16c1a3f0dde056f77b75c.tar.zst phperkaigi-2026-albatross-99ce17ec1e73d876e0c16c1a3f0dde056f77b75c.zip | |
Fix tournament bracket connector lines
The bracket connectors had two issues:
1. The center vertical line from each connector went to the wrong position,
not aligning with child connectors below
2. No vertical lines connected round-0 connectors to player cards
Redesign the Connector component to draw:
- A center stem going UP (connecting to parent round)
- A horizontal line (connecting left/right branches)
- Two legs going DOWN at half-center positions (connecting to children)
Also add vertical stem lines above each player card to bridge the gap
between round-0 connector legs and the player boxes.
https://claude.ai/code/session_01NKA6A2uWXJBRknZZcwMGCn
Diffstat (limited to 'frontend/app/pages/TournamentPage.tsx')
| -rw-r--r-- | frontend/app/pages/TournamentPage.tsx | 97 |
1 files changed, 92 insertions, 5 deletions
diff --git a/frontend/app/pages/TournamentPage.tsx b/frontend/app/pages/TournamentPage.tsx index afcb772..87836b2 100644 --- a/frontend/app/pages/TournamentPage.tsx +++ b/frontend/app/pages/TournamentPage.tsx @@ -20,6 +20,23 @@ function getBorderColor(match: TournamentMatch, userID?: number): string { return "border-gray-400"; } +function getBgColor(match: TournamentMatch, userID?: number): string { + if (!match.winner_user_id) { + return "bg-black"; + } + if (userID !== undefined && match.winner_user_id === userID) { + return "bg-pink-700"; + } + return "bg-gray-400"; +} + +function getWinnerBgColor(match: TournamentMatch | undefined): string { + if (!match?.winner_user_id) { + return "bg-black"; + } + return "bg-pink-700"; +} + function PlayerCard({ entry }: { entry: TournamentEntry | undefined }) { if (!entry) { return ( @@ -51,28 +68,44 @@ function Connector({ position, colSpan, match, + isTopRound, }: { position: number; colSpan: number; match: TournamentMatch | undefined; + isTopRound: boolean; }) { const leftHalf = colSpan / 2; const rightHalf = colSpan - leftHalf; - const leftColor = match + const leftBorderColor = match ? getBorderColor(match, match.player1?.user_id) : "border-black"; - const rightColor = match + const rightBorderColor = match ? getBorderColor(match, match.player2?.user_id) : "border-black"; + const leftBgColor = match + ? getBgColor(match, match.player1?.user_id) + : "bg-black"; + const rightBgColor = match + ? getBgColor(match, match.player2?.user_id) + : "bg-black"; + const winnerBg = getWinnerBgColor(match); return ( <div - className="grid h-8" style={{ gridColumn: `${position * colSpan + 1} / span ${colSpan}`, }} > + {/* Center stem going UP to parent round */} + {!isTopRound && ( + <div className="flex justify-center h-4"> + <div className={`w-0.5 ${winnerBg}`} /> + </div> + )} + + {/* Horizontal line */} <div className="grid" style={{ @@ -80,14 +113,35 @@ function Connector({ }} > <div - className={`border-t-4 border-r-2 ${leftColor}`} + className={`border-t-4 ${leftBorderColor}`} style={{ gridColumn: `1 / span ${leftHalf}` }} /> <div - className={`border-t-4 border-l-2 ${rightColor}`} + className={`border-t-4 ${rightBorderColor}`} style={{ gridColumn: `${leftHalf + 1} / span ${rightHalf}` }} /> </div> + + {/* Two legs going DOWN to child elements */} + <div + className="grid h-4" + style={{ + gridTemplateColumns: `repeat(${colSpan}, 1fr)`, + }} + > + <div + className="flex justify-center" + style={{ gridColumn: `1 / span ${leftHalf}` }} + > + <div className={`w-0.5 ${leftBgColor}`} /> + </div> + <div + className="flex justify-center" + style={{ gridColumn: `${leftHalf + 1} / span ${rightHalf}` }} + > + <div className={`w-0.5 ${rightBgColor}`} /> + </div> + </div> </div> ); } @@ -125,6 +179,7 @@ function TournamentBracket({ tournament }: { tournament: Tournament }) { position={pos} colSpan={colSpan} match={match} + isTopRound={round === num_rounds - 1} />, ); } @@ -141,6 +196,38 @@ function TournamentBracket({ tournament }: { tournament: Tournament }) { ); } + // Player stems row (vertical lines from round-0 connectors to player cards) + const playerStems: React.ReactNode[] = []; + for (let slot = 0; slot < bracket_size; slot++) { + const matchPos = Math.floor(slot / 2); + const match = matchByKey.get(`0-${matchPos}`); + const isPlayer1 = slot % 2 === 0; + const stemColor = match + ? getBgColor( + match, + isPlayer1 ? match.player1?.user_id : match.player2?.user_id, + ) + : "bg-black"; + playerStems.push( + <div + key={`stem-${slot}`} + className="flex justify-center h-4" + style={{ gridColumn: `${slot + 1} / span 1` }} + > + <div className={`w-0.5 ${stemColor}`} /> + </div>, + ); + } + rows.push( + <div + key="player-stems" + className="grid" + style={{ gridTemplateColumns: `repeat(${bracket_size}, 1fr)` }} + > + {playerStems} + </div>, + ); + // Player cards row (bottom) const playerCards: React.ReactNode[] = []; for (let slot = 0; slot < bracket_size; slot++) { |
