feat: fix song view layout - align waveform top, scrollable comments, compose section always visible

This commit is contained in:
Mistral Vibe
2026-04-07 14:36:14 +00:00
parent 5690c9d375
commit ff4985a719

View File

@@ -116,7 +116,8 @@ function Avatar({
} }
return ( return (
<div <div
style={{ style={
{
width: size, width: size,
height: size, height: size,
borderRadius: "50%", borderRadius: "50%",
@@ -129,7 +130,8 @@ function Avatar({
fontSize: size * 0.38, fontSize: size * 0.38,
fontWeight: 700, fontWeight: 700,
flexShrink: 0, flexShrink: 0,
}} }
}
> >
{getInitials(name)} {getInitials(name)}
</div> </div>
@@ -200,7 +202,8 @@ function WaveformPins({
return ( return (
<div <div
key={c.id} key={c.id}
style={{ style={
{
position: "absolute", position: "absolute",
left, left,
top: 0, top: 0,
@@ -212,7 +215,8 @@ function WaveformPins({
zIndex: 10, zIndex: 10,
transition: "transform 0.12s", transition: "transform 0.12s",
...(isHovered ? { transform: "translateX(-50%) scale(1.15)" } : {}), ...(isHovered ? { transform: "translateX(-50%) scale(1.15)" } : {}),
}} }
}
onMouseEnter={() => setHoveredId(c.id)} onMouseEnter={() => setHoveredId(c.id)}
onMouseLeave={() => setHoveredId(null)} onMouseLeave={() => setHoveredId(null)}
onClick={() => { onClick={() => {
@@ -223,7 +227,8 @@ function WaveformPins({
{/* Tooltip */} {/* Tooltip */}
{isHovered && ( {isHovered && (
<div <div
style={{ style={
{
position: "absolute", position: "absolute",
bottom: "calc(100% + 6px)", bottom: "calc(100% + 6px)",
left: "50%", left: "50%",
@@ -235,11 +240,13 @@ function WaveformPins({
width: 180, width: 180,
zIndex: 50, zIndex: 50,
pointerEvents: "none", pointerEvents: "none",
}} }
}
> >
<div style={{ display: "flex", alignItems: "center", gap: 6, marginBottom: 4 }}> <div style={{ display: "flex", alignItems: "center", gap: 6, marginBottom: 4 }}>
<div <div
style={{ style={
{
width: 18, width: 18,
height: 18, height: 18,
borderRadius: "50%", borderRadius: "50%",
@@ -250,7 +257,8 @@ function WaveformPins({
justifyContent: "center", justifyContent: "center",
fontSize: 8, fontSize: 8,
fontWeight: 700, fontWeight: 700,
}} }
}
> >
{getInitials(c.author_name)} {getInitials(c.author_name)}
</div> </div>
@@ -266,7 +274,8 @@ function WaveformPins({
)} )}
{/* Avatar circle */} {/* Avatar circle */}
<div <div
style={{ style={
{
width: 24, width: 24,
height: 24, height: 24,
borderRadius: "50%", borderRadius: "50%",
@@ -279,7 +288,8 @@ function WaveformPins({
fontSize: 9, fontSize: 9,
fontWeight: 700, fontWeight: 700,
boxShadow: "0 2px 8px rgba(0,0,0,0.45)", boxShadow: "0 2px 8px rgba(0,0,0,0.45)",
}} }
}
> >
{getInitials(c.author_name)} {getInitials(c.author_name)}
</div> </div>
@@ -307,7 +317,7 @@ export function SongPage() {
const [composeFocused, setComposeFocused] = useState(false); const [composeFocused, setComposeFocused] = useState(false);
const [waveformWidth, setWaveformWidth] = useState(0); const [waveformWidth, setWaveformWidth] = useState(0);
// ── Data fetching ──────────────────────────────────────────────────────── // ── Data fetching ──────────────────────────────────────────────────────
const { data: me } = useQuery({ const { data: me } = useQuery({
queryKey: ["me"], queryKey: ["me"],
@@ -338,7 +348,7 @@ export function SongPage() {
enabled: !!songId, enabled: !!songId,
}); });
// ── Version selection ──────────────────────────────────────────────────── // ── Version selection ──────────────────────────────────────────────────
const activeVersion = selectedVersionId ?? versions?.[0]?.id ?? null; const activeVersion = selectedVersionId ?? versions?.[0]?.id ?? null;
@@ -361,7 +371,7 @@ export function SongPage() {
return () => ro.disconnect(); return () => ro.disconnect();
}, []); }, []);
// ── Keyboard shortcut: Space ────────────────────────────────────────────── // ── Keyboard shortcut: Space ────────────────────────────────────────────
useEffect(() => { useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => { const handleKeyDown = (e: KeyboardEvent) => {
@@ -401,26 +411,27 @@ export function SongPage() {
}, []); }, []);
// ── Styles ──────────────────────────────────────────────────────────────
// ── Styles ────────────────────────────────────────────────────────────────
const border = "rgba(255,255,255,0.055)"; const border = "rgba(255,255,255,0.055)";
// ── Render ──────────────────────────────────────────────────────────────── // ── Render ──────────────────────────────────────────────────────────────
return ( return (
<div style={{ display: "flex", flexDirection: "column", height: "100%", overflow: "hidden", background: "#0f0f12" }}> <div style={{ display: "flex", flexDirection: "column", height: "100%", overflow: "hidden", background: "#0f0f12" }}>
{/* ── Breadcrumb header ──────────────────────────────────────────── */} {/* ── Breadcrumb header ──────────────────────────────────────────── */}
<div <div
style={{ style={
{
padding: "11px 20px", padding: "11px 20px",
borderBottom: `1px solid ${border}`, borderBottom: `1px solid ${border}`,
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
gap: 8, gap: 8,
flexShrink: 0, flexShrink: 0,
}} }
}
> >
<div style={{ display: "flex", alignItems: "center", gap: 5, flex: 1, minWidth: 0 }}> <div style={{ display: "flex", alignItems: "center", gap: 5, flex: 1, minWidth: 0 }}>
<button <button
@@ -446,14 +457,16 @@ export function SongPage() {
)} )}
<span style={{ color: "rgba(255,255,255,0.15)", fontSize: 11 }}></span> <span style={{ color: "rgba(255,255,255,0.15)", fontSize: 11 }}></span>
<span <span
style={{ style={
{
fontSize: 12, fontSize: 12,
color: "rgba(255,255,255,0.7)", color: "rgba(255,255,255,0.7)",
fontFamily: "'SF Mono', 'Fira Code', monospace", fontFamily: "'SF Mono', 'Fira Code', monospace",
overflow: "hidden", overflow: "hidden",
textOverflow: "ellipsis", textOverflow: "ellipsis",
whiteSpace: "nowrap", whiteSpace: "nowrap",
}} }
}
> >
{song?.title ?? "…"} {song?.title ?? "…"}
</span> </span>
@@ -466,7 +479,8 @@ export function SongPage() {
<button <button
key={v.id} key={v.id}
onClick={() => setSelectedVersionId(v.id)} onClick={() => setSelectedVersionId(v.id)}
style={{ style={
{
background: v.id === activeVersion ? "rgba(232,162,42,0.14)" : "transparent", background: v.id === activeVersion ? "rgba(232,162,42,0.14)" : "transparent",
border: `1px solid ${v.id === activeVersion ? "rgba(232,162,42,0.28)" : "rgba(255,255,255,0.09)"}`, border: `1px solid ${v.id === activeVersion ? "rgba(232,162,42,0.28)" : "rgba(255,255,255,0.09)"}`,
borderRadius: 6, borderRadius: 6,
@@ -475,7 +489,8 @@ export function SongPage() {
cursor: "pointer", cursor: "pointer",
fontSize: 11, fontSize: 11,
fontFamily: "monospace", fontFamily: "monospace",
}} }
}
> >
v{v.version_number}{v.label ? ` · ${v.label}` : ""} v{v.version_number}{v.label ? ` · ${v.label}` : ""}
</button> </button>
@@ -484,7 +499,8 @@ export function SongPage() {
)} )}
<button <button
style={{ style={
{
background: "transparent", background: "transparent",
border: "1px solid rgba(255,255,255,0.09)", border: "1px solid rgba(255,255,255,0.09)",
borderRadius: 6, borderRadius: 6,
@@ -494,28 +510,31 @@ export function SongPage() {
padding: "5px 12px", padding: "5px 12px",
fontFamily: "inherit", fontFamily: "inherit",
flexShrink: 0, flexShrink: 0,
}} }
}
> >
Share Share
</button> </button>
</div> </div>
{/* ── Body: waveform | comments ────────────────────────────────── */} {/* ── Body: waveform | comments ────────────────────────────────── */}
<div className="song-page-body" style={{ display: "flex", flex: 1, overflow: "hidden" }}> <div className="song-page-body" style={{ display: "flex", flexDirection: "column", flex: 1, overflow: "hidden" }}>
{/* ── Left: waveform + transport ──────────────────────────────── */} {/* ── Waveform section (top) ──────────────────────────────── */}
<div className="waveform-section" style={{ flex: 1, display: "flex", flexDirection: "column", overflow: "hidden", padding: "16px 20px" }}> <div className="waveform-section" style={{ display: "flex", flexDirection: "column", overflow: "hidden", padding: "16px 20px" }}>
{/* Waveform card */} {/* Waveform card */}
<div <div
style={{ style={
{
background: "rgba(255,255,255,0.02)", background: "rgba(255,255,255,0.02)",
border: `1px solid ${border}`, border: `1px solid ${border}`,
borderRadius: 10, borderRadius: 10,
padding: "14px 14px 10px", padding: "14px 14px 10px",
marginBottom: 12, marginBottom: 12,
flexShrink: 0, flexShrink: 0,
}} }
}
> >
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 6 }}> <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 6 }}>
<span style={{ fontSize: 11, color: "rgba(255,255,255,0.45)", fontFamily: "monospace" }}> <span style={{ fontSize: 11, color: "rgba(255,255,255,0.45)", fontFamily: "monospace" }}>
@@ -559,13 +578,15 @@ export function SongPage() {
{/* Transport */} {/* Transport */}
<div <div
style={{ style={
{
display: "flex", display: "flex",
justifyContent: "center", justifyContent: "center",
gap: 10, gap: 10,
padding: "4px 0 12px", padding: "4px 0 12px",
flexShrink: 0, flexShrink: 0,
}} }
}
> >
{/* Skip back */} {/* Skip back */}
<TransportButton onClick={() => seekTo(Math.max(0, currentTime - 30))} title="30s"> <TransportButton onClick={() => seekTo(Math.max(0, currentTime - 30))} title="30s">
@@ -576,7 +597,8 @@ export function SongPage() {
<button <button
onClick={isPlaying ? pause : play} onClick={isPlaying ? pause : play}
disabled={!activeVersion} disabled={!activeVersion}
style={{ style={
{
width: 46, width: 46,
height: 46, height: 46,
background: "#e8a22a", background: "#e8a22a",
@@ -589,7 +611,8 @@ export function SongPage() {
opacity: activeVersion ? 1 : 0.4, opacity: activeVersion ? 1 : 0.4,
flexShrink: 0, flexShrink: 0,
transition: "background 0.15s, transform 0.15s", transition: "background 0.15s, transform 0.15s",
}} }
}
onMouseEnter={(e) => { if (activeVersion) e.currentTarget.style.background = "#f0b740"; }} onMouseEnter={(e) => { if (activeVersion) e.currentTarget.style.background = "#f0b740"; }}
onMouseLeave={(e) => { e.currentTarget.style.background = "#e8a22a"; }} onMouseLeave={(e) => { e.currentTarget.style.background = "#e8a22a"; }}
> >
@@ -606,49 +629,207 @@ export function SongPage() {
</div> </div>
{/* ── Right: comment panel ──────────────────────────────────────── */} {/* ── Comments section (bottom) ──────────────────────────────── */}
<div <div
className="comment-panel" className="comment-panel"
style={{ style={
width: 280, {
minWidth: 280,
borderLeft: `1px solid ${border}`,
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
overflow: "hidden", overflow: "hidden",
background: "rgba(0,0,0,0.12)", background: "rgba(0,0,0,0.12)",
// Responsive: center on mobile borderTop: `1px solid ${border}`,
margin: "0 auto", flex: 1,
}} }
}
> >
{/* Header */} {/* Header */}
<div <div
style={{ style={
{
padding: "12px 15px", padding: "12px 15px",
borderBottom: `1px solid ${border}`, borderBottom: `1px solid ${border}`,
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
justifyContent: "space-between", justifyContent: "space-between",
flexShrink: 0, flexShrink: 0,
}} }
}
> >
<span style={{ fontSize: 13, fontWeight: 500, color: "rgba(255,255,255,0.72)" }}>Comments</span> <span style={{ fontSize: 13, fontWeight: 500, color: "rgba(255,255,255,0.72)" }}>Comments</span>
{comments && comments.length > 0 && ( {comments && comments.length > 0 && (
<span <span
style={{ style={
{
fontSize: 11, fontSize: 11,
background: "rgba(232,162,42,0.14)", background: "rgba(232,162,42,0.14)",
color: "#e8a22a", color: "#e8a22a",
padding: "1px 8px", padding: "1px 8px",
borderRadius: 10, borderRadius: 10,
}} }
}
> >
{comments.length} {comments.length}
</span> </span>
)} )}
</div> </div>
{/* Comment list */} {/* Compose section (moved to top) */}
<div
style={
{
padding: "11px 14px",
borderBottom: `1px solid ${border}`,
flexShrink: 0,
}
}
>
<div style={{ display: "flex", gap: 9, alignItems: "flex-start" }}>
{/* My avatar */}
{me ? (
<Avatar name={me.display_name} avatarUrl={me.avatar_url ?? null} authorId={me.id} size={26} />
) : (
<div style={{ width: 26, height: 26, borderRadius: "50%", background: "rgba(255,255,255,0.06)", flexShrink: 0 }} />
)}
<div style={{ flex: 1, minWidth: 0 }}>
{/* Timestamp pill */}
<div style={{ display: "flex", alignItems: "center", gap: 7, marginBottom: 6 }}>
<div
style={
{
fontSize: 11,
fontFamily: "monospace",
background: "rgba(232,162,42,0.1)",
color: "#e8a22a",
border: "1px solid rgba(232,162,42,0.22)",
padding: "3px 9px",
borderRadius: 20,
display: "flex",
alignItems: "center",
gap: 6,
}
}
>
{isPlaying && (
<div
style={
{
width: 6,
height: 6,
borderRadius: "50%",
background: "#e8a22a",
animation: "rh-blink 1.1s infinite",
}
}
/>
)}
{formatTime(currentTime)}
</div>
<span style={{ fontSize: 11, color: "rgba(255,255,255,0.18)" }}>· pins to playhead</span>
</div>
{/* Textarea */}
<textarea
value={commentBody}
onChange={(e) => setCommentBody(e.target.value)}
onFocus={() => setComposeFocused(true)}
onBlur={() => {
if (!commentBody.trim()) setComposeFocused(false);
}}
placeholder="What do you hear at this moment…"
style={
{
width: "100%",
background: "rgba(255,255,255,0.05)",
border: composeFocused
? "1px solid rgba(232,162,42,0.35)"
: "1px solid rgba(255,255,255,0.07)",
borderRadius: 7,
padding: "8px 10px",
color: "#e0e0e8",
fontSize: 12,
resize: "none",
outline: "none",
fontFamily: "inherit",
height: composeFocused ? 68 : 42,
transition: "height 0.18s, border-color 0.15s",
boxSizing: "border-box",
}
}
/>
{/* Tag buttons + Post (visible when focused) */}
{composeFocused && (
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginTop: 7 }}>
<div style={{ display: "flex", gap: 5 }}>
{(["suggestion", "issue", "keeper"] as const).map((tag) => (
<button
key={tag}
onClick={() => setSelectedTag((t) => (t === tag ? "" : tag))}
style={
{
fontSize: 11,
padding: "3px 8px",
borderRadius: 4,
cursor: "pointer",
fontFamily: "inherit",
background:
selectedTag === tag
? TAG_STYLES[tag].bg
: "rgba(255,255,255,0.05)",
border:
selectedTag === tag
? `1px solid ${TAG_STYLES[tag].color}44`
: "1px solid rgba(255,255,255,0.07)",
color:
selectedTag === tag
? TAG_STYLES[tag].color
: "rgba(255,255,255,0.32)",
transition: "all 0.12s",
}
}
>
{tag}
</button>
))}
</div>
<button
onClick={() => {
if (commentBody.trim()) {
addCommentMutation.mutate({
body: commentBody.trim(),
timestamp: currentTime,
tag: selectedTag,
});
}
}}
disabled={!commentBody.trim() || addCommentMutation.isPending}
style={
{
padding: "5px 14px",
borderRadius: 6,
background: "#e8a22a",
border: "none",
color: "#0f0f12",
cursor: commentBody.trim() ? "pointer" : "default",
fontSize: 12,
fontWeight: 600,
fontFamily: "inherit",
opacity: commentBody.trim() ? 1 : 0.35,
transition: "opacity 0.12s",
}
}
>
Post
</button>
</div>
)}
</div>
</div>
</div>
{/* Scrollable comment list */}
<div style={{ flex: 1, overflowY: "auto", padding: "12px 14px" }}> <div style={{ flex: 1, overflowY: "auto", padding: "12px 14px" }}>
{comments?.map((c) => { {comments?.map((c) => {
const tagStyle = c.tag ? TAG_STYLES[c.tag] : null; const tagStyle = c.tag ? TAG_STYLES[c.tag] : null;
@@ -658,7 +839,8 @@ export function SongPage() {
<div <div
key={c.id} key={c.id}
id={`comment-${c.id}`} id={`comment-${c.id}`}
style={{ style={
{
marginBottom: 14, marginBottom: 14,
paddingBottom: 14, paddingBottom: 14,
borderBottom: "1px solid rgba(255,255,255,0.04)", borderBottom: "1px solid rgba(255,255,255,0.04)",
@@ -666,7 +848,8 @@ export function SongPage() {
background: isNearPlayhead ? "rgba(232,162,42,0.04)" : undefined, background: isNearPlayhead ? "rgba(232,162,42,0.04)" : undefined,
border: isNearPlayhead ? "1px solid rgba(232,162,42,0.12)" : undefined, border: isNearPlayhead ? "1px solid rgba(232,162,42,0.12)" : undefined,
padding: isNearPlayhead ? 8 : undefined, padding: isNearPlayhead ? 8 : undefined,
}} }
}
> >
{/* Author row */} {/* Author row */}
<div style={{ display: "flex", alignItems: "center", gap: 7, marginBottom: 5 }}> <div style={{ display: "flex", alignItems: "center", gap: 7, marginBottom: 5 }}>
@@ -679,7 +862,8 @@ export function SongPage() {
onClick={() => { onClick={() => {
seekTo(c.timestamp!); seekTo(c.timestamp!);
}} }}
style={{ style={
{
marginLeft: "auto", marginLeft: "auto",
fontSize: 10, fontSize: 10,
fontFamily: "monospace", fontFamily: "monospace",
@@ -689,7 +873,8 @@ export function SongPage() {
borderRadius: 3, borderRadius: 3,
padding: "1px 5px", padding: "1px 5px",
cursor: "pointer", cursor: "pointer",
}} }
}
onMouseEnter={(e) => (e.currentTarget.style.background = "rgba(232,162,42,0.2)")} onMouseEnter={(e) => (e.currentTarget.style.background = "rgba(232,162,42,0.2)")}
onMouseLeave={(e) => (e.currentTarget.style.background = "rgba(232,162,42,0.1)")} onMouseLeave={(e) => (e.currentTarget.style.background = "rgba(232,162,42,0.1)")}
> >
@@ -698,13 +883,15 @@ export function SongPage() {
)} )}
{tagStyle && ( {tagStyle && (
<span <span
style={{ style={
{
fontSize: 10, fontSize: 10,
padding: "1px 5px", padding: "1px 5px",
borderRadius: 3, borderRadius: 3,
background: tagStyle.bg, background: tagStyle.bg,
color: tagStyle.color, color: tagStyle.color,
}} }
}
> >
{c.tag} {c.tag}
</span> </span>
@@ -744,148 +931,6 @@ export function SongPage() {
)} )}
</div> </div>
{/* Compose */}
<div
style={{
padding: "11px 14px",
borderTop: `1px solid ${border}`,
flexShrink: 0,
}}
>
<div style={{ display: "flex", gap: 9, alignItems: "flex-start" }}>
{/* My avatar */}
{me ? (
<Avatar name={me.display_name} avatarUrl={me.avatar_url ?? null} authorId={me.id} size={26} />
) : (
<div style={{ width: 26, height: 26, borderRadius: "50%", background: "rgba(255,255,255,0.06)", flexShrink: 0 }} />
)}
<div style={{ flex: 1, minWidth: 0 }}>
{/* Timestamp pill */}
<div style={{ display: "flex", alignItems: "center", gap: 7, marginBottom: 6 }}>
<div
style={{
fontSize: 11,
fontFamily: "monospace",
background: "rgba(232,162,42,0.1)",
color: "#e8a22a",
border: "1px solid rgba(232,162,42,0.22)",
padding: "3px 9px",
borderRadius: 20,
display: "flex",
alignItems: "center",
gap: 6,
}}
>
{isPlaying && (
<div
style={{
width: 6,
height: 6,
borderRadius: "50%",
background: "#e8a22a",
animation: "rh-blink 1.1s infinite",
}}
/>
)}
{formatTime(currentTime)}
</div>
<span style={{ fontSize: 11, color: "rgba(255,255,255,0.18)" }}>· pins to playhead</span>
</div>
{/* Textarea */}
<textarea
value={commentBody}
onChange={(e) => setCommentBody(e.target.value)}
onFocus={() => setComposeFocused(true)}
onBlur={() => {
if (!commentBody.trim()) setComposeFocused(false);
}}
placeholder="What do you hear at this moment…"
style={{
width: "100%",
background: "rgba(255,255,255,0.05)",
border: composeFocused
? "1px solid rgba(232,162,42,0.35)"
: "1px solid rgba(255,255,255,0.07)",
borderRadius: 7,
padding: "8px 10px",
color: "#e0e0e8",
fontSize: 12,
resize: "none",
outline: "none",
fontFamily: "inherit",
height: composeFocused ? 68 : 42,
transition: "height 0.18s, border-color 0.15s",
boxSizing: "border-box",
}}
/>
{/* Tag buttons + Post (visible when focused) */}
{composeFocused && (
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginTop: 7 }}>
<div style={{ display: "flex", gap: 5 }}>
{(["suggestion", "issue", "keeper"] as const).map((tag) => (
<button
key={tag}
onClick={() => setSelectedTag((t) => (t === tag ? "" : tag))}
style={{
fontSize: 11,
padding: "3px 8px",
borderRadius: 4,
cursor: "pointer",
fontFamily: "inherit",
background:
selectedTag === tag
? TAG_STYLES[tag].bg
: "rgba(255,255,255,0.05)",
border:
selectedTag === tag
? `1px solid ${TAG_STYLES[tag].color}44`
: "1px solid rgba(255,255,255,0.07)",
color:
selectedTag === tag
? TAG_STYLES[tag].color
: "rgba(255,255,255,0.32)",
transition: "all 0.12s",
}}
>
{tag}
</button>
))}
</div>
<button
onClick={() => {
if (commentBody.trim()) {
addCommentMutation.mutate({
body: commentBody.trim(),
timestamp: currentTime,
tag: selectedTag,
});
}
}}
disabled={!commentBody.trim() || addCommentMutation.isPending}
style={{
padding: "5px 14px",
borderRadius: 6,
background: "#e8a22a",
border: "none",
color: "#0f0f12",
cursor: commentBody.trim() ? "pointer" : "default",
fontSize: 12,
fontWeight: 600,
fontFamily: "inherit",
opacity: commentBody.trim() ? 1 : 0.35,
transition: "opacity 0.12s",
}}
>
Post
</button>
</div>
)}
</div>
</div>
</div>
</div> </div>
</div> </div>
@@ -928,7 +973,8 @@ function TransportButton({ onClick, title, children }: { onClick: () => void; ti
title={title} title={title}
onMouseEnter={() => setHovered(true)} onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)} onMouseLeave={() => setHovered(false)}
style={{ style={
{
width: 34, width: 34,
height: 34, height: 34,
borderRadius: "50%", borderRadius: "50%",
@@ -941,11 +987,10 @@ function TransportButton({ onClick, title, children }: { onClick: () => void; ti
color: hovered ? "rgba(255,255,255,0.7)" : "rgba(255,255,255,0.35)", color: hovered ? "rgba(255,255,255,0.7)" : "rgba(255,255,255,0.35)",
flexShrink: 0, flexShrink: 0,
transition: "all 0.12s", transition: "all 0.12s",
}} }
}
> >
{children} {children}
</button> </button>
); );
} }