# Morph Search: Docs Search

> A docs header with a fake search field that becomes the real one. Press / to open it from anywhere.

A shadcn/ui block from the [@keyframeui](https://keyframeui.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/keyframeui/morph-search-docs-demo).

- Page, with a live preview: https://shadcn.exchange/r/keyframeui/morph-search-docs-demo
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/keyframeui/morph-search-docs-demo-light-e9db7978be1609c9.png
- Registry item: https://keyframeui.com/r/morph-search-docs-demo.json
- Categories: search, command-menu, motion
- Listed: 2026-10-14, source last changed 2026-10-15

## Install

```bash
npx shadcn@latest add https://keyframeui.com/r/morph-search-docs-demo.json
```

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

## Dependencies

- Registry items: `https://keyframeui.com/r/morph-search.json`

## Notes from the registry

Live preview, examples and props: https://keyframeui.com/components/morph-search#morph-search-docs-demo

## Files

### `registry/demos/morph-search-docs-demo.tsx`

```tsx
"use client";

import * as React from "react";
import { motion, useReducedMotion } from "motion/react";

import { MorphSearch, MorphSearchIcon, type MorphSearchItem } from "@/components/ui/morph-search";

const page = (
  <svg aria-hidden viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.75} strokeLinecap="round" strokeLinejoin="round">
    <path d="M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9ZM14 3v6h6" />
  </svg>
);
const heading = (
  <svg aria-hidden viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.75} strokeLinecap="round">
    <path d="M4 9h16M4 15h16M10 3 8 21M16 3l-2 18" />
  </svg>
);

const docs: MorphSearchItem[] = [
  { id: "introduction", group: "Getting started", label: "Introduction", description: "What Glide is, and isn't", icon: page },
  { id: "installation", group: "Getting started", label: "Installation", description: "Add Glide to Next.js or Vite", icon: page, keywords: ["install", "setup", "npm"] },
  { id: "quick-start", group: "Getting started", label: "Quick start", description: "Your first component in five minutes", icon: page },
  { id: "cli", group: "Getting started", label: "CLI", description: "Commands and flags", icon: page, keywords: ["terminal"] },
  { id: "button", group: "Components", label: "Button", description: "Actions, links and loading states", icon: page },
  { id: "dialog", group: "Components", label: "Dialog", description: "Modal windows that trap focus", icon: page, keywords: ["modal"] },
  { id: "popover", group: "Components", label: "Popover", description: "Floating panels anchored to a trigger", icon: page },
  { id: "tabs", group: "Components", label: "Tabs", description: "Switch between related views", icon: page },
  { id: "toast", group: "Components", label: "Toast", description: "Brief, non-blocking messages", icon: page, keywords: ["notification"] },
  { id: "theming", group: "Guides", label: "Theming", description: "Colors, radii and fonts", icon: page, keywords: ["css", "tokens"] },
  { id: "css-variables", group: "Guides", label: "CSS variables", description: "Theming", icon: heading, keywords: ["tokens"] },
  { id: "dark-mode", group: "Guides", label: "Dark mode", description: "Follow the system or a toggle", icon: page },
  { id: "animation", group: "Guides", label: "Animation", description: "Springs, easing and reduced motion", icon: page, keywords: ["motion"] },
  { id: "reduced-motion", group: "Guides", label: "Reduced motion", description: "Animation", icon: heading },
];

const suggested = ["installation", "dialog", "theming", "animation"].map((id) => ({
  ...docs.find((doc) => doc.id === id)!,
  group: "Suggested",
}));

export function MorphSearchDocsDemo() {
  const [doc, setDoc] = React.useState(docs[0]);
  const reduceMotion = useReducedMotion();

  return (
    <div className="w-full max-w-3xl overflow-hidden rounded-xl border border-zinc-200 bg-white dark:border-zinc-800 dark:bg-zinc-950">
      <header className="flex h-14 items-center gap-4 border-b border-zinc-200/80 px-4 dark:border-zinc-800/80">
        <span className="flex shrink-0 items-center gap-2 text-sm font-semibold text-zinc-900 dark:text-zinc-50">
          <span aria-hidden className="size-5 rounded-full bg-linear-to-br from-sky-400 to-emerald-400" />
          Glide
          <span className="rounded-full bg-zinc-100 px-1.5 py-0.5 font-mono text-[10px] font-normal text-zinc-500 dark:bg-zinc-900">
            v3
          </span>
        </span>
        <MorphSearch
          variant="palette"
          hotkey="/"
          items={docs}
          suggestions={suggested}
          placeholder="Search documentation…"
          onSelect={(item) => setDoc(item)}
          className="mx-auto h-9 w-full max-w-64 justify-start gap-2.5 rounded-lg bg-zinc-50 px-2.5 dark:bg-zinc-900/60"
        >
          <MorphSearchIcon />
          <span className="truncate">Search docs…</span>
          <kbd className="ml-auto rounded-[5px] bg-background px-1.5 py-0.5 font-mono text-[10.5px] ring-1 ring-foreground/10">
            /
          </kbd>
        </MorphSearch>
        <span className="hidden shrink-0 text-sm text-zinc-500 sm:block">GitHub</span>
      </header>

      <motion.article
        key={doc.id}
        initial={{ opacity: 0, y: reduceMotion ? 0 : 6 }}
        animate={{ opacity: 1, y: 0 }}
        transition={{ duration: 0.3, ease: "easeOut" }}
        className="px-6 pt-10 pb-14 sm:px-10"
      >
        <p className="text-xs text-zinc-500">
          Docs <span className="px-1 text-zinc-300 dark:text-zinc-700">/</span> {doc.group}
        </p>
        <h2 className="mt-3 text-3xl font-semibold tracking-tight text-zinc-900 dark:text-zinc-50">
          {doc.label}
        </h2>
        <p className="mt-2 text-sm text-zinc-500">{doc.description}.</p>
        <div className="mt-8 space-y-2.5">
          {["w-full", "w-11/12", "w-4/5", "w-2/3"].map((line) => (
            <span key={line} className={`block h-2.5 rounded-full bg-zinc-100 dark:bg-zinc-900 ${line}`} />
          ))}
        </div>
        <p className="mt-10 font-mono text-xs text-zinc-500">Press / to search.</p>
      </motion.article>
    </div>
  );
}
```
