docs: redesign search (#12628)

* docs: redesign search

* add shadow in dark mode
This commit is contained in:
Shahed Nasser
2025-05-28 10:01:04 +03:00
committed by GitHub
parent d155f492be
commit 9b3218885c
13 changed files with 157 additions and 200 deletions

View File

@@ -1,10 +1,6 @@
"use client" "use client"
import { import { usePageLoading, SearchProvider as UiSearchProvider } from "docs-ui"
usePageLoading,
SearchProvider as UiSearchProvider,
searchFilters,
} from "docs-ui"
import { config } from "../config" import { config } from "../config"
import basePathUrl from "../utils/base-path-url" import basePathUrl from "../utils/base-path-url"
@@ -20,17 +16,18 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
appId: process.env.NEXT_PUBLIC_ALGOLIA_APP_ID || "temp", appId: process.env.NEXT_PUBLIC_ALGOLIA_APP_ID || "temp",
apiKey: process.env.NEXT_PUBLIC_ALGOLIA_API_KEY || "temp", apiKey: process.env.NEXT_PUBLIC_ALGOLIA_API_KEY || "temp",
mainIndexName: process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp", mainIndexName: process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
indices: [
{
name: process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
title: "Store & Admin API",
},
{
name: process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
title: "Docs",
},
],
}} }}
indices={[
{
value: process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
title: "Docs",
},
{
value: process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
title: "Store & Admin API",
},
]}
defaultIndex={process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp"}
searchProps={{ searchProps={{
isLoading, isLoading,
suggestions: [ suggestions: [
@@ -55,7 +52,6 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
checkInternalPattern: new RegExp( checkInternalPattern: new RegExp(
`^${config.baseUrl}${basePathUrl(`/(admin|store)`)}` `^${config.baseUrl}${basePathUrl(`/(admin|store)`)}`
), ),
filterOptions: searchFilters,
}} }}
> >
{children} {children}

View File

@@ -1,6 +1,6 @@
"use client" "use client"
import { SearchProvider as UiSearchProvider, searchFilters } from "docs-ui" import { SearchProvider as UiSearchProvider } from "docs-ui"
import { config } from "../config" import { config } from "../config"
type SearchProviderProps = { type SearchProviderProps = {
@@ -15,17 +15,18 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
apiKey: process.env.NEXT_PUBLIC_ALGOLIA_API_KEY || "temp", apiKey: process.env.NEXT_PUBLIC_ALGOLIA_API_KEY || "temp",
mainIndexName: mainIndexName:
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp", process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
indices: [
{
name: process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
title: "Docs",
},
{
name: process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
title: "Store & Admin API",
},
],
}} }}
indices={[
{
value: process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
title: "Docs",
},
{
value: process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
title: "Store & Admin API",
},
]}
defaultIndex={process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp"}
searchProps={{ searchProps={{
isLoading: false, isLoading: false,
suggestions: [ suggestions: [
@@ -51,7 +52,6 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
checkInternalPattern: new RegExp( checkInternalPattern: new RegExp(
`^${config.baseUrl}/([^(resources)])*` `^${config.baseUrl}/([^(resources)])*`
), ),
filterOptions: searchFilters,
}} }}
> >
{children} {children}

View File

@@ -1,6 +1,6 @@
"use client" "use client"
import { SearchProvider as UiSearchProvider, searchFilters } from "docs-ui" import { SearchProvider as UiSearchProvider } from "docs-ui"
import { config } from "../config" import { config } from "../config"
type SearchProviderProps = { type SearchProviderProps = {
@@ -15,17 +15,18 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
apiKey: process.env.NEXT_PUBLIC_ALGOLIA_API_KEY || "temp", apiKey: process.env.NEXT_PUBLIC_ALGOLIA_API_KEY || "temp",
mainIndexName: mainIndexName:
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp", process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
indices: [
{
name: process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
title: "Docs",
},
{
name: process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
title: "Store & Admin API",
},
],
}} }}
indices={[
{
value: process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
title: "Docs",
},
{
value: process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
title: "Store & Admin API",
},
]}
defaultIndex={process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp"}
searchProps={{ searchProps={{
isLoading: false, isLoading: false,
suggestions: [ suggestions: [
@@ -40,7 +41,6 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
}, },
], ],
checkInternalPattern: new RegExp(`^${config.baseUrl}/resources/.*`), checkInternalPattern: new RegExp(`^${config.baseUrl}/resources/.*`),
filterOptions: searchFilters,
}} }}
> >
{children} {children}

View File

@@ -1,6 +1,6 @@
"use client" "use client"
import { SearchProvider as UiSearchProvider, searchFilters } from "docs-ui" import { SearchProvider as UiSearchProvider } from "docs-ui"
import { absoluteUrl } from "../lib/absolute-url" import { absoluteUrl } from "../lib/absolute-url"
type SearchProviderProps = { type SearchProviderProps = {
@@ -15,17 +15,18 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
apiKey: process.env.NEXT_PUBLIC_ALGOLIA_API_KEY || "temp", apiKey: process.env.NEXT_PUBLIC_ALGOLIA_API_KEY || "temp",
mainIndexName: mainIndexName:
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp", process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
indices: [
{
name: process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
title: "Docs",
},
{
name: process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
title: "Store & Admin API",
},
],
}} }}
indices={[
{
value: process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
title: "Docs",
},
{
value: process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
title: "Store & Admin API",
},
]}
defaultIndex={process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp"}
searchProps={{ searchProps={{
isLoading: false, isLoading: false,
suggestions: [ suggestions: [
@@ -35,7 +36,6 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
}, },
], ],
checkInternalPattern: new RegExp(`^${absoluteUrl()}/ui`), checkInternalPattern: new RegExp(`^${absoluteUrl()}/ui`),
filterOptions: searchFilters,
}} }}
> >
{children} {children}

