Skip to content

Commit 9e2ad1f

Browse files
committed
fix(docs): preserve Ask Sim chat state across close/reopen
The panel split unmounted AskAIPanel entirely on close, discarding useChat's message state - reopening always started an empty conversation, unlike the original single-component layout where useChat lived in a component that never unmounted. Fixed by keeping the panel mounted (via a hasOpened flag that never resets) once first opened, and having the panel itself return null when closed rather than being conditionally removed from the tree by its parent - hooks still run every render, so useChat's state persists across visibility toggles. The dynamic import still only fires on the first open, so the initial-load win is unchanged. Verified via a real click-through (open, type, close, reopen): input persists correctly, and the panel chunk still has zero network requests on initial page load. Performance unchanged at 75.
1 parent 8a4a80b commit 9e2ad1f

2 files changed

Lines changed: 31 additions & 18 deletions

File tree

apps/docs/components/ai/ask-ai-panel.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,11 @@ function getText(parts: ReadonlyArray<{ type: string; [key: string]: unknown }>)
4343
interface AskAIPanelProps {
4444
/** Active docs locale, forwarded so retrieval is scoped to the reader's language. */
4545
locale: string
46+
open: boolean
4647
onClose: () => void
4748
}
4849

49-
export function AskAIPanel({ locale, onClose }: AskAIPanelProps) {
50+
export function AskAIPanel({ locale, open, onClose }: AskAIPanelProps) {
5051
const [input, setInput] = useState('')
5152
const scrollRef = useRef<HTMLDivElement>(null)
5253
const textareaRef = useRef<HTMLTextAreaElement>(null)
@@ -63,6 +64,7 @@ export function AskAIPanel({ locale, onClose }: AskAIPanelProps) {
6364
}
6465

6566
useEffect(() => {
67+
if (!open) return
6668
textareaRef.current?.focus()
6769
const handleKeyDown = (event: KeyboardEvent) => {
6870
if (event.key === 'Escape') {
@@ -71,11 +73,12 @@ export function AskAIPanel({ locale, onClose }: AskAIPanelProps) {
7173
}
7274
document.addEventListener('keydown', handleKeyDown)
7375
return () => document.removeEventListener('keydown', handleKeyDown)
74-
}, [])
76+
}, [open])
7577

7678
useEffect(() => {
79+
if (!open) return
7780
scrollRef.current?.scrollTo({ top: scrollRef.current.scrollHeight })
78-
}, [])
81+
}, [open])
7982

8083
useEffect(() => {
8184
scrollRef.current?.scrollTo({ top: scrollRef.current.scrollHeight, behavior: 'smooth' })
@@ -89,6 +92,8 @@ export function AskAIPanel({ locale, onClose }: AskAIPanelProps) {
8992
setInput('')
9093
}
9194

95+
if (!open) return null
96+
9297
return (
9398
<div
9499
role='dialog'

apps/docs/components/ai/ask-ai.tsx

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,27 +15,35 @@ interface AskAIProps {
1515

1616
export function AskAI({ locale }: AskAIProps) {
1717
const [open, setOpen] = useState(false)
18+
const [hasOpened, setHasOpened] = useState(false)
1819
const openButtonRef = useRef<HTMLButtonElement>(null)
1920

21+
const handleOpen = () => {
22+
setHasOpened(true)
23+
setOpen(true)
24+
}
25+
2026
const handleClose = () => {
2127
setOpen(false)
2228
openButtonRef.current?.focus()
2329
}
2430

25-
if (!open) {
26-
return (
27-
<button
28-
ref={openButtonRef}
29-
type='button'
30-
aria-label='Ask Sim'
31-
onClick={() => setOpen(true)}
32-
className='fixed right-4 bottom-4 z-50 flex h-11 items-center gap-1.5 rounded-full border border-[var(--border-1)] bg-[var(--surface-5)] px-4 font-season text-[var(--text-body)] text-sm shadow-[var(--shadow-medium)] transition-colors hover:bg-[var(--surface-active)] dark:bg-[var(--surface-4)]'
33-
>
34-
<MessageCircle className='size-[16px] text-[var(--text-icon)]' />
35-
Ask Sim
36-
</button>
37-
)
38-
}
31+
return (
32+
<>
33+
{!open && (
34+
<button
35+
ref={openButtonRef}
36+
type='button'
37+
aria-label='Ask Sim'
38+
onClick={handleOpen}
39+
className='fixed right-4 bottom-4 z-50 flex h-11 items-center gap-1.5 rounded-full border border-[var(--border-1)] bg-[var(--surface-5)] px-4 font-season text-[var(--text-body)] text-sm shadow-[var(--shadow-medium)] transition-colors hover:bg-[var(--surface-active)] dark:bg-[var(--surface-4)]'
40+
>
41+
<MessageCircle className='size-[16px] text-[var(--text-icon)]' />
42+
Ask Sim
43+
</button>
44+
)}
3945

40-
return <AskAIPanel locale={locale} onClose={handleClose} />
46+
{hasOpened && <AskAIPanel locale={locale} open={open} onClose={handleClose} />}
47+
</>
48+
)
4149
}

0 commit comments

Comments
 (0)