From 71eb34f835add0dd06a698fe9ce3b96664831a35 Mon Sep 17 00:00:00 2001 From: rmarnold Date: Wed, 10 Jun 2026 22:07:04 -0700 Subject: [PATCH] feat: optional inline filter toggles in the message input Add a Settings -> Interface "Inline Filter Toggles" setting (default off). When enabled, the message-input bar shows every toggleable filter as a persistent chip -- greyed when off, highlighted when on -- and clicking a chip toggles its selection in place instead of removing it from the bar. Filters with UserValves expose those via a gear shown on hover, so nothing is lost. Default behavior is unchanged (only selected filters show as removable chips). Restores the inline-toggle behavior some users have asked for (e.g. #17574) without changing the default. No change to selectedFilterIds or the backend. --- src/lib/components/chat/MessageInput.svelte | 71 ++++++++++++++----- .../components/chat/Settings/Interface.svelte | 21 ++++++ src/lib/i18n/locales/en-US/translation.json | 1 + 3 files changed, 75 insertions(+), 18 deletions(-) diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index 646abf24f4..390f96053e 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -80,6 +80,7 @@ import Spinner from '../common/Spinner.svelte'; import XMark from '../icons/XMark.svelte'; + import Cog6 from '../icons/Cog6.svelte'; import GlobeAlt from '../icons/GlobeAlt.svelte'; import Photo from '../icons/Photo.svelte'; import Wrench from '../icons/Wrench.svelte'; @@ -512,6 +513,14 @@ .map((id) => ($models.find((model) => model.id === id) || {})?.filters ?? []) .reduce((acc, filters) => acc.filter((f1) => filters.some((f2) => f2.id === f1.id))); + // With the `inlineFilterToggles` setting on, every available toggle filter is + // shown as a persistent chip (greyed when off, toggled in place); otherwise the + // default shows only the selected filters as removable chips. + let filterChips = []; + $: filterChips = ($settings?.inlineFilterToggles ?? false) + ? toggleFilters + : selectedFilterIds.map((id) => toggleFilters.find((f) => f.id === id)).filter((f) => f); + let showToolsButton = false; $: showToolsButton = ($tools ?? []).length > 0 || ($toolServers ?? []).length > 0; @@ -1791,29 +1800,37 @@ {/if} - {#each selectedFilterIds as filterId (filterId)} - {@const filter = toggleFilters.find((f) => f.id === filterId)} + {#each filterChips as filter (filter.id)} {#if filter} {/if} diff --git a/src/lib/components/chat/Settings/Interface.svelte b/src/lib/components/chat/Settings/Interface.svelte index 250c75a9ff..5da4de1cf9 100644 --- a/src/lib/components/chat/Settings/Interface.svelte +++ b/src/lib/components/chat/Settings/Interface.svelte @@ -30,6 +30,7 @@ let responseAutoCopy = false; let widescreenMode = false; + let inlineFilterToggles = false; let splitLargeChunks = false; let scrollOnBranchChange = true; let userLocation = false; @@ -242,6 +243,7 @@ landingPageMode = $settings?.landingPageMode ?? ''; chatBubble = $settings?.chatBubble ?? true; widescreenMode = $settings?.widescreenMode ?? false; + inlineFilterToggles = $settings?.inlineFilterToggles ?? false; splitLargeChunks = $settings?.splitLargeChunks ?? false; scrollOnBranchChange = $settings?.scrollOnBranchChange ?? true; @@ -740,6 +742,25 @@ +
+
+
+ {$i18n.t('Inline Filter Toggles')} +
+ +
+ { + saveSettings({ inlineFilterToggles }); + }} + /> +
+
+
+ {#if $user.role === 'admin' || $user?.permissions?.chat?.temporary}
diff --git a/src/lib/i18n/locales/en-US/translation.json b/src/lib/i18n/locales/en-US/translation.json index ed6da124f6..d685717c3e 100644 --- a/src/lib/i18n/locales/en-US/translation.json +++ b/src/lib/i18n/locales/en-US/translation.json @@ -1152,6 +1152,7 @@ "Initials": "", "Inject file content into conversation context": "", "Inject the entire content as context for comprehensive processing, this is recommended for complex queries.": "", + "Inline Filter Toggles": "", "Input": "", "Input Key (e.g. text, unet_name, steps)": "", "Input Variables": "",