<audio-ui-piano-roll> is a note editor placed inside an <audio-ui-timeline>, which provides its length, zoom, grid and position. Its entry point also registers the timeline and piano elements. Notes are set through the value property as { id, pitch, start, length, velocity?, chance?, muted? }[], and the selection through the selection property. Rows, notes and velocity bars are generated from them:
Usage
The styles read the theme's CSS variables, which Styling sets.
<style>
audio-ui-timeline {
display: block;
width: 100%;
max-width: 36rem;
}
audio-ui-piano-roll {
display: grid;
grid-template-columns: 3rem 1fr;
overflow: hidden;
border: 1px solid var(--border, oklch(0.922 0 0));
border-radius: calc(var(--radius, 0.625rem) - 2px);
}
audio-ui-piano-roll-keys {
height: calc(var(--spacing, 0.25rem) * 48);
border-inline-end: 1px solid var(--border, oklch(0.922 0 0));
}
audio-ui-piano-roll-keys audio-ui-piano {
display: block;
height: 100%;
}
audio-ui-piano-roll-keys audio-ui-piano-key {
z-index: 0;
top: auto;
right: 0;
left: 0;
box-sizing: border-box;
height: 100%;
border: 0;
border-bottom: 1px solid var(--border, oklch(0.922 0 0));
border-radius: 0;
background: var(--background, oklch(1 0 0));
cursor: pointer;
outline: none;
}
audio-ui-piano-roll-keys audio-ui-piano-key[data-color="black"] {
z-index: 1;
right: 35%;
height: 62%;
border-color: var(--foreground, oklch(0.145 0 0));
background: var(--foreground, oklch(0.145 0 0));
}
audio-ui-piano-roll-keys audio-ui-piano-key[data-active] {
border-color: var(--primary, oklch(0.205 0 0));
background: var(--primary, oklch(0.205 0 0));
}
audio-ui-piano-roll-grid {
height: calc(var(--spacing, 0.25rem) * 48);
outline: none;
}
audio-ui-piano-roll-row[data-color="black"] {
background: color-mix(in oklab, var(--muted, oklch(0.97 0 0)) 70%, transparent);
}
audio-ui-piano-roll-row[data-octave] {
border-bottom: 1px solid var(--border, oklch(0.922 0 0));
}
audio-ui-piano-roll-note {
border-radius: 2px;
background: color-mix(
in oklab,
var(--primary, oklch(0.205 0 0)) calc(40% + 60% * var(--piano-roll-velocity)),
transparent
);
cursor: grab;
outline: none;
}
audio-ui-piano-roll-note[data-selected] {
box-shadow: 0 0 0 2px var(--ring, oklch(0.708 0 0));
}
audio-ui-piano-roll-marquee {
border: 1px dashed var(--primary, oklch(0.205 0 0));
background: color-mix(in oklab, var(--primary, oklch(0.205 0 0)) 8%, transparent);
}
audio-ui-piano-roll-velocity-lane {
grid-column-start: 2;
height: calc(var(--spacing, 0.25rem) * 12);
border-top: 1px solid var(--border, oklch(0.922 0 0));
}
audio-ui-piano-roll-velocity {
width: 3px;
translate: -1px 0;
background: var(--primary, oklch(0.205 0 0));
}
audio-ui-timeline-viewport {
scrollbar-width: none;
}
audio-ui-timeline-playhead {
top: 0;
bottom: 0;
width: 1px;
background: var(--foreground, oklch(0.145 0 0));
}
</style>
<audio-ui-timeline duration="8" snap-step="0.5">
<audio-ui-piano-roll min-pitch="57" max-pitch="74">
<audio-ui-piano-roll-keys>
<audio-ui-piano aria-label="Keys">
<audio-ui-piano-keys></audio-ui-piano-keys>
</audio-ui-piano>
</audio-ui-piano-roll-keys>
<audio-ui-timeline-viewport>
<audio-ui-piano-roll-grid aria-label="Notes">
<audio-ui-piano-roll-rows></audio-ui-piano-roll-rows>
<audio-ui-piano-roll-notes></audio-ui-piano-roll-notes>
<audio-ui-timeline-playhead></audio-ui-timeline-playhead>
</audio-ui-piano-roll-grid>
</audio-ui-timeline-viewport>
</audio-ui-piano-roll>
</audio-ui-timeline>
<script type="module">
import "@audio-ui/elements/piano-roll";
const pianoRoll = document.querySelector("audio-ui-piano-roll");
pianoRoll.addEventListener("change", (event) =>
console.log(event.detail.value)
);
</script>API reference
pnpm add @audio-ui/elements
import "@audio-ui/elements/piano-roll";| Export | Kind | What it is |
|---|---|---|
PIANO_ROLL_TAGS | const | The names the piano roll's elements are registered under, frozen: a page cannot rename them by accident. |
PianoRollElement | class | The root of a note editor, placed inside an <audio-ui-timeline>, which provides its length, zoom, grid and position. |
PianoRollElementEventMap | interface | The events a piano roll fires, as addEventListener types them. |
PianoRollEventDetail | interface | What a roll's input and change events carry, besides the roll itself as their target. |
PianoRollGridElement | class | The note surface: a focusable timeline lane with role="group", with the rows stacked vertically. |
PianoRollKeysElement | class | Lays out the <audio-ui-piano> it contains on the roll's rows, low end at the bottom, and lights the sounding pitches. |
PianoRollMarqueeElement | class | The selection rectangle during a marquee drag. |
PianoRollNoteElement | class | A note, positioned at its start in timeline units and on its pitch's row. |
PianoRollNoteHandleElement | class | Resizes its note from its edge (start or end): the end changes the length, the start trims from the front with the end fixed. |
PianoRollNotesElement | class | Generates an <audio-ui-piano-roll-note> per note in reading order (by start, then highest pitch first), which is also the tab order, from its <template>, such as with <audio-ui-piano-roll-note-handle>s. |
PianoRollRowElement | class | The band of a pitch across the grid, for row shading, scale highlighting and octave lines. |
PianoRollRowsElement | class | Generates an <audio-ui-piano-roll-row> per row, highest pitch first, from its <template> when present. |
PianoRollSelectionSpanElement | class | The time range of the selected notes, spanning the height of its container: the grid, the velocity lane or the ruler. |
PianoRollStretchHandleElement | class | An edge of the selection span. |
PianoRollVelocitiesElement | class | Generates an <audio-ui-piano-roll-velocity> per note, from its <template> when present. |
PianoRollVelocityElement | class | A note's velocity, or chance in a level="chance" lane, rendered as a bar sized by --piano-roll-level. |
PianoRollVelocityLaneElement | class | A timeline lane of per-note bars for velocity or, with level="chance", probability, each at its note's start. |
Props · 9
Lowest row, a MIDI pitch. 60 is middle C.
Highest row.
When present, only pitches with notes get a row;
"scale" also keeps the scale's pitches.The scale's pitch classes, from 0 (C) to 11 (B), such as
0 2 4 5 7 9 11 for a major scale, with scale-root (0 for C). Its rows carry data-in-scale or data-out-of-scale, and those of its root data-scale-root. The scale property takes { pitchClasses, root }, which rollScale of @audio-ui/engine/pitch gives for a scale by name.Behavior of a press on empty grid: marquee selection or note drawing.
In draw mode,
paint draws a note in each grid cell crossed.Minimum note length. Defaults to the timeline's grid step.
Pitches lit externally, separated by spaces, such as MIDI input or playing notes.
| Event | Detail | Description |
|---|---|---|
input, change | { value, reason } | The notes change, then the gesture ends |
noteselect | { selection, reason } | The selection changes. preventDefault() rejects it |
noteon, noteoff | { pitch, reason, event } | A pitch starts or stops sounding. preventDefault() on noteon keeps it silent |
The getNoteLabel(note) property sets each note's accessible name, "C4, 4 to 6" by default.
| Part | Description |
|---|---|
<audio-ui-piano-roll-grid> | The focusable note surface, a timeline lane. Enter adds a note at the position, Escape clears the selection, Cmd/Ctrl+A selects all, and Cmd/Ctrl+D, C, X, V and Q duplicate, copy, cut, paste and quantize |
<audio-ui-piano-roll-rows> | Generates an <audio-ui-piano-roll-row> per pitch, highest first. Rows carry data-color, data-in-scale, data-out-of-scale, data-scale-root, data-octave and data-active |
<audio-ui-piano-roll-notes> | Generates an <audio-ui-piano-roll-note> per note in reading order, from its <template>. Each note is a toggle button positioned at its start and pitch, movable by pointer and keyboard, exposing --piano-roll-velocity and --piano-roll-chance |
<audio-ui-piano-roll-note-handle> | Inside a note, resizes it from its edge |
<audio-ui-piano-roll-marquee> | The selection rectangle during a marquee drag |
<audio-ui-piano-roll-selection-span> | The time range of the selection; an <audio-ui-piano-roll-stretch-handle> per edge stretches it |
<audio-ui-piano-roll-velocity-lane> | A lane of per-note bars, through <audio-ui-piano-roll-velocities>, for velocity or, with level="chance", probability. Each <audio-ui-piano-roll-velocity> is sized by --piano-roll-level and contains a native range input |
<audio-ui-piano-roll-keys> | Lays out the <audio-ui-piano> it contains on the roll's rows. Keys sound through the roll; Shift + press selects the notes of that row |
The same control in React, and its parts' props: PianoRoll.