From 8dcf9d5e08132be958074930eb103a19b4fdfbf9 Mon Sep 17 00:00:00 2001 From: Andreas Knuth Date: Tue, 23 Jun 2026 17:44:38 -0500 Subject: [PATCH] changes --- app/components/Bracket.tsx | 58 +++++++++++++++++++++++++++----------- app/globals.css | 26 +++++++++++++++-- 2 files changed, 65 insertions(+), 19 deletions(-) diff --git a/app/components/Bracket.tsx b/app/components/Bracket.tsx index 78b1670..59ad9c6 100644 --- a/app/components/Bracket.tsx +++ b/app/components/Bracket.tsx @@ -1,20 +1,32 @@ "use client"; +import { useState, useCallback } from "react"; import { GroupTable, Match, Team, ThirdPlaceRow } from "@/lib/types"; import { ThirdAssignment, orderedRound } from "@/lib/bracket"; import { resolveBracket, ResolvedSide, ResolvedTie } from "@/lib/resolve-bracket"; import Flag from "./Flag"; +interface TipState { x: number; y: number; text: string } + function Side({ - s, prob, teams, -}: { s: ResolvedSide; prob?: number | null; teams: Team[] }) { + s, prob, teams, onShowTip, onHideTip, +}: { + s: ResolvedSide; prob?: number | null; teams: Team[]; + onShowTip: (text: string, x: number, y: number) => void; + onHideTip: () => void; +}) { const team = s.teamId ? teams.find((t) => t.id === s.teamId) : undefined; - // fix = ein echtes Team steht fest (nicht vorläufig). Eigene Klasse für klares Styling. const fix = s.teamId != null && !s.provisional; + const hasTip = !!s.tooltip; + return (
) => onShowTip(s.tooltip!, e.clientX, e.clientY), + onMouseMove: (e: React.MouseEvent) => onShowTip(s.tooltip!, e.clientX, e.clientY), + onMouseLeave: onHideTip, + } : {})} > {s.teamId ? ( @@ -35,12 +47,18 @@ function Side({ ); } -function Tie({ tie, teams, isFinal }: { tie: ResolvedTie; teams: Team[]; isFinal?: boolean }) { +function Tie({ + tie, teams, isFinal, onShowTip, onHideTip, +}: { + tie: ResolvedTie; teams: Team[]; isFinal?: boolean; + onShowTip: (text: string, x: number, y: number) => void; + onHideTip: () => void; +}) { return (
Spiel {tie.matchNumber}
- - + +
); } @@ -57,8 +75,6 @@ export default function Bracket({ const r32ByNum = new Map(r32Array.map((t) => [t.matchNumber, t])); - // Korrekte Baum-Reihenfolge: von der Wurzel (Finale) rekursiv die Quellen - // jeder Runde ermitteln, damit die Spalten vertikal ausgerichtet sind. const sfOrder = orderedRound([104]); const qfOrder = orderedRound(sfOrder); const r16Order = orderedRound(qfOrder); @@ -71,6 +87,10 @@ export default function Bracket({ const fin = later[104]; const third = later[103]; + const [tip, setTip] = useState(null); + const showTip = useCallback((text: string, x: number, y: number) => setTip({ x, y, text }), []); + const hideTip = useCallback(() => setTip(null), []); + return (
@@ -87,35 +107,35 @@ export default function Bracket({
Letzte 32
- {r32.map((t) => )} + {r32.map((t) => )}
Achtelfinale
- {r16.map((t) => )} + {r16.map((t) => )}
Viertelfinale
- {qf.map((t) => )} + {qf.map((t) => )}
Halbfinale
- {sf.map((t) => )} + {sf.map((t) => )}
Finale
- {fin && } + {fin && } {third && (
Spiel um Platz 3
- +
)}
@@ -131,6 +151,12 @@ export default function Bracket({ Platzhalter offen %-Werte: Polymarket-Wahrscheinlichkeit (falls verfügbar)
+ + {tip && ( +
+ {tip.text} +
+ )}
); -} \ No newline at end of file +} diff --git a/app/globals.css b/app/globals.css index e485afa..21eb0ba 100644 --- a/app/globals.css +++ b/app/globals.css @@ -190,9 +190,13 @@ table.standings { width: 100%; border-collapse: collapse; } } .bracket-banner .v { font-family: var(--font-mono); font-size: 12px; color: var(--turf); } .bracket-scroll { - max-height: calc(100vh - 260px); - overflow: auto; - padding-bottom: 8px; + margin-left: -20px; + margin-right: -20px; + padding-left: 20px; + padding-right: 20px; + overflow-x: hidden; + overflow-y: visible; + padding-bottom: 10px; scrollbar-gutter: stable; } .bracket { @@ -236,6 +240,22 @@ table.standings { width: 100%; border-collapse: collapse; } .legend span { display: inline-flex; align-items: center; gap: 6px; } .legend i { width: 12px; height: 12px; border-radius: 3px; display: inline-block; } +/* Tooltip im K.o.-Baum (position: fixed, damit overflow-x den Tooltip nicht abschneidet) */ +.kobaum-tip { + position: fixed; + z-index: 200; + pointer-events: none; + background: var(--bg-card); + border: 1px solid var(--line); + color: var(--ink); + font-family: var(--font-mono); + font-size: 12px; + padding: 6px 9px; + border-radius: var(--radius-sm); + white-space: nowrap; + box-shadow: 0 6px 20px rgba(0,0,0,0.4); +} + /* ---------- Zustände ---------- */ .notice { background: var(--bg-card); border: 1px solid var(--line);