Purbayan Pramanik

Snap Panels

Component

About

A resizable split-panel layout whose divider magnetically leans toward configured snap points and can be collapsed, used for sidebars, IDE-style layouts, and mail-client panes.

Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds Snap Panels to your project and fits it to your theme.

Code

How Snap Panels is used: the demo's code. The component's own source comes with a free account.

Usage.tsx

"use client";

import {
  SnapPanel,
  SnapPanelGroup,
  SnapPanelHandle,
} from "@/components/ui/snap-panels";
import { ChevronDown, ChevronRight, FileCode2 } from "lucide-react";
import { cn } from "@/lib/utils";

const TREE = [
  { name: "app", depth: 0, folder: true },
  { name: "layout.tsx", depth: 1, folder: false },
  { name: "page.tsx", depth: 1, folder: false },
  { name: "lib", depth: 0, folder: true },
  { name: "springs.ts", depth: 1, folder: false },
  { name: "utils.ts", depth: 1, folder: false },
];

const CODE = [
  "export const spring = {",
  "  fast:     { duration: 0.08, bounce: 0 },",
  "  quick:    { duration: 0.14, bounce: 0.1 },",
  "  moderate: { duration: 0.2,  bounce: 0.12 },",
  "};",
];

const LOG = [
  "$ bun run build",
  "▲ Next.js 16.2.12",
  "  compiled successfully in 1.4s",
  "  ○ /docs/components/snap-panels",
];

export default function SnapPanelsIdeExample() {
  return (
    <div className="h-80 w-full max-w-2xl overflow-hidden rounded-lg border border-border bg-card">
      <SnapPanelGroup direction="horizontal">
        <SnapPanel
          id="files"
          defaultSize="200px"
          minSize="160px"
          snapPoints={["200px", "280px"]}
          collapsible
        >
          <div className="flex h-full flex-col gap-px bg-background p-1.5">
            {TREE.map((entry) => (
              <span
                key={entry.name}
                style={{ paddingInlineStart: `${entry.depth * 12 + 8}px` }}
                className={cn(
                  "flex items-center gap-1.5 truncate rounded-md py-1 pe-2 font-mono text-2xs",
                  entry.name === "springs.ts"
                    ? "bg-active text-foreground"
                    : "text-muted-foreground",
                )}
              >
                {entry.folder ? (
                  <ChevronDown className="size-3 shrink-0 opacity-60" />
                ) : (
                  <FileCode2 className="size-3 shrink-0 opacity-60" />
                )}
                {entry.name}
              </span>
            ))}
          </div>
        </SnapPanel>
        <SnapPanelHandle aria-label="Resize file tree" />
        <SnapPanel id="main" minSize={30}>
          <SnapPanelGroup direction="vertical">
            <SnapPanel id="editor" minSize={20}>
              <div className="flex h-full flex-col">
                <div className="flex h-9 shrink-0 items-center gap-2 border-b border-border px-3">
                  <FileCode2 className="size-3 shrink-0 text-muted-foreground" />
                  <span className="truncate font-mono text-2xs text-foreground">
                    springs.ts
                  </span>
                  <span className="text-muted-foreground/60">/</span>
                  <span className="truncate font-mono text-2xs text-muted-foreground">
                    utils.ts
                  </span>
                </div>
                <div className="flex flex-col p-3">
                  {CODE.map((line) => (
                    <span
                      key={line}
                      className="truncate whitespace-pre font-mono text-2xs leading-5 text-muted-foreground"
                    >
                      {line}
                    </span>
                  ))}
                </div>
              </div>
            </SnapPanel>
            <SnapPanelHandle aria-label="Resize terminal" />
            <SnapPanel
              id="terminal"
              defaultSize={30}
              minSize={12}
              snapPoints={[30, 60]}
              collapsible
            >
              <div className="flex h-full flex-col bg-background">
                <div className="flex h-8 shrink-0 items-center gap-1.5 px-3">
                  <ChevronRight className="size-3 shrink-0 text-muted-foreground" />
                  <span className="text-label text-muted-foreground uppercase">
                    Terminal
                  </span>
                </div>
                <div className="flex flex-col px-3">
                  {LOG.map((line) => (
                    <span
                      key={line}
                      className="truncate whitespace-pre font-mono text-2xs leading-5 text-muted-foreground"
                    >
                      {line}
                    </span>
                  ))}
                </div>
              </div>
            </SnapPanel>
          </SnapPanelGroup>
        </SnapPanel>
      </SnapPanelGroup>
    </div>
  );
}

Dependencies

More by Purbayan Pramanik

View all
  • Notification Stack

    Notification Stack

    23
  • Proximity Accordion

    Proximity Accordion

    5
  • Plan Checklist

    Plan Checklist

  • Agent Activity

    Agent Activity

  • Checkbox Group

    Checkbox Group

  • Conversation

    Conversation