feat(app): add TransposeBar collapsible header

This commit is contained in:
2026-04-08 02:29:48 +02:00
parent 3844cc2296
commit 8ca80c38f1

View File

@@ -0,0 +1,85 @@
import { useState } from "react";
import { Button } from "~/components/ui/button";
import { ChevronUp, ChevronDown, Minus, Plus } from "lucide-react";
import type { SongMeta } from "~/lib/types";
interface Props {
meta: SongMeta;
offset: number;
onOffsetChange: (offset: number) => void;
}
export function TransposeBar({ meta, offset, onOffsetChange }: Props) {
const [expanded, setExpanded] = useState(true);
const label = offset === 0
? "±0"
: offset > 0
? `+${offset}`
: `${offset}`;
if (!expanded) {
return (
<div className="flex items-center justify-between px-4 py-2 border-b bg-background sticky top-0">
<span className="text-sm font-semibold truncate">{meta.title}</span>
<Button
variant="ghost"
size="icon"
className="h-7 w-7"
onClick={() => setExpanded(true)}
>
<ChevronDown className="w-4 h-4" />
</Button>
</div>
);
}
return (
<div className="border-b bg-background sticky top-0 px-4 py-3 flex flex-col gap-2">
<div className="flex items-start justify-between">
<div className="flex flex-col">
<span className="font-bold text-base">{meta.title}</span>
<span className="text-sm text-muted-foreground">{meta.artist}</span>
</div>
<Button
variant="ghost"
size="icon"
className="h-7 w-7 shrink-0"
onClick={() => setExpanded(false)}
>
<ChevronUp className="w-4 h-4" />
</Button>
</div>
<div className="flex items-center justify-between">
<div className="flex gap-3 text-xs text-muted-foreground">
{meta.original_key && <span>Key: {meta.original_key}</span>}
{meta.capo != null && <span>Capo: {meta.capo}</span>}
{meta.tuning && <span>{meta.tuning}</span>}
</div>
<div className="flex items-center gap-2">
<Button
variant="ghost"
size="icon"
className="h-8 w-8"
onClick={() => onOffsetChange(Math.max(-11, offset - 1))}
>
<Minus className="w-4 h-4" />
</Button>
<span className="w-8 text-center text-sm font-mono font-semibold">
{label}
</span>
<Button
variant="ghost"
size="icon"
className="h-8 w-8"
onClick={() => onOffsetChange(Math.min(11, offset + 1))}
>
<Plus className="w-4 h-4" />
</Button>
</div>
</div>
</div>
);
}