From 4c1bcec02029b070be8e91f6687c9475ff417a10 Mon Sep 17 00:00:00 2001 From: maria-rcks <254055478+maria-rcks@users.noreply.github.com> Date: Mon, 14 Sep 2026 03:53:16 +0000 Subject: [PATCH] revert(web): remove the compact sidebar Reverts the compact sidebar rail and compact thread rows (#11525, #9417, #11644, #11652). The feature added a collapsed icon rail and a denser thread list behind an Appearance > Sidebar setting; we are dropping it. The persisted `compactSidebarEnabled` and `sidebarCompactThreadRows` client settings keys go away with it. Client settings decode drops unknown keys, so anyone who had either flag turned on falls back to the default sidebar with no error, same as the retired sidebar v2 beta keys. A collapsed sidebar returns to the pre-existing offcanvas behavior and is still reopened from the titlebar trigger. Keeps #11595 (sparse shelves stay at the bottom), which was written on top of the rail: its `compact` branches collapse to the expanded case. --- .../settings/DesktopClientSettings.test.ts | 1 - apps/web/src/components/AppSidebarLayout.tsx | 9 +- apps/web/src/components/LegacySidebar.tsx | 77 +- apps/web/src/components/Sidebar.drag.ts | 20 +- apps/web/src/components/Sidebar.tsx | 742 ++++-------------- .../src/components/ThreadStatusIndicators.tsx | 16 +- .../settings/CompactSidebarPreview.tsx | 82 -- .../components/settings/SettingsPanels.tsx | 80 -- .../settings/SettingsSidebarNav.tsx | 33 +- .../src/components/settings/settingsSearch.ts | 8 - .../src/components/sidebar/SidebarChrome.tsx | 14 +- .../sidebar/SidebarCompletedTime.test.tsx | 56 -- .../sidebar/SidebarCompletedTime.tsx | 16 - .../sidebar/SidebarThreadHeader.tsx | 31 +- .../components/sidebar/SidebarUpdatePill.tsx | 2 +- apps/web/src/components/ui/sidebar.tsx | 3 - apps/web/src/hooks/useSettings.ts | 7 - apps/web/src/timestampFormat.test.ts | 12 - apps/web/src/timestampFormat.ts | 8 +- apps/web/src/workspaceTitlebar.ts | 2 +- packages/contracts/src/settings.test.ts | 21 +- packages/contracts/src/settings.ts | 4 - 22 files changed, 208 insertions(+), 1036 deletions(-) delete mode 100644 apps/web/src/components/settings/CompactSidebarPreview.tsx delete mode 100644 apps/web/src/components/sidebar/SidebarCompletedTime.test.tsx delete mode 100644 apps/web/src/components/sidebar/SidebarCompletedTime.tsx diff --git a/apps/desktop/src/settings/DesktopClientSettings.test.ts b/apps/desktop/src/settings/DesktopClientSettings.test.ts index 5ad23ee70582..53044dcf7e5d 100644 --- a/apps/desktop/src/settings/DesktopClientSettings.test.ts +++ b/apps/desktop/src/settings/DesktopClientSettings.test.ts @@ -57,7 +57,6 @@ const clientSettings: ClientSettings = { proactivePanelsEnabled: true, showSkillsInSlashMenu: false, providerModelPreferences: {}, - sidebarCompactThreadRows: false, sidebarProjectGroupingMode: "repository_path", sidebarProjectGroupingOverrides: { "environment-1:/tmp/project-a": "separate", diff --git a/apps/web/src/components/AppSidebarLayout.tsx b/apps/web/src/components/AppSidebarLayout.tsx index 6497df68c8bd..6769586f7fa8 100644 --- a/apps/web/src/components/AppSidebarLayout.tsx +++ b/apps/web/src/components/AppSidebarLayout.tsx @@ -14,11 +14,7 @@ import { getLocalStorageItem, removeLocalStorageItem } from "../hooks/useLocalSt import { resolveShortcutCommand, shortcutLabelForCommand } from "../keybindings"; import { cn, isMacPlatform } from "../lib/utils"; import { primaryServerKeybindingsAtom } from "../state/server"; -import { - useCompactSidebarEnabled, - useEnvironmentIdentificationMode, - useLegacySidebarEnabled, -} from "../hooks/useSettings"; +import { useEnvironmentIdentificationMode, useLegacySidebarEnabled } from "../hooks/useSettings"; import { PanelAnimationSuppressionProvider, usePanelAnimationSettings, @@ -148,7 +144,6 @@ function ProjectProjectionRetention() { export function AppSidebarLayout({ children }: { children: ReactNode }) { const navigate = useNavigate(); const legacySidebarEnabled = useLegacySidebarEnabled(); - const compactSidebarEnabled = useCompactSidebarEnabled(); const { active: panelAnimationsActive, durationMs: panelAnimationDurationMs } = usePanelAnimationSettings(); // Settings routes show the settings nav in place of whichever thread @@ -234,7 +229,7 @@ export function AppSidebarLayout({ children }: { children: ReactNode }) { s.queuePendingFileDrop); const clearPendingFileDrop = useSidebarPendingFileDropStore((s) => s.clearPendingFileDrop); - const { isMobile, setOpenMobile, state, setOpen } = useSidebar(); - const compactSidebarEnabled = useCompactSidebarEnabled(); - const isCompact = compactSidebarEnabled && !isMobile && state === "collapsed"; + const { isMobile, setOpenMobile } = useSidebar(); const markThreadUnread = useUiStateStore((state) => state.markThreadUnread); const setProjectExpanded = useUiStateStore((state) => state.setProjectExpanded); const toggleThreadSelection = useThreadSelectionStore((state) => state.toggleThread); @@ -1451,13 +1445,10 @@ const SidebarProjectItem = memo(function SidebarProjectItem(props: SidebarProjec if (useThreadSelectionStore.getState().hasSelection()) { clearSelection(); } - setProjectExpanded(projectPreferenceKeys, isCompact || !projectExpanded); - if (isCompact) setOpen(true); + setProjectExpanded(projectPreferenceKeys, !projectExpanded); }, [ clearSelection, - isCompact, - setOpen, dragInProgressRef, projectExpanded, projectPreferenceKeys, @@ -1474,17 +1465,9 @@ const SidebarProjectItem = memo(function SidebarProjectItem(props: SidebarProjec if (dragInProgressRef.current) { return; } - setProjectExpanded(projectPreferenceKeys, isCompact || !projectExpanded); - if (isCompact) setOpen(true); + setProjectExpanded(projectPreferenceKeys, !projectExpanded); }, - [ - dragInProgressRef, - isCompact, - projectExpanded, - projectPreferenceKeys, - setOpen, - setProjectExpanded, - ], + [dragInProgressRef, projectExpanded, projectPreferenceKeys, setProjectExpanded], ); const handleProjectButtonPointerDownCapture = useCallback( @@ -2376,10 +2359,8 @@ const SidebarProjectItem = memo(function SidebarProjectItem(props: SidebarProjec <>
- {isCompact ? null : !projectExpanded && projectStatus ? ( + {!projectExpanded && projectStatus ? ( - + {project.displayName} @@ -2434,7 +2415,7 @@ const SidebarProjectItem = memo(function SidebarProjectItem(props: SidebarProjec {/* Environment badge – visible by default, crossfades with the "new thread" button on hover using the same pointer-events + opacity pattern as the thread row archive/timestamp swap. */} - {!isCompact && project.environmentPresence === "remote-only" && ( + {project.environmentPresence === "remote-only" && ( +
); } @@ -754,9 +705,6 @@ const SidebarDraftRow = memo(function SidebarDraftRow(props: { onDiscard: (draftId: DraftId) => void; }) { const { composer, draftId, onDiscard, onNavigate, session } = props; - const compactEnabled = useCompactSidebarEnabled(); - const { state, isMobile } = useSidebar(); - const compact = compactEnabled && state === "collapsed" && !isMobile; const promptPreview = replaceComposerContextReferences(composer.prompt, (occurrence) => occurrence.label) .trim() @@ -795,34 +743,6 @@ const SidebarDraftRow = memo(function SidebarDraftRow(props: { }, [draftId, onDiscard], ); - if (compact) { - return ( -
  • - - - } - > - - - -
    {props.projectDisplayName}
    -
    {preview}
    -
    -
    -
  • - ); - } return (
  • = { const SidebarThreadRow = memo(function SidebarThreadRow(props: { thread: SidebarThreadSummary; variant: "card" | "slim"; - compact: boolean; // Slim rows are either settled (action: un-settle) or merely quiet // (seen Ready threads — action: settle). variantAction: "settle" | "unsettle" | "unsnooze"; @@ -1113,9 +1032,6 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { variant, variantAction, } = props; - const compactEnabled = useCompactSidebarEnabled(); - const { state, isMobile } = useSidebar(); - const compact = compactEnabled && state === "collapsed" && !isMobile; const threadRef = useMemo( () => scopeThreadRef(thread.environmentId, thread.id), [thread.environmentId, thread.id], @@ -1293,16 +1209,6 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { branchMismatch={branchMismatch} terminalStatus={terminalStatus} terminalProcessCount={terminalProcessCount} - compactStatus={ - compact || (props.compact && variant === "card") - ? (topStatus?.label ?? - (variantAction === "unsnooze" - ? "Snoozed" - : variantAction === "unsettle" - ? "Settled" - : "Ready")) - : undefined - } /> ); @@ -1349,7 +1255,6 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { [isRenaming, onStartRename, thread.title, threadRef], ); const [isFileDragOver, setIsFileDragOver] = useState(false); - const [tooltipOpen, setTooltipOpen] = useState(false); const fileDropHandlers = useMemo( () => onFileDropThreads @@ -1512,7 +1417,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { // A zero-height boundary also makes dnd-kit scale the source to // zero. Only projected peers use scaleY as a visibility sentinel. visibility: - sortable.hidden || (!sortable.isDragging && sortable.transform?.scaleY === 0) + !sortable.isDragging && sortable.transform?.scaleY === 0 ? ("hidden" as const) : undefined, }, @@ -1584,21 +1489,18 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { useRightPanelStore.getState().open(threadRef, "pull-requests"); if (!props.isActive) onThreadActivate(threadRef); }, [onThreadActivate, props.isActive, threadRef]); - const renderPrBadge = (iconOnly: boolean, variant: "underline" | "badge" = "underline") => + const prBadge = prBadgeShape?.kind === "stack" || pr || currentLinkedPr ? ( ) : null; - const hasPrBadge = prBadgeShape?.kind === "stack" || pr !== null || currentLinkedPr !== null; - const prBadge = renderPrBadge(false); const terminalStatusIcon = terminalStatus ? ( - - - } - > - - {props.project ? ( - - ) : driverKind ? ( - - ) : ( - - )} - {isRemote ? ( - - - } - > - - - - {props.environmentLabel ?? "Remote environment"} - - - ) : null} - {hasPrBadge ? ( - - {renderPrBadge(true, "badge")} - - ) : null} - - {topStatus ? ( - - ) : hasUnsentDraft ? ( - - ) : null} - {props.jumpLabel ? : null} - - {sortable?.isDragging ? ( - {dragDestination} - ) : ( - detailsTooltip - )} - -
  • - ); - } - if (variant === "slim") { return (
  • - + - + } > -
    -
    +
    +
    {draftIndicator} {props.project ? ( - - - {compactRows && isRemote ? ( - - - } - > - - - - {props.environmentLabel ?? "Remote environment"} - - - ) : null} - - ) : compactRows && isRemote ? ( - - - } - > - - - - {props.environmentLabel ?? "Remote environment"} - - + ) : null} - {compactRows ? ( - title - ) : props.projectDisplayName ? ( + {props.projectDisplayName ? ( )} {pinIndicator} - {compactRows ? ( - <> - {terminalStatusIcon} - {topStatus && CompactStatusIcon ? ( - isWokeStatus ? ( - - ) : ( - - - {topStatus.label} - - ) - ) : null} - {renderPrBadge(true)} - - ) : null} {/* The visible state owns this slot's width: status at rest, actions on hover/keyboard focus or while the popover is open. Keeping the hidden state out of flow lets the project label reclaim @@ -2067,35 +1766,20 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { {sortable?.isDragging ? ( dragDestination ) : ( - + {/* Read-only status labels yield to the hover actions. Woke is itself an action, so it stays pointer-enabled and visible while the other controls appear beside it. */} - {compactRows ? ( - status === "working" ? ( - - - - ) : compactCompletedAt ? ( - - ) : ( - threadTimeLabel(thread) - ) - ) : topStatus ? ( + {topStatus ? ( isWokeStatus ? ( - {compactRows ? null : "Settle"} + Settle Settle thread @@ -2211,70 +1895,68 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { )}
    - {isRegeneratingTitle ? ( - - Regenerating title - - ) : null} - {compactRows ? null : ( - <> -
    {title}
    -
    - {/* Always the branch. The plan step used to take this slot while +
    + {title} + {isRegeneratingTitle ? ( + + Regenerating title + + ) : null} +
    +
    + {/* Always the branch. The plan step used to take this slot while working, but it truncated to a half-sentence and dropped the branch, so the row lost its most stable identifier. */} - {thread.branch ? ( - <> - - - {thread.branch} - - - ) : ( - - )} - {terminalStatusIcon} - {prBadge} - {diff ? ( - - +{diff.insertions}{" "} - −{diff.deletions} - - ) : null} - - {isRemote ? ( - - - - ) : null} - {driverKind ? ( - - - - ) : null} + {thread.branch ? ( + <> + + + {thread.branch} -
    - - )} + + ) : ( + + )} + {terminalStatusIcon} + {prBadge} + {diff ? ( + + +{diff.insertions}{" "} + −{diff.deletions} + + ) : null} + + {isRemote ? ( + + + + ) : null} + {driverKind ? ( + + + + ) : null} + +
    {props.jumpLabel ? : null} @@ -2308,9 +1990,6 @@ const SidebarSearchResultRow = memo(function SidebarSearchResultRow(props: { onFileDropThreads: (threadRef: ScopedThreadRef, files: File[]) => void; }) { const { thread } = props; - const compactEnabled = useCompactSidebarEnabled(); - const { state, isMobile } = useSidebar(); - const compact = compactEnabled && state === "collapsed" && !isMobile; const threadRef = useMemo( () => scopeThreadRef(thread.environmentId, thread.id), [thread.environmentId, thread.id], @@ -2396,7 +2075,6 @@ const SidebarSearchResultRow = memo(function SidebarSearchResultRow(props: { onClick={props.onSelect} className={cn( "flex h-9 w-full cursor-pointer items-center gap-2.5 rounded-md px-2.5 text-left text-sm outline-none", - compact && "justify-center px-0", props.isHighlighted || props.isRouteActive ? "bg-sidebar-row-active text-sidebar-foreground" : "text-sidebar-muted-foreground/75 hover:bg-sidebar-row-hover hover:text-sidebar-foreground", @@ -2408,15 +2086,9 @@ const SidebarSearchResultRow = memo(function SidebarSearchResultRow(props: { > {props.project ? ( - ) : compact ? ( - ) : null} - {thread.title} - + {thread.title} + {threadTimeLabel(thread)} @@ -2444,12 +2116,8 @@ export default function Sidebar() { const projectOrder = useUiStateStore((store) => store.projectOrder); const threads = useThreadShells(); const router = useRouter(); - const { isMobile, setOpenMobile, setOpen, state: sidebarState } = useSidebar(); - const compactEnabled = useCompactSidebarEnabled(); - const compact = compactEnabled && sidebarState === "collapsed" && !isMobile; - const [snoozedFooter, setSnoozedFooter] = useState(null); + const { isMobile, setOpenMobile } = useSidebar(); const keybindings = useAtomValue(primaryServerKeybindingsAtom); - const compactThreadRows = useClientSettings((s) => s.sidebarCompactThreadRows); const confirmThreadDelete = useClientSettings((s) => s.confirmThreadDelete); const confirmThreadArchive = useClientSettings((s) => s.confirmThreadArchive); const sidebarProjectSortOrder = useClientSettings((s) => s.sidebarProjectSortOrder); @@ -3020,7 +2688,6 @@ export default function Sidebar() { [setSettledShelfExpanded], ); const renderedSettledThreads = useMemo(() => { - if (compact) return EMPTY_THREADS; if (settledShelfExpanded) return visibleSettledThreads; if (routeThreadKey === null) return EMPTY_THREADS; const routeThread = visibleSettledThreads.find( @@ -3028,7 +2695,7 @@ export default function Sidebar() { scopedThreadKey(scopeThreadRef(thread.environmentId, thread.id)) === routeThreadKey, ); return routeThread === undefined ? EMPTY_THREADS : [routeThread]; - }, [compact, routeThreadKey, settledShelfExpanded, visibleSettledThreads]); + }, [routeThreadKey, settledShelfExpanded, visibleSettledThreads]); // The snoozed shelf is collapsed by default: out of the way, never gone. // Collapsed threads don't render (and so don't participate in jump @@ -3256,14 +2923,10 @@ export default function Sidebar() { const [renamingThreadKey, setRenamingThreadKey] = useState(null); const [renamingTitle, setRenamingTitle] = useState(""); - const startThreadRename = useCallback( - (threadRef: ScopedThreadRef, title: string) => { - if (compact) setOpen(true); - setRenamingThreadKey(scopedThreadKey(threadRef)); - setRenamingTitle(title); - }, - [compact, setOpen], - ); + const startThreadRename = useCallback((threadRef: ScopedThreadRef, title: string) => { + setRenamingThreadKey(scopedThreadKey(threadRef)); + setRenamingTitle(title); + }, []); const cancelThreadRename = useCallback(() => setRenamingThreadKey(null), []); const commitThreadRename = useCallback( (threadRef: ScopedThreadRef, title: string, originalTitle: string) => { @@ -3425,18 +3088,8 @@ export default function Sidebar() { const threadListRef = useRef(null); const dragLabelOffsetRef = useRef(0); const restrictBelowPins = useCallback( - (args) => - restrictBelowSidebarLabel( - { - ...args, - // The fixed snoozed shelf shares the main list's drag boundary. - containerNodeRect: compact - ? (threadListRef.current?.getBoundingClientRect() ?? args.containerNodeRect) - : args.containerNodeRect, - }, - dragLabelOffsetRef.current, - ), - [compact], + (args) => restrictBelowSidebarLabel(args, dragLabelOffsetRef.current), + [], ); const listMotionRef = useRef | null>(null); const attachListMotionRef = useCallback((node: HTMLUListElement | null) => { @@ -3658,7 +3311,7 @@ export default function Sidebar() { pinnedThreads.length + activeThreads.length + snoozedThreads.length + - (compact ? 0 : settledThreads.length) === + settledThreads.length === 0 ) { return []; @@ -3674,15 +3327,13 @@ export default function Sidebar() { items.push({ kind: "marker", marker: "snoozed-header" }); items.push(...rowsOf(visibleSnoozedThreads, "snoozed")); } - if (!compact) { - items.push({ kind: "marker", marker: "settled-header" }); - items.push({ kind: "marker", marker: "settled-placeholder" }); - items.push(...rowsOf(renderedSettledThreads, "settled")); - } + items.push({ kind: "marker", marker: "settled-header" }); + const settledRows = rowsOf(renderedSettledThreads, "settled"); + items.push({ kind: "marker", marker: "settled-placeholder" }); + items.push(...settledRows); return items; }, [ activeThreads, - compact, pinnedThreads, renderedSettledThreads, settledThreads.length, @@ -3752,7 +3403,6 @@ export default function Sidebar() { () => createSidebarSortingStrategy({ items: sidebarListItems, - compact, boundaryLabelHeight: SIDEBAR_DRAG_LABEL_HEIGHT, settledOrder: draggedSettledOrder, settledExpanded: settledShelfExpanded, @@ -3761,7 +3411,6 @@ export default function Sidebar() { snoozedThreadCount: snoozedThreads.length, }), [ - compact, draggedSettledOrder, routeThreadKey, settledShelfExpanded, @@ -3770,22 +3419,6 @@ export default function Sidebar() { snoozedThreads.length, ], ); - const draggingCompactSnoozed = compact && dragState?.activeSection === "snoozed"; - const compactSnoozedDragThread = - draggingCompactSnoozed && dragState ? threadByKey.get(dragState.activeKey) : undefined; - const compactSidebarSortingStrategy = useCallback( - (args) => { - const item = sidebarListItems[args.index]; - // Footer rows stay anchored while the main list previews a reorder. - if ( - item?.kind === "thread" ? item.section === "snoozed" : item?.marker === "snoozed-header" - ) { - return null; - } - return sidebarSortingStrategy(args); - }, - [sidebarListItems, sidebarSortingStrategy], - ); // Hidden and filtered threads keep their keys. Reserve those slots without // including the rows in the visible drop order or writing to them. const { pinnedKeysById, activeKeysById } = useMemo( @@ -4689,19 +4322,7 @@ export default function Sidebar() { <> 0 ? ( -
      - ) : null - } + className="gap-0 min-h-full" fixedHeader={ // Lifted above the stage backdrop, whose fade bleeds below the // header and would otherwise paint across the search row's outline. @@ -4761,12 +4382,8 @@ export default function Sidebar() { // popup opens under the field, is at least as wide as it, // and grows to fit project names up to a cap, past which // the rows truncate. - anchor={compact ? undefined : headerSearchRef} - side={compact ? "right" : "bottom"} - className={cn( - "max-w-[min(18rem,var(--available-width))] overflow-hidden", - compact && "min-w-56", - )} + anchor={headerSearchRef} + className="max-w-[min(18rem,var(--available-width))] overflow-hidden" > } > - + {isSearchingThreads ? ( threadSearchResults.length > 0 ? ( No threads found

      @@ -4948,23 +4557,20 @@ export default function Sidebar() { modifiers={[ restrictToVerticalAxis, restrictBelowPins, - ...(compact ? [] : [restrictToFirstScrollableAncestor]), + restrictToFirstScrollableAncestor, ]} onDragStart={handleThreadDragStart} onDragOver={handleThreadDragOver} onDragEnd={handleThreadDragEnd} > - +
        0 && "flex-1", + sidebarListItems.length > 0 && "flex-1", )} > {(() => { @@ -4976,9 +4582,10 @@ export default function Sidebar() { const threadKey = scopedThreadKey( scopeThreadRef(thread.environmentId, thread.id), ); - // Settled and snoozed always use slim rows. Active and - // pinned threads use cards unless the user has explicitly - // enabled the compact thread-list preference. + // Settled and snoozed are the ONLY things that collapse a + // row: every other thread is a full card. Density comes + // from users (or the auto rules) actually parking work, + // not from the sidebar second-guessing what still matters. const isCard = section === "active" || section === "pinned"; const rowVariant = isCard ? "card" : "slim"; return ( @@ -4988,7 +4595,6 @@ export default function Sidebar() { key={`${threadKey}:${rowVariant}`} thread={thread} variant={rowVariant} - compact={compactThreadRows} // Snoozed rows wake, settled rows un-settle, and cards settle. variantAction={ section === "snoozed" @@ -5091,25 +4697,11 @@ export default function Sidebar() { !draggableThreadKeys.has(threadKey) || optimisticDrop !== null } > - {(bag) => - renderThreadRowInner( - thread, - section, - draggingCompactSnoozed && bag.isDragging - ? { ...bag, hidden: true } - : bag, - ) - } + {(bag) => renderThreadRowInner(thread, section, bag)} ); }; const from = dragState?.activeSection ?? null; - const showDragLabels = - from !== null && - (!compact || - dragTargetSection === "active" || - dragTargetSection === "pinned"); - const snoozedItems: ReactNode[] = []; const items: ReactNode[] = [ , ]; for (const item of sidebarListItems) { - const destination = - compact && - (item.kind === "thread" - ? item.section === "snoozed" - : item.marker === "snoozed-header") - ? snoozedItems - : items; if (item.kind === "thread") { - destination.push( - renderThreadRow(threadByKey.get(item.key)!, item.section), - ); + items.push(renderThreadRow(threadByKey.get(item.key)!, item.section)); continue; } switch (item.marker) { @@ -5141,7 +4724,7 @@ export default function Sidebar() { key="pinned-header" marker="pinned-header" label="Pinned" - visible={showDragLabels} + visible={from !== null} isDropTarget={dragTargetSection === "pinned"} />, ); @@ -5152,7 +4735,7 @@ export default function Sidebar() { key="pinned-divider" marker="pinned-divider" label="Active" - visible={showDragLabels} + visible={from !== null} isDropTarget={dragTargetSection === "active"} />, ); @@ -5176,11 +4759,11 @@ export default function Sidebar() { ); break; case "snoozed-header": - destination.push( + items.push( -
          - {renderThreadRowInner(compactSnoozedDragThread, "snoozed", { - isDragging: true, - listeners: undefined, - setNodeRef: () => {}, - transform: null, - transition: undefined, - })} -
        - , - document.body, - "compact-snoozed-drag", - ) - : null, - ]; + return items; })()} - {!compact && settledShelfExpanded && hiddenSettledCount > 0 ? ( + {settledShelfExpanded && hiddenSettledCount > 0 ? (
      • - - - } - > - - - Show {Math.min(hiddenSettledCount, SETTLED_TAIL_PAGE_COUNT)} more - - - - Show {Math.min(hiddenSettledCount, SETTLED_TAIL_PAGE_COUNT)} more - - +
      • ) : null}
      @@ -5297,29 +4842,20 @@ export default function Sidebar() { snoozedThreads.length + settledThreads.length === 0 ? ( -
      +
      {projects.length === 0 ? ( <> - No projects yet + No projects yet - ) : compact ? null : scopedProjectGroup ? ( + ) : scopedProjectGroup ? ( `No threads in ${scopedProjectGroup.displayName} yet` ) : ( "No threads yet" diff --git a/apps/web/src/components/ThreadStatusIndicators.tsx b/apps/web/src/components/ThreadStatusIndicators.tsx index 4b26d0442021..7201779f13f1 100644 --- a/apps/web/src/components/ThreadStatusIndicators.tsx +++ b/apps/web/src/components/ThreadStatusIndicators.tsx @@ -144,17 +144,14 @@ export function ThreadPullRequestBadgeControl({ number, url, status, - iconOnly = false, onOpenStack, onOpenPullRequest, }: { - variant: "underline" | "ghost" | "badge"; + variant: "underline" | "ghost"; badge: ThreadPullRequestBadge | null; number?: number | undefined; url?: string | undefined; status: PrStatusIndicator | null; - /** Dense rows drop the number/layer count and keep only the state glyph. */ - iconOnly?: boolean; onOpenStack: () => void; onOpenPullRequest: (event: MouseEvent) => void; }) { @@ -171,9 +168,7 @@ export function ThreadPullRequestBadgeControl({ const className = cn( variant === "ghost" ? buttonVariants({ variant: "ghost", size: "xs" }) - : variant === "badge" - ? "inline-flex size-3 shrink-0 cursor-pointer items-center justify-center rounded-full bg-sidebar ring-1 ring-sidebar outline-none focus-visible:ring-2 focus-visible:ring-ring" - : "inline-flex shrink-0 cursor-pointer items-center gap-0.5 whitespace-nowrap border-b border-transparent hover:border-current focus-visible:outline-2 focus-visible:outline-ring", + : "inline-flex shrink-0 cursor-pointer items-center gap-0.5 whitespace-nowrap border-b border-transparent hover:border-current focus-visible:outline-2 focus-visible:outline-ring", "text-xs tabular-nums", variant === "ghost" && "font-normal text-xs! active:scale-100 [--control-icon-color:currentColor]", @@ -183,11 +178,8 @@ export function ThreadPullRequestBadgeControl({ ); const content = ( <> - - {iconOnly ? null : isStack ? badge.layers : linkedCount !== null ? `+${linkedCount}` : number} + + {isStack ? badge.layers : linkedCount !== null ? `+${linkedCount}` : number} ); return ( diff --git a/apps/web/src/components/settings/CompactSidebarPreview.tsx b/apps/web/src/components/settings/CompactSidebarPreview.tsx deleted file mode 100644 index 4d1e861d14e7..000000000000 --- a/apps/web/src/components/settings/CompactSidebarPreview.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import { useEffect, useRef, useState } from "react"; - -import { cn } from "~/lib/utils"; - -export function CompactSidebarPreview({ - railEnabled, - compactRows, -}: { - railEnabled: boolean; - compactRows: boolean; -}) { - const [collapsed, setCollapsed] = useState(false); - const sidebarRef = useRef(null); - - useEffect(() => { - if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return; - const animation = sidebarRef.current?.animate( - [ - { width: "36px", offset: 0 }, - { width: railEnabled ? "12px" : "0px", offset: 0.45 }, - { width: railEnabled ? "12px" : "0px", offset: 0.6 }, - { width: "36px", offset: 1 }, - ], - { duration: 800, easing: "ease-in-out" }, - ); - return () => animation?.cancel(); - }, [railEnabled, compactRows]); - - return ( - - ); -} diff --git a/apps/web/src/components/settings/SettingsPanels.tsx b/apps/web/src/components/settings/SettingsPanels.tsx index a0d713f58bee..6baa561a91fe 100644 --- a/apps/web/src/components/settings/SettingsPanels.tsx +++ b/apps/web/src/components/settings/SettingsPanels.tsx @@ -170,7 +170,6 @@ import { import { searchableSetting } from "./settingsSearch"; import { ProjectFavicon } from "../ProjectFavicon"; import { PanelAnimationsPreview } from "./PanelAnimationsPreview"; -import { CompactSidebarPreview } from "./CompactSidebarPreview"; const ENVIRONMENT_IDENTIFICATION_LABELS: Record = { artwork: "Artwork", @@ -524,10 +523,6 @@ export function useSettingsRestore(onRestored?: () => void) { ...(theme !== "system" ? ["Theme"] : []), ...(!followSystem ? ["Follow system"] : []), ...(themeHalves !== null ? ["Theme mix"] : []), - ...(settings.compactSidebarEnabled !== DEFAULT_UNIFIED_SETTINGS.compactSidebarEnabled || - settings.sidebarCompactThreadRows !== DEFAULT_UNIFIED_SETTINGS.sidebarCompactThreadRows - ? ["Compact sidebar"] - : []), ...(settings.appearanceContrast !== DEFAULT_UNIFIED_SETTINGS.appearanceContrast ? ["Contrast"] : []), @@ -634,7 +629,6 @@ export function useSettingsRestore(onRestored?: () => void) { settings.browserLinkTarget, settings.browserAutoShowFloatingPreview, settings.appearanceContrast, - settings.compactSidebarEnabled, settings.diffColorScheme, settings.enableAgentBrowserAccess, settings.confirmQuit, @@ -666,7 +660,6 @@ export function useSettingsRestore(onRestored?: () => void) { settings.continueThreadsAfterServerUpdate, settings.sidebarAutoSettleAfterDays, settings.sidebarAutoSettleOnMerge, - settings.sidebarCompactThreadRows, settings.sidebarProjectGroupingMode, settings.sidebarThreadPreviewCount, settings.showSkillsInSlashMenu, @@ -744,7 +737,6 @@ export function useSettingsRestore(onRestored?: () => void) { } updateSettings({ appearanceContrast: DEFAULT_UNIFIED_SETTINGS.appearanceContrast, - compactSidebarEnabled: DEFAULT_UNIFIED_SETTINGS.compactSidebarEnabled, diffColorScheme: DEFAULT_UNIFIED_SETTINGS.diffColorScheme, timestampFormat: DEFAULT_UNIFIED_SETTINGS.timestampFormat, notificationMode: DEFAULT_UNIFIED_SETTINGS.notificationMode, @@ -762,7 +754,6 @@ export function useSettingsRestore(onRestored?: () => void) { panelAnimationDurationMs: DEFAULT_UNIFIED_SETTINGS.panelAnimationDurationMs, sidebarThreadPreviewCount: DEFAULT_UNIFIED_SETTINGS.sidebarThreadPreviewCount, sidebarProjectGroupingMode: DEFAULT_UNIFIED_SETTINGS.sidebarProjectGroupingMode, - sidebarCompactThreadRows: DEFAULT_UNIFIED_SETTINGS.sidebarCompactThreadRows, sidebarAutoSettleAfterDays: DEFAULT_UNIFIED_SETTINGS.sidebarAutoSettleAfterDays, sidebarAutoSettleOnMerge: DEFAULT_UNIFIED_SETTINGS.sidebarAutoSettleOnMerge, responseStreamingMode: DEFAULT_UNIFIED_SETTINGS.responseStreamingMode, @@ -1143,19 +1134,6 @@ export function AppearanceSettingsPanel() { const [isImportThemeOpen, setIsImportThemeOpen] = useState(false); const settings = useScopedSettings(); const updateSettings = useUpdateScopedSettings(); - const compactSidebarMode = settings.compactSidebarEnabled - ? settings.sidebarCompactThreadRows - ? "both" - : "rail" - : settings.sidebarCompactThreadRows - ? "threads" - : "off"; - const compactSidebarModes = { - off: "Off", - rail: "Rail only", - threads: "Threads only", - both: "Both", - }; const environmentStageLabel = useEnvironmentStageLabel(); const showEnvironmentIdentification = resolveEnvironmentIdentificationPillLabel(environmentStageLabel) !== null; @@ -1442,64 +1420,6 @@ export function AppearanceSettingsPanel() { /> - - - updateSettings({ - compactSidebarEnabled: DEFAULT_UNIFIED_SETTINGS.compactSidebarEnabled, - sidebarCompactThreadRows: DEFAULT_UNIFIED_SETTINGS.sidebarCompactThreadRows, - }) - } - /> - ) : null - } - control={ -
      - - -
      - } - /> -
      - ); diff --git a/apps/web/src/components/settings/SettingsSidebarNav.tsx b/apps/web/src/components/settings/SettingsSidebarNav.tsx index c206174a397a..c29068934efa 100644 --- a/apps/web/src/components/settings/SettingsSidebarNav.tsx +++ b/apps/web/src/components/settings/SettingsSidebarNav.tsx @@ -24,7 +24,6 @@ import { XIcon, } from "lucide-react"; import { useLocation, useNavigate } from "@tanstack/react-router"; -import { useCompactSidebarEnabled } from "../../hooks/useSettings"; import { Button } from "../ui/button"; import { Input } from "../ui/input"; @@ -112,13 +111,12 @@ export function SettingsSidebarNav({ pathname }: { pathname: string }) { (item) => item.to !== "/settings/projects" || isSettingsOverviewVisible(scopeSearch), ); const { isMobile, setOpenMobile, open, setOpen } = useSidebar(); - const compactSidebarEnabled = useCompactSidebarEnabled(); const searchInputRef = useRef(null); const [query, setQuery] = useState(""); const [activeResultIndex, setActiveResultIndex] = useState(0); const searchableItems = useAvailableSettingsSearchItems(); const results = useMemo(() => searchSettings(query, searchableItems), [query, searchableItems]); - const isSearching = query.trim().length > 0 && !(compactSidebarEnabled && !isMobile && !open); + const isSearching = query.trim().length > 0; const hasResults = results.length > 0; useEffect(() => { @@ -235,18 +233,7 @@ export function SettingsSidebarNav({ pathname }: { pathname: string }) { <> - { - setOpen(true); - requestAnimationFrame(() => searchInputRef.current?.focus()); - }} - > - - -
      +
      handleSectionClick(item.to)} > - - {item.label} - + {item.label} ); @@ -360,12 +343,10 @@ export function SettingsSidebarNav({ pathname }: { pathname: string }) { -
      - - - -
      -
      + + + +
      diff --git a/apps/web/src/components/settings/settingsSearch.ts b/apps/web/src/components/settings/settingsSearch.ts index 1fe96d2b4df5..837aa7b47ce3 100644 --- a/apps/web/src/components/settings/settingsSearch.ts +++ b/apps/web/src/components/settings/settingsSearch.ts @@ -159,14 +159,6 @@ export const SETTINGS_SEARCH_ITEMS = [ title: "Panel animations", to: "/settings/appearance", }, - { - id: "compact-sidebar", - title: "Compact sidebar", - to: "/settings/appearance", - searchTerms: [ - "collapsed icons rail hover navigation preview expanded dense density one line rows chats threads compact thread list", - ], - }, { id: "environment-identification", title: "Environment identification", diff --git a/apps/web/src/components/sidebar/SidebarChrome.tsx b/apps/web/src/components/sidebar/SidebarChrome.tsx index 2f65cf8c3697..afbbf7671dfc 100644 --- a/apps/web/src/components/sidebar/SidebarChrome.tsx +++ b/apps/web/src/components/sidebar/SidebarChrome.tsx @@ -86,7 +86,7 @@ function SidebarBrand({ onBackdrop }: { onBackdrop: boolean }) { + {currentFooterPage ? ( - + - Back + Back ) : ( @@ -224,10 +224,8 @@ export const SidebarUtilityMenu = memo(function SidebarUtilityMenu() { export const SidebarChromeFooter = memo(function SidebarChromeFooter() { return ( -
      - - -
      + +
      ); diff --git a/apps/web/src/components/sidebar/SidebarCompletedTime.test.tsx b/apps/web/src/components/sidebar/SidebarCompletedTime.test.tsx deleted file mode 100644 index 7327af79e794..000000000000 --- a/apps/web/src/components/sidebar/SidebarCompletedTime.test.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { act, memo } from "react"; -import { create, type ReactTestRenderer } from "react-test-renderer"; -import { afterEach, beforeEach, expect, it, vi } from "vite-plus/test"; - -import { SidebarCompletedTime } from "./SidebarCompletedTime"; - -let renderer: ReactTestRenderer | undefined; - -beforeEach(() => { - vi.useFakeTimers(); - vi.setSystemTime(new Date("2026-09-07T01:01:00Z")); - vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true); - vi.stubGlobal("window", { - setTimeout, - clearTimeout, - setInterval, - clearInterval, - }); -}); - -afterEach(async () => { - await act(() => renderer?.unmount()); - renderer = undefined; - vi.unstubAllGlobals(); - vi.useRealTimers(); -}); - -it("advances visible and accessible completion times without rerendering its memoized row", async () => { - const rowRender = vi.fn(); - const Row = memo(function Row() { - rowRender(); - return ; - }); - await act(() => { - renderer = create(); - }); - expect(renderer!.root.findByType("time").props.dateTime).toBe("2026-09-07T01:00:00Z"); - expect(renderer!.root.findByProps({ className: "sr-only" }).children).toEqual(["Completed "]); - expect( - renderer!.root.findAll((node) => node.props.role === "status" || node.props["aria-live"]), - ).toHaveLength(0); - expect(renderer!.root.findByProps({ className: "text-secondary-label" }).children).toEqual([ - "1m", - ]); - - await act(() => vi.advanceTimersByTime(60_000)); - - expect(renderer!.root.findByProps({ className: "sr-only" }).children).toEqual(["Completed "]); - expect(renderer!.root.findByProps({ className: "text-secondary-label" }).children).toEqual([ - "2m", - ]); - expect(rowRender).toHaveBeenCalledTimes(1); - await act(() => renderer!.unmount()); - renderer = undefined; - expect(vi.getTimerCount()).toBe(0); -}); diff --git a/apps/web/src/components/sidebar/SidebarCompletedTime.tsx b/apps/web/src/components/sidebar/SidebarCompletedTime.tsx deleted file mode 100644 index 785b8d9459d2..000000000000 --- a/apps/web/src/components/sidebar/SidebarCompletedTime.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { useNowMinute } from "../../hooks/useNowMinute"; -import { formatRelativeTimeLabel } from "../../timestampFormat"; - -export function SidebarCompletedTime({ completedAt }: { completedAt: string }) { - // Subscribe inside the label so time advances even when the row is memoized. - const nowMinute = useNowMinute(); - const relativeTime = formatRelativeTimeLabel(completedAt, Date.parse(`${nowMinute}:00Z`)); - const label = relativeTime === "just now" ? "now" : relativeTime.replace(/ ago$/, ""); - - return ( - - ); -} diff --git a/apps/web/src/components/sidebar/SidebarThreadHeader.tsx b/apps/web/src/components/sidebar/SidebarThreadHeader.tsx index d0718d9856f8..878235615b39 100644 --- a/apps/web/src/components/sidebar/SidebarThreadHeader.tsx +++ b/apps/web/src/components/sidebar/SidebarThreadHeader.tsx @@ -20,10 +20,9 @@ import { } from "react"; import { cn } from "~/lib/utils"; -import { useCompactSidebarEnabled } from "../../hooks/useSettings"; import { Button } from "../ui/button"; import { Input } from "../ui/input"; -import { SidebarMenuButton, useSidebar } from "../ui/sidebar"; +import { SidebarMenuButton } from "../ui/sidebar"; import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; export interface SidebarThreadHeaderProps { @@ -70,9 +69,6 @@ export function SidebarThreadHeader({ activeSearchResultIndex, onClearSearch, }: SidebarThreadHeaderProps) { - const compactEnabled = useCompactSidebarEnabled(); - const { state, isMobile, setOpen } = useSidebar(); - const compact = compactEnabled && state === "collapsed" && !isMobile; const resultsVisible = isSearching && searchResultCount > 0; // Results shrink as the query narrows, so the active index can outrun the // list; pointing aria-activedescendant at a removed option strands the @@ -83,24 +79,10 @@ export function SidebarThreadHeader({ : "New thread"; return ( -
      - {compact ? ( - { - setOpen(true); - requestAnimationFrame(() => searchInputRef.current?.focus()); - }} - > - - - ) : null} +
      {/* Segmented well: the icons read as one control instead of three loose buttons competing with the search field beside them. */} -
      +
      {hasProjects ? ( <> {projectScope} diff --git a/apps/web/src/components/sidebar/SidebarUpdatePill.tsx b/apps/web/src/components/sidebar/SidebarUpdatePill.tsx index 8c04eec6fe7d..a94b7801ecfd 100644 --- a/apps/web/src/components/sidebar/SidebarUpdatePill.tsx +++ b/apps/web/src/components/sidebar/SidebarUpdatePill.tsx @@ -348,7 +348,7 @@ function SidebarUpdateControl() { ); return ( - + { diff --git a/apps/web/src/components/ui/sidebar.tsx b/apps/web/src/components/ui/sidebar.tsx index 404295f5f5c1..307feda7abfc 100644 --- a/apps/web/src/components/ui/sidebar.tsx +++ b/apps/web/src/components/ui/sidebar.tsx @@ -591,11 +591,9 @@ function SidebarSeparator({ className, ...props }: React.ComponentProps & { fixedHeader?: React.ReactNode; - fixedFooter?: React.ReactNode; }) { return ( <> @@ -619,7 +617,6 @@ function SidebarContent({ {...props} /> - {fixedFooter ?
      {fixedFooter}
      : null} ); } diff --git a/apps/web/src/hooks/useSettings.ts b/apps/web/src/hooks/useSettings.ts index fa4b8bc8fd31..194cc36c55f4 100644 --- a/apps/web/src/hooks/useSettings.ts +++ b/apps/web/src/hooks/useSettings.ts @@ -379,13 +379,6 @@ export function useLegacySidebarEnabled(): boolean { return settingsHydrated && legacySidebarEnabled; } -/** Keep the default collapsed sidebar until persisted client settings hydrate. */ -export function useCompactSidebarEnabled(): boolean { - const settingsHydrated = useClientSettingsHydrated(); - const compactSidebarEnabled = useClientSettingsValue().compactSidebarEnabled; - return settingsHydrated && compactSidebarEnabled; -} - /** Read current settings for one environment, merged with client-local preferences. */ export function useEnvironmentSettings( environmentId: EnvironmentId, diff --git a/apps/web/src/timestampFormat.test.ts b/apps/web/src/timestampFormat.test.ts index 5169e438bb2d..8c6287010d8f 100644 --- a/apps/web/src/timestampFormat.test.ts +++ b/apps/web/src/timestampFormat.test.ts @@ -228,15 +228,3 @@ describe("formatElapsedDurationLabel", () => { expect(formatElapsedDurationLabel("2026-04-03T12:00:00.000Z")).toBe("4d"); }); }); - -describe("explicit relative-time clock", () => { - it("uses the supplied minute instead of the wall clock", () => { - const completedAt = "2026-09-07T01:00:00Z"; - expect(formatRelativeTimeLabel(completedAt, Date.parse("2026-09-07T01:01:00Z"))).toBe("1m ago"); - expect(formatRelativeTimeLabel(completedAt, Date.parse("2026-09-07T01:02:00Z"))).toBe("2m ago"); - expect(formatRelativeTime(completedAt, Date.parse("2026-09-07T01:02:00Z"))).toEqual({ - value: "2m", - suffix: "ago", - }); - }); -}); diff --git a/apps/web/src/timestampFormat.ts b/apps/web/src/timestampFormat.ts index 983a9bb8b232..9dd463bb50fa 100644 --- a/apps/web/src/timestampFormat.ts +++ b/apps/web/src/timestampFormat.ts @@ -196,10 +196,10 @@ export type RelativeTimeState = | { status: "invalid" } | { status: "relative"; value: string; suffix: string | null }; -export function formatRelativeTime(isoDate: string, nowMs = Date.now()): RelativeTimeParts | null { +export function formatRelativeTime(isoDate: string): RelativeTimeParts | null { const date = parseTimestampDate(isoDate); if (!date) return null; - const diffMs = nowMs - date.getTime(); + const diffMs = Date.now() - date.getTime(); if (diffMs < 0) return { value: "just now", suffix: null }; const seconds = Math.floor(diffMs / 1000); if (seconds < 60) return { value: "just now", suffix: null }; @@ -211,8 +211,8 @@ export function formatRelativeTime(isoDate: string, nowMs = Date.now()): Relativ return { value: `${days}d`, suffix: "ago" }; } -export function formatRelativeTimeLabel(isoDate: string, nowMs = Date.now()) { - const relative = formatRelativeTime(isoDate, nowMs); +export function formatRelativeTimeLabel(isoDate: string) { + const relative = formatRelativeTime(isoDate); if (!relative) return ""; return relative.suffix ? `${relative.value} ${relative.suffix}` : relative.value; } diff --git a/apps/web/src/workspaceTitlebar.ts b/apps/web/src/workspaceTitlebar.ts index aed95897cc55..b481221e63aa 100644 --- a/apps/web/src/workspaceTitlebar.ts +++ b/apps/web/src/workspaceTitlebar.ts @@ -1,2 +1,2 @@ export const COLLAPSED_SIDEBAR_TITLEBAR_INSET_CLASS = - "[[data-sidebar-state=collapsed]_&]:pl-[var(--workspace-titlebar-content-left)] [[data-sidebar-state=collapsed]:has([data-side=left][data-collapsible=icon])_&]:pl-[max(calc(env(safe-area-inset-left)+1.25rem),calc(var(--workspace-titlebar-content-left)-var(--sidebar-width-icon)))]"; + "[[data-sidebar-state=collapsed]_&]:pl-[var(--workspace-titlebar-content-left)]"; diff --git a/packages/contracts/src/settings.test.ts b/packages/contracts/src/settings.test.ts index c8c6922ec020..b090b47fba5b 100644 --- a/packages/contracts/src/settings.test.ts +++ b/packages/contracts/src/settings.test.ts @@ -482,18 +482,7 @@ describe("ClientSettings environment identification", () => { describe("ClientSettings sidebar", () => { it("defaults to the current sidebar", () => { - const settings = decodeClientSettings({}); - expect(settings.legacySidebarEnabled).toBe(false); - expect(settings.sidebarCompactThreadRows).toBe(false); - }); - - it("preserves an explicit compact thread row preference", () => { - expect(decodeClientSettings({ sidebarCompactThreadRows: true }).sidebarCompactThreadRows).toBe( - true, - ); - expect( - decodeClientSettingsPatch({ sidebarCompactThreadRows: true }).sidebarCompactThreadRows, - ).toBe(true); + expect(decodeClientSettings({}).legacySidebarEnabled).toBe(false); }); it("drops the retired sidebar v2 beta keys, resetting everyone to the default", () => { @@ -506,6 +495,14 @@ describe("ClientSettings sidebar", () => { expect(decoded).not.toHaveProperty("sidebarV2ConfiguredByUser"); }); + it("drops the retired compact sidebar keys for users who opted in", () => { + const stored = { compactSidebarEnabled: true, sidebarCompactThreadRows: true }; + const decoded = decodeClientSettings(stored); + expect(decoded).not.toHaveProperty("compactSidebarEnabled"); + expect(decoded).not.toHaveProperty("sidebarCompactThreadRows"); + expect(decodeClientSettingsPatch(stored)).toEqual({}); + }); + it("preserves an explicit legacy sidebar opt-in", () => { expect(decodeClientSettings({ legacySidebarEnabled: true }).legacySidebarEnabled).toBe(true); expect(decodeClientSettingsPatch({ legacySidebarEnabled: true }).legacySidebarEnabled).toBe( diff --git a/packages/contracts/src/settings.ts b/packages/contracts/src/settings.ts index 1262a303ba41..7b3715d704be 100644 --- a/packages/contracts/src/settings.ts +++ b/packages/contracts/src/settings.ts @@ -437,7 +437,6 @@ export const ClientSettingsSchema = Schema.Struct({ // old keys, so everyone, including prior beta opt-outs, resets to the new // default sidebar. legacySidebarEnabled: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))), - compactSidebarEnabled: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))), sidebarProjectGroupingMode: SidebarProjectGroupingMode.pipe( Schema.withDecodingDefault(Effect.succeed(DEFAULT_SIDEBAR_PROJECT_GROUPING_MODE)), ), @@ -451,7 +450,6 @@ export const ClientSettingsSchema = Schema.Struct({ sidebarThreadSortOrder: SidebarThreadSortOrder.pipe( Schema.withDecodingDefault(Effect.succeed(DEFAULT_SIDEBAR_THREAD_SORT_ORDER)), ), - sidebarCompactThreadRows: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))), sidebarThreadPreviewCount: SidebarThreadPreviewCount.pipe( Schema.withDecodingDefault(Effect.succeed(DEFAULT_SIDEBAR_THREAD_PREVIEW_COUNT)), ), @@ -1504,14 +1502,12 @@ export const ClientSettingsPatch = Schema.Struct({ proactivePanelsEnabled: Schema.optionalKey(Schema.Boolean), showSkillsInSlashMenu: Schema.optionalKey(Schema.Boolean), legacySidebarEnabled: Schema.optionalKey(Schema.Boolean), - compactSidebarEnabled: Schema.optionalKey(Schema.Boolean), sidebarProjectGroupingMode: Schema.optionalKey(SidebarProjectGroupingMode), sidebarProjectGroupingOverrides: Schema.optionalKey( Schema.Record(TrimmedNonEmptyString, SidebarProjectGroupingMode), ), sidebarProjectSortOrder: Schema.optionalKey(SidebarProjectSortOrder), sidebarThreadSortOrder: Schema.optionalKey(SidebarThreadSortOrder), - sidebarCompactThreadRows: Schema.optionalKey(Schema.Boolean), sidebarThreadPreviewCount: Schema.optionalKey(SidebarThreadPreviewCount), timestampFormat: Schema.optionalKey(TimestampFormat), snapShotEnabled: Schema.optionalKey(Schema.Boolean),