{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "branch-chip",
  "type": "registry:ui",
  "title": "Branch Chip",
  "description": "Branch/worktree pill — press to copy, with ahead/behind counts and PR state.",
  "dependencies": [
    "motion",
    "lucide-react"
  ],
  "registryDependencies": [
    "https://seamui.dev/r/utils.json",
    "https://seamui.dev/r/motion.json",
    "https://seamui.dev/r/button.json",
    "https://seamui.dev/r/badge.json",
    "https://seamui.dev/r/use-copy.json"
  ],
  "files": [
    {
      "path": "registry/seam/ui/branch-chip.tsx",
      "content": "\"use client\"\n\nimport type * as React from \"react\"\nimport { AnimatePresence, motion } from \"motion/react\"\nimport {\n  ArrowDown,\n  ArrowUp,\n  Check,\n  GitBranch,\n  GitMerge,\n  GitPullRequestArrow,\n  GitPullRequestClosed,\n  GitPullRequestDraft,\n} from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { fades } from \"@/lib/motion\"\nimport { useCopy } from \"@/lib/use-copy\"\nimport { Badge, badgeVariants } from \"./badge\"\nimport { Button } from \"./button\"\n\ntype PrState = \"open\" | \"draft\" | \"merged\" | \"closed\"\n\n// PR state carries conventional git colors (GitHub's palette) rather than the\n// seam monochrome — the color *is* the signal here. Each keeps the embossed\n// key shape (border-transparent + shadow) and reads in both themes.\nconst PR: Record<PrState, { className: string; icon: React.ElementType }> = {\n  open: {\n    className: \"bg-emerald-600 text-white dark:bg-emerald-500 dark:text-black\",\n    icon: GitPullRequestArrow,\n  },\n  draft: {\n    className: \"bg-muted text-muted-foreground shadow-none border-border/60\",\n    icon: GitPullRequestDraft,\n  },\n  merged: {\n    className: \"bg-violet-600 text-white dark:bg-violet-500 dark:text-white\",\n    icon: GitMerge,\n  },\n  closed: {\n    className: \"bg-red-600 text-white dark:bg-red-500 dark:text-white\",\n    icon: GitPullRequestClosed,\n  },\n}\n\ninterface BranchChipProps\n  extends Omit<React.ComponentProps<typeof Button>, \"onCopy\" | \"children\"> {\n  branch: string\n  ahead?: number\n  behind?: number\n  pr?: { number: number; state: PrState }\n  /** Press-to-copy is the default — a branch name exists to be copied.\n   *  Set false to render a static chip (e.g. inside an already-clickable row). */\n  copyable?: boolean\n  onCopy?: (branch: string) => void\n}\n\n// A raised key, not an entry well: the branch is a tappable surface whose one\n// action is copying its name. The icon crossfades GitBranch → Check on copy\n// (opacity-only, identical under reduced motion); press depth and the haptic\n// tap come free from Button.\nfunction BranchChip({\n  branch,\n  ahead,\n  behind,\n  pr,\n  copyable = true,\n  onCopy,\n  className,\n  ...props\n}: BranchChipProps) {\n  const { copied, copy } = useCopy()\n\n  const handleCopy = async () => {\n    if (await copy(branch)) onCopy?.(branch)\n  }\n\n  const sync =\n    (ahead ?? 0) > 0 || (behind ?? 0) > 0 ? (\n      <span\n        data-slot=\"branch-chip-sync\"\n        // arrow glyphs + counts read as one little graphic: \"2 ahead, 1 behind\"\n        // — ahead green (your commits), behind amber (need to pull), git-style.\n        role=\"img\"\n        aria-label={`${ahead ?? 0} ahead, ${behind ?? 0} behind`}\n        className=\"flex items-center gap-1 tabular-nums\"\n      >\n        {(ahead ?? 0) > 0 && (\n          <span className=\"flex items-center gap-0.5 text-emerald-600 dark:text-emerald-500\">\n            <ArrowUp aria-hidden className=\"size-2.5\" />\n            {ahead}\n          </span>\n        )}\n        {(behind ?? 0) > 0 && (\n          <span className=\"flex items-center gap-0.5 text-amber-600 dark:text-amber-500\">\n            <ArrowDown aria-hidden className=\"size-2.5\" />\n            {behind}\n          </span>\n        )}\n      </span>\n    ) : null\n\n  const prBadge = pr ? (\n    <Badge\n      data-slot=\"branch-chip-pr\"\n      role=\"img\"\n      aria-label={`Pull request ${pr.number}, ${pr.state}`}\n      className={cn(\"h-4 gap-0.5 px-1 text-[10px]\", PR[pr.state].className)}\n    >\n      {(() => {\n        const Icon = PR[pr.state].icon\n        return <Icon aria-hidden className=\"size-2.5!\" />\n      })()}#{pr.number}\n    </Badge>\n  ) : null\n\n  const name = <span className=\"max-w-48 truncate\">{branch}</span>\n\n  if (!copyable) {\n    return (\n      <span\n        data-slot=\"branch-chip\"\n        className={cn(\n          badgeVariants({ variant: \"secondary\" }),\n          \"gap-1.5 font-mono font-normal\",\n          className\n        )}\n        {...(props as React.ComponentProps<\"span\">)}\n      >\n        <GitBranch aria-hidden className=\"size-3\" />\n        {name}\n        {sync}\n        {prBadge}\n      </span>\n    )\n  }\n\n  return (\n    <Button\n      data-slot=\"branch-chip\"\n      variant=\"secondary\"\n      size=\"sm\"\n      onClick={handleCopy}\n      aria-label={copied ? \"Copied\" : `Copy branch name ${branch}`}\n      className={cn(\n        \"h-7 gap-1.5 px-2.5 font-mono text-xs font-normal\",\n        className\n      )}\n      {...props}\n    >\n      {/* Confirmation is an opacity crossfade — identical under reduced motion. */}\n      <AnimatePresence mode=\"wait\" initial={false}>\n        <motion.span\n          key={copied ? \"check\" : \"branch\"}\n          initial={{ opacity: 0 }}\n          animate={{ opacity: 1 }}\n          exit={{ opacity: 0 }}\n          transition={fades.fast}\n          className=\"flex items-center\"\n        >\n          {copied ? (\n            <Check className=\"size-3\" />\n          ) : (\n            <GitBranch className=\"size-3\" />\n          )}\n        </motion.span>\n      </AnimatePresence>\n      {name}\n      {sync}\n      {prBadge}\n    </Button>\n  )\n}\n\nexport { BranchChip, type PrState }\n",
      "type": "registry:ui",
      "target": "components/ui/branch-chip.tsx"
    }
  ]
}