ui : keep reasoning submenu visible regardless of model state

This commit is contained in:
Aleksander Grygier
2026-08-15 22:53:26 +02:00
committed by GitHub
parent a43c1c0cde
commit f11a90d113
4 changed files with 18 additions and 13 deletions
@@ -2,7 +2,6 @@
import { File, FolderOpen, MessageSquare, Plus, Zap } from '@lucide/svelte';
import {
ChatFormActionAddMcpServersSubmenu,
ChatFormActionAddReasoningSubmenu,
ChatFormActionAddToolsSubmenu
} from '$lib/components/app';
import { buttonVariants } from '$lib/components/ui/button';
@@ -93,10 +92,6 @@
}
}}
>
<ChatFormActionAddReasoningSubmenu />
<DropdownMenu.Separator />
<DropdownMenu.Sub>
<DropdownMenu.SubTrigger class="flex cursor-pointer items-center gap-2">
<File class={ICON_CLASS_DEFAULT} />
@@ -156,11 +151,11 @@
<ChatFormActionAddToolsSubmenu />
<DropdownMenu.Separator />
<ChatFormActionAddMcpServersSubmenu onMcpSettingsClick={handleMcpSettingsClick} />
{#if chatFormActions.hasMcpPromptsSupport}
<DropdownMenu.Separator />
<DropdownMenu.Item
class="flex cursor-pointer items-center gap-2"
onclick={chatFormActions.onMcpPromptClick}
@@ -8,10 +8,9 @@
const reasoning = useReasoningMenu();
</script>
{#if reasoning.modelSupportsThinking}
<DropdownMenu.Sub>
<DropdownMenu.Sub>
<DropdownMenu.SubTrigger class="flex cursor-pointer items-center gap-2">
{#if reasoning.thinkingEnabled}
{#if reasoning.isReasoningActive}
<Lightbulb class="{ICON_CLASS_DEFAULT} shrink-0 text-amber-400" />
{:else if reasoning.isOff}
<LightbulbOff class="{ICON_CLASS_DEFAULT} shrink-0 text-muted-foreground" />
@@ -20,7 +19,7 @@
{/if}
<span
class="text-sm inline-flex gap-2 {!reasoning.thinkingEnabled
class="text-sm inline-flex gap-2 {!reasoning.isReasoningActive
? 'text-muted-foreground'
: ''}"
>
@@ -73,4 +72,3 @@
{/each}
</DropdownMenu.SubContent>
</DropdownMenu.Sub>
{/if}
@@ -100,7 +100,7 @@
<ChevronRight class="{ICON_CLASS_DEFAULT} shrink-0" />
{/if}
{#if reasoning.thinkingEnabled}
{#if reasoning.isReasoningActive}
<Lightbulb class="{ICON_CLASS_DEFAULT} shrink-0 text-amber-400" />
{:else if reasoning.isOff}
<LightbulbOff class="{ICON_CLASS_DEFAULT} shrink-0 text-muted-foreground" />
@@ -194,6 +194,8 @@
</Collapsible.Content>
</Collapsible.Root>
<div class="h-px bg-border"></div>
<Collapsible.Root open={mcpExpanded} onOpenChange={(open) => (mcpExpanded = open)}>
<Collapsible.Trigger class={sheetItemClass}>
{#if mcpExpanded}
@@ -8,6 +8,7 @@ import { getConversationModel } from '$lib/utils';
export interface UseReasoningMenuReturn {
readonly modelSupportsThinking: boolean;
readonly thinkingEnabled: boolean;
readonly isReasoningActive: boolean;
readonly isOff: boolean;
readonly currentEffort: ReasoningEffort;
readonly levels: ReasoningEffortLevel[];
@@ -59,6 +60,12 @@ export function useReasoningMenu(): UseReasoningMenuReturn {
const thinkingEnabled = $derived(
currentEffort !== ReasoningEffort.OFF && currentEffort !== ReasoningEffort.DEFAULT
);
// Thinking is effectively on (lightbulb lit) either when an explicit effort
// is selected, or when the effort is left at "Default" and the model
// supports thinking.
const isReasoningActive = $derived(
thinkingEnabled || (currentEffort === ReasoningEffort.DEFAULT && modelSupportsThinking)
);
return {
get currentEffort() {
@@ -82,6 +89,9 @@ export function useReasoningMenu(): UseReasoningMenuReturn {
get thinkingEnabled() {
return thinkingEnabled;
},
get isReasoningActive() {
return isReasoningActive;
},
tokenLabel(level: ReasoningEffortLevel): string | null {
if (level.value === ReasoningEffort.DEFAULT) return 'Model default';