Badge Copilot Plus group with privacy + license hint, taller model list

Add a "privacy" badge and a "Copilot license required" hover hint (key
icon) to the Copilot Plus group header in the model enable lists, and
raise the list's max height so more models are visible without scrolling.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018ou7V5v4UYHkzP3csodLLm
This commit is contained in:
Logan Yang 2026-06-29 18:43:46 -07:00
parent f15a84605a
commit 47d3f1e46c
No known key found for this signature in database
3 changed files with 25 additions and 9 deletions

View file

@ -1,12 +1,13 @@
import { Badge } from "@/components/ui/badge";
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
import { FreeModelWarningIcon } from "@/components/ui/FreeModelWarningIcon";
import { HelpTooltip } from "@/components/ui/help-tooltip";
import { ModelCapabilityIcons, hasCapabilityIcons } from "@/components/ui/model-display";
import { SearchBar } from "@/components/ui/SearchBar";
import { SettingSwitch } from "@/components/ui/setting-switch";
import type { ModelCapability } from "@/constants";
import { cn } from "@/lib/utils";
import { ChevronRight } from "lucide-react";
import { ChevronRight, KeyRound } from "lucide-react";
import React from "react";
/** A single toggleable model row. */
@ -39,11 +40,17 @@ export interface ModelEnableGroup {
/** Group heading — a provider display name (no glyphs/avatars). */
label: string;
/**
* Origin badge (e.g. "BYOK", "Agent Provided"). Set only when the list spans
* multiple origins, so it actually disambiguates. Copilot Plus carries no
* badge its label already reads "Copilot Plus".
* Short badge shown after the label. For most origins it's an origin tag
* (e.g. "BYOK", "Agent Provided") set only when the list spans multiple
* origins, so it actually disambiguates. Copilot Plus instead carries a
* "privacy" badge.
*/
badge?: string;
/**
* Optional hover hint rendered as a small icon after the badge (e.g.
* "Copilot license required" for the Copilot Plus group).
*/
tooltip?: string;
/**
* Visually emphasize the group header (accent color). Set for Copilot Plus,
* which the caller also floats to the top of the list.
@ -126,7 +133,7 @@ export const ModelEnableList: React.FC<ModelEnableListProps> = ({
<div className="tw-flex tw-flex-col tw-gap-2">
<SearchBar value={query} onChange={onQueryChange} placeholder={searchPlaceholder} />
<div className="tw-max-h-80 tw-overflow-y-auto tw-pr-1">
<div className="tw-max-h-[36rem] tw-overflow-y-auto tw-pr-1">
{!hasRows ? (
<div className="tw-py-6 tw-text-center tw-text-sm tw-text-muted">
{emptyState ?? (searching ? `No models match “${query.trim()}”.` : "No models.")}
@ -162,6 +169,11 @@ export const ModelEnableList: React.FC<ModelEnableListProps> = ({
{group.badge}
</Badge>
)}
{group.tooltip && (
<HelpTooltip content={group.tooltip} side="top" buttonClassName="tw-size-4">
<KeyRound className="tw-size-3.5 tw-shrink-0 tw-text-muted" />
</HelpTooltip>
)}
</div>
</CollapsibleTrigger>
<CollapsibleContent>

View file

@ -439,7 +439,7 @@ describe("buildModelEnableGroups", () => {
expect(groups.find((g) => g.label === "opencode")?.badge).toBe("Agent Provided");
});
it("floats Copilot Plus to the top, highlights it, and gives it no redundant badge", () => {
it("floats Copilot Plus to the top, highlights it, and gives it the privacy badge + license tooltip", () => {
const plusProvider: Provider = {
providerId: "plus-1",
providerType: "anthropic",
@ -472,7 +472,8 @@ describe("buildModelEnableGroups", () => {
// Copilot Plus is first regardless of candidate order.
expect(groups[0].key).toBe("byok:plus-1");
expect(groups[0].highlight).toBe(true);
expect(groups[0].badge).toBeUndefined();
expect(groups[0].badge).toBe("privacy");
expect(groups[0].tooltip).toBe("Copilot license required");
// Non-Plus groups are not highlighted.
expect(groups.find((g) => g.key === "byok:byok-1")?.highlight).toBeUndefined();
});

View file

@ -214,12 +214,15 @@ export function buildModelEnableGroups(
}
// Copilot Plus is highlighted and floated to the top; its provider name
// already reads "Copilot Plus", so it carries no disambiguating badge. Every
// other origin gets a badge only when the list actually mixes origins.
// already reads "Copilot Plus", so instead of a disambiguating origin badge
// it carries a "privacy" badge plus a license-required hover hint. Every
// other origin gets an origin badge only when the list mixes origins.
const mixed = new Set(out.map((o) => o.kind)).size > 1;
for (const o of out) {
if (o.kind === "copilot-plus") {
o.group.highlight = true;
o.group.badge = "privacy";
o.group.tooltip = "Copilot license required";
} else if (mixed) {
o.group.badge = originBadgeLabel(o.kind);
}