2026-07-28 12:17:58 +07:00
|
|
|
"use client";
|
|
|
|
|
|
2026-08-14 10:49:44 +07:00
|
|
|
import { Avatar } from "@/components/primitives/avatar";
|
2026-07-28 12:17:58 +07:00
|
|
|
import type { ActiveSpeaker } from "@/lib/types";
|
2026-08-07 17:33:12 +07:00
|
|
|
import { cn } from "@/lib/utils";
|
2026-07-28 12:17:58 +07:00
|
|
|
|
2026-08-14 10:49:44 +07:00
|
|
|
export function SpeakerWaveform({ speakers }: { speakers: ActiveSpeaker[] }) {
|
2026-07-28 12:17:58 +07:00
|
|
|
if (speakers.length === 0) {
|
|
|
|
|
return (
|
2026-08-14 10:49:44 +07:00
|
|
|
<div className="flex items-center gap-2 rounded-[var(--radius-r-control)] bg-[var(--color-surface-2)] px-3 py-1.5 text-xs text-[var(--color-ink-soft)]">
|
|
|
|
|
No active speakers
|
|
|
|
|
</div>
|
2026-07-28 12:17:58 +07:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
return (
|
2026-08-14 10:49:44 +07:00
|
|
|
<div className="flex items-end gap-1.5 rounded-[var(--radius-r-control)] bg-[var(--color-surface-2)] px-3 py-2">
|
|
|
|
|
{speakers.map((s) => (
|
|
|
|
|
<div key={s.userId} className="flex flex-col items-center gap-1">
|
|
|
|
|
<Avatar src={s.avatar} name={s.username} size={28} />
|
|
|
|
|
<div className="flex items-end gap-0.5">
|
|
|
|
|
{Array.from({ length: 5 }).map((_, i) => (
|
|
|
|
|
<span
|
|
|
|
|
key={i}
|
|
|
|
|
className={cn(
|
|
|
|
|
"w-0.5 rounded-t-[2px] bg-[var(--color-signal)] transition-[height]",
|
|
|
|
|
s.speaking ? "h-3 animate-eq" : "h-1 opacity-30",
|
|
|
|
|
)}
|
|
|
|
|
style={
|
|
|
|
|
s.speaking ? { animationDelay: `${i * 0.08}s` } : undefined
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
))}
|
2026-07-28 12:17:58 +07:00
|
|
|
</div>
|
2026-08-14 10:49:44 +07:00
|
|
|
<span className="mono text-[9px] text-[var(--color-ink-soft)]">
|
|
|
|
|
{s.username.split(/[\s.#]/)[0]}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
2026-07-28 12:17:58 +07:00
|
|
|
);
|
|
|
|
|
}
|