Skip to content
Neon UI
Esc
navigateopen⌘Jpreview
On this page

BranchTree

A drawn Neon branch graph with compute-state nodes and curved edges to each parent.

BranchTree draws a project’s branches as a real graph: each branch is a node, and a curved edge runs from its parent’s lane into it, so the hierarchy is physical rather than implied by indentation. The node color is the branch’s compute state, the default and selected branches wear a ring, and each row carries its state word and relative last-updated time. It is presentational: the branches come from your backend as plain data.

Branches6

Behavior

  • Graph each branch sits in the lane of its depth; an edge leaves the parent’s lane, runs down, and curves into the child node. Selecting a branch highlights its row and rings its node.
  • State the node dot is painted from the compute state (active/scaling breathe on the house cadence; idle holds green; suspended goes gray). Omit state for a neutral node.
  • Status default shows a badge and a primary ring; protected shows a lock; updatedAt renders as relative time.

Install

npx shadcn@latest add https://ui.neon.com/r/branch-tree.json

Usage

import { BranchTree } from "@/components/neon-ui/branch-tree";

<BranchTree branches={branches} value={branchId} onValueChange={setBranchId} />;

Controlled with value + onValueChange, or uncontrolled with defaultValue.

Wiring to Neon

A server component lists a project’s branches and selects the default:

import { createNeonClient } from "@/lib/neon-client";

const neon = createNeonClient(process.env.NEON_API_KEY);
const { data } = await neon.branches.list(projectId).all();
// map each branch to { id, name, default, protected, parent, updatedAt }

updatedAt comes straight off the branch. Fill state from the compute endpoints (neon.postgres.endpoints.listByBranch) if you want the node to reflect live compute. Wire onValueChange in a client wrapper, since selection is client state.

Props

PropType
branchesBranch[]

The branches to draw. Each is { id, name, default?, protected?, parent?, state?, updatedAt? }, where parent is the parent branch's id.

TypeBranch[]
value?string

Selected branch id (controlled).

Typestring
defaultValue?string

Initial selected branch id (uncontrolled).

Typestring
onValueChange?(id: string) => void

Notified when a branch node is chosen.

Type(id: string) => void

Accessibility

Each branch is a real button; the selected one carries aria-current. The graph is decorative (aria-hidden), so the tree reads as a plain list of branch names with their status. The breathing node states hold still under reduced motion.