11'use client'
22
3- import { type ReactNode , useEffect , useRef , useState } from 'react'
3+ import { useEffect , useRef , useState } from 'react'
44import { Button , cn , scrollFadeAttributes , scrollFadeClass , useScrollEdges } from '@sim/emcn'
55import { ArrowUp , Search } from '@sim/emcn/icons'
66import { useRouter } from 'next/navigation'
@@ -122,7 +122,7 @@ function SearchField({
122122
123123/**
124124 * Sim Search over the organization's sources. Empty, it is the greeting over the
125- * query field, centered like Home; once results arrive the field docks at
125+ * query field, centered like Home; once a query is submitted the field docks at
126126 * the top of the page — where every other organization page's title sits — and
127127 * the results scroll beneath it under the sidebar's edge fade. The submitted
128128 * query lives in the URL; the field holds the draft until the next submit.
@@ -141,6 +141,13 @@ function OrganizationSearchContent() {
141141 const query = q . trim ( )
142142 const scope : ResourceScope = { kind : 'organization' , organizationId : organization . id }
143143
144+ const scrollContainerRef = useRef < HTMLDivElement > ( null )
145+ const scrollContentRef = useRef < HTMLDivElement > ( null )
146+ const scrollEdges = useScrollEdges ( scrollContainerRef , {
147+ contentRef : scrollContentRef ,
148+ enabled : query . length > 0 ,
149+ } )
150+
144151 const summarize = ( message : string , assistantSearch : WorkspaceSearchFilters ) => {
145152 MothershipHandoffStorage . store (
146153 { message, assistantSearch } ,
@@ -155,95 +162,45 @@ function OrganizationSearchContent() {
155162 void setParams ( { q : next } )
156163 }
157164
158- const renderLayout = ( results : ReactNode , docked : boolean ) => (
159- < SearchLayout query = { q } onSubmit = { submit } docked = { docked } >
160- { results }
161- </ SearchLayout >
162- )
163-
164- return query ? (
165- < KnowledgeSearchResults
166- scope = { scope }
167- query = { query }
168- onSummarize = { summarize }
169- renderLayout = { renderLayout }
170- />
171- ) : (
172- renderLayout ( null , false )
173- )
174- }
175-
176- interface SearchLayoutProps {
177- query : string
178- onSubmit : ( draft : string ) => void
179- docked : boolean
180- children : ReactNode
181- }
182-
183- function SearchLayout ( { query, onSubmit, docked, children } : SearchLayoutProps ) {
184- const { organization } = useOrganizationContext ( )
185- const scrollContainerRef = useRef < HTMLDivElement > ( null )
186- const scrollContentRef = useRef < HTMLDivElement > ( null )
187- const scrollEdges = useScrollEdges ( scrollContainerRef , { contentRef : scrollContentRef } )
165+ const searching = query . length > 0
188166
189167 return (
190168 < div className = 'flex h-full min-h-0 flex-col bg-[var(--bg)]' >
191169 < div className = { PAGE_HEADER_BAR } >
192170 < div className = { HEADER_ACTION_CLUSTER } />
193171 </ div >
194- < div
195- className = { cn (
196- 'flex min-h-0 flex-1 flex-col' ,
197- ! docked && 'overflow-y-auto [scrollbar-gutter:stable_both-edges]'
198- ) }
199- >
200- < div
201- className = { cn (
202- 'flex min-h-0 flex-col' ,
203- docked ? 'flex-1' : 'min-h-full items-center justify-center px-6 pt-[2vh] pb-[22vh]'
204- ) }
205- >
206- < div
207- className = { cn (
208- 'shrink-0' ,
209- docked
210- ? cn ( PAGE_COLUMN_CLASS , SIDEBAR_DIVIDER_PAD_ABOVE_CLASS , 'pt-8' )
211- : 'w-full max-w-chat'
212- ) }
213- >
214- { ! docked && (
215- < h1 className = 'mb-7 text-balance text-center font-season text-[26px] text-[var(--text-primary)] leading-[1.15] tracking-[-0.01em] sm:text-[28px]' >
216- Search { organization . name }
217- </ h1 >
218- ) }
219- < SearchField
220- key = { query }
221- initialValue = { query }
222- onSubmit = { onSubmit }
223- docked = { docked }
224- focusOnMount
225- />
172+ { searching ? (
173+ < >
174+ < div className = { cn ( PAGE_COLUMN_CLASS , SIDEBAR_DIVIDER_PAD_ABOVE_CLASS , 'shrink-0 pt-8' ) } >
175+ < SearchField key = { q } initialValue = { q } onSubmit = { submit } docked focusOnMount />
226176 </ div >
227177 < div
228178 ref = { scrollContainerRef }
229179 className = { cn (
230- docked
231- ? cn (
232- SIDEBAR_DIVIDER_PAD_BELOW_CLASS ,
233- SIDEBAR_DIVIDER_PAD_ABOVE_CLASS ,
234- scrollFadeClass ,
235- 'min-h-0 flex-1 overflow-y-auto [scrollbar-gutter:stable_both-edges]'
236- )
237- : 'w-full max-w-chat'
180+ SIDEBAR_DIVIDER_PAD_BELOW_CLASS ,
181+ SIDEBAR_DIVIDER_PAD_ABOVE_CLASS ,
182+ scrollFadeClass ,
183+ 'min-h-0 flex-1 overflow-y-auto [scrollbar-gutter:stable_both-edges]'
238184 ) }
239185 { ...scrollFadeAttributes ( scrollEdges ) }
240186 >
241- < div ref = { scrollContentRef } className = { docked ? cn ( PAGE_COLUMN_CLASS , 'px-8' ) : 'px-2' } >
242- { children }
187+ < div ref = { scrollContentRef } className = { cn ( PAGE_COLUMN_CLASS , 'px-8' ) } >
188+ < KnowledgeSearchResults scope = { scope } query = { query } onSummarize = { summarize } />
189+ </ div >
190+ </ div >
191+ </ >
192+ ) : (
193+ < div className = 'min-h-0 flex-1 overflow-y-auto [scrollbar-gutter:stable_both-edges]' >
194+ < div className = 'flex min-h-full flex-col items-center justify-center px-6 pt-[2vh] pb-[22vh]' >
195+ < h1 className = 'mb-7 max-w-chat text-balance text-center font-season text-[26px] text-[var(--text-primary)] leading-[1.15] tracking-[-0.01em] sm:text-[28px]' >
196+ Search { organization . name }
197+ </ h1 >
198+ < div className = 'w-full max-w-chat' >
199+ < SearchField key = { q } initialValue = { q } onSubmit = { submit } focusOnMount />
243200 </ div >
244201 </ div >
245202 </ div >
246- </ div >
203+ ) }
247204 </ div >
248205 )
249206}
0 commit comments