1
0
Fork 0

feat(poker): move action toolbar below the felt on narrow screens

Co-authored-by: Sisyphus <sisyphus@ohmyopencode.dev>
This commit is contained in:
Jason Fraley 2026-09-14 19:25:34 -04:00
parent 90070abb2e
commit df90a34c99
3 changed files with 41 additions and 3 deletions

View file

@ -1893,6 +1893,15 @@
font-size: 0.7rem; font-size: 0.7rem;
} }
/* Below-felt variant: on narrow screens the toolbar renders in normal flow
under the felt because the felt's overflow-hidden clips the overlay row
there; static positioning cancels the overlay anchor. */
.poker-action-toolbar-below {
position: static;
transform: none;
width: min(30rem, 100%);
}
.poker-action-toolbar .poker-betting-controls-compact { .poker-action-toolbar .poker-betting-controls-compact {
width: 100%; width: 100%;
gap: 0.4rem; gap: 0.4rem;

View file

@ -11,12 +11,14 @@ interface PokerActionToolbarProps {
readonly snapshot: SeatedSnapshot; readonly snapshot: SeatedSnapshot;
readonly onSnapshot: (snapshot: PokerSnapshot) => void; readonly onSnapshot: (snapshot: PokerSnapshot) => void;
readonly onActionFeedback: () => void; readonly onActionFeedback: () => void;
readonly below?: boolean;
} }
export function PokerActionToolbar({ export function PokerActionToolbar({
snapshot, snapshot,
onSnapshot, onSnapshot,
onActionFeedback, onActionFeedback,
below = false,
}: PokerActionToolbarProps) { }: PokerActionToolbarProps) {
const view = snapshot.you; const view = snapshot.you;
@ -25,14 +27,20 @@ export function PokerActionToolbar({
if (!view.yourTurn) { if (!view.yourTurn) {
const actingPlayer = view.players.find((player) => player.seatId === view.toActSeat); const actingPlayer = view.players.find((player) => player.seatId === view.toActSeat);
return ( return (
<div className="poker-action-toolbar poker-action-toolbar-waiting" role="status"> <div
className={`poker-action-toolbar poker-action-toolbar-waiting${below ? " poker-action-toolbar-below" : ""}`}
role="status"
>
{actingPlayer ? `Waiting for ${actingPlayer.name}` : "Waiting for the table"} {actingPlayer ? `Waiting for ${actingPlayer.name}` : "Waiting for the table"}
</div> </div>
); );
} }
return ( return (
<div className="poker-action-toolbar" aria-label="Poker actions"> <div
className={`poker-action-toolbar${below ? " poker-action-toolbar-below" : ""}`}
aria-label="Poker actions"
>
<BettingControls <BettingControls
tableId={snapshot.tableId} tableId={snapshot.tableId}
snapshotVersion={snapshot.version} snapshotVersion={snapshot.version}

View file

@ -1,5 +1,6 @@
"use client"; "use client";
import { useEffect, useState } from "react";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import type { Card, PublicPlayerView } from "@/lib/minigames/poker"; import type { Card, PublicPlayerView } from "@/lib/minigames/poker";
import type { PokerSnapshot } from "@/app/(frontend)/minigames/poker/actions"; import type { PokerSnapshot } from "@/app/(frontend)/minigames/poker/actions";
@ -110,6 +111,17 @@ export function PokerFeltCanvas({
const viewerPopups = popupsForSeat(view.viewerSeat); const viewerPopups = popupsForSeat(view.viewerSeat);
const tableAnnouncements = popups.filter((popup) => popup.tone === "leave"); const tableAnnouncements = popups.filter((popup) => popup.tone === "leave");
// Narrow screens render the action toolbar below the felt in flow: the
// overlay row is wider than the felt there and the felt clips it.
const [toolbarBelow, setToolbarBelow] = useState(false);
useEffect(() => {
const query = window.matchMedia("(max-width: 640px)");
const update = () => setToolbarBelow(query.matches);
update();
query.addEventListener("change", update);
return () => query.removeEventListener("change", update);
}, []);
return ( return (
<div className="poker-table-stage"> <div className="poker-table-stage">
<div <div
@ -252,7 +264,7 @@ export function PokerFeltCanvas({
</div> </div>
)} )}
{!spectator && ( {!spectator && !toolbarBelow && (
<PokerActionToolbar <PokerActionToolbar
snapshot={snapshot} snapshot={snapshot}
onSnapshot={onSnapshot} onSnapshot={onSnapshot}
@ -287,6 +299,15 @@ export function PokerFeltCanvas({
)} )}
</div> </div>
{!spectator && toolbarBelow && (
<PokerActionToolbar
snapshot={snapshot}
onSnapshot={onSnapshot}
onActionFeedback={onActionFeedback}
below
/>
)}
<PokerActionConsole <PokerActionConsole
snapshot={snapshot} snapshot={snapshot}
handLabel={handLabel} handLabel={handLabel}