docs: integrate search functionality with new SearchDialog component

- Added a new SearchDialog component to enhance user experience for searching documentation.
- Updated the layout to include the SearchDialog within the RootProvider for improved accessibility.
- Enhanced the search API to support tag filtering based on the first slug, allowing for more refined search results.
This commit is contained in:
Mauricio Siu
2025-12-07 18:11:04 -06:00
parent 4f685a2df9
commit b605ad10e3
3 changed files with 76 additions and 1 deletions

View File

@@ -1,7 +1,21 @@
import { source } from '@/lib/source';
import { createFromSource } from 'fumadocs-core/search/server';
import type { InferPageType } from 'fumadocs-core/source';
export const { GET } = createFromSource(source, {
// https://docs.orama.com/docs/orama-js/supported-languages
language: 'english',
// Configure tag filter based on the first slug (core, cli, api)
buildIndex(page: InferPageType<typeof source>) {
const tag = page.slugs[0] || 'all';
return {
title: page.data.title,
description: page.data.description,
url: page.url,
id: page.url,
structuredData: page.data.structuredData,
// Assign tag based on the first slug (core, cli, api)
tag,
} as any;
},
});

View File

@@ -3,6 +3,7 @@ import './global.css';
import { Inter } from 'next/font/google';
import type { Metadata } from 'next';
import { GoogleAnalytics } from '@next/third-parties/google';
import SearchDialog from '@/components/SearchDialog';
const inter = Inter({
subsets: ['latin'],
@@ -28,7 +29,13 @@ export default function Layout({ children }: LayoutProps<'/'>) {
<html lang="en" className={inter.className} suppressHydrationWarning>
<body className="flex flex-col min-h-screen">
<GoogleAnalytics gaId="G-HZ71HG38HN" />
<RootProvider>{children}</RootProvider>
<RootProvider
search={{
SearchDialog,
}}
>
{children}
</RootProvider>
</body>
</html>
);

View File

@@ -0,0 +1,54 @@
'use client';
import {
SearchDialog,
SearchDialogClose,
SearchDialogContent,
SearchDialogFooter,
SearchDialogHeader,
SearchDialogIcon,
SearchDialogInput,
SearchDialogList,
SearchDialogOverlay,
TagsList,
TagsListItem,
type SharedProps,
} from 'fumadocs-ui/components/dialog/search';
import { useDocsSearch } from 'fumadocs-core/search/client';
import { useState } from 'react';
export default function CustomSearchDialog(props: SharedProps) {
const [tag, setTag] = useState<string | undefined>('all');
// When tag is "all", don't filter by tag (pass undefined)
const { search, setSearch, query } = useDocsSearch({
type: 'fetch',
tag: tag === 'all' ? undefined : tag,
});
return (
<SearchDialog
search={search}
onSearchChange={setSearch}
isLoading={query.isLoading}
{...props}
>
<SearchDialogOverlay />
<SearchDialogContent>
<SearchDialogHeader>
<SearchDialogIcon />
<SearchDialogInput />
<SearchDialogClose />
</SearchDialogHeader>
<SearchDialogList items={query.data !== 'empty' ? query.data : null} />
<SearchDialogFooter>
<TagsList tag={tag} onTagChange={setTag}>
<TagsListItem value="all">All</TagsListItem>
<TagsListItem value="core">Core</TagsListItem>
<TagsListItem value="cli">CLI</TagsListItem>
<TagsListItem value="api">API</TagsListItem>
</TagsList>
</SearchDialogFooter>
</SearchDialogContent>
</SearchDialog>
);
}