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 && (
)}
@@ -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);