A sentence set on a stave, each word a note. Point at one and the phrase plays from it; or sing along discs on the staff; or draw the staff only where there are words.
Say it slowly enough and the sentence begins to sing, one word at a time, over the quiet.Every word you reach is sung, and the rest are still to come.Where nothing sounds, the lines fall silent, and only the words keep their place.
Its own tuneNothing is louder than the pause before it.
A given contourUp the stairs and down again
Noteheads, to comeUp the stairs and down again
Noteheads, right to leftقلها ببطء فتبدأ الجملة بالغناء
CutawayNothing is louder than the pause before it.
Cutaway, a given contourUp the stairs and down again
Install
Run it in a project that has the shadcn CLI set up. It brings the 0nlyType base along.
import{Melody}from"@/components/ui/melody"/** The words as notes; the tune as discs with the words sung under them; and the staff drawn only under the words. */exportdefaultfunctionExample(){return(<divclassName="grid grid-cols-[minmax(0,1fr)] gap-y-(--ot-space-8)"><MelodyclassName="max-w-[40rem]">Say it slowly enough and the sentence begins to sing, one word at a time, over the quiet.</Melody><Melodyvariant="noteheads"className="max-w-[40rem]">Every word you reach is sung, and the rest are still to come.</Melody><Melodyvariant="cutaway"className="max-w-[40rem]">Where nothing sounds, the lines fall silent, and only the words keep their place.</Melody></div>)}
Contract
Underneath: native, plus a hook that measures and lays the words out with pretext (@chenglou/pretext, loaded when it's needed).
Anatomy: <figure class="ot-melody" tabindex="0" aria-label> holding one .ot-melody-stave per line, each with a .ot-melody-staff (five hairlines in --ot-rule, an opening barline, and a closing one), an svg.ot-melody-marks (the engraving) and its .ot-melody-note words, positioned by pretext's measures. The last stave ends on a double bar.
The engraving is the marks a singer reads, in pencil and nothing else: a slur over each phrase (the words up to a comma or a full stop, never across a stave), a pen stroke that swells in the middle and thins to nothing at its ends, bowed just enough to clear every word it passes over and leaning toward the end that needs the lift; a fermata (an arc over a dot) above the staff over the last word; and under the first word its dynamic, .ot-melody-dynamic, in the bold italic. The dynamic is the type size the melody is set at, since the sizes are dynamics already: at --ot-mp it's mp. A word's letters wear a halo of the paper (--ot-melody-ground), so the lines and slurs stop just short of them.
A sentence set on a stave, each word a note: its baseline sits on a line or in a space, following contour (steps, 0 the bottom line, 8 the top, odd numbers the spaces). Without one, the sentence writes its own tune: long words rise, the phrase rocks, and it comes home to where it began.
The words are spaced evenly across the measure and wrap onto a new stave when it's full; the last stave keeps to a moderate gap, a rest rather than a stretch. No word stands alone on the last stave: it takes one from the stave before when that one can spare it.
Pointing at a word sounds it: it takes the accent, lifts a little and lands, and the words after it do the same in turn, one --ot-arpeggio apart, then settle back to ink. The last word, under its fermata, holds the accent for as long again before it lets go. The same word sounded twice starts over.
Keyboard: the figure is one focus stop, and Enter plays the phrase from the first word. The words are aria-hidden; the figure's label is the plain sentence. Under reduced motion there's no lift and no travel: the sounded words hold the accent until you leave.
It lays out again when its width changes or <html> changes face. Before the fonts arrive, or without script, it's the plain sentence.
variant (data-variant): stave (the default), noteheads or cutaway.
noteheads: after the calendar poster's discs and the score's lyric underlay. Each word's note is a disc (.ot-melody-head) one staff space across on its step, with no stem, and the words are sung under the staff on one lyric baseline (below the lowest disc too), each under its disc. No slurs, since every word is one note. The fermata stands over the last disc, and the dynamic goes above the staff over the first, where a vocal score puts it to keep the words below clear. The discs say where you are in the song, as the poster says where you are in the month: to come in hairline rings (--ot-rule-strong, filled with the ground), sung in ink, the word you're at in the accent. Pointing at a word or its disc moves there, and the discs fill or empty in turn from where you were, one --ot-arpeggio apart; leaving lets it go. Keyboard: the arrows step along the words (mirrored right to left), Home and End go to the first and the last, Enter sings it through to the last, Escape and blur let it go. Reduced motion: the discs change at once.
cutaway: after the cutaway score, which drops an instrument's staff while it rests. The continuous staff and its barlines are not drawn; under each word, and 0.12em beyond it, a piece of the five lines (.ot-melody-bit) stands instead, so the silences between the words are paper and the slurs carry across them. Everything else, the tune, the marks and the arpeggio, is the stave's.
Forced colours: the discs ring and fill in CanvasText, the one you're at in Highlight; the staff lines are GrayText, and the words drop their halo, which would be forced to the text colour.
Props
Props of Melody
Prop
Type
Default
What it does
children
string
The sentence, as plain text: pretext measures each word.
contour
number[]
from the words
The staff step of each word. 0 is the bottom line, 2 the next, 8 the top, and odd numbers the spaces between. By default the sentence writes its own tune from its word lengths.
variant
"stave" | "noteheads" | "cutaway"
"stave"
stave: each word is a note, its baseline on its step, under slurs. noteheads, after the calendar poster's discs: the tune is a disc on the staff for each word (a staff space across, no stems), and the words are sung under it on one lyric line. Point at a word or its disc, or step with the arrows, and the discs fill in turn: sung in ink, the one you're at in the accent, the rest still rings; Enter sings it through, Escape lets it go. cutaway, after the cutaway score: the five lines are drawn only under the words, so the silences between them are paper, and the slurs carry across.
Craft
Where its move comes from
Where its move comes from
Component
Reference
Move
Melody
The score
The sentence sits on a stave, a word to a line or space
Noteheads melody
"Less but better" calendar; the score's lyric underlay
Discs on the staff: sung in ink, here in the accent, to come in rings
Cutaway melody
The cutaway score; "Less is more."
The staff is drawn only under the words
How it moves
How it moves
Component
Articulation
What moves
Melody
Arpeggio
The word you point at sounds, then the rest of the phrase in turn; the last holds under its fermata
Noteheads melody
Ink
The discs fill in turn up to the word you're at, which takes the accent