Skip to content

Commit 6982d99

Browse files
authored
fix(annotate): make Ask AI announcement provider cards clickable (#972) (#975)
The PlanAIAnnouncementDialog rendered provider cards as plain <div>s with selection styling but no onClick, so clicking a card did nothing despite the UI implying it switched the active AI provider. Cards now render as buttons for actually-detected providers and call the existing AI config change handler (same path as the Settings provider selector). Providers that aren't installed are shown greyed out as "not installed" rather than appearing selectable. The dialog is fed the raw detected provider list (aiProviders) instead of visibleAIProviders, so the agent-terminal substitution doesn't make every card read "not installed".
1 parent 1e631ac commit 6982d99

2 files changed

Lines changed: 54 additions & 12 deletions

File tree

packages/editor/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4655,6 +4655,8 @@ const App: React.FC = () => {
46554655
isOpen={shouldShowPlanAIAnnouncement}
46564656
origin={origin}
46574657
providerName={selectedAIProvider?.name ?? null}
4658+
providers={aiProviders}
4659+
onSelectProvider={(providerId) => handleAIConfigChange({ providerId })}
46584660
onOpenAI={handleOpenAIAnnouncement}
46594661
onDismiss={dismissPlanAIAnnouncement}
46604662
/>

packages/ui/components/PlanAIAnnouncementDialog.tsx

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,18 @@ import { AGENT_CONFIG, getAgentAIProviderTypes, getAgentName } from '@plannotato
55
import { SparklesIcon } from './SparklesIcon';
66
import { getProviderMeta } from './ProviderIcons';
77

8+
interface PlanAIAnnouncementProvider {
9+
id: string;
10+
name: string;
11+
}
12+
813
interface PlanAIAnnouncementDialogProps {
914
isOpen: boolean;
1015
origin?: Origin | null;
1116
providerName?: string | null;
17+
/** Actually-detected providers (installed + authenticated). Cards matching one of these are selectable. */
18+
providers?: PlanAIAnnouncementProvider[];
19+
onSelectProvider?: (providerId: string) => void;
1220
onOpenAI: () => void;
1321
onDismiss: () => void;
1422
}
@@ -27,6 +35,8 @@ export const PlanAIAnnouncementDialog: React.FC<PlanAIAnnouncementDialogProps> =
2735
isOpen,
2836
origin,
2937
providerName,
38+
providers = [],
39+
onSelectProvider,
3040
onOpenAI,
3141
onDismiss,
3242
}) => {
@@ -67,25 +77,55 @@ export const PlanAIAnnouncementDialog: React.FC<PlanAIAnnouncementDialogProps> =
6777
const meta = getProviderMeta(providerType);
6878
const Icon = meta.icon;
6979
const isSelected = providerType === providerName;
70-
return (
71-
<div
72-
key={providerType}
73-
className={`flex min-h-16 items-center gap-2 rounded-lg border p-2.5 ${
74-
isSelected
75-
? 'border-primary bg-primary/5'
76-
: 'border-border bg-muted/35'
77-
}`}
78-
>
80+
// A card is selectable only if the provider is actually detected on this machine.
81+
const detected = providers.find(p => p.name === providerType) ?? null;
82+
const isSelectable = Boolean(detected && onSelectProvider);
83+
84+
const inner = (
85+
<>
7986
<div className="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-md bg-background/70 text-muted-foreground">
8087
<Icon className="h-[18px] w-[18px]" />
8188
</div>
8289
<div className="min-w-0">
8390
<div className="truncate text-sm font-medium">{meta.label}</div>
84-
{isSelected && (
91+
{isSelected ? (
8592
<div className="text-[10px] uppercase tracking-wide text-primary">selected</div>
86-
)}
93+
) : !detected ? (
94+
<div className="text-[10px] text-muted-foreground/60">not installed</div>
95+
) : null}
8796
</div>
88-
</div>
97+
</>
98+
);
99+
100+
if (!isSelectable) {
101+
return (
102+
<div
103+
key={providerType}
104+
className={`flex min-h-16 items-center gap-2 rounded-lg border p-2.5 ${
105+
isSelected
106+
? 'border-primary bg-primary/5'
107+
: 'border-border bg-muted/35 opacity-60'
108+
}`}
109+
>
110+
{inner}
111+
</div>
112+
);
113+
}
114+
115+
return (
116+
<button
117+
key={providerType}
118+
type="button"
119+
onClick={() => onSelectProvider?.(detected!.id)}
120+
aria-pressed={isSelected}
121+
className={`flex min-h-16 items-center gap-2 rounded-lg border p-2.5 text-left transition-colors ${
122+
isSelected
123+
? 'border-primary bg-primary/5'
124+
: 'border-border bg-muted/35 hover:border-muted-foreground/30 hover:bg-muted/60'
125+
}`}
126+
>
127+
{inner}
128+
</button>
89129
);
90130
})}
91131
</div>

0 commit comments

Comments
 (0)