# Planes > Planes — interactive components for modern interfaces. A set of beautifully crafted React components and interactions you can customize, extend, and build on. Planes is a shadcn-style registry, not an npm package. The shadcn CLI writes real `.tsx` source files into the consuming project, so every component is owned and editable by the person who installs it. Built with React 19, Next.js, Tailwind CSS v4, TypeScript, and Motion — Motion is the only runtime animation dependency. There are two tiers across 91 components. The 80 Pro components require a Planes Pro license. One-time setup registers the `@useplanes` namespace in `components.json` and puts the key in `.env.local` (`npx @useplanes/cli init --key your_key`), after which Pro components install by name: ``` npx shadcn add @useplanes/command-palette ``` The 11 free components install from a public registry URL with no account: ``` npx shadcn add https://useplanes.com/r/segmented-control.json ``` The gated registry validates the license on every request, so Pro install commands fail without a valid key. Each component entry below carries its install command, what it is for, a usage snippet, and its props; the linked page adds a live demo. ## When to use Planes Reach for Planes when: - You are building a React or Next.js app with Tailwind CSS and need a polished, animated UI piece — a carousel, marquee, card stack, command palette, knob, or full hero section — without writing the motion code from scratch. - You want the component's source inside the project. Every install writes editable `.tsx` files via the shadcn CLI; there is no runtime package to configure or fork. - You are an agent installing components for a user: point the shadcn MCP server at Planes (see the MCP doc below) and add components from natural language, or run the exact install command listed next to each component in this file. Planes is not a fit for non-React stacks, projects without Tailwind CSS v4, or teams that want a versioned npm dependency instead of owned source. How to call it: free components — `npx shadcn add ` (URLs listed below). Pro components — run `npx @useplanes/cli init --key your_key` once, then `npx shadcn add @useplanes/`. ## Docs - [Introduction](https://useplanes.com/components/introduction): What Planes is, what it is built on, and how the registry distributes source instead of a package. - [Installation](https://useplanes.com/components/installation): Install free components from the public registry URL, or configure the @useplanes registry with a license key for Pro. - [MCP](https://useplanes.com/components/mcp): Point the shadcn MCP server at Planes so agents like Claude Code and Cursor can browse and install components from natural language. Includes a snippet to paste into your project's AGENTS.md. - [All components](https://useplanes.com/components): The full catalog, grouped by category, with a live demo, props table, and install command per component. - [Hero sections](https://useplanes.com/components/heroes): Gallery page for the hero components; individual hero slugs redirect here. - [Login pages](https://useplanes.com/components/logins): Gallery page for the login components; individual login slugs redirect here. - [Developer portal](https://useplanes.com/developers): HTTP API, authentication with a license key, rate limits, error format, CLI, and MCP — everything needed to integrate programmatically. - [OpenAPI spec](https://useplanes.com/openapi.json): OpenAPI 3.1 document for the registry, license, and checkout endpoints. - [Full component reference](https://useplanes.com/llms-full.txt): Every component with its usage snippet, props, and examples in one file (~150K characters; the per-component pages carry the same content). - [CLI](https://www.npmjs.com/package/@useplanes/cli): `npx @useplanes/cli init --key ` configures the @useplanes registry and license in a project. - [Planes Pro](https://useplanes.com/#pricing): One-time payment for lifetime access to every Pro component and template. Unlimited commercial use, all sales final (no refunds). - [Set up Planes Pro](https://useplanes.com/setup): Activate a license key and wire PLANES_LICENSE_KEY into a project. - [About](https://useplanes.com/about): Who builds Planes and how the project is run. - [Contact](https://useplanes.com/contact): Support email and where to reach the maintainer. ## AI ### Thinking Loader Free. An AI thinking pill that cycles through phase labels like Searching and Writing, then pops a check when it finishes. Page: https://useplanes.com/components/thinking-loader Install: `npx shadcn add https://useplanes.com/r/thinking-loader.json` Use for: LLM response latency (Keep users informed while a model thinks, searches, and writes); Multi-step jobs (Surface pipeline stages (uploading, processing, finishing) with real labels); Agent activity (Show what an autonomous agent is doing right now); Search-in-progress (A premium alternative to a spinner for RAG-backed search). ```tsx import { ThinkingLoader } from "@/components/ui/ThinkingLoader"; ``` Props: - phases (string[]) — Labels to cycle through. Defaults to a Thinking → Writing sequence. - interval (number, default 2200) — Milliseconds each phase is shown. - loop (boolean, default true) — Restart from the first phase after the last. - done (boolean, default false) — Settles the pill into a green check + Done state. - className (string) — Tailwind classes on the pill. ### AI Prompt Composer Pro. An AI chat composer with an auto-growing input, a model picker, and a send button that turns into a stop button while a response streams. Page: https://useplanes.com/components/ai-prompt-composer Install: `npx shadcn add @useplanes/ai-prompt-composer` Use for: Chat app composer (The main input for a chatbot or assistant, with model switching built in); AI search bar (A prompt box that kicks off a generation or retrieval flow); Agent command input (Send instructions to an agent and stop a run that is taking too long); Support copilot (An embedded composer for an in-product AI helper). ```tsx import { AIPromptComposer } from "@/components/ui/AIPromptComposer"; send(text, model)} /> ``` Props: - onSubmit ((text: string, modelId: string) => void) — Fired when the user sends a message. - onStop (() => void) — Fired when the stop button is pressed mid-stream. - streaming (boolean) — Controlled streaming state. When set, the send button shows stop. Leave undefined to let the component simulate a stream on submit. - models ({ id: string; label: string }[]) — Models shown in the picker. Defaults to a small Claude lineup. - defaultModel (string) — Id of the model selected on first render. - placeholder (string, default "Ask anything...") — Placeholder text for the input. - className (string) — Tailwind classes on the root container. ### Streaming Message Pro. An assistant message that develops in like ink — a soft-feathered edge sweeps down the text with an iridescent glow riding the write-frontier, then copy, regenerate, and feedback actions fade in without shifting the layout. Page: https://useplanes.com/components/streaming-message Install: `npx shadcn add @useplanes/streaming-message` Use for: Chat responses (Render assistant replies as they stream from the model); Generated copy (Reveal AI-written summaries or drafts with a live, typing feel); Inline answers (Stream a short answer under a search box or command result); Onboarding tips (Animate a friendly message the first time a user lands somewhere). ```tsx import { StreamingMessage } from "@/components/ui/StreamingMessage"; regenerate()} /> ``` Props: - content (string) — The full message text. It is revealed word by word. - speed (number, default 55) — Milliseconds between each word as it streams in. - autoPlay (boolean, default true) — Start streaming on mount. Set false to show the full message immediately. - onRegenerate (() => void) — Fired when the regenerate action is pressed (also replays the stream). - className (string) — Tailwind classes on the root container. ### Reasoning Trace Pro. A collapsible thinking panel that streams reasoning steps one at a time, then folds down to a short summary you can reopen. Page: https://useplanes.com/components/reasoning-trace Install: `npx shadcn add @useplanes/reasoning-trace` Use for: Chain-of-thought UI (Show a model's reasoning steps, then collapse to a summary like o1 or Claude); Agent step log (Stream what an agent is doing before it returns a result); Tool-call trace (Reveal the steps a RAG or tool-using flow took to answer); Debug panel (A collapsible, readable trace of an automated process). ```tsx import { ReasoningTrace } from "@/components/ui/ReasoningTrace"; ``` Props: - steps (string[]) — Reasoning lines, revealed one at a time while thinking. - stepDelay (number, default 850) — Milliseconds between each step appearing. - autoPlay (boolean, default true) — Start streaming steps on mount. - className (string) — Tailwind classes on the root container. ### Tool Call Card Pro. The inline row an agent leaves when it uses a tool: a mono call signature like read_file(page.tsx), the tool's glyph with a spinner that resolves into a drawn check, a note that shimmers while it runs, and a panel that unfolds to the arguments and result. Page: https://useplanes.com/components/tool-call-card Install: `npx shadcn add @useplanes/tool-call-card` Use for: Agent transcripts (Every tool the assistant calls gets a row the user can open, so the chat stays readable while nothing is hidden); Coding assistants (Read, search, and edit calls stacked above a reply, the way Cursor and Claude Code render them); RAG and search products (Show the retrieval step with its query and the documents it returned before the answer streams); Workflow runners (One card per step in an automation, with failures surfacing inline instead of in a log). ```tsx import { ToolCallCard } from "@/components/ui/ToolCallCard"; ``` Props: - name* (string) — Tool identifier, rendered in mono as name(firstArg) like a call signature. - label (string) — Plain-language note shown after the mono tool signature, e.g. "Read the page". Shimmers while running. - args (Record | string) — Call arguments. The first value previews in the header; all of them list in the panel. - result (string) — Output shown in the panel once status is done. - error (string) — Failure message. In autoPlay mode its presence makes the call end in the error state. - status ("pending" | "running" | "done" | "error") — Controlled status. Drive it from your stream; omit to let autoPlay run a demo lifecycle. - autoPlay (boolean, default true) — Uncontrolled mode: pending, then running, then done or error on a timer. - runDuration (number, default 1600) — Milliseconds spent in the running state under autoPlay. - startDelay (number, default 0) — Milliseconds to wait before autoPlay starts, for chaining several cards. - icon (ReactNode) — The tool's glyph, shown at the start of the row. Status is drawn over its corner. Defaults to a wrench. - defaultOpen (boolean, default false) — Start with the arguments and result panel expanded. - onComplete ((status) => void) — Fires once when the call reaches done or error. - className (string) — Tailwind classes on the card. Drive it from a real stream: Pass status yourself and the card follows your tool lifecycle instead of the demo timer. ```tsx const [call, setCall] = useState({ status: "running", result: "" }); ``` Chain several calls: Mount each row when its call starts, inline with the assistant's text. A tool call has no pending state in a real transcript. ```tsx {events.map((e) => e.type === "tool" ? :

