Align dictation controls with settings dropdowns and show setup guidance
This commit is contained in:
@@ -71,7 +71,7 @@ import {
|
||||
import type { ThinkingLevel } from "@earendil-works/pi-agent-core";
|
||||
import { prettyModel } from "@/components/usage-format";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { SettingsGroup, SettingsRow, Toggle, CommitInput } from "./controls.tsx";
|
||||
import { SettingsGroup, SettingsRow, SettingsMenuTrigger, Toggle, CommitInput } from "./controls.tsx";
|
||||
import { ModelMenuList, ThinkingMenuList } from "./model-menu";
|
||||
import { ChatGPTBackgroundAccess } from "./chatgpt-connection";
|
||||
import { NativeSubscriptionBackgroundAccess } from "./subscription-connections";
|
||||
@@ -245,23 +245,17 @@ function MenuTrigger({
|
||||
disabled?: boolean;
|
||||
}) {
|
||||
const button = (
|
||||
<button
|
||||
type="button"
|
||||
<SettingsMenuTrigger
|
||||
value={value || emptyLabel}
|
||||
aria-label={ariaLabel}
|
||||
aria-expanded={open}
|
||||
data-testid={testid}
|
||||
onClick={() => {
|
||||
if (!disabled) onClick();
|
||||
}}
|
||||
className={`flex h-7 items-center gap-1 rounded-sm border border-border bg-background px-1.5 font-ui text-xs text-foreground transition-colors ${
|
||||
disabled ? "cursor-not-allowed" : "hover:border-muted-foreground/50"
|
||||
} ${widthClass}`}
|
||||
>
|
||||
<span className="min-w-0 flex-1 truncate">{value || emptyLabel}</span>
|
||||
<span aria-hidden className="text-muted-foreground">
|
||||
▾
|
||||
</span>
|
||||
</button>
|
||||
unavailable={disabled}
|
||||
className={widthClass}
|
||||
/>
|
||||
);
|
||||
return hint ? <Hint label={hint}>{button}</Hint> : button;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ import { MenuShell } from "@/components/menu-shell";
|
||||
import { Hint } from "@/components/ui/hint";
|
||||
import { useAppearance } from "./appearance.tsx";
|
||||
import { FontMenuList } from "./model-menu";
|
||||
import { CommitInput, SettingsRow, ThinSelect, Toggle } from "./controls.tsx";
|
||||
import { CommitInput, SettingsMenuTrigger, SettingsRow, ThinSelect, Toggle } from "./controls.tsx";
|
||||
|
||||
/** The factory reading family — the DEFAULT row's identity (unset =
|
||||
* this). Exported for tests. */
|
||||
@@ -210,29 +210,22 @@ export function AppearanceSection({
|
||||
testid="row-font"
|
||||
>
|
||||
<span ref={fontMenuOpen ? menuAnchorRef : undefined} className="relative flex items-center gap-2">
|
||||
{/* The MenuTrigger look (agent-section's collapsed
|
||||
select — it lives unexported there, so the
|
||||
classes ride inline; the searchable machine is
|
||||
the shared part). The tooltip rides the CLOSED
|
||||
button ONLY (owner ruling 2026-09-26: never while
|
||||
{/* The shared Agent/Appearance collapsed-menu trigger.
|
||||
The tooltip rides the CLOSED button ONLY
|
||||
(owner ruling 2026-09-26: never while
|
||||
the dropdown is out — it popped over the open
|
||||
menu when the wrap covered the whole anchor
|
||||
span). */}
|
||||
{(() => {
|
||||
const triggerButton = (
|
||||
<button
|
||||
type="button"
|
||||
<SettingsMenuTrigger
|
||||
value={appearance?.fontFamily || DEFAULT_READING_FONT}
|
||||
aria-label="Reading font"
|
||||
aria-expanded={fontMenuOpen}
|
||||
data-testid="font-trigger"
|
||||
onClick={openFontMenu}
|
||||
className="flex h-7 min-w-20 items-center gap-1 rounded-sm border border-border bg-background px-1.5 font-ui text-xs text-foreground transition-colors hover:border-muted-foreground/50"
|
||||
>
|
||||
<span className="min-w-0 flex-1 truncate">{appearance?.fontFamily || DEFAULT_READING_FONT}</span>
|
||||
<span aria-hidden className="text-muted-foreground">
|
||||
▾
|
||||
</span>
|
||||
</button>
|
||||
className="min-w-20"
|
||||
/>
|
||||
);
|
||||
return fontMenuOpen ? (
|
||||
triggerButton
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* control together) and the control itself locks — the row owns the dim.
|
||||
*/
|
||||
|
||||
import { useState, type ReactNode } from "react";
|
||||
import { useState, type ComponentPropsWithRef, type ReactNode } from "react";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
/** A section block: pronounced mono heading + content. */
|
||||
@@ -81,6 +81,30 @@ export function SettingsRow({
|
||||
);
|
||||
}
|
||||
|
||||
/** The existing Agent/Appearance collapsed-menu look, shared with dictation.
|
||||
* `unavailable` preserves callers that gate clicks without native disabling;
|
||||
* `disabled` retains native button semantics where the caller requires them. */
|
||||
export function SettingsMenuTrigger({
|
||||
value, unavailable, disabled, className, ...props
|
||||
}: Omit<ComponentPropsWithRef<"button">, "value" | "children"> & {
|
||||
value: string;
|
||||
unavailable?: boolean;
|
||||
}) {
|
||||
return <button
|
||||
type="button"
|
||||
{...props}
|
||||
disabled={disabled}
|
||||
className={cn(
|
||||
"flex h-7 items-center gap-1 rounded-sm border border-border bg-background px-1.5 font-ui text-xs text-foreground transition-colors",
|
||||
disabled || unavailable ? "cursor-not-allowed" : "hover:border-muted-foreground/50",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<span className="min-w-0 flex-1 truncate">{value}</span>
|
||||
<span aria-hidden className="text-muted-foreground">▾</span>
|
||||
</button>;
|
||||
}
|
||||
|
||||
/** The on/off switch — a plain button in the switch role. */
|
||||
export function Toggle({
|
||||
checked,
|
||||
|
||||
@@ -490,7 +490,17 @@ export function KeysSection({
|
||||
testid={`key-${status.id.toLowerCase()}`}
|
||||
/>
|
||||
))}
|
||||
{label === "Dictation" && <DictationLanguageSetting />}
|
||||
{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"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="underline underline-offset-2 hover:text-foreground"
|
||||
>Member role or higher</a>, then add it above.
|
||||
</p>
|
||||
</>}
|
||||
</SettingsGroup>)}
|
||||
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user