Skip to content

Commit 6d17ff0

Browse files
committed
Remove blur from chat sidebar
- Drop backdrop blur from the left sidebar to avoid flickering - Add a regression test to keep the blur class out of the route - Tidy layout store formatting while touching related code
1 parent 505236e commit 6d17ff0

4 files changed

Lines changed: 38 additions & 15 deletions

File tree

apps/web/src/hooks/useLayoutActions.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -137,29 +137,28 @@ export function useLayoutActions(): UseLayoutActionsResult {
137137
const diffViewerOpen = diffState.isOpen;
138138
const simulationOpen = useSimulationViewerStore.getState().isOpen;
139139
const previewState = usePreviewStateStore.getState();
140-
const previewOpen = projectId
141-
? (previewState.openByProjectId[projectId] ?? false)
142-
: false;
140+
const previewOpen = projectId ? (previewState.openByProjectId[projectId] ?? false) : false;
143141

144142
const terminalStoreState = useTerminalStateStore.getState();
145143
const threadTerminal = threadId
146144
? selectThreadTerminalState(terminalStoreState.terminalStateByThreadId, threadId)
147145
: null;
148146

149-
const previewDock = projectId
150-
? (previewState.dockByProjectId[projectId] ?? null)
151-
: null;
152-
const previewSize = projectId
153-
? (previewState.sizeByProjectId[projectId] ?? null)
154-
: null;
147+
const previewDock = projectId ? (previewState.dockByProjectId[projectId] ?? null) : null;
148+
const previewSize = projectId ? (previewState.sizeByProjectId[projectId] ?? null) : null;
155149

156150
const now = Date.now();
157151
return {
158152
id: generateLayoutId(),
159153
name: name.trim().slice(0, 128) || "Untitled Layout",
160154
createdAt: now,
161155
updatedAt: now,
162-
activePanel: resolveActivePanel(codeViewerOpen, diffViewerOpen, previewOpen, simulationOpen),
156+
activePanel: resolveActivePanel(
157+
codeViewerOpen,
158+
diffViewerOpen,
159+
previewOpen,
160+
simulationOpen,
161+
),
163162
terminalOpen: threadTerminal?.terminalOpen ?? false,
164163
terminalHeight: threadTerminal?.terminalHeight ?? null,
165164
sidebarWidths: readSidebarWidths(),

apps/web/src/layoutStore.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,13 @@ export interface SavedLayout {
5151
const LAYOUT_STORAGE_KEY = "okcode:saved-layouts:v1";
5252
const MAX_SAVED_LAYOUTS = 32;
5353

54-
const VALID_PANELS = new Set<string>(["none", "code-viewer", "diff-viewer", "preview", "simulation"]);
54+
const VALID_PANELS = new Set<string>([
55+
"none",
56+
"code-viewer",
57+
"diff-viewer",
58+
"preview",
59+
"simulation",
60+
]);
5561
const VALID_DOCKS = new Set<string>(["left", "right", "top", "bottom"]);
5662

5763
// ─── Validation helpers ─────────────────────────────────────────────
@@ -100,8 +106,10 @@ function normalizeLayout(raw: unknown): SavedLayout | null {
100106
return {
101107
id: obj.id.trim(),
102108
name: obj.name.trim().slice(0, 128),
103-
createdAt: typeof obj.createdAt === "number" && Number.isFinite(obj.createdAt) ? obj.createdAt : now,
104-
updatedAt: typeof obj.updatedAt === "number" && Number.isFinite(obj.updatedAt) ? obj.updatedAt : now,
109+
createdAt:
110+
typeof obj.createdAt === "number" && Number.isFinite(obj.createdAt) ? obj.createdAt : now,
111+
updatedAt:
112+
typeof obj.updatedAt === "number" && Number.isFinite(obj.updatedAt) ? obj.updatedAt : now,
105113
activePanel: isValidPanel(obj.activePanel) ? obj.activePanel : "none",
106114
terminalOpen: typeof obj.terminalOpen === "boolean" ? obj.terminalOpen : false,
107115
terminalHeight: isFinitePositiveOrNull(obj.terminalHeight) ? obj.terminalHeight : null,
@@ -254,7 +262,10 @@ export const useLayoutStore = create<LayoutStoreState>((set) => ({
254262
const nextLayouts = state.savedLayouts.filter((l) => l.id !== id);
255263
if (nextLayouts.length === state.savedLayouts.length) return state;
256264
const nextActiveId = state.activeLayoutId === id ? null : state.activeLayoutId;
257-
const next: PersistedLayoutState = { savedLayouts: nextLayouts, activeLayoutId: nextActiveId };
265+
const next: PersistedLayoutState = {
266+
savedLayouts: nextLayouts,
267+
activeLayoutId: nextActiveId,
268+
};
258269
persistState(next);
259270
return next;
260271
});

apps/web/src/routes/_chat.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { readFileSync } from "node:fs";
2+
import { resolve } from "node:path";
3+
import { describe, expect, it } from "vitest";
4+
5+
describe("chat route sidebar chrome", () => {
6+
it("keeps the left sidebar off the backdrop blur path", () => {
7+
const src = readFileSync(resolve(import.meta.dirname, "./_chat.tsx"), "utf8");
8+
9+
expect(src).not.toContain("backdrop-blur-sm");
10+
});
11+
});

apps/web/src/routes/_chat.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,9 @@ function ChatRouteLayout() {
255255
<Sidebar
256256
side="left"
257257
collapsible="offcanvas"
258-
className="border-r-2 border-border/60 bg-card/80 text-foreground backdrop-blur-sm shadow-[2px_0_12px_-4px_rgba(0,0,0,0.08)] dark:border-border/40 dark:bg-card/60 dark:shadow-[2px_0_16px_-4px_rgba(0,0,0,0.3)]"
258+
// Keep the primary sidebar on a simpler paint path. The blur layer is
259+
// visually nice, but it is also the most likely source of display-only shimmer.
260+
className="border-r-2 border-border/60 bg-card/80 text-foreground shadow-[2px_0_12px_-4px_rgba(0,0,0,0.08)] dark:border-border/40 dark:bg-card/60 dark:shadow-[2px_0_16px_-4px_rgba(0,0,0,0.3)]"
259261
style={
260262
{
261263
"--sidebar-background-opacity": settings.sidebarOpacity,

0 commit comments

Comments
 (0)