"use client"; import * as React from "react"; import { Trophy } from "lucide-react"; import { ProviderIcon } from "@/components/brand/provider-icon"; import type { ColumnStatus } from "./types"; import { StatusDot } from "./metrics-strip"; import { BlindAvatar } from "./blind"; import { cn } from "@/lib/utils"; export interface ModelTabItem { key: string; name: string; provider: string | null; status: ColumnStatus; tokensPerSecond: number | null; isWinner?: boolean; /** Blind: identity hidden. */ hidden?: boolean; blindIndex: number; } /** * Sticky model tab bar for the phone carousel (Segmented-like): provider icon (or blind letter), * status dot, name and live tok/s. Selecting a tab scrolls the carousel; swiping updates the tab. */ export function ModelTabs({ items, active, onSelect, className }: { items: ModelTabItem[]; active: number; onSelect: (index: number) => void; className?: string }) { const ref = React.useRef(null); // Keep the active tab in view while swiping. React.useEffect(() => { const el = ref.current?.children[active] as HTMLElement | undefined; el?.scrollIntoView({ block: "nearest", inline: "center", behavior: "smooth" }); }, [active]); const onKey = (e: React.KeyboardEvent) => { if (e.key !== "ArrowLeft" && e.key !== "ArrowRight") return; e.preventDefault(); const next = (active + (e.key === "ArrowLeft" ? -1 : 1) + items.length) % items.length; onSelect(next); (ref.current?.children[next] as HTMLElement | undefined)?.focus(); }; return (
{items.map((it, i) => { const on = i === active; return ( ); })}
); }