perf(desktop): defer model-row submenu bodies until hover

ModelMenuPanel mounts a ModelEditSubmenu per model row, and each body ran
its hooks and built its JSX eagerly on menu open — ~90 rows of switches,
radio groups, and preset lookups nobody hovered yet, the largest app-code
slice in the open-latency profile. Wrap the body in a child component under
SubContent so Radix's presence gate leaves it unrendered until the submenu
actually opens; open latency drops roughly in half on a 91-model catalog.
This commit is contained in:
Brooklyn Nicholson 2026-07-26 01:10:22 -05:00
parent be00a7176c
commit 667758ac24

View file

@ -96,7 +96,20 @@ interface ModelEditSubmenuProps {
requestGateway: <T>(method: string, params?: Record<string, unknown>) => Promise<T>
}
export function ModelEditSubmenu({
export function ModelEditSubmenu(props: ModelEditSubmenuProps) {
// The panel mounts one of these per model row; only the hovered row's
// submenu is ever open. Keep this wrapper hook-free and render the body as
// a CHILD of SubContent so Radix's Presence gate leaves it unrendered until
// the sub actually opens — eagerly running the body's hooks/JSX for every
// row made opening the menu itself lag on large catalogs.
return (
<DropdownMenuSubContent className="w-52 p-0" sideOffset={4}>
<ModelEditSubmenuBody {...props} />
</DropdownMenuSubContent>
)
}
function ModelEditSubmenuBody({
effort,
fastControl,
isActive,
@ -213,50 +226,46 @@ export function ModelEditSubmenu({
const hasFast = fastControl.kind !== 'none'
const fastOn = fastControl.kind === 'none' ? false : fastControl.on
return (
<DropdownMenuSubContent className="w-52 p-0" sideOffset={4}>
{!hasFast && !reasoning ? (
<div className="px-2.5 py-3 text-xs text-(--ui-text-tertiary)">{copy.noOptions}</div>
) : (
return !hasFast && !reasoning ? (
<div className="px-2.5 py-3 text-xs text-(--ui-text-tertiary)">{copy.noOptions}</div>
) : (
<>
<DropdownMenuLabel className={dropdownMenuSectionLabel}>{copy.options}</DropdownMenuLabel>
{reasoning ? (
<DropdownMenuItem className={dropdownMenuRow} onSelect={event => event.preventDefault()}>
{copy.thinking}
<Switch
checked={thinkingOn}
className="ml-auto"
onCheckedChange={checked => void patchReasoning(checked ? effortValue || defaultEffort : 'none')}
size="xs"
/>
</DropdownMenuItem>
) : null}
{hasFast ? (
<DropdownMenuItem className={dropdownMenuRow} onSelect={event => event.preventDefault()}>
{copy.fast}
<Switch checked={fastOn} className="ml-auto" onCheckedChange={toggleFast} size="xs" />
</DropdownMenuItem>
) : null}
{reasoning ? (
<>
<DropdownMenuLabel className={dropdownMenuSectionLabel}>{copy.options}</DropdownMenuLabel>
{reasoning ? (
<DropdownMenuItem className={dropdownMenuRow} onSelect={event => event.preventDefault()}>
{copy.thinking}
<Switch
checked={thinkingOn}
className="ml-auto"
onCheckedChange={checked => void patchReasoning(checked ? effortValue || defaultEffort : 'none')}
size="xs"
/>
</DropdownMenuItem>
) : null}
{hasFast ? (
<DropdownMenuItem className={dropdownMenuRow} onSelect={event => event.preventDefault()}>
{copy.fast}
<Switch checked={fastOn} className="ml-auto" onCheckedChange={toggleFast} size="xs" />
</DropdownMenuItem>
) : null}
{reasoning ? (
<>
<DropdownMenuSeparator className="mx-0" />
<DropdownMenuLabel className={dropdownMenuSectionLabel}>{copy.effort}</DropdownMenuLabel>
<DropdownMenuRadioGroup onValueChange={value => void patchReasoning(value)} value={effortValue}>
{REASONING_EFFORTS.map(value => (
<DropdownMenuRadioItem
className={dropdownMenuRow}
key={value}
onSelect={event => event.preventDefault()}
value={value}
>
{copy[value]}
</DropdownMenuRadioItem>
))}
</DropdownMenuRadioGroup>
</>
) : null}
<DropdownMenuSeparator className="mx-0" />
<DropdownMenuLabel className={dropdownMenuSectionLabel}>{copy.effort}</DropdownMenuLabel>
<DropdownMenuRadioGroup onValueChange={value => void patchReasoning(value)} value={effortValue}>
{REASONING_EFFORTS.map(value => (
<DropdownMenuRadioItem
className={dropdownMenuRow}
key={value}
onSelect={event => event.preventDefault()}
value={value}
>
{copy[value]}
</DropdownMenuRadioItem>
))}
</DropdownMenuRadioGroup>
</>
)}
</DropdownMenuSubContent>
) : null}
</>
)
}