From dbb7cbd92f6cf95023aecd6165309c4ec696388b Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Thu, 9 Apr 2026 01:15:49 +0200 Subject: [PATCH] fix: use var(--x) not hsl(var(--x)) for oklch theme vars, redesign fretboard with explicit string lines --- .../chord-diagram/guitar-fretboard.tsx | 194 +++++++++++------- .../components/chord-diagram/piano-keys.tsx | 42 ++-- 2 files changed, 146 insertions(+), 90 deletions(-) diff --git a/app/app/components/chord-diagram/guitar-fretboard.tsx b/app/app/components/chord-diagram/guitar-fretboard.tsx index bb9b001..d4ff27d 100644 --- a/app/app/components/chord-diagram/guitar-fretboard.tsx +++ b/app/app/components/chord-diagram/guitar-fretboard.tsx @@ -1,7 +1,13 @@ import type { GuitarVoicing } from '~/lib/chord-voicing'; -const FRETS_SHOWN = 4; const STRING_COUNT = 6; +const FRET_COUNT = 4; +const STRING_SPACING = 13; // px between adjacent string lines +const FRET_HEIGHT = 18; // px per fret +const DOT_R = 5; // finger dot radius + +const GRID_W = STRING_SPACING * (STRING_COUNT - 1); // 65px +const GRID_H = FRET_HEIGHT * FRET_COUNT; // 72px interface Props { voicing: GuitarVoicing | null; @@ -10,93 +16,139 @@ interface Props { export function GuitarFretboard({ voicing }: Props) { if (!voicing) { return ( -
+
no voicing
); } const { frets, baseFret, barre } = voicing; - - // Show fret number label when not at open position const showFretLabel = baseFret > 0; return ( -
- {/* Open/muted string indicators above nut */} -
- {frets.map((f, i) => ( -
- {f === null ? ( - - ) : f === 0 ? ( - - ) : null} -
- ))} +
+ {/* O/X string indicators above nut */} +
+ {frets.map((f, i) => + f === null ? ( + + ✕ + + ) : f === 0 ? ( + + ○ + + ) : null + )}
- {/* Fretboard grid */} -
- {/* Fret number label */} - {showFretLabel && ( -
- {baseFret} -
- )} + {/* Fret number + grid */} +
+ {/* Fret number label (barre position) */} +
+ {showFretLabel && ( + + {baseFret} + + )} +
- {/* Strings (columns) */} - {frets.map((fret, stringIdx) => ( -
- {/* Nut or top border */} + {/* Fretboard grid */} +
+ {/* String lines (6 vertical lines) */} + {Array.from({ length: STRING_COUNT }, (_, i) => (
- {/* Fret cells */} - {Array.from({ length: FRETS_SHOWN }, (_, fretIdx) => { - // Open position (baseFret=0): rows represent frets 1-4 (nut is shown above) - // Barre position (baseFret>0): rows represent frets baseFret, baseFret+1, … - const absoluteFret = baseFret === 0 ? fretIdx + 1 : baseFret + fretIdx; - const hasDot = fret !== null && fret > 0 && fret === absoluteFret; - return ( -
- {hasDot && ( -
- )} -
- ); - })} -
- ))} + ))} - {/* Barre indicator — only for actual barre chords (not open position) */} - {barre !== null && barre > 0 && ( -
- )} + {/* Fret lines (horizontal, between frets) */} + {Array.from({ length: FRET_COUNT - 1 }, (_, i) => ( +
+ ))} + + {/* Barre bar — only for transposed barre chords */} + {barre !== null && barre > 0 && ( +
+ )} + + {/* Finger dots */} + {frets.map((fret, stringIdx) => { + if (fret === null || fret === 0) return null; + // Skip strings covered by the barre bar + if (barre !== null && fret === barre) return null; + const fretIdx = baseFret === 0 ? fret - 1 : fret - baseFret; + if (fretIdx < 0 || fretIdx >= FRET_COUNT) return null; + return ( +
+ ); + })} +
); diff --git a/app/app/components/chord-diagram/piano-keys.tsx b/app/app/components/chord-diagram/piano-keys.tsx index d24534f..1292216 100644 --- a/app/app/components/chord-diagram/piano-keys.tsx +++ b/app/app/components/chord-diagram/piano-keys.tsx @@ -43,7 +43,7 @@ export function PianoKeys({ notes }: Props) { return (
?
@@ -52,7 +52,7 @@ export function PianoKeys({ notes }: Props) { return (
- {/* Keyboard — light container so keys are visible in any theme */} + {/* Keyboard — gray container makes keys visible in any theme */}
{active && (
)} @@ -103,19 +102,18 @@ export function PianoKeys({ notes }: Props) { top: 0, width: BLACK_KEY_W, height: BLACK_KEY_H, - background: active ? 'hsl(var(--primary))' : '#1c1c1c', + background: active ? 'var(--primary)' : '#1c1c1c', }} > {active && (
)} @@ -124,15 +122,21 @@ export function PianoKeys({ notes }: Props) { })}
- {/* Note labels below keyboard */} + {/* White key note labels */}
{WHITE_KEYS.map((note) => { const active = activeChroma.has(NOTE_CHROMA[note]); return (
{note}
@@ -140,13 +144,13 @@ export function PianoKeys({ notes }: Props) { })}
- {/* Active note names — unambiguous list including black keys */} -
+ {/* Active note names — clearly lists all notes including black keys */} +
{notes.map((note) => ( {note}