feat(banner): slim loop strip — big Now Playing chord removed (task L-50, commit 1/2)
Key chip + last-5 history + loop chips on one wrapping row; the playhead loop chip and the enlarged current history chip are the "now"; p-2 chrome trim. The text-6xl Now Playing column, its divider, and the dead currentRN computation are gone — the loop shows once. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,15 +2,21 @@ import { useRef, useEffect } from 'react'
|
|||||||
import { toRomanNumeral } from '../lib/theory'
|
import { toRomanNumeral } from '../lib/theory'
|
||||||
import { findLoopPosition } from '../lib/match'
|
import { findLoopPosition } from '../lib/match'
|
||||||
|
|
||||||
const HISTORY_SHOWN = 8
|
// ─── ProgressionBanner — the SLIM LOOP STRIP (task L-50, one-screen.md §1.2) ──
|
||||||
|
//
|
||||||
|
// One full-width status row: key chip · chord history (last 5, age-faded) ·
|
||||||
|
// ♻ loop chips. The old right-30% "Now Playing" text-6xl chord + its divider
|
||||||
|
// are GONE per the user directive — the enlarged current history chip and the
|
||||||
|
// accent-glowing active loop chip ARE the now-playing display. Chrome trimmed
|
||||||
|
// (p-4 → p-2, history pb-1 dropped) so the strip lands at ~76px.
|
||||||
|
const HISTORY_SHOWN = 5
|
||||||
|
|
||||||
export default function ProgressionBanner({ chordHistory, keyInfo, detectedProgression, currentChord, onChordClick }) {
|
export default function ProgressionBanner({ chordHistory, keyInfo, detectedProgression, onChordClick }) {
|
||||||
const { root, mode, confidence } = keyInfo ?? {}
|
const { root, mode, confidence } = keyInfo ?? {}
|
||||||
|
|
||||||
const visible = chordHistory.slice(-HISTORY_SHOWN)
|
const visible = chordHistory.slice(-HISTORY_SHOWN)
|
||||||
const current = visible[visible.length - 1]
|
const current = visible[visible.length - 1]
|
||||||
const loopPos = findLoopPosition(chordHistory, detectedProgression)
|
const loopPos = findLoopPosition(chordHistory, detectedProgression)
|
||||||
const currentRN = root && current ? toRomanNumeral(current, root, mode) : ''
|
|
||||||
|
|
||||||
const currentRef = useRef(null)
|
const currentRef = useRef(null)
|
||||||
const prevChord = useRef(null)
|
const prevChord = useRef(null)
|
||||||
@@ -25,14 +31,10 @@ export default function ProgressionBanner({ chordHistory, keyInfo, detectedProgr
|
|||||||
}, [current])
|
}, [current])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-panel border border-border rounded-2xl p-4 mb-3 flex gap-4">
|
<div className="bg-panel border border-border rounded-2xl p-2 mb-3 flex flex-wrap items-end gap-x-3 gap-y-1">
|
||||||
|
|
||||||
{/* ── Left: key + chord history + loop ── */}
|
{/* ── Key chip ── */}
|
||||||
<div className="w-full lg:w-[70%] min-w-0 flex flex-col gap-2">
|
<div className="shrink-0 flex items-baseline gap-1.5 self-center">
|
||||||
|
|
||||||
{/* Key + history on one row */}
|
|
||||||
<div className="flex items-end gap-3">
|
|
||||||
<div className="shrink-0 flex items-baseline gap-1.5">
|
|
||||||
{root ? (
|
{root ? (
|
||||||
<>
|
<>
|
||||||
<span className="text-2xl font-bold text-accent">{root}</span>
|
<span className="text-2xl font-bold text-accent">{root}</span>
|
||||||
@@ -46,12 +48,13 @@ export default function ProgressionBanner({ chordHistory, keyInfo, detectedProgr
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="w-px h-6 bg-border shrink-0" />
|
<div className="w-px h-6 bg-border shrink-0 self-center" />
|
||||||
|
|
||||||
|
{/* ── Chord history (the enlarged current chip is the "now") ── */}
|
||||||
{!chordHistory.length ? (
|
{!chordHistory.length ? (
|
||||||
<p className="text-gray-600 text-sm">Start listening…</p>
|
<p className="text-gray-600 text-sm self-center">Start listening…</p>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex items-end gap-1 overflow-x-auto pb-1">
|
<div className="flex items-end gap-1 overflow-x-auto">
|
||||||
{visible.map((chord, i) => {
|
{visible.map((chord, i) => {
|
||||||
const isCurrent = i === visible.length - 1
|
const isCurrent = i === visible.length - 1
|
||||||
const age = visible.length - 1 - i
|
const age = visible.length - 1 - i
|
||||||
@@ -77,18 +80,19 @@ export default function ProgressionBanner({ chordHistory, keyInfo, detectedProgr
|
|||||||
<span className={`text-xs font-semibold mt-0.5 ${
|
<span className={`text-xs font-semibold mt-0.5 ${
|
||||||
isCurrent ? 'text-amber-400' : 'text-gray-500'
|
isCurrent ? 'text-amber-400' : 'text-gray-500'
|
||||||
}`}>
|
}`}>
|
||||||
{rn || '\u00A0'}
|
{rn || ' '}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Loop */}
|
{/* ── Loop — on the same row (divider between); playhead chip = the now ── */}
|
||||||
{detectedProgression && (
|
{detectedProgression && (
|
||||||
<div className="flex items-center gap-1.5 flex-wrap">
|
<>
|
||||||
|
<div className="w-px h-6 bg-border shrink-0 self-center" />
|
||||||
|
<div className="flex items-center gap-1.5 flex-wrap self-center">
|
||||||
<span className="text-xs text-gray-500">♻</span>
|
<span className="text-xs text-gray-500">♻</span>
|
||||||
{detectedProgression.map((chord, i) => {
|
{detectedProgression.map((chord, i) => {
|
||||||
const isActive = i === loopPos
|
const isActive = i === loopPos
|
||||||
@@ -112,29 +116,8 @@ export default function ProgressionBanner({ chordHistory, keyInfo, detectedProgr
|
|||||||
})}
|
})}
|
||||||
<span className="text-gray-600 text-xs">→ loop</span>
|
<span className="text-gray-600 text-xs">→ loop</span>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* ── Divider ── */}
|
|
||||||
<div className="hidden lg:block w-px bg-border shrink-0" />
|
|
||||||
|
|
||||||
{/* ── Right: big chord ── */}
|
|
||||||
<div className="hidden lg:flex w-[30%] flex-col items-center justify-center gap-1">
|
|
||||||
{current ? (
|
|
||||||
<button
|
|
||||||
onClick={() => onChordClick?.(current)}
|
|
||||||
className="flex flex-col items-center gap-1 px-4 py-2 rounded-xl hover:bg-accent/10 transition-colors group"
|
|
||||||
title="Click to see voicings"
|
|
||||||
>
|
|
||||||
<p className="text-xs text-gray-600 uppercase tracking-widest">Now Playing</p>
|
|
||||||
<div className="text-6xl font-black text-amber-400 leading-none group-hover:text-accent transition-colors">{current}</div>
|
|
||||||
<div className="text-sm text-gray-500">{currentRN}</div>
|
|
||||||
<p className="text-[10px] text-gray-700 group-hover:text-gray-500 transition-colors">tap for voicings</p>
|
|
||||||
</button>
|
|
||||||
) : (
|
|
||||||
<p className="text-gray-600 text-xs text-center">Play a chord</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user