import type { Meta, StoryObj } from "@storybook/react"; import { useEffect } from "react"; import { SearchPalette, SearchProvider, SearchTrigger, useSearchContext, } from "./index"; import type { SearchResult } from "./searchbox-types"; /** * Mock documents copied verbatim from app/demo/searchbox/page.tsx */ const mockDocuments: SearchResult[] = [ { id: "1", title: "What is Functions.do", url: "/docs/apis/functions", breadcrumbs: ["APIs", "Functions"], matches: [ { type: "content", snippet: "Introducing Functions.do, a serverless function platform that you can scale.", }, { type: "content", snippet: "Most serverless platforms can already suffice the needs of simple functions.", }, { type: "section", heading: "Getting Started", snippet: "Functions.do provides serverless function execution with automatic scaling...", }, { type: "section", heading: "Authentication", snippet: "Use Bearer tokens to authenticate API requests to Functions.do...", }, ], }, { id: "2", title: "Workflows.do", url: "/docs/apis/workflows", breadcrumbs: ["APIs", "Workflows"], matches: [ { type: "content", snippet: "Workflows.do enables complex multi-step automation pipelines...", }, { type: "section", heading: "Triggers", snippet: "Configure triggers to start your workflows automatically...", }, ], }, { id: "3", title: "Authentication", url: "/docs/guides/authentication", breadcrumbs: ["Guides", "Authentication"], matches: [ { type: "content", snippet: "Configure authentication for your application using OAuth 2.0, API keys, or JWT.", }, { type: "section", heading: "OAuth 2.0", snippet: "Configure OAuth 2.0 authentication for your application...", }, { type: "section", heading: "API Keys", snippet: "Generate and manage API keys from the dashboard...", }, ], }, { id: "4", title: "Database.do", url: "/docs/apis/database", breadcrumbs: ["APIs", "Database"], matches: [ { type: "content", snippet: "A fully managed database with automatic backups and scaling.", }, { type: "section", heading: "Queries", snippet: "Execute SQL queries with Database.do's query builder...", }, ], }, { id: "5", title: "Deployment", url: "/docs/guides/deployment", breadcrumbs: ["Guides", "Deployment"], matches: [ { type: "section", heading: "Vercel", snippet: "Deploy to Vercel with zero configuration...", }, { type: "section", heading: "Docker", snippet: "Containerize your application with Docker...", }, ], }, { id: "6", title: "LLM.do", url: "/docs/apis/llm", breadcrumbs: ["APIs", "LLM"], matches: [ { type: "content", snippet: "Access powerful language models through a simple API.", }, { type: "section", heading: "Chat Completions", snippet: "Generate chat completions using LLM.do...", }, { type: "section", heading: "Streaming", snippet: "Stream responses in real-time for better UX...", }, ], }, ]; /** * Wrapper that renders the trigger button */ function TriggerWrapper() { const { setIsOpen } = useSearchContext(); return (
setIsOpen(true)} />
); } /** * Wrapper that opens the palette automatically */ function AutoOpenWrapper({ initialQuery = "" }: { initialQuery?: string }) { const { setIsOpen, setQuery } = useSearchContext(); useEffect(() => { setIsOpen(true); if (initialQuery) { setQuery(initialQuery); } }, [setIsOpen, setQuery, initialQuery]); return null; } /** * Story wrapper component that combines provider, palette, and optional trigger */ function SearchBoxStory({ documents = mockDocuments, placeholder, showTrigger = true, autoOpen = false, initialQuery = "", }: { documents?: SearchResult[]; placeholder?: string; showTrigger?: boolean; autoOpen?: boolean; initialQuery?: string; }) { return ( {showTrigger && } {autoOpen && } ); } const meta: Meta = { title: "Widgets/SearchBox", component: SearchBoxStory, parameters: { layout: "centered", docs: { description: { component: ` Command palette-style search widget for documentation and content search. Features: - **Keyboard Shortcut** - Opens with ⌘K / Ctrl+K - **Fuzzy Search** - Matches across titles, headings, and content - **Breadcrumbs** - Shows document path for context - **Highlighted Matches** - Query text highlighted in results \`\`\`tsx import { SearchProvider, SearchPalette, SearchTrigger, useSearchContext } from '@mdxui/widgets' setIsOpen(true)} /> \`\`\` `, }, }, }, tags: ["autodocs"], argTypes: { documents: { control: false }, placeholder: { control: "text" }, showTrigger: { control: "boolean" }, autoOpen: { control: "boolean" }, initialQuery: { control: "text" }, }, }; export default meta; type Story = StoryObj; /** * Default state showing the search trigger button. * Click the button or press ⌘K to open the command palette. */ export const Default: Story = { args: { documents: mockDocuments, placeholder: "Search documentation...", showTrigger: true, autoOpen: false, }, }; /** * Command palette open and ready for search. * Type to search through the documentation. */ export const PaletteOpen: Story = { args: { documents: mockDocuments, placeholder: "Search documentation...", showTrigger: false, autoOpen: true, }, }; /** * Shows search results for the query "functions". * Results are ranked by relevance with query text highlighted. */ export const WithResults: Story = { args: { documents: mockDocuments, placeholder: "Search documentation...", showTrigger: false, autoOpen: true, initialQuery: "functions", }, }; /** * Shows the empty state when no results match the query. */ export const NoResults: Story = { args: { documents: mockDocuments, placeholder: "Search documentation...", showTrigger: false, autoOpen: true, initialQuery: "xyznonexistent", }, }; /** * Shows the palette with no documents provided. * Useful for testing the empty/loading state. */ export const NoDocuments: Story = { args: { documents: [], placeholder: "Search documentation...", showTrigger: false, autoOpen: true, initialQuery: "test", }, }; /** * Shows a custom placeholder text in the search input. */ export const CustomPlaceholder: Story = { args: { documents: mockDocuments, placeholder: "Search APIs, guides, and more...", showTrigger: true, autoOpen: false, }, };