Repository Public
1'use client';2import type { TerminalSession } from '@cr/shared';3import { Pin, SquareTerminal, Sparkles } from 'lucide-react';4import { cn } from '@/lib/cn';5import { fmtRelative } from '@/lib/format';6import { SESSION_STATE } from '@/lib/states';7import { SessionDot } from './state-badge';89export function SessionRow({ session, active, onSelect, now, dense }: { session: TerminalSession; active?: boolean; onSelect: () => void; now: number; dense?: boolean }) {10 const waiting = session.state === 'WAITING_FOR_INPUT';11 const Icon = session.kind === 'claude' ? Sparkles : SquareTerminal;12 return (13 <button14 onClick={onSelect}15 data-testid="session-row"16 data-session-id={session.id}17 aria-current={active ? 'true' : undefined}18 className={cn(19 'group flex w-full items-center gap-2.5 rounded-[10px] px-2.5 text-left transition-colors hover:bg-hover',20 dense ? 'min-h-8 py-1' : 'min-h-12 py-2 pointer-coarse:min-h-14',21 active && 'bg-surface shadow-card hover:bg-surface',22 waiting && 'bg-coral/12 hover:bg-coral/18',23 )}24 >25 <SessionDot state={session.state} />26 <span className="min-w-0 flex-1">27 <span className="flex items-center gap-1.5">28 {!dense && <Icon className="size-3.5 shrink-0 text-muted" aria-hidden />}29 <span className={cn('truncate text-[13px]', active ? 'text-text' : 'text-text-2 group-hover:text-text')}>{session.title}</span>30 {session.pinned && <Pin className="size-3 shrink-0 text-muted" aria-label="Pinned" />}31 </span>32 {!dense && (33 <span className={cn('mt-0.5 block truncate text-[11px]', waiting ? 'text-coral-ink' : 'text-muted')}>34 {waiting ? (session.waitingReason ?? 'Waiting for input') : `${session.projectName ?? 'No project'} · ${SESSION_STATE[session.state].label}`}35 </span>36 )}37 </span>38 {!dense && <span className="tnum shrink-0 text-[11px] text-muted">{fmtRelative(session.lastActivityAt ?? session.createdAt, now)}</span>}39 </button>40 );41}42