Files
boocode/apps/web/src/components/StatusDot.tsx
indifferentketchup 2bce4d85fa feat(mobile): v1.8 tab switcher + branch indicator + git_status tool
Mobile header is now two rows. Row 1: hamburger | project · branch
indicator (live via GET /api/projects/:id/git, 30s poll) | ModelPicker |
FolderTree. Row 2: pane-switcher pill (hand-rolled BottomSheet) +
NewPaneMenu. Chat-within-pane navigation hidden on mobile; users switch
panes via the sheet. Cross-tab status sync via chat_status frames
published from inference.ts at working/idle/error transitions; StatusDot
component renders amber-pulse/green/red/gray on each pane row and on
desktop ChatTabBar tabs. Level 1 git awareness exposes a read-only
git_status tool to the model, backed by services/git_meta.ts (execFile
+ 2s timeout + 30s cache). Workspace.tsx now receives panes/chats hooks
as props (hoisted into Session.tsx) so the header pill shares state
with the pane grid.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 20:07:53 +00:00

37 lines
884 B
TypeScript

import { useChatStatus, type DerivedStatus } from '@/hooks/useChatStatus';
import { cn } from '@/lib/utils';
interface Props {
chatId: string | null | undefined;
className?: string;
}
const STATUS_CLASS: Record<DerivedStatus, string> = {
working: 'bg-amber-500 animate-pulse',
idle_warm: 'bg-emerald-500',
idle_cold: 'bg-muted-foreground/40',
error: 'bg-destructive',
};
const STATUS_LABEL: Record<DerivedStatus, string> = {
working: 'working',
idle_warm: 'idle',
idle_cold: 'idle',
error: 'error',
};
export function StatusDot({ chatId, className }: Props) {
const status = useChatStatus(chatId);
return (
<span
aria-label={`Status: ${STATUS_LABEL[status]}`}
title={STATUS_LABEL[status]}
className={cn(
'inline-block w-1.5 h-1.5 rounded-full shrink-0',
STATUS_CLASS[status],
className,
)}
/>
);
}