Use sans settings labels and link Deepgram key setup

This commit is contained in:
amosblomqvist
2026-10-27 22:32:55 +02:00
parent 27e277099f
commit 8337836199
8 changed files with 42 additions and 21 deletions
+2 -2
View File
@@ -328,12 +328,12 @@ function AccountDialog({ children, onClose, busy }: { children: React.ReactNode;
}
/** Shared compact settings/setup row; account selection precedes the quiet action. */
export function ChatGPTConnection(_props: { setup?: boolean } = {}) {
export function ChatGPTConnection({ labelClassName }: { setup?: boolean; labelClassName?: string } = {}) {
const ui = useContext(Context);
const active = ui.status.accounts.find((a) => a.id === ui.status.activeId && a.connected);
const accounts = ui.status.accounts.filter((a) => a.connected);
return <div className="flex flex-col gap-2" data-testid="chatgpt-connection">
<ConnectionRow label="ChatGPT" actionTestid={active ? undefined : "chatgpt-login"} action={active ? "Manage…" : "Connect"} disabled={!ui.status.available || ui.busy || ui.status.pending} onAction={() => active ? ui.manage(active.id) : ui.connect()}>
<ConnectionRow label="ChatGPT" labelClassName={labelClassName} actionTestid={active ? undefined : "chatgpt-login"} action={active ? "Manage…" : "Connect"} disabled={!ui.status.available || ui.busy || ui.status.pending} onAction={() => active ? ui.manage(active.id) : ui.connect()}>
{active && <select aria-label="ChatGPT account" value={active.id} disabled={ui.busy || ui.status.pending} onChange={(event) => ui.select(event.target.value)} className="min-w-0 rounded-sm border border-border bg-background px-2 py-1 text-xs text-foreground">
{accounts.map((a) => <option key={a.id} value={a.id}>{a.email || "ChatGPT account"}</option>)}
</select>}
+2 -2
View File
@@ -4,9 +4,9 @@ import { createPortal } from "react-dom";
import { useBackdropDismiss } from "@/components/backdrop-dismiss";
import { Button } from "@/components/ui/button";
export function ConnectionRow({ label, action, disabled, onAction, children, testid, actionTestid }: { label: string; action: string; disabled: boolean; onAction: () => void; children?: React.ReactNode; testid?: string; actionTestid?: string }) {
export function ConnectionRow({ label, action, disabled, onAction, children, testid, actionTestid, labelClassName }: { label: string; action: string; disabled: boolean; onAction: () => void; children?: React.ReactNode; testid?: string; actionTestid?: string; labelClassName?: string }) {
return <div className="flex flex-wrap items-center gap-3" data-testid={testid}>
<span className="font-ui text-xs text-foreground">{label}</span>
<span className={labelClassName ?? "font-ui text-xs text-foreground"}>{label}</span>
{children}
<Button type="button" size="xs" variant={action === "Connect" ? "outline" : "ghost"} className={`cursor-pointer disabled:cursor-not-allowed ${action === "Connect" ? "" : "text-muted-foreground hover:text-foreground"}`} data-testid={actionTestid} disabled={disabled} onClick={onAction}>{action}</Button>
</div>;
+3 -3
View File
@@ -493,12 +493,12 @@ export function KeysSection({
{label === "Dictation" && <>
<DictationLanguageSetting />
<p data-testid="dictation-setup-hint" className="px-1 text-[11px] leading-relaxed text-muted-foreground/70">
Create a Deepgram key with the <a
href="https://developers.deepgram.com/reference/auth/tokens/grant"
Create a <a
href="https://console.deepgram.com/"
target="_blank"
rel="noreferrer"
className="underline underline-offset-2 hover:text-foreground"
>Member role or higher</a>, then add it above.
>Deepgram API key</a> with the Member role or higher, then add it above.
</p>
</>}
</SettingsGroup>)}
@@ -119,16 +119,19 @@ export function NativeSubscriptionUIProvider({ children }: { children: React.Rea
</Context.Provider>;
}
export function NativeSubscriptionConnection({ providerId }: { providerId: NativeSubscriptionProviderId }) {
export function NativeSubscriptionConnection({ providerId, labelClassName }: { providerId: NativeSubscriptionProviderId; labelClassName?: string }) {
const ui = useContext(Context), descriptor = NATIVE_SUBSCRIPTIONS.find((p) => p.providerId === providerId)!;
const status = ui.statuses.find((s) => s.providerId === providerId) ?? emptySubscriptionStatus(providerId);
return <div className="flex flex-col gap-2" data-testid={`${providerId}-connection`}>
<ConnectionRow label={descriptor.label} action={status.connectionId ? "Manage…" : "Connect"} disabled={ui.busy || !status.available || ui.statuses.some((s) => s.pending)} onAction={() => ui.open(providerId)} />
<ConnectionRow label={descriptor.label} labelClassName={labelClassName} action={status.connectionId ? "Manage…" : "Connect"} disabled={ui.busy || !status.available || ui.statuses.some((s) => s.pending)} onAction={() => ui.open(providerId)} />
{status.error && <p role="alert" className="text-xs text-red-400">{status.error}</p>}
</div>;
}
export function SubscriptionConnections({ setup = false }: { setup?: boolean }) {
return <div className="space-y-3" data-testid="subscription-connections"><ChatGPTConnection setup={setup} />{NATIVE_SUBSCRIPTIONS.map((p) => <NativeSubscriptionConnection key={p.providerId} providerId={p.providerId} />)}</div>;
// Providers uses ordinary settings-label typography. The setup surface
// keeps its existing compact labels; dialogs and actions are untouched.
const labelClassName = setup ? undefined : "font-prose text-(length:--lh-prose-size) text-foreground";
return <div className="space-y-3" data-testid="subscription-connections"><ChatGPTConnection setup={setup} labelClassName={labelClassName} />{NATIVE_SUBSCRIPTIONS.map((p) => <NativeSubscriptionConnection key={p.providerId} providerId={p.providerId} labelClassName={labelClassName} />)}</div>;
}
export function NativeSubscriptionBackgroundAccess({ provider }: { provider: string | undefined }) {
const ui = useContext(Context), descriptor = NATIVE_SUBSCRIPTIONS.find((p) => p.logicalId === provider);