From e70f31cee831984f9d3644afe0a3c3bf26e8a556 Mon Sep 17 00:00:00 2001 From: flexi767 Date: Wed, 4 Nov 2026 20:41:11 +0100 Subject: [PATCH 1/2] feat(web): add optional flush alignment for folder threads --- .../components/settings/LabsSettingsPanel.tsx | 21 +++++++++++++++++++ .../src/components/settings/settingsSearch.ts | 6 ++++++ .../components/sidebar/SidebarThreadRow.tsx | 5 +++-- packages/contracts/src/settings.ts | 2 ++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/apps/web/src/components/settings/LabsSettingsPanel.tsx b/apps/web/src/components/settings/LabsSettingsPanel.tsx index 36c289b8335bc..70ec5077a11cb 100644 --- a/apps/web/src/components/settings/LabsSettingsPanel.tsx +++ b/apps/web/src/components/settings/LabsSettingsPanel.tsx @@ -21,6 +21,7 @@ export function LabsSettingsPanel() { + {/* Clerk is only mounted when this build has T3 Connect. */} {hasCloudPublicConfig() ? : } @@ -52,6 +53,26 @@ function BoringSidebarRow() { ); } +function BoringSidebarFlushRowsRow() { + const settings = useScopedSettings(); + const updateSettings = useUpdateScopedSettings(); + return ( + + updateSettings({ boringSidebarFlushRows: Boolean(checked) }) + } + aria-label="Align threads with project icon" + /> + } + /> + ); +} + function BoringSidebarMultilineRow() { const settings = useScopedSettings(); const updateSettings = useUpdateScopedSettings(); diff --git a/apps/web/src/components/settings/settingsSearch.ts b/apps/web/src/components/settings/settingsSearch.ts index e61a064431c55..695977b6b0756 100644 --- a/apps/web/src/components/settings/settingsSearch.ts +++ b/apps/web/src/components/settings/settingsSearch.ts @@ -465,6 +465,12 @@ export const SETTINGS_SEARCH_ITEMS = [ to: "/settings/labs", searchTerms: ["beta boring sidebar folder rows multiline branch pull request details"], }, + { + id: "boring-sidebar-flush-rows", + title: "Align threads with project icon", + to: "/settings/labs", + searchTerms: ["sidebar folder indent indentation flush left align spacing margin compact"], + }, { id: "guest-links", title: "Guest links", diff --git a/apps/web/src/components/sidebar/SidebarThreadRow.tsx b/apps/web/src/components/sidebar/SidebarThreadRow.tsx index ed3a8276be8bd..6110b1152cca2 100644 --- a/apps/web/src/components/sidebar/SidebarThreadRow.tsx +++ b/apps/web/src/components/sidebar/SidebarThreadRow.tsx @@ -72,6 +72,7 @@ import { formatRelativeTimeLabel, parseTimestampDate } from "../../timestampForm import type { SidebarThreadSummary } from "../../types"; import type { EnvironmentProject } from "@t3tools/client-runtime/state/shell"; import { cn } from "~/lib/utils"; +import { useClientSettings } from "~/hooks/useSettings"; import { textDirection } from "~/textDirection"; import { EnvironmentMachineIcon } from "../EnvironmentMachineIcon"; import { @@ -654,6 +655,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: SidebarThreadRowP variantAction, } = props; const threadRef = scopeThreadRef(thread.environmentId, thread.id); + const flushFolderRows = useClientSettings((settings) => settings.boringSidebarFlushRows); const threadKey = scopedThreadKey(threadRef); const canOperateThread = useEnvironmentScope(thread.environmentId, AuthOrchestrationOperateScope); const { leaseLiveStatus, rowRef: leaseRowRef } = useSidebarRowSubscriptionLease(props.isActive); @@ -1221,8 +1223,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: SidebarThreadRowP multiline ? "flex flex-col justify-center px-2.5 py-1.5" : "flex h-9 items-center gap-2.5 px-2.5", - // Lines titles up with the folder name, past its chevron and icon. - inFolder && "ps-9", + inFolder && (flushFolderRows ? "ps-(--sidebar-row-content-inset)" : "ps-9"), )} onClick={handleClick} onDoubleClick={handleDoubleClick} diff --git a/packages/contracts/src/settings.ts b/packages/contracts/src/settings.ts index 7f6e8a4aea8dd..d79b6b54a8be8 100644 --- a/packages/contracts/src/settings.ts +++ b/packages/contracts/src/settings.ts @@ -480,6 +480,7 @@ export const ClientSettingsSchema = Schema.Struct({ boringSidebarMultilineRows: Schema.Boolean.pipe( Schema.withDecodingDefault(Effect.succeed(false)), ), + boringSidebarFlushRows: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))), // Retired Labs toggle. Still read as the default for the Usage item in threadDetailsItems. threadDetailsUsageEnabled: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))), // Sparse show/hide overrides for thread details card items. Missing ids use the client's @@ -1817,6 +1818,7 @@ export const ClientSettingsPatch = Schema.Struct({ showSkillsInSlashMenu: Schema.optionalKey(Schema.Boolean), boringSidebarEnabled: Schema.optionalKey(Schema.Boolean), boringSidebarMultilineRows: Schema.optionalKey(Schema.Boolean), + boringSidebarFlushRows: Schema.optionalKey(Schema.Boolean), threadDetailsUsageEnabled: Schema.optionalKey(Schema.Boolean), threadDetailsItems: Schema.optionalKey(Schema.Record(Schema.String, Schema.Boolean)), legacySidebarEnabled: Schema.optionalKey(Schema.Boolean), From 4140e9ed23260f0bd5fa97054d6bff86a3f125d1 Mon Sep 17 00:00:00 2001 From: flexi767 Date: Thu, 12 Nov 2026 20:21:23 +0100 Subject: [PATCH 2/2] fix(web): settings search lands on the boring sidebar row for flush alignment Co-Authored-By: Claude Opus 5.5 --- apps/web/src/components/settings/settingsSearch.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/web/src/components/settings/settingsSearch.ts b/apps/web/src/components/settings/settingsSearch.ts index a9bfac76659d7..4dd3f2f6e55d9 100644 --- a/apps/web/src/components/settings/settingsSearch.ts +++ b/apps/web/src/components/settings/settingsSearch.ts @@ -480,6 +480,7 @@ export const SETTINGS_SEARCH_ITEMS = [ id: "boring-sidebar-flush-rows", title: "Align threads with project icon", to: "/settings/labs", + targetId: "boring-sidebar", searchTerms: ["sidebar folder indent indentation flush left align spacing margin compact"], }, {