Add wheel segment colors and hover labels
All checks were successful
Deploy Sokko G / deploy (push) Successful in 18s

This commit is contained in:
Shinuwa 2026-09-15 19:19:09 +02:00
parent a4268dac54
commit 418921934b
3 changed files with 87 additions and 2 deletions

View file

@ -12,6 +12,7 @@ export function WheelRandomizer({ data, textContent, onChange, context }) {
const [drawing, setDrawing] = useState(false); const [drawing, setDrawing] = useState(false);
const [displayResults, setDisplayResults] = useState(data.results); const [displayResults, setDisplayResults] = useState(data.results);
const [entriesText, setEntriesText] = useState(""); const [entriesText, setEntriesText] = useState("");
const [hoveredSegment, setHoveredSegment] = useState(null);
const { queueTimer, clearTimers: clearWheelTimers } = useTimeoutQueue(); const { queueTimer, clearTimers: clearWheelTimers } = useTimeoutQueue();
const skipWheelSyncRef = useRef(false); const skipWheelSyncRef = useRef(false);
const segments = useMemo(() => buildWheelSegments(data.entries), [data.entries]); const segments = useMemo(() => buildWheelSegments(data.entries), [data.entries]);
@ -117,9 +118,26 @@ export function WheelRandomizer({ data, textContent, onChange, context }) {
<span className="randomizer-wheel-spacer" aria-hidden="true" /> <span className="randomizer-wheel-spacer" aria-hidden="true" />
<div className="randomizer-wheel-center"> <div className="randomizer-wheel-center">
<span className="randomizer-wheel-pointer" aria-hidden="true" /> <span className="randomizer-wheel-pointer" aria-hidden="true" />
<span className={`randomizer-wheel-tooltip ${hoveredSegment ? "is-visible" : ""}`} aria-live="polite">
{hoveredSegment || ""}
</span>
<svg className={`randomizer-wheel ${spinning ? "is-spinning" : ""}`} viewBox="0 0 100 100" style={{ "--randomizer-wheel-rotation": `${rotation}deg` }}> <svg className={`randomizer-wheel ${spinning ? "is-spinning" : ""}`} viewBox="0 0 100 100" style={{ "--randomizer-wheel-rotation": `${rotation}deg` }}>
{segments.length ? segments.map((segment) => ( {segments.length ? segments.map((segment) => (
<path key={segment.entry.id} d={describeWheelArc(segment.startAngle, segment.endAngle)} fill={WHEEL_COLORS[segment.index % WHEEL_COLORS.length]} /> <path
className="randomizer-wheel-segment"
key={segment.entry.id}
d={describeWheelArc(segment.startAngle, segment.endAngle)}
fill={WHEEL_COLORS[segment.index % WHEEL_COLORS.length]}
tabIndex="0"
role="img"
aria-label={segment.entry.label}
onBlur={() => setHoveredSegment(null)}
onFocus={() => setHoveredSegment(segment.entry.label)}
onMouseEnter={() => setHoveredSegment(segment.entry.label)}
onMouseLeave={() => setHoveredSegment(null)}
>
<title>{segment.entry.label}</title>
</path>
)) : <circle cx="50" cy="50" r="48" fill="rgba(139, 92, 246, 0.18)" />} )) : <circle cx="50" cy="50" r="48" fill="rgba(139, 92, 246, 0.18)" />}
<circle cx="50" cy="50" r="12" fill="rgba(7, 10, 24, 0.92)" /> <circle cx="50" cy="50" r="12" fill="rgba(7, 10, 24, 0.92)" />
</svg> </svg>

View file

@ -1,5 +1,30 @@
// Rôle : regroupe les helpers UI et animation purs du Randomizer. // Rôle : regroupe les helpers UI et animation purs du Randomizer.
export const WHEEL_COLORS = ["#8b5cf6", "#f6c453", "#22d3ee", "#d946ef", "#6366f1", "#22c55e"]; export const WHEEL_COLORS = [
"#8b5cf6",
"#f6c453",
"#22d3ee",
"#d946ef",
"#6366f1",
"#22c55e",
"#f97316",
"#ec4899",
"#14b8a6",
"#eab308",
"#3b82f6",
"#f43f5e",
"#84cc16",
"#a855f7",
"#06b6d4",
"#fb7185",
"#10b981",
"#c084fc",
"#38bdf8",
"#f59e0b",
"#4ade80",
"#818cf8",
"#f472b6",
"#2dd4bf"
];
export const DRAW_PAUSE_MS = 500; export const DRAW_PAUSE_MS = 500;
export const DICE_ROLL_DELAYS = [62, 70, 82, 98, 120, 148, 182, 224, 276, 338, 410]; export const DICE_ROLL_DELAYS = [62, 70, 82, 98, 120, 148, 182, 224, 276, 338, 410];
export const TEAM_REEL_DELAYS = [58, 66, 78, 94, 116, 144, 180, 226, 286, 360]; export const TEAM_REEL_DELAYS = [58, 66, 78, 94, 116, 144, 180, 226, 286, 360];

View file

@ -38,6 +38,34 @@
filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.42)); filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.42));
} }
.randomizer-wheel-tooltip {
position: absolute;
top: 0;
left: 50%;
z-index: 3;
max-width: min(100%, 210px);
overflow: hidden;
padding: 5px 10px;
border: 1px solid rgba(246, 196, 83, 0.34);
border-radius: var(--radius-pill);
background: rgba(7, 10, 24, 0.94);
box-shadow: 0 12px 28px rgba(0, 0, 0, 0.28);
color: var(--color-text-primary);
font-size: var(--font-size-xs);
font-weight: 900;
line-height: 1.2;
opacity: 0;
pointer-events: none;
text-overflow: ellipsis;
transform: translate(-50%, -82%);
transition: opacity var(--duration-fast) var(--ease-standard);
white-space: nowrap;
}
.randomizer-wheel-tooltip.is-visible {
opacity: 1;
}
.randomizer-wheel { .randomizer-wheel {
width: min(100%, 190px); width: min(100%, 190px);
aspect-ratio: 1; aspect-ratio: 1;
@ -110,6 +138,20 @@
stroke-width: 0.8; stroke-width: 0.8;
} }
.randomizer-wheel-segment {
cursor: help;
outline: none;
transition:
filter var(--duration-fast) var(--ease-standard),
opacity var(--duration-fast) var(--ease-standard);
}
.randomizer-wheel-segment:hover,
.randomizer-wheel-segment:focus-visible {
filter: brightness(1.16);
opacity: 0.94;
}
.randomizer-wheel-form .randomizer-entry-form { .randomizer-wheel-form .randomizer-entry-form {
padding: 0; padding: 0;
} }