Flytende "Registrer score" når banekartet er utvidet

V0-eksport integrert: RegisterScoreButton gjenbrukt i normal flyt
(kollapset) og som fixed bottom-pinnet knapp (utvidet), med gradient-
scrim, skygge, safe-area-inset-bottom, og aria-hidden/pointer-events-none
korrekt håndtert når skjult. Se CHANGELOG.md #140. Ikke rullet ut ennå.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Erol Haagenrud 2026-08-20 08:25:11 +02:00
parent 7426984e67
commit ee31b2d00b
2 changed files with 87 additions and 9 deletions

View file

@ -13513,3 +13513,35 @@ Neste steg:
**Ikke rullet ut ennå** -- venter på bekreftelse fra bruker (og på
V0-eksporten for punkt 1 før neste utrullingsrunde, om bruker ønsker
å samle dem).
140. **Flytende "Registrer score" når banekartet er utvidet, 2026-08-20.**
Direkte oppfølging av #139 sitt punkt 1 -- V0-eksporten kom inn samme
dag. Claude skrev prompten, bruker kjørte den og lastet opp
(`floating-register-score.tsx`).
`round-detail.tsx`: ny liten `RegisterScoreButton`-komponent (samme
visuelle knapp, nå gjenbrukt to steder). I `PlayerHoleCards`:
- Banekart kollapset (standard): knappen ligger i normal side-flyt,
uendret oppførsel fra før.
- Banekart utvidet: knappen er i stedet `fixed inset-x-0 bottom-0`,
festet til viewportets bunn uansett scroll-posisjon i det høye
diagrammet. Gradient-scrim (`bg-gradient-to-t from-background`) +
skygge løfter den visuelt over innholdet under. `aria-hidden` +
`pointer-events-none` når skjult/i overgang -- blokkerer aldri klikk
på innhold bak. `env(safe-area-inset-bottom)` i bunnpaddingen for
gest-navigasjon. Samme klikk-handling (`scrollIntoView` til
spillerlisten) begge steder -- kun plasseringen er ny.
- Liten spacer (`h-20`) lagt til nederst når kartet er utvidet, slik
at siste innhold (kommentarfeltet) kan scrolles fritt for den
flytende knappen i stedet for å bli permanent skjult bak den.
**Verifisert i scratch:** mocket `RoundDetail` med ekte
tee/green-koordinater + stubbet GPS (samme oppsett som #139).
Bekreftet: kollapset ser uendret ut, utvidet gjør knappen flytende og
forblir synlig ved scroll, kun ÉN "Registrer score"-knapp i a11y-treet
om gangen (aldri to samtidig), klikk hopper fortsatt korrekt til
spillerlisten (med riktig `scroll-mt-28` fra #139), ingen blokkering
av klikk på innhold bak den flytende sonen. Sjekket lys og mørk modus.
`tsc --noEmit` rent.
**Ikke rullet ut ennå** -- venter på bekreftelse fra bruker.

View file

@ -6634,6 +6634,23 @@ function sumForPlayer(list: ApiHole[] | undefined, numbers: number[]): { strokes
// Trykk åpner SAMME eksisterende fullskjerm-veiviser som før (onOpenEntry)
// -- selve registreringsvinduet er bevisst IKKE rørt av denne rundens
// V0-prompt.
// "Registrer score" -- samme knapp, to plasseringer (se PlayerHoleCards):
// i normal side-flyt når banekartet er kollapset, flytende festet nederst
// på skjermen når det er utvidet (V0-eksport, 2026-08-20, brukerønske --
// det utvidede diagrammet kunne dytte knappen langt utenfor synlig område).
function RegisterScoreButton({ onClick }: { onClick: () => void }) {
return (
<button
type="button"
onClick={onClick}
className="flex h-14 w-full items-center justify-center gap-2 rounded-2xl bg-primary text-base font-extrabold text-primary-foreground shadow-sm transition-colors hover:brightness-105 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
>
Registrer score
<ArrowDown aria-hidden="true" className="size-5" />
</button>
)
}
function PlayerHoleCards({
roundId,
players,
@ -6835,15 +6852,16 @@ function PlayerHoleCards({
{/* Alltid synlig, tydelig snarvei rett til score-registreringen under
-- samme grunn som knappen over: en førstegangsbruker skal ikke
måtte oppdage ved et tilfeldig sveip at dette finnes. */}
<button
type="button"
onClick={() => playerListRef.current?.scrollIntoView({ behavior: "smooth", block: "start" })}
className="flex h-14 w-full items-center justify-center gap-2 rounded-2xl bg-primary text-base font-extrabold text-primary-foreground shadow-sm transition-colors hover:brightness-105 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
>
Registrer score
<ArrowDown aria-hidden="true" className="size-5" />
</button>
måtte oppdage ved et tilfeldig sveip at dette finnes. KUN i normal
side-flyt når banekartet er kollapset -- utvidet blir den samme
knappen flytende i stedet, se render-stedet nederst i denne
komponenten (brukerønske 2026-08-20: det utvidede diagrammet
kunne dytte knappen helt utenfor synlig skjermbilde). */}
{!mapExpanded && (
<RegisterScoreButton
onClick={() => playerListRef.current?.scrollIntoView({ behavior: "smooth", block: "start" })}
/>
)}
{isTwoSided && sides.length === 2 && (
<div className="flex items-center justify-center gap-2 rounded-2xl border border-border bg-card px-4 py-2.5 text-sm">
@ -7083,6 +7101,34 @@ function PlayerHoleCards({
onClose={() => setHistoryPlayerId(null)}
/>
)}
{/* Flytende "Registrer score" (V0-eksport, 2026-08-20) -- kun mens
banekartet er utvidet. `fixed` posisjonerer mot selve viewporten
(ingen ancestor her setter transform/filter, det er trygt),
gradient-scrim + skygge løfter den visuelt over innholdet under,
`env(safe-area-inset-bottom)` unngår at den klemmes helt inntil
kanten telefoner med gest-navigasjon. `pointer-events-none`
selve scrim-sonen når skjult/i overgang, slik at den aldri
blokkerer klikk innhold bak. */}
<div
aria-hidden={!mapExpanded}
className={cn(
"fixed inset-x-0 bottom-0 z-30 px-5 pb-[calc(0.875rem+env(safe-area-inset-bottom))] pt-8 transition-all duration-300 ease-out",
"bg-gradient-to-t from-background via-background/90 to-transparent",
mapExpanded ? "translate-y-0 opacity-100" : "pointer-events-none translate-y-full opacity-0",
)}
>
<div className={cn("mx-auto w-full max-w-3xl", mapExpanded ? "pointer-events-auto" : "pointer-events-none")}>
<div className="rounded-2xl shadow-xl shadow-black/25">
<RegisterScoreButton
onClick={() => playerListRef.current?.scrollIntoView({ behavior: "smooth", block: "start" })}
/>
</div>
</div>
</div>
{/* Gir siste innhold på siden rom til å scrolle klar av den flytende
knappen i stedet for å bli permanent skjult bak den. */}
{mapExpanded && <div aria-hidden="true" className="h-20" />}
</div>
)
}