fix(pilot): auto-scroll Resolve preview into view when opened

The ResolutionNotePreview popover renders inside TaskLane's
overflow-y-auto region at the bottom of the lane. On a 720px
viewport with the default question/check list expanded, the
popover lands below the visible scroll position — the engineer
clicks "Preview Resolve note", sees the button label flip to
"Showing", but no preview appears on screen.

Add a useEffect that calls scrollIntoView({block: 'nearest'}) on
the popover's outer div whenever `open` flips to true. block:
'nearest' scrolls just enough to make it visible without yanking
the lane to the top.

Discovered during Phase 9 QA. Reproduced at 1280x720; fix verified
visually in the same QA run (screenshots in
.gstack/qa-reports/phase9-*/).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-24 23:45:52 -04:00
parent 49c6c8fd00
commit 875bd924a9

View File

@@ -9,7 +9,7 @@
* Kind switches the labels, button colors, and confirm-CTA text — the
* underlying mechanics (preview fetch + edit + post) are identical.
*/
import { useState, useEffect } from 'react'
import { useRef, useState, useEffect } from 'react'
import { Loader2, RefreshCw, X, FileText, Pencil, Check, ArrowUpRight } from 'lucide-react'
import { MarkdownContent } from '@/components/ui/MarkdownContent'
import { cn } from '@/lib/utils'
@@ -43,6 +43,7 @@ export function ResolutionNotePreview({
const [refreshing, setRefreshing] = useState(false)
const [editing, setEditing] = useState(false)
const [draft, setDraft] = useState('')
const popoverRef = useRef<HTMLDivElement>(null)
// Keep the draft textarea in sync whenever fresh markdown arrives and we
// aren't in the middle of editing. Once the engineer edits, their changes
@@ -53,6 +54,15 @@ export function ResolutionNotePreview({
}
}, [preview?.markdown, editing])
// The popover renders at the bottom of TaskLane's scrollable region, which
// can leave it below the fold on smaller viewports. Scroll it into view
// whenever it opens so the engineer sees their preview immediately.
useEffect(() => {
if (open && popoverRef.current) {
popoverRef.current.scrollIntoView({ behavior: 'smooth', block: 'nearest' })
}
}, [open])
if (!open) return null
const label = kind === 'resolve' ? 'Resolution note' : 'Escalation handoff package'
@@ -73,7 +83,7 @@ export function ResolutionNotePreview({
}
return (
<div className="rounded-lg border border-default bg-elevated/30 mx-3 mb-3 overflow-hidden shadow-lg">
<div ref={popoverRef} className="rounded-lg border border-default bg-elevated/30 mx-3 mb-3 overflow-hidden shadow-lg">
<div className="flex items-center justify-between px-3 py-2 border-b border-default bg-bg-page">
<div className="flex items-center gap-2">
<KindIcon size={13} className={kind === 'resolve' ? 'text-success' : 'text-warning'} />