Compare commits

..

No commits in common. "03579c9d119a1b3b875ebdb8971615d2c10e896a" and "b704a9c378962ff6cdda012f9e69a209079a1a05" have entirely different histories.

3 changed files with 12 additions and 89 deletions

View file

@ -5931,37 +5931,7 @@ Rettet til `grid grid-cols-3` (samme mønster som `NumberPicker` allerede
brukte). Alle FIRE andre `ChoiceRow`-bruk i filen (Kjønn,
Statistikk-nivå × 2) har nøyaktig 3 valg fra før — visuelt uendret for
dem, kun 6-alternativs-tilfellet endrer seg. Browserverifisert lys+mørk.
Committet (`17e4793`), deployet 2026-08-11 sammen med tagging-runden
(se ADR-063).
**Oppfølging 2026-08-11 — punkt 6 (ScrollFade) hadde TO reelle feil,
brukeren rapporterte via skjermbilde av Retning-steget:** "Den
sprettende ned-pilen fungerer ikke. Den ligger OPPÅ en annen nedpil."
1. `ResizeObserver` observerte scroll-BEHOLDEREN (`el`), ikke
innholdet. Beholderens boks-størrelse er fast (`flex-1`, bundet av
veiviserens layout) og endrer seg ALDRI når man bytter steg —
observeren fyrte derfor aldri når et steg med reelt overflow ble
vist, og `hasMore` ble stående på sin opprinnelige (ofte `false`)
verdi. Hintet virket rett og slett ikke der det trengtes, nøyaktig
det brukeren rapporterte. Rettet ved å observere en egen
`contentRef`-div rundt `children` i stedet for beholderen selv.
2. Fade-/piloverlayet er absolutt posisjonert over de siste 64px av
scroll-området uten noen garanti om at ekte innhold ikke havner
der. På Retning-steget (med fullt kølle-utvalg satt på testbrukeren
for å reprodusere brukerens eksakte rutenett) landet nettopp
"Kort"-knappens eget `ArrowDown`-ikon i den sonen — to piler oppå
hverandre, akkurat som beskrevet. Rettet med en usynlig 64px-buffer
(`SCROLL_FADE_HEIGHT_PX`) etter innholdet; `hasMore`-utregningen
trekker fra samme høyde så bufferen selv aldri gir et falskt
positivt hint på kort innhold.
Browserverifisert (samme reproduksjon: full kølle-liste for å tvinge
frem overflow): hintet vises korrekt (`opacity: 1`) når steget faktisk
overflower, forsvinner korrekt (`opacity: 0`) ved reell bunn, "Kort"
fullt synlig og klar av overlay-sonen ved skrolling, lys+mørk, ingen
konsollfeil. `tsc --noEmit` rent, 45/45 vitest grønt. Committet
(`ee91d03`).
Committet (`17e4793`), IKKE deployet ennå i skrivende stund.
---

View file

@ -10505,31 +10505,3 @@ Neste steg:
tidligere upubliserte ChoiceRow-fiksen (`17e4793`). Ren omstart,
ingen feil i containerloggene, ingen konsollfeil på
`https://teecup.golf/logg-inn` etter omstart.
73. **Fiks: ScrollFade-scrollhintet (fra ADR-062 punkt 6) hadde to
reelle feil — 2026-08-11, se oppfølgingsnotatet i ADR-062.**
Bruker sendte skjermbilde: "Den sprettende ned-pilen fungerer
ikke. Den ligger OPPÅ en annen nedpil."
To separate rotårsaker i samme `ScrollFade`-komponent
(`round-detail.tsx`): (1) `ResizeObserver` observerte scroll-
beholderen i stedet for innholdet — beholderens boksstørrelse er
fast, så observeren fyrte aldri ved stegbytte i veiviseren, og
hintet virket dermed rett og slett ikke på steg med reelt
overflow-innhold (som Retning-steget). Rettet ved å observere en
egen `contentRef`-div rundt innholdet i stedet for beholderen selv.
(2) Fade-/piloverlayet (absolutt posisjonert, siste 64px av
scroll-området) hadde ingen garanti mot å dekke ekte innhold —
på Retning-steget landet "Kort"-knappens eget `ArrowDown`-ikon i
akkurat den sonen, to piler oppå hverandre. Rettet med en usynlig
64px-buffer etter innholdet (`hasMore`-utregningen trekker fra
samme høyde for å unngå falske positiver på kort innhold).
**Verifisert:** Full scratch-stack, testbruker med fullt
kølle-utvalg for å reprodusere nøyaktig samme rutenett som i
brukerens skjermbilde. Bekreftet: hintet vises (`opacity: 1`) når
steget faktisk overflower, forsvinner (`opacity: 0`) ved reell
bunn, "Kort" fullt synlig og klar av overlay-sonen ved skrolling,
lys+mørk, ingen konsollfeil. `tsc --noEmit` rent, 45/45 vitest
grønt. `teecup_db` urørt (ren frontend-endring). Committet
(`ee91d03`), **ikke rullet ut ennå**.