View File

@@ -1,6 +1,6 @@
"use client" "use client"
import { SearchProvider as UiSearchProvider, searchFilters } from "docs-ui" import { SearchProvider as UiSearchProvider } from "docs-ui"
import { config } from "../config" import { config } from "../config"
type SearchProviderProps = { type SearchProviderProps = {
@@ -15,17 +15,18 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
apiKey: process.env.NEXT_PUBLIC_ALGOLIA_API_KEY || "temp", apiKey: process.env.NEXT_PUBLIC_ALGOLIA_API_KEY || "temp",
mainIndexName: mainIndexName:
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp", process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
indices: [
{
name: process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
title: "Docs",
},
{
name: process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
title: "Store & Admin API",
},
],
}} }}
indices={[
{
value: process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
title: "Docs",
},
{
value: process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
title: "Store & Admin API",
},
]}
defaultIndex={process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp"}
searchProps={{ searchProps={{
isLoading: false, isLoading: false,
suggestions: [ suggestions: [
@@ -43,7 +44,6 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
}, },
], ],
checkInternalPattern: new RegExp(`^${config.baseUrl}/user-guide`), checkInternalPattern: new RegExp(`^${config.baseUrl}/user-guide`),
filterOptions: searchFilters,
}} }}
> >
{children} {children}

View File

@@ -0,0 +1,31 @@
"use client"
import clsx from "clsx"
import React from "react"
import { useSearch } from "../../../providers"
export const SearchFilters = () => {
const { indices, selectedIndex, setSelectedIndex } = useSearch()
return (
<div className="pt-docs_0.75 px-docs_0.5 justify-center items-center w-full">
<div className="flex flex-wrap bg-medusa-bg-disabled rounded-docs_DEFAULT p-docs_0.125">
{indices.map((index) => (
<button
key={index.value}
className={clsx(
"text-compact-small-plus flex-1 p-docs_0.25",
selectedIndex === index.value && [
"rounded-docs_sm text-medusa-fg-base bg-medusa-bg-base",
"shadow-elevation-card-rest dark:shadow-elevation-card-rest-dark",
],
selectedIndex !== index.value && "text-medusa-fg-muted"
)}
onClick={() => setSelectedIndex(index.value)}
>
{index.title}
</button>
))}
</div>
</div>
)
}

View File

