Assist mode: taller live-note staff box (88px)

The Assist card wrapped the LiveNoteStaff in .sheet-music-container,
which clips (overflow: hidden) — extreme ledger lines poked out of the
64px box by a few px. LiveNoteStaff now takes a height prop; stave y is
computed as (h-38)/2 - 40.5 (equals the old -28 for h=64). Assist uses
88px; mic bar keeps 64px.
This commit is contained in:
2026-09-20 00:25:36 +02:00
parent 05d5548d0c
commit 56ace9efac
2 changed files with 13 additions and 6 deletions

View File

@@ -61,6 +61,7 @@ export const AssistMode: React.FC<AssistModeProps> = ({ pitchData, windowWidth }
keySignature={settings.keySignature}
clef={clef === 'grand' ? undefined : clef}
width={Math.min(240, staffWidth)}
height={88}
theme={settings.theme}
/>
</div>

View File

@@ -21,14 +21,19 @@ interface LiveNoteStaffProps {
* clef auto-switches treble/bass around middle C (piano-style). */
clef?: 'treble' | 'bass';
width?: number;
/** Box height. 64px matches the mic bar; larger boxes (e.g. 88px in
* Assist mode) give ledger lines room inside instead of being clipped
* by the parent's overflow: hidden. */
height?: number;
theme?: 'light' | 'dark' | 'auto';
}
const BOX_H = 64; // mic button height — vertical centering via the bar
// VexFlow draws the first stave line ~40.5px BELOW the constructor y
// (default space_above_staff_ln = 4 line-spaces). To center a 38px staff in
// the 64px box the constructor y must be negative.
const STAVE_Y = -28;
// (default space_above_staff_ln = 4 line-spaces). To center the ~38px staff
// in a box of height h the constructor y must be negative. For h = 64 this
// yields -27.5 ≈ -28 (the original hardcoded value).
const staveYFor = (h: number) => (h - 38) / 2 - 40.5;
export const LiveNoteStaff: React.FC<LiveNoteStaffProps> = ({
midi,
@@ -36,6 +41,7 @@ export const LiveNoteStaff: React.FC<LiveNoteStaffProps> = ({
keySignature = 'C',
clef: clefOverride,
width = 130,
height: boxH = BOX_H,
theme = 'auto',
}) => {
const containerRef = useRef<HTMLDivElement>(null);
@@ -53,7 +59,7 @@ export const LiveNoteStaff: React.FC<LiveNoteStaffProps> = ({
container.innerHTML = '';
const renderer = new Renderer(container, Renderer.Backends.SVG);
renderer.resize(width, BOX_H);
renderer.resize(width, boxH);
const context = renderer.getContext();
const resolvedColor =
@@ -63,7 +69,7 @@ export const LiveNoteStaff: React.FC<LiveNoteStaffProps> = ({
context.setFillStyle(resolvedColor);
context.setStrokeStyle(resolvedColor);
const stave = new Stave(0, STAVE_Y, width - 2);
const stave = new Stave(0, staveYFor(boxH), width - 2);
stave.setDefaultLedgerLineStyle({ strokeStyle: resolvedColor, lineWidth: 2 });
const written0 = midi !== null ? midi + transpose : null;
// Instrument-fixed clef when provided (guitar always treble, bass
@@ -119,7 +125,7 @@ export const LiveNoteStaff: React.FC<LiveNoteStaffProps> = ({
<div
ref={containerRef}
className="live-note-staff"
style={{ width, height: BOX_H }}
style={{ width, height: boxH }}
role="img"
aria-label={midi !== null ? 'Currently played note' : 'No note currently detected'}
/>