// Shared presentation extracted from the Codex subscription-account dropdown.
// Adapters own loading, authorization, usage freshness, and selection semantics.
import { ChevronDownIcon, Loader2Icon } from "lucide-react";
import type { ReactNode } from "react";
import {
DropdownMenu,
DropdownMenuCheck,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuMeta,
DropdownMenuNote,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "../../../ui/dropdown-menu";
import { cn } from "../../lib/utils";
export type SubscriptionAccountMenuRow = {
id: string;
label: string;
plan?: string | null | undefined;
status?: string | null;
detail?: string;
personal?: boolean;
disabled?: boolean;
/** Only supplied when the adapter has a trustworthy quota reading. */
remaining?: number | null;
/** Cached window readings, not an aggregate capacity/eligibility estimate. */
usageSummary?: string | undefined;
};
export type SubscriptionAccountUsageWindow = {
label: string;
remaining?: number;
usedPercent?: number | null;
detail?: string;
};
function UsageRow({ label, remaining, usedPercent, detail }: SubscriptionAccountUsageWindow) {
const value = remaining ?? usedPercent;
const known = typeof value === "number" && Number.isFinite(value);
const pct = known ? Math.min(100, Math.max(0, value)) : 0;
const measure = remaining !== undefined ? "remaining" : "used";
const text = known ? `${Math.round(value)}% ${measure}` : "Unknown";
return (
{label}
{known ? (
= 90)
? "bg-status-waiting"
: "bg-brand",
)}
style={{ width: `${pct}%` }}
/>
) : (
)}
{text}
{detail ?
{detail}
: null}
);
}
function MiniBar({ remaining }: { remaining: number }) {
const pct = Math.min(100, Math.max(0, remaining));
return (
{Math.round(pct)}% remaining
);
}
export function SubscriptionAccountMenu({
ariaLabel,
triggerMark,
headerMark,
selectionLabel,
displayName,
metadata,
identity,
tone = "ok",
usage,
accounts,
selectedId,
automaticSelected,
choosing,
choosingTarget,
actionLabel = "Use for next turn",
automaticLabel = "Automatic",
emptyMessage,
error,
note,
onOpenChange,
onChoose,
}: {
ariaLabel: string;
triggerMark: ReactNode;
headerMark: ReactNode;
selectionLabel: string;
displayName: string;
metadata: string;
identity?: string | null | undefined;
tone?: "ok" | "warn" | "bad" | undefined;
usage: {
checking?: boolean | undefined;
unavailable?: boolean | undefined;
message?: string | undefined;
note?: string | undefined;
windows?: SubscriptionAccountUsageWindow[] | undefined;
};
accounts: SubscriptionAccountMenuRow[];
selectedId: string | null;
automaticSelected: boolean;
choosing: boolean;
choosingTarget: string | null | undefined;
actionLabel?: string | undefined;
automaticLabel?: string | undefined;
emptyMessage?: string | undefined;
error?: string | null | undefined;
note: string;
onOpenChange?: ((open: boolean) => void) | undefined;
onChoose: (connectionId: string | null) => void;
}) {
const row = (account: SubscriptionAccountMenuRow) => (
{
event.preventDefault();
onChoose(account.id);
}}
className="cursor-pointer"
>
{account.label}
{account.usageSummary ? (
{account.usageSummary}
) : null}
{account.plan ? {account.plan} : null}
{account.remaining != null ? : null}
{account.status ? (
{account.status}
) : null}
{choosingTarget === account.id ? (
) : (
)}
);
const personal = accounts.filter((account) => account.personal);
return (
{headerMark}
{selectionLabel}
{displayName}
{identity ? (
{identity}
) : null}
{metadata}
{usage.checking ? (
Checking usageā¦
) : usage.unavailable ? (
Usage unavailable
) : usage.message ? (
{usage.message}
) : (
{usage.windows?.map((window) => (
))}
)}
{usage.note ?
{usage.note}
: null}
{actionLabel}
{
event.preventDefault();
onChoose(null);
}}
className="cursor-pointer"
>
{automaticLabel}
{choosingTarget === null ? (
) : (
)}
{accounts.filter((account) => !account.personal).map(row)}
{personal.length > 0 ? (
<>
Your accounts
{personal.map(row)}
>
) : null}
{accounts.length === 0 && emptyMessage ? (
{emptyMessage}
) : null}
{error ? (
{error}
) : (
{note}
)}
);
}