Chord Graph

chord-graphVisualizers

How the chords in a progression connect, by shared notes.

$ pnpm dlx shadcn@latest add @pluginui/core-chord-graph
Loading interactive preview…

Install

Copies the source into your project. Anything it depends on comes with it. Run this in your React project with shadcn initialized; no registry configuration is needed.

Pulls in

control-theme
Install using the registry URL
$ pnpm dlx shadcn@latest add https://pluginui.com/r/core-chord-graph.json

Usage

Connect the documented props to your application or host.

example.tsx
import { ChordGraph } from "@/components/ui/chord-graph"

// Pitch classes in root-first order; the fifths layout positions by pcs[0].
<ChordGraph
  chords={[
    { label: "C", pcs: [0, 4, 7] },
    { label: "G", pcs: [7, 11, 2] },
    { label: "Am", pcs: [9, 0, 4] },
    { label: "F", pcs: [5, 9, 0] },
  ]}
  activeIndex={0}
  layout="ring"
/>
About Chord Graph

A chord chart shows the order chords arrive in, but not why one leads comfortably to another while a different transition lands with a jolt. Shared pitch classes explain much of that difference: C and Am share two notes and slide together almost imperceptibly; C and F♯ share none and feel like a cut. This component draws that relation directly, with an edge between every pair sharing at least one note and a weight based on how many. The result maps a progression's internal gravity: a tightly connected cluster interchanges freely, while an isolated node sounds like an arrival. Ring layout preserves your sequence as the geometry; fifths layout places each chord by its root, making screen distance represent harmonic distance.

Props

PropTypeDefaultDescription
chords{ label: string, pcs: number[], color?: string }[]—Chords to plot. Give each chord's pitch classes ROOT FIRST because pcs[0] determines its position in the fifths layout. Values are reduced mod 12 and deduplicated, so octave doublings do not inflate a shared count.
layout"ring" | "fifths""ring"Even spacing in the order given, or placement at each root's circle-of-fifths angle. Chords sharing a root are pulled inward so they never stack.
activeIndexnumber | nullnullEnlarges this chord's node and emphasises the edges touching it, dimming the rest.
sizenumber280Overall square size in pixels.
colorstring—Default node and edge colour; individual chords can override it. Defaults to the --uikit-accent token.

Interaction

  • Drag with pointer capture, so the gesture keeps tracking past the edge of the control.
  • Shift while dragging for a fine pass; release it mid-gesture and coarse tracking resumes.
  • Double-click resets to defaultValue.
  • Arrow keys step normally, Shift+arrow steps finely, PageUp/PageDown jump by ten, Home/End go to the extremes.
  • Proper slider and switch roles with live aria-valuetext, so a screen reader announces the formatted value rather than the raw number.
  • The scroll wheel adjusts the value while the pointer is over the control; stepped ranges move at least one declared step per notch by default.