Skip to main content

ChordSheet

Renders chord symbols above lyrics, grouped into measures and wrapped into visual lines.

Cm7The
F7au-
Bbmaj7tumn
Ebmaj7leaves
Am7b5are
D7falling…

Usage

import { ChordSheet, createScore, createTrack, createMeasure, createChord, createLyric } from 'react-notation'
import 'react-notation/style.css'

const score = createScore({
timeSignature: { beats: 4, value: 4 },
keySignature: { root: 'G', mode: 'major' },
tracks: [
createTrack({
measures: [
createMeasure({
number: 1,
section: 'Verse',
events: [
createChord({ beat: 1, duration: 'half', symbol: 'Cm7', root: 'C', quality: 'min7' }),
createChord({ beat: 3, duration: 'half', symbol: 'F7', root: 'F', quality: 'dominant7' }),
createLyric({ beat: 1, duration: 'half', text: 'The' }),
createLyric({ beat: 3, duration: 'half', text: 'au-' }),
],
}),
],
}),
],
})

<ChordSheet score={score} />

Props

PropTypeDefaultDescription
scoreMusicScoreRequired. Score to render. Only the first track is used.
measuresPerLinenumber4Maximum measures per visual line before wrapping.
breakAtSectionsbooleantrueStart a new line when a measure has a section label.
showMeasureNumbersbooleanfalseShow bar numbers above each measure.
classNamestringAdditional CSS class applied to the root element.
...restHTMLAttributes<HTMLDivElement>All standard div props are forwarded.

ChordSheet is a forwardRef component — you can pass a ref to access the root <div>.

Section breaks

When a Measure has a section field and breakAtSections is true, the section name is rendered as a label and the measure starts a new line, regardless of how many measures are already on the current line.

createMeasure({ number: 5, section: 'Chorus', events: [...] })

Line wrapping

measuresPerLine sets the maximum number of measures per row. Actual lines may be shorter due to section breaks. Set breakAtSections={false} to disable section-based breaks and rely solely on measuresPerLine.

Theming

ChordSheet reads the following --notation-* CSS tokens:

TokenDefaultControls
--notation-font-familyGeorgia, serifAll text
--notation-font-size-chord1remChord symbols
--notation-font-weight-chord600Chord symbols
--notation-font-size-lyric0.9375remLyric text
--notation-color-chordinheritChord symbol color
--notation-color-lyricinheritLyric text color
--notation-color-section-labelinheritSection label color
--notation-color-measure-bordercurrentColorBar line color
--notation-measure-gap1remGap between measures
--notation-beat-gap0.5remGap between beat columns
--notation-line-gap1.5remGap between lines
--notation-section-gap2remExtra gap above section labels

Override via ThemeProvider or plain CSS.

Interactive / editor mode

Pass a ScoreEditor (from useScore) to activate interactive mode — selection, keyboard navigation, and inline chord editing.

import { ChordSheet, useScore, createScore } from 'react-notation'

function Editor() {
const editor = useScore(initialScore)
return <ChordSheet score={editor.score} editor={editor} />
}
PropTypeDefaultDescription
editorScoreEditorReturned by useScore. Activates interactive mode.
inlineEditbooleantrueShow built-in inline input on Enter. Set false to handle editing via onEditStart.
onSelect(sel: Selection) => voidFired when an element is focused or clicked.
onEditStart(sel: Selection) => void | falseFired when editing begins. Return false to suppress the built-in input.
onEditCommit(sel: Selection, value: string) => voidFired when an edit is committed.
onEditCancel(sel: Selection) => voidFired when an edit is cancelled.

See the Editing guide for the full API, keyboard shortcuts, and popup integration.

Known limitations

  • Only the first track of a MusicScore is rendered.
  • Beat columns are spaced equally — no proportional beat placement.
  • Multi-verse lyrics are not differentiated visually (only verse 1 text is shown per beat).