# Search Results Page

> Search results page with a query field, live result count, empty state, and result cards carrying a type badge, snippet, and last updated date.

A shadcn/ui block from the [@7ovr](https://7ovr.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/7ovr/search-2).

- Page, with a live preview: https://shadcn.exchange/r/7ovr/search-2
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/7ovr/search-2-light-61b0ebd91b73415e.png
- Registry item: https://7ovr.com/r/search-2.json
- Categories: search
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://7ovr.com/r/search-2.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- npm packages: `@base-ui/react`
- Registry items: `badge`, `input`

## Files

### `registry/blocks/search/2/search-block.tsx`

```tsx
"use client"

import * as React from "react"
import { Badge } from "@/components/ui/badge"
import { Input } from "@/components/ui/input"
import { IconPlaceholder } from "@/components/icons/icon-placeholder"

type Result = {
  title: string
  snippet: string
  type: string
  updated: string
}

const results: Result[] = [
  {
    title: "Getting started with Acme",
    snippet:
      "Install the CLI, create your first project, and ship a page in under five minutes with copy-paste blocks.",
    type: "Docs",
    updated: "Jun 12, 2026",
  },
  {
    title: "Authentication and sessions",
    snippet:
      "Connect a provider, protect your routes, and read the current session on the server or the client.",
    type: "Guide",
    updated: "May 30, 2026",
  },
  {
    title: "Theming and design tokens",
    snippet:
      "Every block is theme-aware. Override semantic tokens once and every component updates automatically.",
    type: "Docs",
    updated: "Jun 18, 2026",
  },
  {
    title: "Deploying to production",
    snippet:
      "A checklist for going live: environment variables, build caching, and zero-downtime releases.",
    type: "Guide",
    updated: "Jun 02, 2026",
  },
]

export default function SearchBlock() {
  const [query, setQuery] = React.useState("")

  const q = query.trim().toLowerCase()
  const filtered = q
    ? results.filter((r) =>
        `${r.title} ${r.snippet} ${r.type}`.toLowerCase().includes(q)
      )
    : results

  return (
    <section className="flex w-full items-center justify-center bg-muted/30 px-6 py-16 text-foreground">
      <div className="flex w-full max-w-xl flex-col gap-5">
        <div className="relative">
          <IconPlaceholder
            lucide="Search"
            tabler="IconSearch"
            hugeicons="SearchIcon"
            phosphor="MagnifyingGlass"
            remixicon="RiSearchLine"
            className="absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted-foreground"
            aria-hidden="true"
          />
          <Input
            type="search"
            value={query}
            onChange={(e) => setQuery(e.target.value)}
            placeholder="Search the docs..."
            aria-label="Search"
            className="h-11 bg-background pl-10"
          />
        </div>

        <p className="text-sm text-muted-foreground tabular-nums">
          {filtered.length} {filtered.length === 1 ? "Result" : "Results"}
        </p>

        {filtered.length === 0 ? (
          <div className="rounded-lg border border-border bg-background px-4 py-12 text-center text-sm text-muted-foreground">
            No results for &ldquo;{query}&rdquo;.
          </div>
        ) : (
          <ul className="flex flex-col gap-3">
            {filtered.map((result) => (
              <li
                key={result.title}
                className="flex flex-col gap-2 rounded-lg border border-border bg-background p-4 transition-colors hover:border-muted-foreground/40"
              >
                <div className="flex items-center justify-between gap-3">
                  <Badge variant="secondary">{result.type}</Badge>
                  <span className="text-xs text-muted-foreground tabular-nums">
                    Updated {result.updated}
                  </span>
                </div>
                <a
                  href="#"
                  className="text-sm font-semibold text-foreground hover:underline"
                >
                  {result.title}
                </a>
                <p className="text-sm/relaxed text-muted-foreground">
                  {result.snippet}
                </p>
              </li>
            ))}
          </ul>
        )}
      </div>
    </section>
  )
}
```