{e.text}

)} ``` ### Agent Plan Pro. A plan that behaves like an agent's plan: steps light up along a rail that fills as they finish, the active one breathes and shimmers its sub-status, failures insert recovery steps that slide the list apart, and the whole thing folds into one line when it's done. Page: https://useplanes.com/components/agent-plan Install: `npx shadcn add @useplanes/agent-plan` Use for: Agent task lists (The live plan Claude Code and Cursor show while they work, including the steps they add when something fails); Multi-step forms and setups (Onboarding or deployment flows where the system does the work and the user watches it land); Background jobs (Imports, migrations and builds with a stage list that folds into a one-line receipt); Checkout and order tracking (Any sequence with a current stage, finished stages and a rail between them). ```tsx import { AgentPlan } from "@/components/ui/AgentPlan"; ``` Props: - steps* (PlanStep[]) — Controlled list. Each step is { id, title, detail?, status?, duration? }. Change statuses, insert, remove or reorder and every transition animates. Keep ids stable. - title (string, default "Plan") — Header label while the plan is in progress. Replaced by the completion summary. - collapseOnComplete (boolean, default true) — Fold the steps away once every step is done, failed or skipped. The header still reopens them. - defaultOpen (boolean, default true) — Start with the steps expanded. - onComplete (() => void) — Fires once when the last step settles. - className (string) — Tailwind classes on the root. Recover from a failure: Mark a step failed and splice a recovery step after it. The rows below slide down to make room. ```tsx setSteps((prev) => { const i = prev.findIndex((s) => s.id === "test"); const failed = { ...prev[i], status: "failed", detail: "1 test failed" }; const fix = { id: "fix", title: "Update the snapshot", status: "active" }; return [...prev.slice(0, i), failed, fix, ...prev.slice(i + 1)]; }); ``` Skip with a reason: A skipped step strikes through and keeps its detail as the explanation. ```tsx { id: "docs", title: "Update the docs", status: "skipped", detail: "No docs mention this page" } ``` ### AI Chat Pro. A full chat experience that ties the AI components together. Send a prompt and watch the reasoning stream, the reply type out, and the view pin to the bottom. Page: https://useplanes.com/components/ai-chat Install: `npx shadcn add @useplanes/ai-chat` Use for: Chatbot UI (A complete, ready-to-skin chat surface for an AI product); Support assistant (An embedded help chat with streaming answers and reasoning); In-app copilot (A side panel that composes prompts, reasoning, and replies); Demo and prototypes (Show off a chat flow without wiring a backend). ```tsx import { AIChat } from "@/components/ui/AIChat"; ``` Props: - script (ChatTurn[]) — An ordered, single-topic conversation. The composer is prefilled with each turn's question; pressing send streams that turn's answer (and optional reasoning), then prefills the next question. - greeting (string, default "Let's build something.") — Headline shown in the empty state. - greetingHint (string, default "Press send to start the conversation.") — Sub-text in the empty state. - title (string, default "New Chat") — Header title. - subtitle (string, default "How can I help you today?") — Header subtitle. - headerLeading (ReactNode) — Rendered before the title in the header, for an avatar or status dot. - onClose (() => void) — When set, a close button appears in the header and calls this. - className (string) — Tailwind classes on the root container. ### Inline Diff Pro. A code change streaming in the way an agent writes it: removed lines strike through first, each block of additions develops in from a blur top to bottom, unchanged context folds away, and Accept or Reject collapses the losing side out of the block. Page: https://useplanes.com/components/inline-diff Install: `npx shadcn add @useplanes/inline-diff` Use for: Coding agents (Show the edit an assistant is making as it writes it, with the user deciding at the end); AI rewrite suggestions (Prose, config or SQL changes proposed by a model, reviewed line by line); Pull request summaries (A compact, animated patch for release notes or changelog pages); Migration previews (Show what a codemod will do to a file before the user runs it). ```tsx import { InlineDiff } from "@/components/ui/InlineDiff"; ``` Props: - before* (string) — Original source. Diffed line by line against after with a built-in LCS, no dependency. - after* (string) — Edited source. - fileName (string) — Path shown in the header. - context (number, default 2) — Unchanged lines kept around each change. Longer runs fold into an expandable row. - autoPlay (boolean, default true) — Play the change in on mount: removed lines strike through first, then each block of additions develops in from a blur, top to bottom. - speed (number, default 140) — Pace of the reveal in milliseconds per added line. A block's develop time scales with its line count, clamped between 0.55s and 1.4s. - startDelay (number, default 0) — Milliseconds before streaming begins. - decision ("pending" | "accepted" | "rejected") — Controlled decision. Accepted collapses the removed lines and clears the tints; rejected collapses the additions. - showActions (boolean, default true) — Show Accept and Reject in the header once streaming finishes. - onComplete (() => void) — Fires when the last line has streamed in. - onAccept (() => void) — Accept pressed. - onReject (() => void) — Reject pressed. - className (string) — Tailwind classes on the block. Static patch: Turn off autoPlay and hide the actions to show a finished change. ```tsx ``` Own the decision: Control decision when the accept happens elsewhere, like a toolbar for the whole file set. ```tsx ``` ### Approval Card Pro. The permission prompt an agent shows before a risky action: a risk badge and mono command, Allow with a countdown ring that pauses while you hover, Deny that shakes the card, then the whole thing folds into a one-line receipt. Page: https://useplanes.com/components/approval-card Install: `npx shadcn add @useplanes/approval-card` Use for: Coding agents (Gate shell commands, file writes, and git pushes the way Claude Code and Cursor do, inline in the transcript); Browser and computer-use agents (Confirm a purchase, a form submit, or a sent email before the agent clicks); Workflow automations (A human-in-the-loop step between two automated ones, with a timer for approvals that are usually fine); Admin and ops tools (Any destructive action a bot proposes, with the risk level set from your own policy engine). ```tsx import { ApprovalCard } from "@/components/ui/ApprovalCard"; respond(decision)} /> ``` Props: - title* (string) — What the agent is asking to do, e.g. "Run command" or "Edit file". - description (string) — One sentence of context under the title explaining why. - command (string) — The exact action in mono: a shell command, a file path, an API call. Its first line becomes the receipt detail after a decision. - risk ("low" | "medium" | "high", default "medium") — Tints the badge and border: zinc, amber, or red. Labels read Low risk, Needs review, Destructive. - icon (ReactNode) — Glyph in the top-left tile. Defaults to a shield. - autoApproveIn (number, default 0) — Seconds until Allow fires on its own. Draws a countdown ring inside the button that pauses while the pointer or focus is on the card. 0 disables it. - allowAlways (boolean, default true) — Show the Always allow button between Allow and Deny. - allowLabel (string, default "Allow") — Label for the primary button. Enter triggers it while the card has focus. - alwaysLabel (string, default "Always allow") — Label for the remember-this-choice button. - denyLabel (string, default "Deny") — Label for the deny button. Escape triggers it while the card has focus. - decision ("allow" | "always" | "deny" | null) — Controlled decision. Pass null while waiting and the chosen value once your backend has recorded it; omit to let the card manage it. - collapseOnDecide (boolean, default true) — Fold the card into a one-line receipt after a decision. Set false to keep the prompt visible and append the receipt below it. - children (ReactNode) — Detail rendered between the command and the buttons. Drop an InlineDiff here for edit requests, or a preview of what the agent is about to send. - onDecide ((decision) => void) — Fires once with the choice, including an automatic allow from the countdown. - className (string) — Tailwind classes on the card. Gate a tool call: Render the tool row in its pending state with the card beneath it, then flip the row to running once the user allows. Deny ends the row in error. ```tsx {status === "pending" && ( (d === "deny" ? setDenied(true) : resume(d))} /> )} ``` Edit requests carry the diff: Put an InlineDiff in the children slot so the user approves what they can see, not a file path. ```tsx ``` Auto-approve the routine ones: Low-risk actions can carry a short timer. Hovering the card pauses it, so nobody gets approved past while reading. ```tsx ``` Keep the prompt on screen: For audit views, leave the request visible and let the receipt append underneath. ```tsx ``` ### Chat Orb Pro. The chatbot launcher for any site: a small sphere with pill eyes that blink and follow your cursor, a teaser bubble that pops in, and a press that morphs the orb into the full AI Chat with its face shrinking into the header. Page: https://useplanes.com/components/chat-orb Install: `npx shadcn add @useplanes/chat-orb` Use for: Site-wide support bot (Drop it in the root layout and every page gets a launcher that feels alive); Docs assistant (An always-there helper that opens into a scripted or live chat); Product onboarding (The teaser nudges new users, the orb watches them until they click); Marketing demo (Show your AI product with a mascot instead of a generic chat icon). ```tsx import { ChatOrb } from "@/components/ui/ChatOrb"; ``` Props: - position ("bottom-right" | "bottom-left" | "inline", default "bottom-right") — Fixed to a page corner, or inline to fill a container you position yourself. - teaser (string, default "Hi there! Need a hand?") — Speech bubble that pops in next to the orb until it is opened. Pass an empty string to disable. - teaserDelay (number, default 1400) — Milliseconds before the teaser appears. - defaultOpen (boolean, default false) — Start with the chat panel open. - chat (AIChatProps) — Props forwarded to the AIChat rendered inside the panel: title, subtitle, greeting, script. - panelClassName (string) — Tailwind classes on the expanded panel, for size overrides. - className (string) — Tailwind classes on the root container. ## Media ### Link Preview Pro. Hyperlinks that show an image tooltip on hover, tracking your cursor with a parallax tilt on the artwork. Page: https://useplanes.com/components/link-preview Install: `npx shadcn add @useplanes/link-preview` Use for: Editorial article body (Inline links in long-form blog posts that preview the destination without a click); Wiki / docs cross-references (Replace plain `[term]` links with a glanceable preview of the target page); Changelog entries (Link to PRs, designs, or videos with an instant thumbnail); Mentions in chat / comments (@-mentions of people or projects that expand into an avatar / cover on hover). ```tsx import { LinkPreview } from "@/components/ui/LinkPreview";

