webui: Add setting to always show sidebar on Desktop (#17809)

* feat: Add setting to always show Sidebar on Desktop

* chore: update webui build output

* feat: Add auto-show sidebar setting

* fix: Mobile settings dialog UI

* chore: update webui build output

* feat: UI label update

* chore: update webui build output

* chore: update webui build output

* chore: update webui build output

* refactor: Cleanup

* chore: update webui build output
This commit is contained in:
Aleksander Grygier 2025-12-16 07:31:37 +01:00 committed by GitHub
parent 2995341730
commit a20979d433
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 40 additions and 9 deletions

Binary file not shown.

View File

@ -109,6 +109,16 @@
key: 'disableAutoScroll', key: 'disableAutoScroll',
label: 'Disable automatic scroll', label: 'Disable automatic scroll',
type: 'checkbox' type: 'checkbox'
},
{
key: 'alwaysShowSidebarOnDesktop',
label: 'Always show sidebar on desktop',
type: 'checkbox'
},
{
key: 'autoShowSidebarOnNewChat',
label: 'Auto-show sidebar on new chat',
type: 'checkbox'
} }
] ]
}, },
@ -404,7 +414,7 @@
</div> </div>
<!-- Mobile Header with Horizontal Scrollable Menu --> <!-- Mobile Header with Horizontal Scrollable Menu -->
<div class="flex flex-col md:hidden"> <div class="flex flex-col pt-6 md:hidden">
<div class="border-b border-border/30 py-4"> <div class="border-b border-border/30 py-4">
<!-- Horizontal Scrollable Category Menu with Navigation --> <!-- Horizontal Scrollable Category Menu with Navigation -->
<div class="relative flex items-center" style="scroll-padding: 1rem;"> <div class="relative flex items-center" style="scroll-padding: 1rem;">

View File

@ -15,6 +15,8 @@ export const SETTING_CONFIG_DEFAULT: Record<string, string | number | boolean> =
pdfAsImage: false, pdfAsImage: false,
disableAutoScroll: false, disableAutoScroll: false,
renderUserContentAsMarkdown: false, renderUserContentAsMarkdown: false,
alwaysShowSidebarOnDesktop: false,
autoShowSidebarOnNewChat: true,
autoMicOnEmpty: false, autoMicOnEmpty: false,
// make sure these default values are in sync with `common.h` // make sure these default values are in sync with `common.h`
samplers: 'top_k;typ_p;top_p;min_p;temperature', samplers: 'top_k;typ_p;top_p;min_p;temperature',
@ -96,6 +98,10 @@ export const SETTING_CONFIG_INFO: Record<string, string> = {
disableAutoScroll: disableAutoScroll:
'Disable automatic scrolling while messages stream so you can control the viewport position manually.', 'Disable automatic scrolling while messages stream so you can control the viewport position manually.',
renderUserContentAsMarkdown: 'Render user messages using markdown formatting in the chat.', renderUserContentAsMarkdown: 'Render user messages using markdown formatting in the chat.',
alwaysShowSidebarOnDesktop:
'Always keep the sidebar visible on desktop instead of auto-hiding it.',
autoShowSidebarOnNewChat:
'Automatically show sidebar when starting a new chat. Disable to keep the sidebar hidden until you click on it.',
autoMicOnEmpty: autoMicOnEmpty:
'Automatically show microphone button instead of send button when textarea is empty for models with audio modality support.', 'Automatically show microphone button instead of send button when textarea is empty for models with audio modality support.',
pyInterpreterEnabled: pyInterpreterEnabled:

View File

@ -14,6 +14,7 @@
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { modelsStore } from '$lib/stores/models.svelte'; import { modelsStore } from '$lib/stores/models.svelte';
import { TOOLTIP_DELAY_DURATION } from '$lib/constants/tooltip-config'; import { TOOLTIP_DELAY_DURATION } from '$lib/constants/tooltip-config';
import { IsMobile } from '$lib/hooks/is-mobile.svelte';
let { children } = $props(); let { children } = $props();
@ -21,6 +22,10 @@
let isHomeRoute = $derived(page.route.id === '/'); let isHomeRoute = $derived(page.route.id === '/');
let isNewChatMode = $derived(page.url.searchParams.get('new_chat') === 'true'); let isNewChatMode = $derived(page.url.searchParams.get('new_chat') === 'true');
let showSidebarByDefault = $derived(activeMessages().length > 0 || isLoading()); let showSidebarByDefault = $derived(activeMessages().length > 0 || isLoading());
let alwaysShowSidebarOnDesktop = $derived(config().alwaysShowSidebarOnDesktop);
let autoShowSidebarOnNewChat = $derived(config().autoShowSidebarOnNewChat);
let isMobile = new IsMobile();
let isDesktop = $derived(!isMobile.current);
let sidebarOpen = $state(false); let sidebarOpen = $state(false);
let innerHeight = $state<number | undefined>(); let innerHeight = $state<number | undefined>();
let chatSidebar: let chatSidebar:
@ -76,6 +81,11 @@
} }
$effect(() => { $effect(() => {
if (alwaysShowSidebarOnDesktop && isDesktop) {
sidebarOpen = true;
return;
}
if (isHomeRoute && !isNewChatMode) { if (isHomeRoute && !isNewChatMode) {
// Auto-collapse sidebar when navigating to home route (but not in new chat mode) // Auto-collapse sidebar when navigating to home route (but not in new chat mode)
sidebarOpen = false; sidebarOpen = false;
@ -83,8 +93,11 @@
// Keep sidebar open in new chat mode // Keep sidebar open in new chat mode
sidebarOpen = true; sidebarOpen = true;
} else if (isChatRoute) { } else if (isChatRoute) {
// On chat routes, show sidebar by default // On chat routes, only auto-show sidebar if setting is enabled
sidebarOpen = true; if (autoShowSidebarOnNewChat) {
sidebarOpen = true;
}
// If setting is disabled, don't change sidebar state - let user control it manually
} else { } else {
// Other routes follow default behavior // Other routes follow default behavior
sidebarOpen = showSidebarByDefault; sidebarOpen = showSidebarByDefault;
@ -190,12 +203,14 @@
<ChatSidebar bind:this={chatSidebar} /> <ChatSidebar bind:this={chatSidebar} />
</Sidebar.Root> </Sidebar.Root>
<Sidebar.Trigger {#if !(alwaysShowSidebarOnDesktop && isDesktop)}
class="transition-left absolute left-0 z-[900] h-8 w-8 duration-200 ease-linear {sidebarOpen <Sidebar.Trigger
? 'md:left-[var(--sidebar-width)]' class="transition-left absolute left-0 z-[900] h-8 w-8 duration-200 ease-linear {sidebarOpen
: ''}" ? 'md:left-[var(--sidebar-width)]'
style="translate: 1rem 1rem;" : ''}"
/> style="translate: 1rem 1rem;"
/>
{/if}
<Sidebar.Inset class="flex flex-1 flex-col overflow-hidden"> <Sidebar.Inset class="flex flex-1 flex-col overflow-hidden">
{@render children?.()} {@render children?.()}