Webui: Disable attachment button and model selector button when prompt textbox is disabled. (#17925)

* Pass disabled state to the file attachments button and the model
selector button.

* Update index.html.gz

* Fix model info card in non-router mode.

* Update index.html.gz
This commit is contained in:
Darius Lukas 2025-12-16 01:15:49 -05:00 committed by GitHub
parent d6a1e18c65
commit 40d9c394f4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 200 additions and 185 deletions

Binary file not shown.

View File

@ -35,7 +35,7 @@
<div class="flex items-center gap-1 {className}"> <div class="flex items-center gap-1 {className}">
<DropdownMenu.Root> <DropdownMenu.Root>
<DropdownMenu.Trigger name="Attach files"> <DropdownMenu.Trigger name="Attach files" {disabled}>
<Tooltip.Root> <Tooltip.Root>
<Tooltip.Trigger> <Tooltip.Trigger>
<Button <Button

View File

@ -173,6 +173,7 @@
/> />
<ModelsSelector <ModelsSelector
{disabled}
bind:this={selectorModelRef} bind:this={selectorModelRef}
currentModel={conversationModel} currentModel={conversationModel}
forceForegroundText={true} forceForegroundText={true}

View File

@ -179,9 +179,12 @@
}); });
}); });
// Handle changes to the model selector pop-down or the model dialog, depending on if the server is in
// router mode or not.
function handleOpenChange(open: boolean) { function handleOpenChange(open: boolean) {
if (loading || updating) return; if (loading || updating) return;
if (isRouter) {
if (open) { if (open) {
isOpen = true; isOpen = true;
searchTerm = ''; searchTerm = '';
@ -192,38 +195,21 @@
requestAnimationFrame(() => searchInputRef?.focus()); requestAnimationFrame(() => searchInputRef?.focus());
}); });
if (isRouter) {
modelsStore.fetchRouterModels().then(() => { modelsStore.fetchRouterModels().then(() => {
modelsStore.fetchModalitiesForLoadedModels(); modelsStore.fetchModalitiesForLoadedModels();
}); });
}
} else { } else {
isOpen = false; isOpen = false;
searchTerm = ''; searchTerm = '';
highlightedIndex = -1; highlightedIndex = -1;
} }
} else {
showModelDialog = open;
} }
function handleTriggerClick() {
if (loading || updating) return;
if (!isRouter) {
// Single model mode: show dialog instead of popover
showModelDialog = true;
}
// For router mode, the Popover handles open/close
} }
export function open() { export function open() {
if (isRouter) {
handleOpenChange(true); handleOpenChange(true);
} else {
showModelDialog = true;
}
}
function closeMenu() {
handleOpenChange(false);
} }
function handleSearchKeyDown(event: KeyboardEvent) { function handleSearchKeyDown(event: KeyboardEvent) {
@ -292,7 +278,7 @@
} }
if (shouldCloseMenu) { if (shouldCloseMenu) {
closeMenu(); handleOpenChange(false);
// Focus the chat textarea after model selection // Focus the chat textarea after model selection
requestAnimationFrame(() => { requestAnimationFrame(() => {
@ -360,6 +346,7 @@
{:else} {:else}
{@const selectedOption = getDisplayOption()} {@const selectedOption = getDisplayOption()}
{#if isRouter}
<Popover.Root bind:open={isOpen} onOpenChange={handleOpenChange}> <Popover.Root bind:open={isOpen} onOpenChange={handleOpenChange}>
<Popover.Trigger <Popover.Trigger
class={cn( class={cn(
@ -374,8 +361,7 @@
isOpen ? 'text-foreground' : '' isOpen ? 'text-foreground' : ''
)} )}
style="max-width: min(calc(100cqw - 6.5rem), 32rem)" style="max-width: min(calc(100cqw - 6.5rem), 32rem)"
onclick={handleTriggerClick} disabled={disabled || updating}
disabled={disabled || updating || !isRouter}
> >
<Package class="h-3.5 w-3.5" /> <Package class="h-3.5 w-3.5" />
@ -385,7 +371,7 @@
{#if updating} {#if updating}
<Loader2 class="h-3 w-3.5 animate-spin" /> <Loader2 class="h-3 w-3.5 animate-spin" />
{:else if isRouter} {:else}
<ChevronDown class="h-3 w-3.5" /> <ChevronDown class="h-3 w-3.5" />
{/if} {/if}
</Popover.Trigger> </Popover.Trigger>
@ -405,7 +391,7 @@
placeholder="Search models..." placeholder="Search models..."
bind:value={searchTerm} bind:value={searchTerm}
bind:ref={searchInputRef} bind:ref={searchInputRef}
onClose={closeMenu} onClose={() => handleOpenChange(false)}
onKeyDown={handleSearchKeyDown} onKeyDown={handleSearchKeyDown}
/> />
</div> </div>
@ -533,6 +519,34 @@
</div> </div>
</Popover.Content> </Popover.Content>
</Popover.Root> </Popover.Root>
{:else}
<button
class={cn(
`inline-flex cursor-pointer items-center gap-1.5 rounded-sm bg-muted-foreground/10 px-1.5 py-1 text-xs transition hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-60`,
!isCurrentModelInCache()
? 'bg-red-400/10 !text-red-400 hover:bg-red-400/20 hover:text-red-400'
: forceForegroundText
? 'text-foreground'
: isHighlightedCurrentModelActive
? 'text-foreground'
: 'text-muted-foreground',
isOpen ? 'text-foreground' : ''
)}
style="max-width: min(calc(100cqw - 6.5rem), 32rem)"
onclick={() => handleOpenChange(true)}
disabled={disabled || updating}
>
<Package class="h-3.5 w-3.5" />
<span class="truncate font-medium">
{selectedOption?.model}
</span>
{#if updating}
<Loader2 class="h-3 w-3.5 animate-spin" />
{/if}
</button>
{/if}
{/if} {/if}
</div> </div>