Back to components
Form

Search Toolbar

A reusable search and filtering toolbar for workbench-style pages.

Page preview
Source
This is the component source that shadcn installs into a consuming project.
registry/default/search-toolbar/search-toolbar.tsx
import { SearchIcon, SlidersHorizontalIcon } from "lucide-react"

import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"
import {
  Field,
  FieldGroup,
  FieldLabel,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"

type SearchToolbarCopy = {
  title: string
  description: string
  label: string
  placeholder: string
  resultCount: string
  filterLabel: string
  submitLabel: string
}

type SearchToolbarProps = {
  copy?: SearchToolbarCopy
}

const defaultCopy: SearchToolbarCopy = {
  title: "Search workspace",
  description: "Filter reusable components, documents, or operational records.",
  label: "Keyword",
  placeholder: "Search by name, tag, or owner",
  resultCount: "128 items",
  filterLabel: "Filters",
  submitLabel: "Search",
}

export function SearchToolbar({ copy = defaultCopy }: SearchToolbarProps) {
  return (
    <Card className="w-full max-w-2xl">
      <CardHeader>
        <div className="flex flex-wrap items-start justify-between gap-3">
          <div className="flex min-w-0 flex-col gap-1">
            <CardTitle>{copy.title}</CardTitle>
            <CardDescription>{copy.description}</CardDescription>
          </div>
          <Badge variant="secondary">{copy.resultCount}</Badge>
        </div>
      </CardHeader>
      <CardContent>
        <form className="flex flex-col gap-3 md:flex-row md:items-end">
          <FieldGroup className="min-w-0 flex-1">
            <Field>
              <FieldLabel htmlFor="workspace-search">{copy.label}</FieldLabel>
              <Input
                id="workspace-search"
                name="q"
                type="search"
                placeholder={copy.placeholder}
              />
            </Field>
          </FieldGroup>
          <div className="flex flex-wrap gap-2">
            <Button type="button" variant="outline">
              <SlidersHorizontalIcon data-icon="inline-start" />
              {copy.filterLabel}
            </Button>
            <Button type="submit">
              <SearchIcon data-icon="inline-start" />
              {copy.submitLabel}
            </Button>
          </div>
        </form>
      </CardContent>
    </Card>
  )
}