Read more about{" "} Spy × Family .

``` Props: - href* (string) — Destination URL for the underlying anchor. - src* (string) — Preview image shown in the hover tooltip. - alt (string) — Alt text for the preview image. - width (number, default 200) — Preview tooltip width in px. - height (number, default 140) — Preview tooltip height in px. - children* (ReactNode) — The visible link text. - className (string) — Classes applied to the anchor. ### Direction-Aware Flip Card Pro. A flip card that swings toward the side your cursor enters from, with a tracked sheen, parallax tilt, and a lifting shadow. Page: https://useplanes.com/components/direction-aware-flip-card Install: `npx shadcn add @useplanes/direction-aware-flip-card` Use for: Trading-card / collectibles UI (Reveal alternate art or stats on the back of a card without leaving the page); Pricing tier compare (Flip from headline pricing to detailed feature breakdown); Profile / member card (Front: portrait + name. Back: bio + links); Event ticket / boarding pass (Cover art on the front, QR code and itinerary on the back of a digital pass). ```tsx import { DirectionAwareFlipCard } from "@/components/ui/DirectionAwareFlipCard"; ``` Props: - frontSrc* (string) — Image shown on the front face. - backSrc* (string) — Image shown on the back face. - frontAlt (string) — Alt text for the front image. - backAlt (string) — Alt text for the back image. - width* (number) — Card width in px. - height* (number) — Card height in px. - radius (number, default 20) — Border radius in px. - duration (number) — Flip duration in seconds. Used as a fallback when the spring is disabled. - className (string) — Classes merged onto the card root. ### Hover Reveal Pro. A two-column client index. Hover a name and its preview scales into focus while the row drifts under your cursor. Page: https://useplanes.com/components/hover-reveal Install: `npx shadcn add @useplanes/hover-reveal` Use for: Client / logo wall (Replace a static logo grid with an editorial index that rewards exploration); Team page (List of team members with portrait reveals on hover); Case studies index (Studio / agency site listing recent projects, each with a representative cover); Press / press kit (Editorial list of features and mentions, each with a hero shot of the publication). ```tsx import { HoverReveal } from "@/components/ui/HoverReveal"; ``` Props: - items* (HoverRevealItem[]) — List of `{ name, src, alt? }`. 2–12 entries works best for the typography rhythm. - label (string | null, default "Clients") — Small uppercase label above the list. Pass `null` to hide. - defaultActiveIndex (number, default 0) — Initial active row for uncontrolled use. - activeIndex (number) — Controlled active index. When provided, the component is fully controlled. - onActiveChange ((index: number) => void) — Fires whenever the active index changes (hover, focus, click, keyboard). - imageAspect (string, default "4/5") — CSS aspect-ratio for the mobile image frame. - imageMinHeight (number | string, default "34rem") — Min height of the desktop frame. Numbers are treated as px. - formatIndex ((index: number) => string) — Custom formatter for the index column. Defaults to zero-padded `01`, `02`… - hideIndex (boolean, default false) — Hide the index column entirely. - imageZoom (number, default 1.4) — Starting scale of an entering image — zooms from this down to 1. - imageScaleDuration (number, default 1.4) — Duration of the image zoom-out, in seconds. - disableParallax (boolean, default false) — Disable cursor-driven parallax on the active image. - disableFloat (boolean, default false) — Disable the idle vertical float. - disableMagnetic (boolean, default false) — Disable the magnetic pull on row text. - disableSkew (boolean, default false) — Disable the skew on the active row. - className (string) — Classes applied to the root. - imageClassName (string) — Classes applied to the image element inside the frame. ### Hero Card Stack Pro. A fanned arc of overlapping artwork cards. Hover one and it springs forward while its neighbors nudge aside. Page: https://useplanes.com/components/hero-card-stack Install: `npx shadcn add @useplanes/hero-card-stack` Use for: Portfolio heroes (Lead a creative platform's landing page with a fanned wall of community artwork); Marketplace showcases (Surface featured listings or designs with attributed creator badges); Gallery teasers (Preview a collection where hovering lifts each piece into focus); Community highlights (Spotlight user contributions with floating @handle callouts). ```tsx import { HeroCardStack } from "@/components/ui/HeroCardStack"; ``` Props: - items* (HeroCardStackItem[]) — Artwork cards: src and optional alt. Rendered as a fanned, overlapping row. - badges (HeroCardStackBadge[], default []) — Floating handle pills: label, cardIndex to anchor above, and optional color. - cardWidth (number, default 168) — Card width in px. - cardHeight (number, default 168) — Card height in px. - overlap (number, default 44) — How many px each card overlaps its left neighbor. - maxRotation (number, default 14) — Rotation in degrees of the outermost cards in the fan. - className (string) — Tailwind classes on the root container. ### Swipe Card Deck Pro. A swipeable card deck. The front card drags off in your swipe direction, then tucks behind a fanned stack. Built for touch, with a reduced-motion fallback. Page: https://useplanes.com/components/swipe-card-deck Install: `npx shadcn add @useplanes/swipe-card-deck` Use for: Mobile-first browsing (Tinder-style swiping through cards, profiles, or products on touch devices); Onboarding decks (Step users through a stack of intro cards one swipe at a time); Content shuffles (Cycle featured items where dismissed cards loop to the back of the deck); Responsive fallback (Drop-in mobile presentation for fanned or grid layouts that don't fit small screens). ```tsx import { SwipeCardDeck } from "@/components/ui/SwipeCardDeck"; ``` Props: - items* (SwipeCardDeckItem[]) — Deck cards: src and optional alt. The front card is draggable; dismissed cards cycle to the back. - hint (string | null, default "Swipe") — Caption shown below the deck. Pass null to hide it. - showCaption (boolean, default true) — Overlay the front card's alt text as a gradient caption. - offsetX (number, default 14) — Horizontal px each card behind is nudged, building the fan. - offsetY (number, default 12) — Vertical px each card behind drops. - rotateStep (number, default 3.5) — Degrees of tilt added per depth so the back cards splay. - scaleStep (number, default 0.05) — Scale reduction per depth for the receding-stack effect. - className (string) — Tailwind classes on the root container. ### GitHub Chart Pro. A GitHub contribution graph with a linked profile header, hover tooltips, and a staggered reveal. Point it at any username for live data, or feed it your own counts. Page: https://useplanes.com/components/github-chart Install: `npx shadcn add @useplanes/github-chart` Use for: Portfolio activity proof (Show your real GitHub cadence with a single username prop); Team dashboards (Render one chart per engineer from live data); Any streak data (Feed the data prop daily counts of anything — commits, workouts, writing streaks); Landing page texture (The generated mode ships an organic-looking graph with zero setup). ```tsx import { GithubChart } from "@/components/ui/GithubChart"; ``` Props: - username (string) — GitHub username. Fetches the profile's real contribution calendar (cell levels match github.com) and shows the avatar and username as a linked header. While loading it renders an empty grid (or your data counts); on failure it stays empty rather than showing fake activity. - weeks (number, default 52) — How many trailing weeks to render. - data (number[]) — Explicit per-day contribution counts, oldest first. Without a username it drives the chart; with one it doubles as the placeholder while live data loads. - seed (number, default 22) — Seed for the generated placeholder data. - tone ("green" | "neutral", default "green") — Cell palette: GitHub's native greens or a monochrome scale. - endDate (string, default today) — Last day of the generated range (YYYY-MM-DD). Defaults to the current date. Ignored when username or data supply real dates. - title (string | null) — Summary line shown under the grid beside the legend. Defaults to the contribution total; pass null to hide. - showLegend (boolean, default true) — Show the Less-to-More legend row. - className (string) — Tailwind classes on the card. ### Avatar Cluster Pro. Avatars fly in from the blurred foreground and pack into a slowly orbiting rosette, computed for any head-count. Page: https://useplanes.com/components/avatar-cluster Install: `npx shadcn add @useplanes/avatar-cluster` Use for: Social proof (Form a ring of customer or community avatars as a hero section loads); Waitlist counters (Pair the ring with a centered "+2,140" count via the children slot); Team introductions (Snap the team into place on an about page, reshuffling on replay); Call participants (Announce everyone joining a room or session with one settling motion). ```tsx import { AvatarCluster } from "@/components/ui/AvatarCluster"; ``` Props: - images* ((string | AvatarClusterImage)[]) — Avatar image URLs — plain strings or `{ src, alt? }` objects. Positions are computed from the count, so any number works. - layout ("rosette" | "ring", default "rosette") — Rosette pins the first image at the center and packs the rest around it; ring places every image on the circle. - size (number, default 320) — Square stage size in px. Clamped to the parent's width, with every length scaling down proportionally, so the cluster never overflows narrow screens. - avatarSize (number, default 64) — Avatar diameter in px at the full stage size. - ringRadius (number) — Radius of the ring. Defaults to a radius derived from the count and `overlap` so the cluster packs tightly. - overlap (number, default 0.15) — Fraction (0–0.9) of the avatar size that ring neighbours may overlap. - centerGap (number, default 10) — Clear space in px between the center avatar's edge and the ring avatars in rosette layout. - centerScale (number, default 1.12) — Size multiplier for the center avatar so it reads as the anchor. Pass 1 for uniform sizing. - startAngle (number, default -90) — Angle in degrees of the first ring avatar (default 12 o'clock). - scatterSpread (number, default 1.6) — How far out avatars start, as a multiple of the cluster extent — past the stage edge by default. - scatterSeed (number, default 7) — Seed for the deterministic scatter — SSR-safe, no render-time randomness. - scatterBlur (number, default 16) — Gaussian blur in px on incoming avatars, so they read as out-of-focus foreground. - scatterScale (number, default 2.4) — Starting scale of incoming avatars — big reads as close to the camera. - scatterOpacity (number, default 0) — Starting opacity. Avatars fade up quickly and stay fully visible mid-flight. - spring ({ stiffness?; damping?; mass? }, default { stiffness: 240, damping: 28, mass: 1 }) — Spring used for the flight into place. - stagger (number, default 0.12) — Per-avatar delay in seconds so arrivals land one after another. - delay (number, default 0.1) — Delay in seconds before the center avatar appears. - orbit (number | false, default 12) — Seconds per revolution of the idle orbit once formed. Positive is counterclockwise, negative clockwise, false disables. Faces stay upright. - glare (boolean, default true) — Sweep a diagonal glare across the center avatar every few seconds, matching the Dot Monogram shimmer cadence. - autoReplay (number | false, default false) — Replay the whole cycle every N ms, reseeding the scatter each time. - replayKey (React.Key) — Change this key to replay the animation imperatively. - children (React.ReactNode) — Rendered at the center of the ring — e.g. a "+128" count or logo. - className (string) — Classes applied to the root stage. - avatarClassName (string) — Classes applied to each avatar image. ### Expanding Card Pro. A feature card that grows from its place in the grid into a full detail view, artwork welded to the card the whole way, with body copy that lands after it settles. Page: https://useplanes.com/components/expanding-card Install: `npx shadcn add @useplanes/expanding-card` Use for: Editorial features ("Story of the day" cards for blogs and galleries that open into the full piece); Portfolio case studies (A project grid where each tile expands into the write-up); Product highlights (Feature announcements that open in place instead of navigating away); Travel and media grids (Image-first cards whose detail view keeps full visual continuity). ```tsx import { ExpandingCard } from "@/components/ui/ExpandingCard";

