Commit b5cb8f6f4 for llama.cpp

commit b5cb8f6f470a3a4d6f329bbb050e9a34fde6638d
Author: Aleksander Grygier <aleksander.grygier@gmail.com>
Date:   Tue Nov 10 22:44:23 2026 +0100

    ui: keep a hidden sidebar from intercepting clicks again (#32035)

    The hidden desktop strip relied on inherited `visibility: hidden` to keep
    its content from catching clicks. Since the sidebar's sections fold
    (#31936), an open section's CollapsibleRegion sets `visibility: visible`
    again, and its rows' context-menu triggers carry an inline
    `pointer-events: auto`, so they caught clicks meant for the page.

    Make the hidden strip's content inert, which no descendant can undo, and
    add a client test that hit-tests the hidden sidebar's area.

    Fixes #31971

    Assisted-by: Claude (Opus 5.5 Medium)

diff --git a/tools/ui/src/lib/components/app/navigation/SidebarNavigation/SidebarNavigation.svelte b/tools/ui/src/lib/components/app/navigation/SidebarNavigation/SidebarNavigation.svelte
index e261ab064..3a195bff5 100644
--- a/tools/ui/src/lib/components/app/navigation/SidebarNavigation/SidebarNavigation.svelte
+++ b/tools/ui/src/lib/components/app/navigation/SidebarNavigation/SidebarNavigation.svelte
@@ -648,12 +648,16 @@
 				{/if}
 			</div>

+			<!-- the hidden strip's content goes inert, not only invisible: descendants can opt
+			     back into visibility (an open CollapsibleRegion) and pointer events (the inline
+			     style of a context-menu trigger), and would catch clicks meant for the page -->
 			<div
 				in:fade={{ duration: SIDEBAR_CONTENT_FADE_MS }}
 				out:fade={{ duration: SIDEBAR_CONTENT_FADE_MS }}
 				class="mt-2 flex min-h-0 flex-1 flex-col gap-7 max-md:mt-6 md:gap-1 md:transition-opacity md:duration-150 md:ease-out {isStripHidden
 					? 'md:opacity-0 md:invisible'
 					: ''}"
+				inert={isStripHidden}
 			>
 				<!-- a phone has no footer: its items join these -->
 				<SidebarNavigationActions
diff --git a/tools/ui/tests/client/components/SidebarNavigationHarness.svelte b/tools/ui/tests/client/components/SidebarNavigationHarness.svelte
new file mode 100644
index 000000000..08721f21b
--- /dev/null
+++ b/tools/ui/tests/client/components/SidebarNavigationHarness.svelte
@@ -0,0 +1,9 @@
+<script lang="ts">
+	import SidebarNavigation from '$lib/components/app/navigation/SidebarNavigation/SidebarNavigation.svelte';
+	import * as Tooltip from '$lib/components/ui/tooltip';
+</script>
+
+<!-- the sidebar with the tooltip provider +layout.svelte gives it -->
+<Tooltip.Provider>
+	<SidebarNavigation />
+</Tooltip.Provider>
diff --git a/tools/ui/tests/client/sidebar-hidden-clicks.svelte.test.ts b/tools/ui/tests/client/sidebar-hidden-clicks.svelte.test.ts
new file mode 100644
index 000000000..4de1ac86d
--- /dev/null
+++ b/tools/ui/tests/client/sidebar-hidden-clicks.svelte.test.ts
@@ -0,0 +1,66 @@
+// A hidden desktop sidebar keeps its full width in the layout, floated under the page's
+// left edge, so whatever it still lets the pointer hit there steals the page's clicks
+// (#31971). Hiding it by inherited `visibility` alone is not enough: an open section's
+// CollapsibleRegion sets `visibility: visible` again, and bits-ui's context-menu triggers
+// put `pointer-events: auto` inline on the rows.
+
+import '../../src/app.css';
+import SidebarNavigationHarness from './components/SidebarNavigationHarness.svelte';
+import { uiStore } from '$lib/stores';
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
+import { page } from 'vitest/browser';
+import { render } from 'vitest-browser-svelte';
+
+const GRID_STEP_PX = 8;
+
+/** Elements of the sidebar the pointer lands on over its box, the expand toggle aside. */
+function hitTargetsInSidebar(aside: HTMLElement): Element[] {
+	const toggle = aside.querySelector('[aria-label="Expand navigation"]');
+	const box = aside.getBoundingClientRect();
+	const hits = new Set<Element>();
+
+	for (let x = box.left + 1; x < box.right; x += GRID_STEP_PX) {
+		for (let y = box.top + 1; y < box.bottom; y += GRID_STEP_PX) {
+			const el = document.elementFromPoint(x, y);
+
+			if (el && aside.contains(el) && !toggle?.contains(el)) hits.add(el);
+		}
+	}
+
+	return [...hits];
+}
+
+describe('hidden sidebar', () => {
+	let wasExpanded: boolean;
+
+	beforeEach(async () => {
+		await page.viewport(1280, 900);
+		wasExpanded = uiStore.isSidebarExpanded;
+	});
+
+	afterEach(() => {
+		uiStore.isSidebarExpanded = wasExpanded;
+	});
+
+	it('lets clicks over its strip through to the page', async () => {
+		uiStore.isSidebarExpanded = false;
+		render(SidebarNavigationHarness);
+
+		const aside = await vi.waitFor(() => {
+			const el = document.querySelector<HTMLElement>('aside');
+
+			if (!el) throw new Error('sidebar not rendered');
+
+			return el;
+		});
+
+		// an open section is what used to bring the rows back to the pointer
+		await vi.waitFor(() =>
+			expect(aside.querySelector('.collapsible-region-content')).not.toBeNull()
+		);
+		// its width settles over a transition; the strip's area is what counts
+		await vi.waitFor(() => expect(aside.getBoundingClientRect().width).toBeGreaterThan(48));
+
+		expect(hitTargetsInSidebar(aside).map((el) => el.outerHTML.slice(0, 120))).toEqual([]);
+	});
+});