@@ -8,13 +8,16 @@ export const SearchFooter = () => {
className={clsx( className={clsx(
"py-docs_0.75 hidden md:flex items-center justify-end px-docs_1", "py-docs_0.75 hidden md:flex items-center justify-end px-docs_1",
"border-medusa-border-base border-t", "border-medusa-border-base border-t",
"bg-medusa-bg-field" "bg-medusa-bg-field z-10"
)} )}
> >
<div className="flex items-center gap-docs_0.75"> <div className="flex items-center gap-docs_0.75">
<div className="flex items-center gap-docs_0.5"> <div className="flex items-center gap-docs_0.5">
<span <span
className={clsx("text-medusa-fg-subtle", "text-compact-x-small")} className={clsx(
"text-medusa-fg-subtle",
"text-compact-x-small-plus"
)}
> >
Navigation Navigation
</span> </span>
@@ -40,7 +43,10 @@ export const SearchFooter = () => {
<div className={clsx("h-docs_0.75 w-px bg-medusa-border-strong")}></div> <div className={clsx("h-docs_0.75 w-px bg-medusa-border-strong")}></div>
<div className="flex items-center gap-docs_0.5"> <div className="flex items-center gap-docs_0.5">
<span <span
className={clsx("text-medusa-fg-subtle", "text-compact-x-small")} className={clsx(
"text-medusa-fg-subtle",
"text-compact-x-small-plus"
)}
> >
Open Result Open Result
</span> </span>

View File

@@ -1,6 +1,6 @@
"use client" "use client"
import React, { Fragment, useEffect, useMemo, useState } from "react" import React, { useEffect, useMemo, useState } from "react"
import clsx from "clsx" import clsx from "clsx"
import { import {
Configure, Configure,
@@ -11,7 +11,7 @@ import {
useInstantSearch, useInstantSearch,
} from "react-instantsearch" } from "react-instantsearch"
import { SearchNoResult } from "../NoResults" import { SearchNoResult } from "../NoResults"
import { AlgoliaIndex, useSearch } from "@/providers" import { useSearch } from "@/providers"
import { Link, SearchHitGroupName } from "@/components" import { Link, SearchHitGroupName } from "@/components"
export type Hierarchy = "lvl0" | "lvl1" | "lvl2" | "lvl3" | "lvl4" | "lvl5" export type Hierarchy = "lvl0" | "lvl1" | "lvl2" | "lvl3" | "lvl4" | "lvl5"
@@ -42,7 +42,6 @@ export type GroupedHitType = {
export type SearchHitWrapperProps = { export type SearchHitWrapperProps = {
configureProps: ConfigureProps configureProps: ConfigureProps
indices: AlgoliaIndex[]
} & Omit<SearchHitsProps, "indexName" | "setNoResults"> } & Omit<SearchHitsProps, "indexName" | "setNoResults">
export type IndexResults = { export type IndexResults = {
@@ -51,41 +50,46 @@ export type IndexResults = {
export const SearchHitsWrapper = ({ export const SearchHitsWrapper = ({
configureProps, configureProps,
indices,
...rest ...rest
}: SearchHitWrapperProps) => { }: SearchHitWrapperProps) => {
const { status } = useInstantSearch() const { status } = useInstantSearch()
const [hasNoResults, setHashNoResults] = useState<IndexResults>({ const { selectedIndex, indices } = useSearch()
[indices[0].name]: false, const [hasNoResults, setHasNoResults] = useState<IndexResults>({
[indices[1].name]: false, [indices[0].value]: false,
[indices[1].value]: false,
}) })
const showNoResults = useMemo(() => {
return Object.values(hasNoResults).every((value) => value === true)
}, [hasNoResults])
const setNoResults = (index: string, value: boolean) => { const setNoResults = (index: string, value: boolean) => {
setHashNoResults((prev: IndexResults) => ({ setHasNoResults((prev) => ({
...prev, ...prev,
[index]: value, [index]: value,
})) }))
} }
const showNoResults = useMemo(() => {
return Object.values(hasNoResults).every((val) => val)
}, [hasNoResults])
return ( return (
<div className="h-full overflow-auto px-docs_0.5"> <div className="overflow-auto px-docs_0.5 flex-1">
{status !== "loading" && showNoResults && <SearchNoResult />} {status !== "loading" && showNoResults && <SearchNoResult />}
{indices.map((index, key) => ( {indices.map((index) => (
// @ts-expect-error React v19 doesn't see this type as a React element <div
<Index indexName={index.name} key={key}> className={clsx(index.value !== selectedIndex && "hidden")}
{!hasNoResults[index.name] && ( key={index.value}
<SearchHitGroupName name={index.title} /> data-index
)} >
<SearchHits {/* @ts-expect-error React v19 doesn't see this type as a React element */}
indexName={index.name} <Index indexName={index.value}>
setNoResults={setNoResults} {!hasNoResults[index.value] && (
{...rest} <SearchHitGroupName name={index.title} />
/> )}
<Configure {...configureProps} /> <SearchHits
</Index> indexName={index.value}
setNoResults={setNoResults}
{...rest}
/>
<Configure {...configureProps} />
</Index>
</div>
))} ))}
</div> </div>
) )

View File

@@ -1,16 +1,16 @@
"use client" "use client"
import React, { useEffect, useMemo, useRef, useState } from "react" import React, { useEffect, useRef } from "react"
import { InstantSearch, SearchBox } from "react-instantsearch" import { InstantSearch, SearchBox } from "react-instantsearch"
import clsx from "clsx" import clsx from "clsx"
import { SearchEmptyQueryBoundary } from "./EmptyQueryBoundary" import { SearchEmptyQueryBoundary } from "./EmptyQueryBoundary"
import { SearchSuggestions, type SearchSuggestionType } from "./Suggestions" import { SearchSuggestions, type SearchSuggestionType } from "./Suggestions"
import { AlgoliaProps, useSearch } from "@/providers" import { AlgoliaProps, useSearch } from "@/providers"
import { checkArraySameElms } from "@/utils"
import { SearchHitsWrapper } from "./Hits" import { SearchHitsWrapper } from "./Hits"
import { SelectBadge, SpinnerLoading } from "@/components" import { SpinnerLoading } from "@/components"
import { useSearchNavigation, type OptionType } from "@/hooks" import { useSearchNavigation, type OptionType } from "@/hooks"
import { SearchFooter } from "./Footer" import { SearchFooter } from "./Footer"
import { SearchFilters } from "./Filters"
export type SearchProps = { export type SearchProps = {
algolia: AlgoliaProps algolia: AlgoliaProps
@@ -25,21 +25,13 @@ export const Search = ({
suggestions, suggestions,
isLoading = false, isLoading = false,
checkInternalPattern, checkInternalPattern,
filterOptions = [],
}: SearchProps) => { }: SearchProps) => {
const { isOpen, defaultFilters, searchClient, modalRef } = useSearch() const { isOpen, searchClient, modalRef } = useSearch()
const [filters, setFilters] = useState<string[]>(defaultFilters)
const searchBoxRef = useRef<HTMLFormElement>(null) const searchBoxRef = useRef<HTMLFormElement>(null)
const focusSearchInput = () => const focusSearchInput = () =>
searchBoxRef.current?.querySelector("input")?.focus() searchBoxRef.current?.querySelector("input")?.focus()
useEffect(() => {
if (!checkArraySameElms(defaultFilters, filters)) {
setFilters(defaultFilters)
}
}, [defaultFilters])
useEffect(() => { useEffect(() => {
if (isOpen && searchBoxRef.current) { if (isOpen && searchBoxRef.current) {
focusSearchInput() focusSearchInput()
@@ -57,14 +49,6 @@ export const Search = ({
} }
}, [isOpen]) }, [isOpen])
const facetFilters = useMemo(() => {
const filtersToUse =
!filters.length || filters[0] === "all"
? filterOptions.map((option) => option.value)
: filters
return filtersToUse.map((filter) => "_tags:" + filter)
}, [filters, defaultFilters])
useSearchNavigation({ useSearchNavigation({
getInputElm: () => getInputElm: () =>
searchBoxRef.current?.querySelector("input") as HTMLInputElement, searchBoxRef.current?.querySelector("input") as HTMLInputElement,
@@ -76,30 +60,6 @@ export const Search = ({
return ( return (
<div className="h-full flex flex-col"> <div className="h-full flex flex-col">
{filterOptions.length > 0 && (
<SelectBadge
multiple
options={filterOptions}
value={filters}
setSelected={(value) =>
setFilters(Array.isArray(value) ? [...value] : [value])
}
addSelected={(value) => setFilters((prev) => [...prev, value])}
removeSelected={(value) =>
setFilters((prev) => prev.filter((v) => v !== value))
}
showClearButton={false}
placeholder="Filters"
handleAddAll={(isAllSelected: boolean) => {
if (isAllSelected) {
setFilters(defaultFilters)
} else {
setFilters(filterOptions.map((option) => option.value))
}
}}
className="px-docs_1 pt-docs_1 bg-medusa-bg-base z-10"
/>
)}
{/* @ts-expect-error React v19 doesn't see this type as a React element */} {/* @ts-expect-error React v19 doesn't see this type as a React element */}
<InstantSearch <InstantSearch
indexName={algolia.mainIndexName} indexName={algolia.mainIndexName}
@@ -143,26 +103,16 @@ export const Search = ({
</div> </div>
<div <div
className={clsx( className={clsx(
"md:flex-initial", "md:flex-initial flex flex-col",
filterOptions.length > 0 && "h-[calc(100%-75px)] lg:max-h-[calc(100%-100px)] lg:min-h-[calc(100%-100px)]"
"h-[calc(100%-95px)] lg:max-h-[calc(100%-140px)] lg:min-h-[calc(100%-140px)]",
filterOptions.length === 0 &&
"h-[calc(100%-75px)] lg:max-h-[calc(100%-100px)] lg:min-h-[calc(100%-100px)]"
)} )}
> >
<SearchFilters />
<SearchEmptyQueryBoundary <SearchEmptyQueryBoundary
fallback={<SearchSuggestions suggestions={suggestions} />} fallback={<SearchSuggestions suggestions={suggestions} />}
> >
<SearchHitsWrapper <SearchHitsWrapper
configureProps={{ configureProps={{}}
// filters array has to be wrapped
// in another array for an OR condition
// to be applied between the items.
facetFilters: [facetFilters],
getRankingInfo: true,
hitsPerPage: 3,
}}
indices={algolia.indices}
checkInternalPattern={checkInternalPattern} checkInternalPattern={checkInternalPattern}
/> />
</SearchEmptyQueryBoundary> </SearchEmptyQueryBoundary>

View File

@@ -82,6 +82,7 @@ export const VerticalCodeTabs = ({
{...tabs[selectedTabIndex].code} {...tabs[selectedTabIndex].code}
noCopy={true} noCopy={true}
noReport={true} noReport={true}
noAskAi={true}
forceNoTitle={true} forceNoTitle={true}
wrapperClassName="h-full !rounded-docs_DEFAULT" wrapperClassName="h-full !rounded-docs_DEFAULT"
className={clsx( className={clsx(

View File

@@ -1,4 +1,3 @@
import { OptionType } from "@/hooks"
import { NavigationItem } from "types" import { NavigationItem } from "types"
export const GITHUB_ISSUES_LINK = export const GITHUB_ISSUES_LINK =
@@ -356,31 +355,3 @@ export const navDropdownItems: NavigationItem[] = [
link: "/user-guide", link: "/user-guide",
}, },
] ]
export const searchFilters: OptionType[] = [
{
value: "concepts-guides",
label: "Concepts & Guides",
hitsPerPage: 8,
},
{
value: "references",
label: "References",
},
{
value: "admin-v2",
label: "Admin API",
},
{
value: "store-v2",
label: "Store API",
},
{
value: "user-guide",
label: "User Guide",
},
{
value: "troubleshooting",
label: "Troubleshooting",
},
]

View File

@@ -87,7 +87,7 @@ export const useSearchNavigation = ({
if (isInput) { if (isInput) {
// go to the first data-hit item // go to the first data-hit item
const nextItem = modalRef.current?.querySelector( const nextItem = modalRef.current?.querySelector(
"[data-hit]" "[data-index]:not(.hidden) [data-hit]"
) as HTMLElement ) as HTMLElement
nextItem?.focus() nextItem?.focus()
} else { } else {

View File

@@ -9,7 +9,6 @@ import React, {
useRef, useRef,
} from "react" } from "react"
import { BadgeProps, Modal, Search, SearchProps } from "@/components" import { BadgeProps, Modal, Search, SearchProps } from "@/components"
import { checkArraySameElms } from "../../utils"
import { import {
liteClient as algoliasearch, liteClient as algoliasearch,
LiteClient as SearchClient, LiteClient as SearchClient,
@@ -30,20 +29,21 @@ export type SearchCommand = {
export type SearchContextType = { export type SearchContextType = {
isOpen: boolean isOpen: boolean
setIsOpen: React.Dispatch<React.SetStateAction<boolean>> setIsOpen: React.Dispatch<React.SetStateAction<boolean>>
defaultFilters: string[]
setDefaultFilters: (value: string[]) => void
searchClient: SearchClient searchClient: SearchClient
commands: SearchCommand[] commands: SearchCommand[]
command: SearchCommand | null command: SearchCommand | null
setCommand: React.Dispatch<React.SetStateAction<SearchCommand | null>> setCommand: React.Dispatch<React.SetStateAction<SearchCommand | null>>
setCommands: React.Dispatch<React.SetStateAction<SearchCommand[]>> setCommands: React.Dispatch<React.SetStateAction<SearchCommand[]>>
modalRef: React.MutableRefObject<HTMLDialogElement | null> modalRef: React.RefObject<HTMLDialogElement | null>
indices: AlgoliaIndex[]
selectedIndex: string
setSelectedIndex: (value: string) => void
} }
const SearchContext = createContext<SearchContextType | null>(null) const SearchContext = createContext<SearchContextType | null>(null)
export type AlgoliaIndex = { export type AlgoliaIndex = {
name: string value: string
title: string title: string
} }
@@ -51,12 +51,12 @@ export type AlgoliaProps = {
appId: string appId: string
apiKey: string apiKey: string
mainIndexName: string mainIndexName: string
indices: AlgoliaIndex[]
} }
export type SearchProviderProps = { export type SearchProviderProps = {
children: React.ReactNode children: React.ReactNode
initialDefaultFilters?: string[] indices: AlgoliaIndex[]
defaultIndex: string
algolia: AlgoliaProps algolia: AlgoliaProps
searchProps: Omit<SearchProps, "algolia"> searchProps: Omit<SearchProps, "algolia">
commands?: SearchCommand[] commands?: SearchCommand[]
@@ -65,16 +65,16 @@ export type SearchProviderProps = {
export const SearchProvider = ({ export const SearchProvider = ({
children, children,
initialDefaultFilters = [], defaultIndex: initialDefaultIndex,
searchProps, searchProps,
algolia, algolia,
commands: initialCommands = [], commands: initialCommands = [],
modalClassName, modalClassName,
indices,
}: SearchProviderProps) => { }: SearchProviderProps) => {
const [isOpen, setIsOpen] = useState(false) const [isOpen, setIsOpen] = useState(false)
const [defaultFilters, setDefaultFilters] = useState<string[]>( const [selectedIndex, setSelectedIndex] =
initialDefaultFilters useState<string>(initialDefaultIndex)
)
const [commands, setCommands] = useState<SearchCommand[]>(initialCommands) const [commands, setCommands] = useState<SearchCommand[]>(initialCommands)
const [command, setCommand] = useState<SearchCommand | null>(null) const [command, setCommand] = useState<SearchCommand | null>(null)
@@ -88,13 +88,10 @@ export const SearchProvider = ({
}, [algolia.appId, algolia.apiKey]) }, [algolia.appId, algolia.apiKey])
useEffect(() => { useEffect(() => {
if ( if (initialDefaultIndex !== selectedIndex) {
initialDefaultFilters.length && setSelectedIndex(initialDefaultIndex)
!checkArraySameElms(defaultFilters, initialDefaultFilters)
) {
setDefaultFilters(initialDefaultFilters)
} }
}, [initialDefaultFilters]) }, [initialDefaultIndex])
const componentWrapperRef = useRef(null) const componentWrapperRef = useRef(null)
@@ -107,14 +104,15 @@ export const SearchProvider = ({
value={{ value={{
isOpen, isOpen,
setIsOpen, setIsOpen,
defaultFilters,
setDefaultFilters,
searchClient, searchClient,
commands, commands,
command, command,
setCommand, setCommand,
modalRef, modalRef,
setCommands, setCommands,
indices,
selectedIndex,
setSelectedIndex,
}} }}
> >
{children} {children}