1import type {Peer} from '../types'
2import {shortId} from '../util'
4type Props = {
5 others: Peer[]
6 target: string | null
7 onSelectTarget: (target: string | null) => void
8}
10export function PeerList({others, target, onSelectTarget}: Props) {
11 return (
12 <div className="panel">
13 <h2 className="panel-title">Send messages to</h2>
15 <ul className="peer-list">
16 <li>
17 <button
18 className={`peer broadcast ${target === null ? 'selected' : ''}`}
19 onClick={() => onSelectTarget(null)}
20 >
21 <span className="peer-avatar">📣</span>
22 <span className="peer-name">Everyone</span>
23 <span className="peer-sub">broadcast to all peers</span>
24 </button>
25 </li>
27 {others.map(p => (
28 <li key={p.id}>
29 <button
30 className={`peer ${target === p.id ? 'selected' : ''}`}
31 onClick={() => onSelectTarget(p.id)}
32 title={p.id}
33 >
34 <span className="peer-avatar">{initials(p.name)}</span>
35 <span className="peer-name">{p.name}</span>
36 <span className="peer-sub">
37 <code>{shortId(p.id)}</code>
38 </span>
39 </button>
40 </li>
41 ))}
42 </ul>
44 {others.length === 0 && (
45 <p className="empty">
46 No other peers yet. Open this page in a second browser tab (or send the
47 URL to a friend) and they'll show up here.
48 </p>
49 )}
50 </div>
51 )
52}
54function initials(name: string): string {
55 const cleaned = name.replace(/[()]/g, '').trim()
56 return cleaned.slice(0, 2).toUpperCase() || '??'
57}