import { useEffect, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { Avatar, Badge } from "@trails-cool/ui"; import type { Participant } from "~/lib/use-participants"; interface ParticipantAvatarsProps { participants: Participant[]; /** Called when the local participant commits a new display name. */ onRenameLocal?: (name: string) => void; } /** * Presentational participant strip: a colored Avatar per participant, the * local user's name inline-editable, and a Host badge. Driven entirely by the * plain `participants` array so it renders in the /dev/ui gallery without a * live session. */ export function ParticipantAvatars({ participants, onRenameLocal, }: ParticipantAvatarsProps) { const { t } = useTranslation("planner"); const [editing, setEditing] = useState(false); const [value, setValue] = useState(""); const inputRef = useRef(null); useEffect(() => { if (editing && inputRef.current) { inputRef.current.focus(); inputRef.current.select(); } }, [editing]); const startEditing = (name: string) => { setValue(name); setEditing(true); }; const commit = () => { onRenameLocal?.(value); setEditing(false); }; return (
{participants.map((p) => (
{p.isLocal && editing ? ( setValue(e.target.value)} onBlur={commit} onKeyDown={(e) => { if (e.key === "Enter") commit(); else if (e.key === "Escape") setEditing(false); }} maxLength={20} className="w-24 rounded border border-border bg-bg-raised px-1.5 py-0.5 text-base text-text-hi focus:border-accent focus:outline-none sm:text-xs" /> ) : ( )} {p.isHost && {t("participants.host")}}
))}
); }