Expanded editorial copy…

``` Props: - image* (string) — Cover image shared by the card and the expanded view. - title* (string) — Card title, carried through the transition. - eyebrow (string) — Small caps label above the title, e.g. "FEATURED". - subtitle (string) — One-liner pinned to the card's bottom edge. - children (ReactNode) — Expanded body content, revealed after the card lands. - height (number, default 340) — Collapsed card height in px. - className (string) — Tailwind classes on the collapsed card. ### Photo Lightbox Pro. An image grid that flies the tapped photo into a fullscreen viewer. Swipe between shots, then drag down and let go — it shrinks in your hand and flicks back to its cell. Page: https://useplanes.com/components/photo-lightbox Install: `npx shadcn add @useplanes/photo-lightbox` Use for: Travel galleries (Photo journals where each shot opens fullscreen without leaving the page); Product imagery (E-commerce detail shots that zoom to full view and flick away); Portfolio grids (Photography or design work presented with iOS-Photos-grade transitions); Event recaps (Dense image grids for conferences and launches, browsable with swipes and arrow keys). ```tsx import { PhotoLightbox } from "@/components/ui/PhotoLightbox"; ``` Props: - images* ({ src: string; alt?: string; width?: number; height?: number }[]) — Photos shown in the grid and carried into the fullscreen viewer. Intrinsic width and height are optional — measured from the image once it decodes, but supplying them lets the very first open morph straight to the correct aspect ratio instead of settling into it. - columns (number, default 3) — Number of columns in the thumbnail grid. - gap (number, default 8) — Gap between thumbnails, in pixels. - rounded (number, default 14) — Thumbnail corner radius, carried through the open and close morph. - className (string) — Tailwind classes on the grid container. ### Curved Video Player Pro. A YouTube player on an IMAX-style curved screen, backlit by ambient light that tracks playback, with YouTube's own controls left in charge. Letterboxed films are measured and cropped to fit. Page: https://useplanes.com/components/curved-video-player Install: `npx shadcn add @useplanes/curved-video-player` Use for: Product launch page (A hero trailer that feels like a theatre screen instead of an embedded iframe); Course and lesson players (Long-form video that keeps YouTube's own scrubber, captions, and quality controls); Portfolio showreels (Case-study reels lit by their own artwork, with the ambient glow left on); Marketing demos (Feature walkthroughs that stay on-brand around the edges, with playback left to YouTube's own player). ```tsx import { CurvedVideoPlayer } from "@/components/ui/CurvedVideoPlayer"; ``` Props: - videoId* (string) — YouTube video id — the v= part of the watch URL. - title (string) — Shown over the top of the screen and used as the player's accessible name. - poster (string, default YouTube maxresdefault thumbnail) — Still frame used for the idle state and as the source of the ambient backlight. - curve (number, default 0.7) — How far the screen wraps around you, 0 (flat) to 1 (38° of arc). Drives the edge arcs and the side falloff together, so both stay physically consistent. - cornerRadius (number, default 10) — Corner radius of the screen, in pixels. Real screens have near-sharp corners — keep this small or the arcs read as a pillow. - fit ("cover" | "native" | "contain", default "native") — How a letterboxed video fills the screen. The component probes YouTube's preview frames on a canvas to measure the black bars. "native" reshapes the screen to the film's true aspect; "cover" keeps 16:9 and zooms to fill it. Both fully remove the bars, but since that means zooming the whole iframe, YouTube's own control bar can end up partly below the visible frame on a heavily letterboxed video. "contain" skips all of this and shows YouTube's letterboxing (and full control bar) as-is. - ambient (boolean, default true) — Enables the backlight glow. Cross-blends YouTube's still preview frames on a tiny canvas as playback advances — cheap, and works everywhere. - ambientFrames (string[]) — Stills the backlight interpolates through as playback advances, spread evenly across the duration. Defaults to YouTube's four public preview frames (0%, 25%, 50%, 75%); pass your own for tighter tracking. - ambientStrength (number, default 1) — Multiplier on the glow's opacity, clamped to 2. - ambientSpread (number, default 1) — How far the light reaches, clamped to 0.25–2.5. Scales all three blur layers at once, so the falloff keeps its shape as the glow grows. Raising it costs fill rate — the widest layer is the expensive one. - startMuted (boolean, default false) — Starts playback muted. Useful when several players share a page. - loop (boolean, default false) — Restarts the video when it reaches the end. - tilt (boolean, default true) — Cursor-tracked parallax tilt on the screen. Ignored under reduced motion. - className (string) — Tailwind classes on the root container. ### Dither Renderer Pro. Any image, redrawn live as ordered Bayer dither on the GPU. The cursor acts like a loupe — the pattern sharpens and the original colors develop under it. Page: https://useplanes.com/components/dither-renderer Install: `npx shadcn add @useplanes/dither-renderer` Use for: Hero art direction (Turn stock photography into a deliberate e-paper aesthetic instead of a default image); Portfolio and case-study covers (Project thumbnails that develop into full color as the cursor passes over them); Team and about pages (Portraits rendered as a unified dither so mismatched photos read as one set); Dev-tool marketing (The terminal/retro-shading look on product screenshots without baking assets in an editor). ```tsx import { DitherRenderer } from "@/components/ui/DitherRenderer"; ``` Props: - src* (string) — Image to render. Cover-fitted to the container, so size the component with className. Cross-origin images need CORS headers — the pixels are read on the GPU. - pixelSize (number, default 4) — Dither cell size in CSS pixels. 2–3 reads as fine grain, 6+ goes full retro. - darkColor (string, default "#0a0a0a") — Hex color of the dark half of the pattern. - lightColor (string, default "#f4f4f5") — Hex color of the light half of the pattern. - pointerRadius (number, default 180) — Radius of the cursor loupe in CSS pixels. The pattern sharpens toward focusScale inside it. 0 disables pointer reactivity. - focusScale (number, default 0.35) — How much the cells shrink at the loupe's center — 0.35 means cells drop to 35% of pixelSize. Lower = sharper reveal. - revealColor (boolean, default true) — Develops the image's original colors inside the loupe. Off keeps the whole surface duotone. - className (string) — Classes on the container — use these to set the size and aspect ratio. - style (CSSProperties) — Inline styles merged onto the container. ### Photo Stack Pro. A neat deck of photos with the rest peeking out behind the cover. Hover and they slide into a row one by one on a spring. Page: https://useplanes.com/components/photo-stack Install: `npx shadcn add @useplanes/photo-stack` Use for: Trip highlights (A compact pile of travel shots that opens into the full set on hover); Project thumbnails (Case-study cards that tease one cover image and reveal the rest of the gallery); Team or event photos (An about-page moment — a casual stack that spreads into everyone's photo); Product angle shots (Show the hero angle by default and fan out the remaining views without a carousel). ```tsx import { PhotoStack } from "@/components/ui/PhotoStack"; ``` Props: - images* ({ src: string; alt?: string }[]) — Photos in the stack, first item on top of the pile. - photoWidth (number, default 200) — Width of each photo, in pixels. - photoHeight (number, default 250) — Height of each photo, in pixels. - gap (number, default 18) — Gap between photos in the revealed row, in pixels. - peek (number, default 14) — How far each photo behind the top one peeks out, in pixels. - stagger (number, default 0.09) — Delay between each photo's reveal, in seconds. - hint (string | null, default "Hover to reveal") — Caption under the stack. Pass null to hide it. - className (string) — Tailwind classes on the outer wrapper. ### Watch Face Pro. An Apple-style analog clock whose tick ring and numerals wrap the card's own rounded corners, with a vermillion sweeping second hand. Page: https://useplanes.com/components/watch-face Install: `npx shadcn add @useplanes/watch-face` Use for: Bento grid tile (Drop into a portfolio or dashboard grid cell — the tick ring measures the cell and wraps its own rounded corners); World clock row (Render several instances side by side, each with a different timeZone); Personal site footer (A small live clock showing where you're based); Idle / loading state (A ticking second hand doubles as a subtle sign of life while content loads). ```tsx import { WatchFace } from "@/components/ui/WatchFace";
``` Props: - timeZone (string, default "Asia/Kolkata") — IANA time zone the hands are driven from, e.g. "America/New_York". - className (string) — Tailwind classes on the root container. ### Digital Watch Face Pro. The iOS world-clock widget as a live component — a tick ring fills with the passing seconds around rolling digits, a city label, and the offset from your local time. Page: https://useplanes.com/components/digital-watch-face Install: `npx shadcn add @useplanes/digital-watch-face` Use for: World clock row (Render several instances side by side, one per office or teammate time zone — each shows its offset from the viewer); Bento grid tile (Drop into a portfolio or dashboard grid cell — the tick ring measures the cell and wraps its own rounded corners); Remote team dashboard (The relative offset label answers "how far ahead are they?" at a glance); Pair with Watch Face (Use alongside the analog WatchFace for a mixed analog/digital clock cluster). ```tsx import { DigitalWatchFace } from "@/components/ui/DigitalWatchFace";
``` Props: - timeZone (string, default "America/Los_Angeles") — IANA time zone the clock is driven from, e.g. "Asia/Tokyo". - label (string) — City abbreviation shown above the time. Defaults to the first three letters of the time zone's city name. - hour12 (boolean, default true) — 12-hour display without a meridiem, like the iOS widget. Set false for a 24-hour clock. - className (string) — Tailwind classes on the root container. ### Apple Music Card Pro. A now-playing card that resolves tracks straight from iTunes search URLs and plays their previews, shuffling through the list and auto-advancing between songs. Page: https://useplanes.com/components/apple-music-card Install: `npx shadcn add @useplanes/apple-music-card` Use for: Portfolio bento tile (A now-playing card fed by your real listening via iTunes search URLs); Music discovery lists (Rotate through a curated set of tracks with playable previews); Artist or release pages (Give visitors a one-tap preview of the featured song); About pages (A personal touch — the songs you have on repeat, playing in random order). ```tsx import { AppleMusicCard } from "@/components/ui/AppleMusicCard";
``` Props: - itunesUrls (string[]) — iTunes Search API URLs. Each resolves to a track (title, artist, artwork, 30s preview); the list is shuffled and played in random order, auto-advancing when a preview ends. - title (string, default "Midnight Sakura") — Fallback track title shown before iTunes data resolves or when no URLs are passed. - artist (string, default "Late Night Jazz") — Fallback artist name. - artworkUrl (string) — Fallback artwork image. Without it, a placeholder music glyph is shown. - audioUrl (string) — Fallback audio source (e.g. a direct preview URL) used when no itunesUrls are given. - eyebrow (string, default "Recently Played") — Small uppercase label above the title. - className (string) — Tailwind classes on the card. Give the card a definite height (e.g. h-44) — the artwork square derives its size from it. ### Album Cover Pro. A vinyl sleeve player. The record lifts out, spins, and responds to the transport controls. Page: https://useplanes.com/components/album-cover Install: `npx shadcn add @useplanes/album-cover` Use for: Music & podcast products (Now-playing widget on a streaming service or a podcast episode page); Portfolio audio embed (Composer or sound designer site where each track gets a dedicated tactile player); Marketing release pages (Album / single launch landing pages with a single hero cover and preview clip); Audiobook / chapter preview (Sample a chapter on a book detail page with cover art that doubles as the player). ```tsx import { AlbumCover } from "@/components/ui/AlbumCover"; ``` Props: - coverSrc* (string) — Square album artwork. WebP or AVIF recommended. - title* (string) — Track or album title shown above the transport. - subtitle (string) — Artist, album, or any secondary line. - audioSrc (string) — Optional audio file. When present, transport controls drive playback; otherwise they animate visually only. - size (number, default 260) — Square size of the cover in px. Vinyl scales accordingly. - theme ("light" | "dark") — Force a theme. Falls back to the app's color scheme when omitted. - className (string) — Classes merged onto the player wrapper. ### Retro Music Player Pro. A handheld retro media player with a CRT display, a speaker grill, and spring-loaded transport buttons. Page: https://useplanes.com/components/retro-music-player Install: `npx shadcn add @useplanes/retro-music-player` Use for: Music player UI (A characterful player for a portfolio, label site, or playlist page); Podcast or audio embeds (Wrap a single track or episode in a device that stands out); Landing page centerpiece (An interactive hero element for a music or audio product); Now-playing widget (Show the current track with working transport controls). ```tsx import { RetroMusicPlayer } from "@/components/ui/RetroMusicPlayer"; const [playing, setPlaying] = useState(false); setPlaying((p) => !p)} /> ``` Props: - songTitle (string, default "No Signal") — Track title shown on the CRT display. - artist (string) — Artist name shown under the title. - imageUrl (string) — Cover art shown on the display. - mediaUrl (string) — Audio file the transport controls play. - isPlaying (boolean, default false) — Whether playback is active (controlled). - onPlay (() => void) — Fired when the play/pause button is pressed. - onNext (() => void) — Fired when the next button is pressed. - onPrev (() => void) — Fired when the previous button is pressed. ### Progressive Blur Pro. Apple-style scroll-edge blur: content dissolves into stacked backdrop layers that get progressively stronger toward the edge, with an optional tint and room for a floating header or toolbar inside. Page: https://useplanes.com/components/progressive-blur Install: `npx shadcn add @useplanes/progressive-blur` Use for: Scroll containers (Lists and feeds whose last rows melt away instead of clipping against a hard edge); Floating toolbars (A bottom dock or tab bar that reads over any content scrolling beneath it); Sticky headers (A page title that stays legible over photos without an opaque bar); Horizontal strips (Carousels and marquees whose ends soften rather than fade to a color). ```tsx import { ProgressiveBlur } from "@/components/ui/ProgressiveBlur";
{items}
``` Props: - side ("top" | "bottom" | "left" | "right", default "bottom") — Which edge the blur builds toward. - size (number | string, default 96) — Extent of the blurred band along the chosen axis, in px or any CSS length. - blur (number, default 12) — Blur radius at the strongest edge, in px. Seven stacked layers ramp toward it: 0.5, 1, 2, 3, 5, 8, 12 at the default. - tint (string) — Optional color blended over the band, fading in toward the edge. Use your page background at partial alpha. - className (string) — Classes on the wrapper. Add sticky positioning to pin it inside a scroller. - children (ReactNode) — Content laid over the blur, such as a title or toolbar. Receives pointer events. ### Radial Pop-out Pro. A center card ringed by smaller cards. Hovering the center scatters them outward with spring overshoot; leaving snaps them back behind. Page: https://useplanes.com/components/radial-pop-out Install: `npx shadcn add @useplanes/radial-pop-out` Use for: Cast / character explorer (Hero protagonist with supporting characters that scatter on hover — perfect for film, anime, or game pages); Featured collection (A spotlight item with related products fanning out behind it); Team / org spotlight (Highlight a single person with their team scattering around them); Album / playlist hub (Hero release with related tracks, EPs, or remixes radiating out behind it). ```tsx import { RadialPopOut } from "@/components/ui/RadialPopOut"; ``` Props: - hero* (RadialPopOutItem) — Center card. `{ src, alt? }`. - items* (RadialPopOutItem[]) — Secondary cards that scatter radially around the hero. - cardSize (number, default 140) — Pixel size of each secondary card (square). - heroSize (number) — Pixel size of the hero card. Defaults to 1.25× cardSize. - radius (number) — Radius of the radial scatter, in px. Defaults to ~1.05× cardSize. - jitter (number, default 8) — Maximum random tilt applied to scattered cards, in degrees. - stagger (number, default 0.04) — Stagger between each card's entry, in seconds. - maxTilt (number, default 10) — Maximum 3D tilt of the hero card in response to cursor position, in degrees. - shift (number, default 0.08) — Maximum translation of the hero toward the cursor, as a fraction of heroSize (0–1). - className (string) — Classes applied to the root wrapper. ### Hero Media Scroll-Out Pro. A hero screenshot that stands up from a tilted perspective to flat as the visitor scrolls in — transform-only, driven by scroll position. Page: https://useplanes.com/components/hero-media-scroll-out Install: `npx shadcn add @useplanes/hero-media-scroll-out` Use for: SaaS hero (The Vercel/Linear hero screenshot that lies back and stands up as you scroll); Feature section media (Any screenshot below the fold that should arrive with depth); Device mockups (Wrap a phone or laptop frame); Video hero (Works with a muted autoplay video as the child). ```tsx import { HeroMediaScrollOut } from "@/components/ui/HeroMediaScrollOut"; Dashboard ``` Props: - children (ReactNode) — The media — an img, video, or any block element. - tilt (number, default 18) — Starting rotateX in degrees. - scale (number, default 0.9) — Starting scale. - distance (number, default 0.6) — Progress completes when the element's top reaches this fraction of the viewport height. - container (RefObject) — Scroll container to track instead of the window. - frameClassName (string) — Classes on the animated frame (radius, border, shadow). Reduced motion: Renders flat and full-size with no scroll coupling. ```tsx {media} ``` ## Carousels ### Marquee Pro. A velocity-driven marquee that eases to a crawl on hover instead of freezing, pauses for keyboard focus, and can be flung by hand — the engine under logo rows and testimonial bands. Page: https://useplanes.com/components/marquee Install: `npx shadcn add @useplanes/marquee` Use for: Logo walls (Customer logos that keep moving without ever snapping to a stop under the cursor); Testimonial rows (Two rows in opposite directions; keyboard focus on a card pauses so it can be read); Ticker tape (Vertical news or changelog feed in a sidebar); Product screenshots (A draggable strip visitors can fling through). ```tsx import { Marquee } from "@/components/ui/Marquee"; {logos.map((l) => )} ``` Props: - speed (number, default 40) — Travel speed in px/s. - direction ("left" | "right" | "up" | "down", default "left") — Travel direction. Vertical values stack children in a column. - pauseOnHover ("slow" | "stop" | false, default "slow") — How a hover-capable pointer affects speed: ease to 15%, ease to a stop, or ignore. Never fires on touch taps. - draggable (boolean, default false) — Drag to scrub; release flings with pointer velocity that decays back to cruising speed. - paused (boolean, default false) — Controlled pause — wire it to a visible pause button for WCAG 2.2.2. - gap (number, default 16) — Gap between children in px, also used for the seamless wrap. - fade (boolean, default true) — Mask the leading and trailing edges. - className (string) — Classes on the clipping shell. - trackClassName (string) — Classes on each copy of the child row. Two opposing rows: Compose rows; each Marquee owns its own frame loop and pauses when scrolled out of view or the tab is hidden. ```tsx {cards} {cards} ``` Reduced motion: Renders a single static, natively scrollable row with no frame loop and no edge mask. ```tsx {logos} ``` ### Cover Flow Free. A 3D coverflow carousel with spring physics. Navigate by drag, scroll wheel, or keyboard, with optional reflection and audio feedback. Page: https://useplanes.com/components/cover-flow Install: `npx shadcn add https://useplanes.com/r/cover-flow.json` Use for: Music library (Browse album art with a tactile 3D flip — classic iTunes-style navigation for a music or podcast app); Product gallery (Showcase product variants or catalogue items with depth and drama that flat carousels can't match); Portfolio showcase (Present case studies or project covers in a way that invites exploration rather than passive scrolling); Media catalogue (Game, film, or book cover browsers where the 3D perspective communicates hierarchy at a glance). ```tsx import { CoverFlow } from "@/components/ui/CoverFlow"; ``` Props: - items* (CoverFlowItem[]) — Array of items. Each needs `id`, `image`, and `title`. Optional: `subtitle`. - itemWidth (number, default 400) — Width of each card in pixels. - itemHeight (number, default 400) — Height of each card in pixels. - stackSpacing (number, default 100) — Pixel gap between stacked off-center cards. - centerGap (number, default 250) — Pixel distance between the center card and its immediate neighbors. - rotation (number, default 50) — Y-axis rotation in degrees applied to off-center cards. - initialIndex (number, default 0) — Index of the card shown as active on first render. - enableReflection (boolean, default false) — Render a glass-like reflection beneath each card. - enableClickToSnap (boolean, default true) — Clicking an off-center card snaps it to the active position. - enableScroll (boolean, default true) — Horizontal scroll-wheel navigates between cards. - enableAudio (boolean, default false) — Play a synthesized tick sound on each navigation step. - scrollMode ("scrub" | "step", default "scrub") — scrub glides the deck 1:1 with a trackpad's horizontal wheel and snaps to the nearest cover 120ms after the fingers lift, carrying release velocity. step is the previous behavior: deltas accumulate to scrollThreshold and jump one cover. Notched mouse wheels always step. - scrollThreshold (number, default 100) — Accumulated scroll delta required to advance one card. Only used by scrollMode="step" and by notched mouse wheels. - reduceMotion (boolean) — Override the system prefers-reduced-motion setting. - onIndexChange ((index: number) => void) — Fired whenever the active index changes. - onItemClick ((item: CoverFlowItem, index: number) => void) — Fired when the active (center) card is clicked. - renderImage ((props: RenderImageProps) => ReactNode) — Custom image renderer — pass Next.js `` here for framework-native optimisation. - className (string) — Tailwind classes merged onto the root container. Headless hook: useCoverFlow returns activeIndex, scrollX, effectiveScrollX, isDragging, scale, goTo, containerRef, containerProps and handleCardClick — spread containerProps onto a motion.div with containerRef and render your own covers. ```tsx import { useCoverFlow } from "@/components/ui/CoverFlow"; const { effectiveScrollX, activeIndex, containerRef, containerProps } = useCoverFlow({ items, scrollMode: "scrub", centerGap: 250 }); {/* your covers, driven by effectiveScrollX */} ``` ### Image Flow Carousel Pro. A gallery that stretches whichever frame you hover into focus. Page: https://useplanes.com/components/image-flow-carousel Install: `npx shadcn add @useplanes/image-flow-carousel` Use for: Product gallery (Showcase shots of a hardware product where the focused frame deserves real estate); Editorial / lookbook (Magazine-style story where hover or autoplay leads the eye through a sequence); Case study covers (Agency or studio site listing recent projects with a single hero per card); Travel destinations (Itinerary pages where each stop gets a generous photo without losing the rest of the trip). ```tsx import { ImageFlowCarousel } from "@/components/ui/ImageFlowCarousel"; ``` Props: - images* (ImageItem[]) — Array of `{ src, title?, subtitle? }`. Title/subtitle render over the active frame. - autoPlay (boolean, default false) — Auto-advance to the next frame on an interval. - interval (number, default 3000) — Auto-play interval in ms. - height (number, default 560) — Desktop track height in px. - mobileHeight (number, default 360) — Track height in px on viewports below the `sm` breakpoint. - imageFit (CSSProperties["objectFit"], default "cover") — How each image fills its frame. - activeRatio (number, default 4) — Width multiplier of the active frame relative to inactive frames. - className (string) — Classes merged onto the carousel root. ### Arc Marquee Pro. Portrait cards ride a curved arc, tilting and dropping toward the edges as they auto-scroll past. Drag to scrub, hover to slow. Page: https://useplanes.com/components/arc-marquee Install: `npx shadcn add @useplanes/arc-marquee` Use for: Marketing hero (A curved band of lifestyle shots under a headline, motion drawing the eye without stealing focus); Brand / logo wall (Auto-scrolling proof strip where the arc gives an otherwise flat row of frames some depth); Photography showreel (A portfolio ticker that keeps every frame in view while quietly cycling the set); Product lineup (Loop through catalogue shots in a compact ribbon that reads as one continuous surface). ```tsx import { ArcMarquee } from "@/components/ui/ArcMarquee"; ``` Props: - images (ArcImage[]) — Array of `{ src, alt? }`. Falls back to a built-in demo set when omitted. - cardWidth (number, default 200) — Card width in px. - cardHeight (number, default 280) — Card height in px. - gap (number, default 18) — Horizontal gap between cards in px. - speed (number, default 34) — Auto-scroll speed in px per second. - curveDepth (number, default 64) — How far the edge cards drop below the center of the arc, in px. - maxRotate (number, default 9) — Peak tilt of the outermost cards, in degrees. - pauseOnHover (boolean, default true) — Ease the scroll to a stop while the pointer is over the strip. - draggable (boolean, default true) — Allow drag-to-scrub the arc with the pointer or touch, with release momentum. - wheelControl (boolean, default true) — Let the mouse wheel or trackpad scrub the arc horizontally (vertical or horizontal delta, whichever dominates). - mobileScale (number, default 0.62) — Multiplier applied to card size, gap, and curve depth below the `sm` breakpoint. - direction (1 | -1, default 1) — Scroll direction: 1 moves the arc left, -1 moves it right. - label (string, default "Image gallery") — Accessible label for the region. - className (string) — Classes merged onto the viewport root. ### Parallax Carousel Pro. A straight marquee of cards where each photo pans inside its frame as it crosses the viewport — direction-aware parallax that follows your drag, scroll, or the auto-glide. Page: https://useplanes.com/components/parallax-carousel Install: `npx shadcn add @useplanes/parallax-carousel` Use for: Marketing hero slider (A landing-page hero that rotates through product or lifestyle shots with cinematic depth); Travel / editorial stories (Full-bleed destination photos where the parallax drift sells the sense of place); Portfolio case studies (Cycle through project covers; the direction-aware motion makes browsing feel tactile); Product photo gallery (Swipeable gallery on product pages — drag, arrows, dots, and keyboard all supported). ```tsx import { ParallaxCarousel } from "@/components/ui/ParallaxCarousel"; ``` Props: - images (ParallaxImage[]) — Array of `{ src, alt? }`. Falls back to a built-in demo set when omitted. - cardWidth (number, default 200) — Card width in px. - cardHeight (number, default 280) — Card height in px. - gap (number, default 18) — Horizontal gap between cards in px. - speed (number, default 34) — Auto-scroll speed in px per second. - parallax (number, default 56) — How far each photo pans inside its frame across the viewport, in px. Higher reads as deeper. - pauseOnHover (boolean, default true) — Ease the scroll to a stop while the pointer is over the strip. - draggable (boolean, default true) — Allow drag-to-scrub with the pointer or touch, with release momentum. - wheelControl (boolean, default true) — Let a horizontal wheel or trackpad swipe scrub the strip. - mobileScale (number, default 0.62) — Multiplier applied to card size, gap, and parallax below the `sm` breakpoint. - direction (1 | -1, default 1) — Scroll direction: 1 moves the strip left, -1 moves it right. - label (string, default "Image gallery") — Accessible label for the region. - className (string) — Classes merged onto the viewport root. ### Image Wheel Pro. A wheel of photos that spins past the lens, blurring everything but the frame in focus. Page: https://useplanes.com/components/image-wheel Install: `npx shadcn add @useplanes/image-wheel` Use for: Photography portfolio (Let a body of work spin past with only the current frame resolving into focus); Launch hero (A cinematic header for a product or film site that rewards a drag); Album or cover browser (Flip through artwork with the depth-of-field feel of a physical rack); Case study picker (Pick a project from an arc of covers instead of a flat grid). ```tsx import { ImageWheel } from "@/components/ui/ImageWheel"; ``` Props: - images* (ImageWheelImage[]) — Array of `{ src, alt? }` rendered as cards on the wheel. - cardSize (number, default 190) — Edge length of each square card in px. - radius (number, default 420) — Radius of the wheel in px — larger means a flatter, wider arc. - height (number, default 520) — Height of the wheel container in px. - spread (number, default 24) — Degrees of arc between adjacent cards. - lift (number, default 90) — How far cards rise as they travel away from the focus, in px. - maxBlur (number, default 9) — Blur ceiling in px for depth and motion blur combined. - scatter (boolean, default true) — Adds a deterministic per-card tilt and vertical jitter for a hand-strewn look. - onChange ((index: number) => void) — Fires when the focused card changes. - className (string) — Classes merged onto the wheel root. ### Logo Wall Pro. A bordered grid of logos where each cell cycles independently, rippling in a wave across the columns. Page: https://useplanes.com/components/logo-wall Install: `npx shadcn add @useplanes/logo-wall` Use for: Customer logo walls ("Trusted by" sections that stay alive without demanding attention); Integration grids (Show a large set of supported tools or partners in a fixed footprint); Sponsor boards (Cycle through more sponsors than fit on screen at once). ```tsx import { LogoWall } from "@/components/ui/LogoWall"; {/* ...more logos */} ``` Props: - children* (ReactNode) — Logo elements to cycle through. Each child is rendered as one logo. - columnCount (number, default 5) — Number of columns in the grid. - rowCount (number, default 1) — Number of rows in the grid. - direction ("ltr" | "rtl", default "ltr") — Direction the ripple sweeps across the columns. - className (string) — Tailwind classes on the grid container. ### Bend Carousel Pro. Photos and videos ride the outside of a cylinder: the frame in front faces you flat, the neighbours bend away and dim toward the edges. Auto-glides, drags with momentum, scrubs with a trackpad, and videos only play while they are on screen. Page: https://useplanes.com/components/bend-carousel Install: `npx shadcn add @useplanes/bend-carousel` Use for: Campaign reel (Mix product stills and short clips in one strip that reads as a single object); Portfolio hero (A cinematic first impression for photographers and studios); App screenshots (Show portrait mobile screens curving past the way they sit on a device rack); Testimonial videos (Muted looping clips of customers, each unmuted on its own page). ```tsx import { BendCarousel } from "@/components/ui/BendCarousel"; ``` Props: - items (BendMedia[]) — Array of `{ src, type?, alt?, poster? }`. `type` is inferred from the file extension when omitted. Falls back to a built-in demo set. - cardWidth (number, default 260) — Card width in px. - cardHeight (number, default 440) — Card height in px. - gap (number, default 16) — Gap between cards along the arc, in px. - radius (number, default 900) — Radius of the cylinder in px. Smaller bends harder; larger flattens toward a straight strip. - perspective (number, default 1400) — CSS perspective distance in px. Lower exaggerates the depth. - speed (number, default 28) — Auto-glide speed in px per second along the arc. - dim (number, default 0.45) — How dark the outermost cards get, 0 to 1. - pauseOnHover (boolean, default true) — Ease the glide to a stop while the pointer is over the carousel. - draggable (boolean, default true) — Drag to spin with release momentum. - wheelControl (boolean, default true) — Let a horizontal wheel or trackpad swipe spin the ring. - mobileScale (number, default 0.6) — Multiplier applied to card size, gap, and radius below the `sm` breakpoint. - direction (1 | -1, default 1) — Auto-glide direction. - label (string, default "Media carousel") — Accessible label for the region. - className (string) — Tailwind classes on the root container. ## Controls ### Segmented Control Free. Segmented tabs with a pill that stretches as it moves and settles into the selected tab. Page: https://useplanes.com/components/segmented-control Install: `npx shadcn add https://useplanes.com/r/segmented-control.json` Use for: Dashboard view switcher (Toggle between Overview / Analytics / Activity panels without a full route change); Settings sub-sections (Group related preference panes — Profile, Account, Billing — under one screen); Filter modes (Switch list density, sort order, or time range on a data view); Pricing toggle (Switch monthly / yearly billing or currency on a pricing page with a clear active state). ```tsx import { SegmentedControl } from "@/components/ui/SegmentedControl"; const [tab, setTab] = useState("overview"); ``` Props: - options* (SegmentedControlOption[]) — Tabs to render. Each option needs `label` and `value`; an optional `icon` renders inline. - value* (string) — Currently selected option value (controlled). - onChange* ((value: string) => void) — Fired when a tab is selected via click or keyboard. - className (string) — Tailwind classes merged onto the tablist container. ### Number Stepper Free. A number input with rolling digits and plus and minus buttons that spring on press. Page: https://useplanes.com/components/number-stepper Install: `npx shadcn add https://useplanes.com/r/number-stepper.json` Use for: Cart quantity (Adjust line-item quantity in a checkout drawer or product page); Pricing calculator (Pick seat counts on a SaaS pricing page where the digits should feel weighty); Reservations (Choose number of guests for a booking flow where every tap should feel deliberate); Inventory adjustments (Admin dashboards where staff bump stock counts and want unambiguous tactile feedback). ```tsx import { NumberStepper } from "@/components/ui/NumberStepper"; const [qty, setQty] = useState(1); ``` Props: - value* (number) — Current numeric value (controlled). - onChange* ((value: number) => void) — Fired on increment, decrement, or keyboard step. - min (number, default -Infinity) — Lower bound. Decrement disables at this value. - max (number, default Infinity) — Upper bound. Increment disables at this value. - step (number, default 1) — Step amount for ArrowUp / ArrowDown. - size ("sm" | "md" | "lg", default "md") — Visual scale of the digits and step buttons. - label (string, default "Quantity") — Accessible label exposed to screen readers. - className (string) — Tailwind classes merged onto the root container. ### Email Capture Pro. An email signup that expands from a button and animates from idle into a success state. Page: https://useplanes.com/components/email-capture Install: `npx shadcn add @useplanes/email-capture` Use for: Marketing waitlist (Drop a low-friction CTA on a landing page without commandeering hero space); Newsletter signup (Inline footer or blog signup that stays unobtrusive until tapped); Product launch alerts (“Notify me when this ships” pattern for unreleased features or product variants); Beta access requests (Gate an early-access program behind a single email field that confirms in place). ```tsx import { EmailCapture } from "@/components/ui/EmailCapture"; { await fetch("/api/waitlist", { method: "POST", body: JSON.stringify({ email }) }); }} /> ``` Props: - placeholder (string, default "Enter your email") — Placeholder shown inside the expanded input. - buttonLabel (string, default "Subscribe") — Label for the idle/CTA state of the trigger button. - successMessage (string, default "Subscribed") — Confirmation copy shown after a successful submit. - onSubmit ((email: string) => Promise | void) — Handler invoked with the validated email. Throw to surface an error state. ### Card Stack Pro. Stacked notification cards that fan out into a full list, then collapse back into a compact peek. Page: https://useplanes.com/components/card-stack Install: `npx shadcn add @useplanes/card-stack` Use for: Writing section on a portfolio (Drop this on your personal site to link to your articles — the latest piece stays front and center, the rest are one tap away without cluttering the page); Featured projects (Showcase your top project as the primary card with links to the case study or live demo, and let visitors expand to browse the rest of your work); Resource / link list (Curate a set of links — tools you use, talks you've given, interviews — and embed them anywhere without a dedicated page); Press & mentions (Surface the most recent coverage or feature on top, let visitors unfold older mentions on demand). ```tsx import { CardStack } from "@/components/ui/CardStack"; // or with your own articles: ``` Props: - cards (CardItem[]) — Array of card items to render. Defaults to a built-in article set when omitted. - cards[].id* (string) — Unique key for the card. Used as the React key — must be stable across renders. - cards[].title* (string) — Primary heading line. Truncated with an ellipsis if it overflows. - cards[].image (ReactNode) — Optional icon or image for the leading thumbnail (48×48 px). Pass any React element — a Lucide icon, , or component. - cards[].subtitle (string) — Optional secondary line beneath the title. Typically a category, publication, or short description. - cards[].time (string) — Optional trailing label. Works for read time ("5 min read"), publish date, or relative time. - cards[].href (string) — Optional URL. When provided the card becomes a link that opens in a new tab. - width (number, default 384) — Max width of the card stack in px. Increase for wider layouts or decrease for sidebars. - className (string) — Tailwind classes merged onto the root container. ### Date Picker Pro. A calendar picker with spring month transitions and day cells that stagger in as you navigate. Page: https://useplanes.com/components/animated-date-picker Install: `npx shadcn add @useplanes/animated-date-picker` Use for: Booking flows (Check-in / check-out date selection with min/max constraints); Form date fields (Drop-in replacement for any native that needs premium feel); Event scheduling (Pick a date for meetings, reminders, or deadlines); Billing / subscription start dates (Allow users to choose when a plan takes effect). ```tsx import { AnimatedDatePicker } from "@/components/ui/AnimatedDatePicker"; const [date, setDate] = useState(); ``` Props: - value (Date) — Currently selected date (controlled). - onChange ((date: Date) => void) — Fired when a date is selected. - placeholder (string, default "Pick a date") — Trigger label when no date is selected. - disabled (boolean, default false) — Disables the trigger and prevents opening. - minDate (Date) — Earliest selectable date. Days before this are dimmed. - maxDate (Date) — Latest selectable date. Days after this are dimmed. - className (string) — Tailwind classes on the root container. ### Animated Select Pro. A searchable, grouped select that becomes a drag-to-dismiss bottom sheet on mobile and a spring popover on desktop. Page: https://useplanes.com/components/animated-select Install: `npx shadcn add @useplanes/animated-select` Use for: Native-feeling mobile select (Below 640px it becomes a drag-to-dismiss bottom sheet instead of a cramped dropdown — resize your browser (or open on a phone) to see it morph. No separate mobile component, no extra code); Settings forms (Country, timezone, language, currency — any setting with many options benefits from search); Filter dropdowns (Replace bare