@@ -167,83 +167,87 @@ export function SpecExplorer() {
167167 value = { search }
168168 onChange = { ( e ) => setSearch ( e . target . value ) }
169169 onKeyDown = { handleKeyDown }
170- placeholder = "Ask about the ECMA-376 spec ..."
170+ placeholder = "e.g. paragraph spacing, table borders, how to style text runs ..."
171171 rows = { 2 }
172172 className = "w-full resize-none rounded-lg border border-[var(--color-border)] bg-transparent px-4 py-3 text-sm leading-relaxed outline-none transition placeholder:text-[var(--color-text-muted)] focus:border-[var(--color-text-primary)] focus:shadow-[0_0_0_3px_rgba(0,0,0,0.05)]"
173173 autoFocus
174174 />
175- < div className = "mt-2 text-[11px] text-[var(--color-text-muted)]" >
176- Press{ " " }
177- < kbd className = "rounded border border-[var(--color-border)] bg-[var(--color-bg-secondary)] px-1" >
178- Enter
179- </ kbd > { " " }
180- to search
175+ < div className = "mt-2 flex items-center justify-between text-[11px] text-[var(--color-text-muted)]" >
176+ < span > Use natural language or element names</ span >
177+ < span >
178+ < kbd className = "rounded border border-[var(--color-border)] bg-[var(--color-bg-secondary)] px-1.5 py-0.5" >
179+ ↵
180+ </ kbd >
181+ </ span >
181182 </ div >
182183 </ div >
183184
184185 { /* Results */ }
185- < div ref = { resultsRef } className = "min-h-0 flex-1 overflow-y-auto" >
186- { /* Results count */ }
187- { results . length > 0 && (
188- < div className = "px-5 pb-2 text-xs text-[var(--color-text-muted)]" >
189- { results . length } results
190- </ div >
191- ) }
186+ < div className = "relative min-h-0 flex-1" >
187+ < div ref = { resultsRef } className = "h-full overflow-y-auto" >
188+ { /* Results count */ }
189+ { results . length > 0 && (
190+ < div className = "px-5 pb-2 text-xs text-[var(--color-text-muted)]" >
191+ { results . length } results
192+ </ div >
193+ ) }
192194
193- { /* Loading state */ }
194- { isLoading && (
195- < div className = "flex items-center justify -center py-12 " >
196- < Loader2 size = { 24 } className = "animate-spin text-[var(--color-text-muted)]" />
197- </ div >
198- ) }
195+ { /* Empty state */ }
196+ { ! isLoading && ! submittedSearch && (
197+ < div className = "px-5 py-12 text -center text-sm text-[var(--color-text-muted)] " >
198+ Search the ECMA-376 specification
199+ </ div >
200+ ) }
199201
200- { /* Empty state */ }
201- { ! isLoading && ! submittedSearch && (
202- < div className = "px-5 py-12 text-center text-sm text-[var(--color-text-muted)]" >
203- Search the ECMA-376 specification
204- </ div >
205- ) }
202+ { /* No results */ }
203+ { ! isLoading && submittedSearch && results . length === 0 && (
204+ < div className = "px-5 py-12 text-center text-sm text-[var(--color-text-muted)]" >
205+ No results found
206+ </ div >
207+ ) }
206208
207- { /* No results */ }
208- { ! isLoading && submittedSearch && results . length === 0 && (
209- < div className = "px-5 py-12 text-center text-sm text-[var(--color-text-muted)]" >
210- No results found
209+ { /* Results list */ }
210+ { results . map ( ( result , idx ) => (
211+ < button
212+ key = { result . id }
213+ type = "button"
214+ data-selected = { idx === selectedIndex }
215+ onClick = { ( ) => handleSelectResult ( result , idx ) }
216+ onMouseEnter = { ( ) => setSelectedIndex ( idx ) }
217+ className = { clsx (
218+ "w-full cursor-pointer border-b border-[var(--color-bg-tertiary)] px-5 py-3 text-left transition" ,
219+ idx === selectedIndex
220+ ? "bg-[var(--color-bg-tertiary)]"
221+ : "hover:bg-[var(--color-bg-secondary)]" ,
222+ ) }
223+ >
224+ < div className = "flex items-baseline gap-2" >
225+ < span className = "shrink-0 font-mono text-[11px] font-medium text-[var(--color-accent)]" >
226+ §{ result . sectionId }
227+ </ span >
228+ < span className = "truncate text-sm font-medium text-[var(--color-text-primary)]" >
229+ { result . title }
230+ </ span >
231+ </ div >
232+ { result . description && (
233+ < div className = "mt-1 line-clamp-1 text-xs text-[var(--color-text-muted)]" >
234+ { result . description }
235+ </ div >
236+ ) }
237+ < div className = "mt-1.5 text-[10px] text-[var(--color-text-muted)]" >
238+ Part { result . partNumber } · Page { result . pageNumber || "—" }
239+ </ div >
240+ </ button >
241+ ) ) }
242+ </ div >
243+
244+ { /* Loading overlay */ }
245+ { isLoading && (
246+ < div className = "absolute inset-0 flex flex-col items-center justify-center gap-3 bg-white/85" >
247+ < Loader2 size = { 28 } className = "animate-spin text-[var(--color-accent)]" />
248+ < span className = "text-sm text-[var(--color-text-secondary)]" > Searching...</ span >
211249 </ div >
212250 ) }
213-
214- { /* Results list */ }
215- { results . map ( ( result , idx ) => (
216- < button
217- key = { result . id }
218- type = "button"
219- data-selected = { idx === selectedIndex }
220- onClick = { ( ) => handleSelectResult ( result , idx ) }
221- onMouseEnter = { ( ) => setSelectedIndex ( idx ) }
222- className = { clsx (
223- "w-full cursor-pointer border-b border-[var(--color-bg-tertiary)] px-5 py-3 text-left transition" ,
224- idx === selectedIndex
225- ? "bg-[var(--color-bg-tertiary)]"
226- : "hover:bg-[var(--color-bg-secondary)]" ,
227- ) }
228- >
229- < div className = "flex items-baseline gap-2" >
230- < span className = "shrink-0 font-mono text-[11px] font-medium text-[var(--color-accent)]" >
231- §{ result . sectionId }
232- </ span >
233- < span className = "truncate text-sm font-medium text-[var(--color-text-primary)]" >
234- { result . title }
235- </ span >
236- </ div >
237- { result . description && (
238- < div className = "mt-1 line-clamp-1 text-xs text-[var(--color-text-muted)]" >
239- { result . description }
240- </ div >
241- ) }
242- < div className = "mt-1.5 text-[10px] text-[var(--color-text-muted)]" >
243- Part { result . partNumber } · Page { result . pageNumber || "—" }
244- </ div >
245- </ button >
246- ) ) }
247251 </ div >
248252 </ div >
249253
0 commit comments