View file

@ -6577,49 +6577,30 @@ function WizardSection({ title, children }: { title: string; children: React.Rea
// finnes mer innhold under fold-linjen -- og skjuler seg av seg selv idet man
// har scrollet helt ned. Fanger både resize og innholdsendringer (ulikt
// stat_level/par gir ulik høyde) via en ResizeObserver på selve scrollboksen.
// Høyden (px) på fade-/piloverlayet under -- MÅ matche spacer-diven sin
// h-16 og trekkes fra i hasMore-utregningen, se begrunnelse der.
const SCROLL_FADE_HEIGHT_PX = 64
function ScrollFade({ children, className }: { children: React.ReactNode; className?: string }) {
const scrollRef = useRef<HTMLDivElement>(null)
const contentRef = useRef<HTMLDivElement>(null)
const ref = useRef<HTMLDivElement>(null)
const [hasMore, setHasMore] = useState(false)
useEffect(() => {
const scrollEl = scrollRef.current
const contentEl = contentRef.current
if (!scrollEl || !contentEl) return
const el = ref.current
if (!el) return
const update = () => {
// Trekker fra spacer-divens egen høyde (samme SCROLL_FADE_HEIGHT_PX)
// i tillegg til 4px slingring -- uten dette ville "hasMore" blitt
// sant utelukkende fordi spaceren selv gjør scrollHeight større, selv
// når ALT ekte innhold allerede er synlig (falskt positivt hint).
setHasMore(scrollEl.scrollTop + scrollEl.clientHeight < scrollEl.scrollHeight - SCROLL_FADE_HEIGHT_PX - 4)
// 4px slingring: unngår at en sub-piksel-rest holder hintet i live
// når man i praksis ER nederst.
setHasMore(el.scrollTop + el.clientHeight < el.scrollHeight - 4)
}
update()
scrollEl.addEventListener("scroll", update, { passive: true })
// Observerer INNHOLDS-diven, IKKE scroll-beholderen selv --
// beholderens egen boks-størrelse er fast (flex-1, bundet av
// veiviserens layout), den endrer seg ALDRI når man bytter steg. Uten
// dette ble "hasMore" aldri regnet på nytt ved stegbytte -- den
// sprettende pilen dukket rett og slett ikke opp på steg som faktisk
// trengte scrolling (f.eks. "Retning"-steget med kølle-rutenett).
el.addEventListener("scroll", update, { passive: true })
const ro = new ResizeObserver(update)
ro.observe(contentEl)
ro.observe(el)
return () => {
scrollEl.removeEventListener("scroll", update)
el.removeEventListener("scroll", update)
ro.disconnect()
}
}, [])
return (
<div className="relative flex min-h-0 flex-1 flex-col">
<div ref={scrollRef} className={className}>
<div ref={contentRef}>{children}</div>
{/* Usynlig buffer, SAMME høyde som fade-/piloverlayet -- garanterer at
overlayet aldri dekker et ekte, interaktivt element (f.eks. en
retningsknapp med sin egen pil-ikon nederst i steget). Uten denne
kunne den sprettende pilen havne rett oppå en annen pil. */}
<div aria-hidden="true" className="h-16 shrink-0" />
<div ref={ref} className={className}>
{children}
</div>
{/* Rent dekorativt -- selve scrollingen er fullt mulig uten dette. */}
<div