diff --git a/apps/web/src/components/settings/LabsSettingsPanel.tsx b/apps/web/src/components/settings/LabsSettingsPanel.tsx
index 38be7d611518e..98ef0ddf7eebd 100644
--- a/apps/web/src/components/settings/LabsSettingsPanel.tsx
+++ b/apps/web/src/components/settings/LabsSettingsPanel.tsx
@@ -48,12 +48,34 @@ function BoringSidebarRow() {
{settings.boringSidebarEnabled ? (
+
) : null}
);
}
+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 7d7939e7f21f9..fe390c2155152 100644
--- a/apps/web/src/components/settings/settingsSearch.ts
+++ b/apps/web/src/components/settings/settingsSearch.ts
@@ -479,6 +479,13 @@ export const SETTINGS_SEARCH_ITEMS = [
targetId: "boring-sidebar",
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",
+ targetId: "boring-sidebar",
+ searchTerms: ["sidebar folder indent indentation flush left align spacing margin compact"],
+ },
{
id: "tool-call-visibility",
title: "Tool calls in chat",
diff --git a/apps/web/src/components/sidebar/SidebarThreadRow.tsx b/apps/web/src/components/sidebar/SidebarThreadRow.tsx
index 2a3893737c0b0..f0d6206390cf1 100644
--- a/apps/web/src/components/sidebar/SidebarThreadRow.tsx
+++ b/apps/web/src/components/sidebar/SidebarThreadRow.tsx
@@ -79,6 +79,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 {
@@ -668,6 +669,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);
@@ -1249,8 +1251,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 7bbb03595d4bb..7c41e3d8bb474 100644
--- a/packages/contracts/src/settings.ts
+++ b/packages/contracts/src/settings.ts
@@ -530,6 +530,7 @@ export const ClientSettingsSchema = Schema.Struct({
boringSidebarMultilineRows: Schema.Boolean.pipe(
Schema.withDecodingDefault(Effect.succeed(false)),
),
+ boringSidebarFlushRows: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))),
toolCallVisibility: ToolCallVisibility.pipe(
Schema.withDecodingDefault(Effect.succeed("showAll" as const)),
),
@@ -2086,6 +2087,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),
toolCallVisibility: Schema.optionalKey(ToolCallVisibility),
screenReaderAnnouncements: Schema.optionalKey(ScreenReaderAnnouncements),
screenReaderWindowTitle: Schema.optionalKey(Schema.Boolean),