From 5d98e310123e38d01583bc920c8a0fc49ea74592 Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Sun, 31 May 2026 21:34:19 -0700 Subject: [PATCH] Revert workspace board width control (#4334) --- src/main/persistence.ts | 7 --- src/main/runtime/rpc/methods/client-ui.ts | 1 - .../sidebar/WorkspaceKanbanDrawer.tsx | 59 +------------------ .../WorkspaceKanbanDrawerHeader.test.tsx | 7 +-- .../sidebar/WorkspaceKanbanDrawerHeader.tsx | 11 +--- .../sidebar/WorkspaceKanbanLaneGrid.tsx | 4 +- .../sidebar/WorkspaceKanbanSettingsMenu.tsx | 41 +------------ src/renderer/src/store/slices/ui.test.ts | 24 -------- src/renderer/src/store/slices/ui.ts | 14 ----- src/shared/constants.ts | 6 +- src/shared/types.ts | 3 - src/shared/workspace-statuses.test.ts | 32 ---------- src/shared/workspace-statuses.ts | 31 +--------- 13 files changed, 9 insertions(+), 231 deletions(-) diff --git a/src/main/persistence.ts b/src/main/persistence.ts index 9f44270c2..4bfff0920 100644 --- a/src/main/persistence.ts +++ b/src/main/persistence.ts @@ -98,7 +98,6 @@ import { DEFAULT_WORKSPACE_STATUS_ID, clampWorkspaceBoardColumnWidth, clampWorkspaceBoardOpacity, - normalizeWorkspaceBoardColumnLayout, normalizePersistedWorkspaceStatuses, normalizeWorkspaceStatuses } from '../shared/workspace-statuses' @@ -2914,9 +2913,6 @@ export class Store { ), workspaceStatuses: normalizeWorkspaceStatuses(this.state.ui?.workspaceStatuses), workspaceBoardOpacity: clampWorkspaceBoardOpacity(this.state.ui?.workspaceBoardOpacity), - workspaceBoardColumnLayout: normalizeWorkspaceBoardColumnLayout( - this.state.ui?.workspaceBoardColumnLayout - ), workspaceBoardColumnWidth: clampWorkspaceBoardColumnWidth( this.state.ui?.workspaceBoardColumnWidth ), @@ -2957,9 +2953,6 @@ export class Store { workspaceBoardOpacity: clampWorkspaceBoardOpacity( updates.workspaceBoardOpacity ?? this.state.ui?.workspaceBoardOpacity ), - workspaceBoardColumnLayout: normalizeWorkspaceBoardColumnLayout( - updates.workspaceBoardColumnLayout ?? this.state.ui?.workspaceBoardColumnLayout - ), workspaceBoardColumnWidth: clampWorkspaceBoardColumnWidth( updates.workspaceBoardColumnWidth ?? this.state.ui?.workspaceBoardColumnWidth ), diff --git a/src/main/runtime/rpc/methods/client-ui.ts b/src/main/runtime/rpc/methods/client-ui.ts index d97776205..900ae14a3 100644 --- a/src/main/runtime/rpc/methods/client-ui.ts +++ b/src/main/runtime/rpc/methods/client-ui.ts @@ -146,7 +146,6 @@ const UiUpdate = z agentActivityDisplayMode: AgentActivityDisplayMode.optional(), workspaceStatuses: z.array(WorkspaceStatusDefinition).optional(), workspaceBoardOpacity: z.number().finite().optional(), - workspaceBoardColumnLayout: z.enum(['full', 'fit']).optional(), workspaceBoardColumnWidth: z.number().finite().optional(), _workspaceStatusesDefaultOrderMigrated: z.boolean().optional(), _workspaceStatusesDefaultWorkflowMigrated: z.boolean().optional(), diff --git a/src/renderer/src/components/sidebar/WorkspaceKanbanDrawer.tsx b/src/renderer/src/components/sidebar/WorkspaceKanbanDrawer.tsx index 6e12e8f9e..3a0c49e95 100644 --- a/src/renderer/src/components/sidebar/WorkspaceKanbanDrawer.tsx +++ b/src/renderer/src/components/sidebar/WorkspaceKanbanDrawer.tsx @@ -31,11 +31,7 @@ import { type WorktreeDragGroup } from './worktree-manual-order' import type { WorkspaceStatus, WorktreeMeta } from '../../../../shared/types' -import { - WORKSPACE_BOARD_COLUMN_GAP, - fitWorkspaceBoardColumnWidth, - makeWorkspaceStatusId -} from '../../../../shared/workspace-statuses' +import { makeWorkspaceStatusId } from '../../../../shared/workspace-statuses' type WorkspaceKanbanDrawerProps = { open: boolean @@ -57,8 +53,6 @@ export default function WorkspaceKanbanDrawer({ const updateWorktreesMeta = useAppStore((s) => s.updateWorktreesMeta) const workspaceStatuses = useAppStore((s) => s.workspaceStatuses) const setWorkspaceStatuses = useAppStore((s) => s.setWorkspaceStatuses) - const workspaceBoardColumnLayout = useAppStore((s) => s.workspaceBoardColumnLayout) - const setWorkspaceBoardColumnLayout = useAppStore((s) => s.setWorkspaceBoardColumnLayout) const workspaceBoardColumnWidth = useAppStore((s) => s.workspaceBoardColumnWidth) const setWorkspaceBoardColumnWidth = useAppStore((s) => s.setWorkspaceBoardColumnWidth) const sortBy = useAppStore((s) => s.sortBy) @@ -70,7 +64,6 @@ export default function WorkspaceKanbanDrawer({ const areaSelectionOverlayRef = useRef(null) const [dragOverStatus, setDragOverStatus] = useState(null) const [pinDragOver, setPinDragOver] = useState(false) - const [laneScrollerWidth, setLaneScrollerWidth] = useState(0) const { canCreateWorktree, createWorktreeForStatus } = useWorkspaceKanbanCreateWorktree() const visibleWorktreeIdSet = useVisibleWorkspaceKanbanWorktreeIds({ allWorktrees, @@ -119,33 +112,6 @@ export default function WorkspaceKanbanDrawer({ }) const { columnWidth, isResizingColumn, onColumnResizeStart, onColumnResizeKeyDown } = useWorkspaceKanbanColumnResize(workspaceBoardColumnWidth, setWorkspaceBoardColumnWidth) - const laneScrollerResizeRef = useRef(null) - const attachLaneScroller = useCallback((node: HTMLDivElement | null) => { - laneScrollerRef.current = node - laneScrollerResizeRef.current?.disconnect() - laneScrollerResizeRef.current = null - if (!node) { - return - } - setLaneScrollerWidth(node.clientWidth) - if (typeof ResizeObserver === 'undefined') { - return - } - const observer = new ResizeObserver(() => setLaneScrollerWidth(node.clientWidth)) - observer.observe(node) - laneScrollerResizeRef.current = observer - }, []) - const renderColumnWidth = useMemo( - () => - workspaceBoardColumnLayout === 'fit' - ? fitWorkspaceBoardColumnWidth({ - containerWidth: laneScrollerWidth, - columnCount: workspaceStatuses.length, - capWidth: columnWidth - }) - : columnWidth, - [columnWidth, laneScrollerWidth, workspaceBoardColumnLayout, workspaceStatuses.length] - ) const moveWorktreeToStatus = useCallback( (worktreeId: string, status: WorkspaceStatus) => { const current = worktreeById.get(worktreeId) @@ -503,19 +469,6 @@ export default function WorkspaceKanbanDrawer({ const drawerLeftCss = sidebarOpen ? `var(--workspace-sidebar-live-width, ${sidebarWidth}px)` : '0px' - const fitPanelBoardWidthCss = `min(calc(100vw - ${drawerLeftCss}), 1294px)` - // Why: full-width mode keeps user-sized columns and expands the companion - // board over adjacent panes; fit mode preserves the older fixed panel. - const boardContentWidth = - workspaceStatuses.length * columnWidth + - Math.max(0, workspaceStatuses.length - 1) * WORKSPACE_BOARD_COLUMN_GAP + - 24 - const fullBoardWidthCss = `min(calc(100vw - ${drawerLeftCss}), ${Math.max( - boardContentWidth, - 1294 - )}px)` - const boardWidthCss = - workspaceBoardColumnLayout === 'fit' ? fitPanelBoardWidthCss : fullBoardWidthCss return ( @@ -531,7 +484,7 @@ export default function WorkspaceKanbanDrawer({ left: drawerLeftCss, top: 36, height: 'calc(100% - 36px)', - width: boardWidthCss + width: `min(calc(100vw - ${drawerLeftCss}), 1294px)` } as React.CSSProperties } onOpenAutoFocus={(event) => { @@ -591,12 +544,7 @@ export default function WorkspaceKanbanDrawer({ > { - useAppStore.getState().recordFeatureInteraction('workspace-board-actions') - setWorkspaceBoardColumnLayout(layout) - }} onRenameStatus={handleRenameStatus} onChangeStatusColor={handleChangeStatusColor} onChangeStatusIcon={handleChangeStatusIcon} @@ -620,7 +568,7 @@ export default function WorkspaceKanbanDrawer({ onDragLeave={handlePinDragLeave} />
void): React.ReactElement { return WorkspaceKanbanDrawerHeader({ selectedCount: 0, - columnLayout: 'fit' satisfies WorkspaceBoardColumnLayout, workspaceStatuses: statuses, - onColumnLayoutChange: vi.fn(), onRenameStatus: vi.fn(), onChangeStatusColor: vi.fn(), onChangeStatusIcon: vi.fn(), diff --git a/src/renderer/src/components/sidebar/WorkspaceKanbanDrawerHeader.tsx b/src/renderer/src/components/sidebar/WorkspaceKanbanDrawerHeader.tsx index 8f1ad11d4..f44782468 100644 --- a/src/renderer/src/components/sidebar/WorkspaceKanbanDrawerHeader.tsx +++ b/src/renderer/src/components/sidebar/WorkspaceKanbanDrawerHeader.tsx @@ -2,18 +2,13 @@ import React from 'react' import { X } from 'lucide-react' import { Button } from '@/components/ui/button' import { SheetDescription, SheetHeader, SheetTitle } from '@/components/ui/sheet' -import type { - WorkspaceBoardColumnLayout, - WorkspaceStatusDefinition -} from '../../../../shared/types' +import type { WorkspaceStatusDefinition } from '../../../../shared/types' import SidebarFilter from './SidebarFilter' import WorkspaceKanbanSettingsMenu from './WorkspaceKanbanSettingsMenu' type WorkspaceKanbanDrawerHeaderProps = { selectedCount: number - columnLayout: WorkspaceBoardColumnLayout workspaceStatuses: readonly WorkspaceStatusDefinition[] - onColumnLayoutChange: (layout: WorkspaceBoardColumnLayout) => void onRenameStatus: (statusId: string, label: string) => void onChangeStatusColor: (statusId: string, color: string) => void onChangeStatusIcon: (statusId: string, icon: string) => void @@ -26,9 +21,7 @@ type WorkspaceKanbanDrawerHeaderProps = { export default function WorkspaceKanbanDrawerHeader({ selectedCount, - columnLayout, workspaceStatuses, - onColumnLayoutChange, onRenameStatus, onChangeStatusColor, onChangeStatusIcon, @@ -62,9 +55,7 @@ export default function WorkspaceKanbanDrawerHeader({ onMenuOpenChange={onFilterMenuOpenChange} /> activeWorktreeId: string | null columnWidth: number - renderColumnWidth: number isResizingColumn: boolean dragOverStatus: WorkspaceStatus | null canCreateWorktree: boolean @@ -39,7 +38,6 @@ export default function WorkspaceKanbanLaneGrid({ repoMap, activeWorktreeId, columnWidth, - renderColumnWidth, isResizingColumn, dragOverStatus, canCreateWorktree, @@ -59,7 +57,7 @@ export default function WorkspaceKanbanLaneGrid({
{statuses.map((status) => ( diff --git a/src/renderer/src/components/sidebar/WorkspaceKanbanSettingsMenu.tsx b/src/renderer/src/components/sidebar/WorkspaceKanbanSettingsMenu.tsx index 743f36c60..3afe7d549 100644 --- a/src/renderer/src/components/sidebar/WorkspaceKanbanSettingsMenu.tsx +++ b/src/renderer/src/components/sidebar/WorkspaceKanbanSettingsMenu.tsx @@ -5,23 +5,16 @@ import { DropdownMenu, DropdownMenuContent, DropdownMenuLabel, - DropdownMenuSeparator, DropdownMenuTrigger } from '@/components/ui/dropdown-menu' -import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' import { cn } from '@/lib/utils' -import type { - WorkspaceBoardColumnLayout, - WorkspaceStatusDefinition -} from '../../../../shared/types' +import type { WorkspaceStatusDefinition } from '../../../../shared/types' import { getWorkspaceStatusVisualMeta } from './workspace-status' import WorkspaceStatusAppearancePopover from './WorkspaceStatusAppearancePopover' type WorkspaceKanbanSettingsMenuProps = { - columnLayout: WorkspaceBoardColumnLayout workspaceStatuses: readonly WorkspaceStatusDefinition[] - onColumnLayoutChange: (layout: WorkspaceBoardColumnLayout) => void onRenameStatus: (statusId: string, label: string) => void onChangeStatusColor: (statusId: string, color: string) => void onChangeStatusIcon: (statusId: string, icon: string) => void @@ -31,9 +24,7 @@ type WorkspaceKanbanSettingsMenuProps = { } export default function WorkspaceKanbanSettingsMenu({ - columnLayout, workspaceStatuses, - onColumnLayoutChange, onRenameStatus, onChangeStatusColor, onChangeStatusIcon, @@ -75,36 +66,6 @@ export default function WorkspaceKanbanSettingsMenu({ } }} > - Column layout -
- { - if (value === 'full' || value === 'fit') { - onColumnLayoutChange(value) - } - }} - variant="outline" - size="sm" - className="h-7 w-full justify-stretch" - aria-label="Workspace board column layout" - > - - Full width - - - Fit panel - - -
- Statuses
{workspaceStatuses.map((status, index) => { diff --git a/src/renderer/src/store/slices/ui.test.ts b/src/renderer/src/store/slices/ui.test.ts index c27b34ad2..dbd4c8bf8 100644 --- a/src/renderer/src/store/slices/ui.test.ts +++ b/src/renderer/src/store/slices/ui.test.ts @@ -674,30 +674,6 @@ describe('createUISlice hydratePersistedUI', () => { expect(store.getState().workspaceBoardColumnWidth).toBe(520) }) - it('hydrates workspace board column layout', () => { - const store = createUIStore() - - store.getState().hydratePersistedUI( - makePersistedUI({ - workspaceBoardColumnLayout: 'fit' - }) - ) - - expect(store.getState().workspaceBoardColumnLayout).toBe('fit') - }) - - it('defaults invalid workspace board column layout to full width', () => { - const store = createUIStore() - - store.getState().hydratePersistedUI( - makePersistedUI({ - workspaceBoardColumnLayout: 'compact' as never - }) - ) - - expect(store.getState().workspaceBoardColumnLayout).toBe('full') - }) - it('hydrates a valid Kagi session link', () => { const store = createUIStore() diff --git a/src/renderer/src/store/slices/ui.ts b/src/renderer/src/store/slices/ui.ts index 06944bbba..ad05c73b9 100644 --- a/src/renderer/src/store/slices/ui.ts +++ b/src/renderer/src/store/slices/ui.ts @@ -18,7 +18,6 @@ import type { TaskViewPresetId, TuiAgent, UpdateStatus, - WorkspaceBoardColumnLayout, WorkspaceStatusDefinition, AgentActivityDisplayMode, WorktreeCardProperty @@ -56,7 +55,6 @@ import { clampWorkspaceBoardColumnWidth, clampWorkspaceBoardOpacity, cloneDefaultWorkspaceStatuses, - normalizeWorkspaceBoardColumnLayout, normalizeWorkspaceStatuses } from '../../../../shared/workspace-statuses' import { normalizeKagiSessionLink } from '../../../../shared/browser-url' @@ -630,8 +628,6 @@ export type UISlice = { setWorkspaceStatuses: (statuses: WorkspaceStatusDefinition[]) => void workspaceBoardOpacity: number setWorkspaceBoardOpacity: (opacity: number) => void - workspaceBoardColumnLayout: WorkspaceBoardColumnLayout - setWorkspaceBoardColumnLayout: (layout: WorkspaceBoardColumnLayout) => void workspaceBoardColumnWidth: number setWorkspaceBoardColumnWidth: (width: number) => void statusBarItems: StatusBarItem[] @@ -1347,13 +1343,6 @@ export const createUISlice: StateCreator = (set, get) set({ workspaceBoardOpacity: clamped }) }, - workspaceBoardColumnLayout: 'full', - setWorkspaceBoardColumnLayout: (layout) => { - const normalized = normalizeWorkspaceBoardColumnLayout(layout) - window.api.ui.set({ workspaceBoardColumnLayout: normalized }).catch(console.error) - set({ workspaceBoardColumnLayout: normalized }) - }, - workspaceBoardColumnWidth: WORKSPACE_BOARD_COLUMN_WIDTH_DEFAULT, setWorkspaceBoardColumnWidth: (width) => { const clamped = clampWorkspaceBoardColumnWidth(width) @@ -1530,9 +1519,6 @@ export const createUISlice: StateCreator = (set, get) agentActivityDisplayMode: normalizeAgentActivityDisplayMode(ui.agentActivityDisplayMode), workspaceStatuses: normalizeWorkspaceStatuses(ui.workspaceStatuses), workspaceBoardOpacity: clampWorkspaceBoardOpacity(ui.workspaceBoardOpacity), - workspaceBoardColumnLayout: normalizeWorkspaceBoardColumnLayout( - ui.workspaceBoardColumnLayout - ), workspaceBoardColumnWidth: clampWorkspaceBoardColumnWidth(ui.workspaceBoardColumnWidth), statusBarItems, statusBarVisible: ui.statusBarVisible ?? true, diff --git a/src/shared/constants.ts b/src/shared/constants.ts index 1b1fe5f87..aeeaaf3e6 100644 --- a/src/shared/constants.ts +++ b/src/shared/constants.ts @@ -14,10 +14,7 @@ import { DEFAULT_STATUS_BAR_ITEMS } from './status-bar-defaults' import { DEFAULT_TERMINAL_FONT_WEIGHT } from './terminal-fonts' import { getDefaultTerminalQuickCommands } from './terminal-quick-commands' import type { VoiceSettings } from './speech-types' -import { - WORKSPACE_BOARD_COLUMN_LAYOUT_DEFAULT, - cloneDefaultWorkspaceStatuses -} from './workspace-statuses' +import { cloneDefaultWorkspaceStatuses } from './workspace-statuses' import { TASK_PROVIDERS } from './task-providers' import { DEFAULT_WORKTREE_CARD_PROPERTIES } from './worktree-card-properties' import { getDefaultSourceControlAiSettings } from './source-control-ai' @@ -401,7 +398,6 @@ export function getDefaultUIState(): PersistedUIState { agentActivityDisplayMode: DEFAULT_AGENT_ACTIVITY_DISPLAY_MODE, workspaceStatuses: cloneDefaultWorkspaceStatuses(), workspaceBoardOpacity: 1, - workspaceBoardColumnLayout: WORKSPACE_BOARD_COLUMN_LAYOUT_DEFAULT, workspaceBoardColumnWidth: 308, _workspaceStatusesDefaultOrderMigrated: true, _workspaceStatusesDefaultWorkflowMigrated: true, diff --git a/src/shared/types.ts b/src/shared/types.ts index 0143f8a73..e54dcaf4a 100644 --- a/src/shared/types.ts +++ b/src/shared/types.ts @@ -2417,8 +2417,6 @@ export type WorktreeCardProperty = export type AgentActivityDisplayMode = 'compact' | 'full' -export type WorkspaceBoardColumnLayout = 'full' | 'fit' - export type StatusBarItem = | 'claude' | 'codex' @@ -2479,7 +2477,6 @@ export type PersistedUIState = { agentActivityDisplayMode?: AgentActivityDisplayMode workspaceStatuses?: WorkspaceStatusDefinition[] workspaceBoardOpacity?: number - workspaceBoardColumnLayout?: WorkspaceBoardColumnLayout workspaceBoardColumnWidth?: number /** One-shot migration flag for a short-lived build that persisted the * default workspace statuses in reverse workflow order. Once stamped, diff --git a/src/shared/workspace-statuses.test.ts b/src/shared/workspace-statuses.test.ts index 2e8ae5915..ed8e8b7e5 100644 --- a/src/shared/workspace-statuses.test.ts +++ b/src/shared/workspace-statuses.test.ts @@ -5,9 +5,7 @@ import { WORKSPACE_BOARD_COLUMN_WIDTH_MIN, clampWorkspaceBoardColumnWidth, cloneDefaultWorkspaceStatuses, - fitWorkspaceBoardColumnWidth, normalizePersistedWorkspaceStatuses, - normalizeWorkspaceBoardColumnLayout, normalizeWorkspaceStatuses } from './workspace-statuses' @@ -251,34 +249,4 @@ describe('workspace status visuals', () => { expect(clampWorkspaceBoardColumnWidth(321.6)).toBe(322) expect(clampWorkspaceBoardColumnWidth(900)).toBe(WORKSPACE_BOARD_COLUMN_WIDTH_MAX) }) - - it('defaults workspace board column layout to full width', () => { - expect(normalizeWorkspaceBoardColumnLayout(undefined)).toBe('full') - expect(normalizeWorkspaceBoardColumnLayout('fit')).toBe('fit') - expect(normalizeWorkspaceBoardColumnLayout('compact')).toBe('full') - }) - - it('fits workspace board columns inside the visible panel without exceeding saved width', () => { - expect( - fitWorkspaceBoardColumnWidth({ - containerWidth: 960, - columnCount: 4, - capWidth: 308 - }) - ).toBe(231) - expect( - fitWorkspaceBoardColumnWidth({ - containerWidth: 1600, - columnCount: 4, - capWidth: 308 - }) - ).toBe(308) - expect( - fitWorkspaceBoardColumnWidth({ - containerWidth: 100, - columnCount: 4, - capWidth: 308 - }) - ).toBe(WORKSPACE_BOARD_COLUMN_WIDTH_MIN) - }) }) diff --git a/src/shared/workspace-statuses.ts b/src/shared/workspace-statuses.ts index ae144ca2b..08bc54c9e 100644 --- a/src/shared/workspace-statuses.ts +++ b/src/shared/workspace-statuses.ts @@ -1,9 +1,4 @@ -import type { - Worktree, - WorkspaceBoardColumnLayout, - WorkspaceStatus, - WorkspaceStatusDefinition -} from './types' +import type { Worktree, WorkspaceStatus, WorkspaceStatusDefinition } from './types' import { DEFAULT_STATUS_VISUALS, DEFAULT_WORKSPACE_STATUSES } from './workspace-status-defaults' import { isKnownBadPRReorderedDefaultStatusPayload, @@ -27,10 +22,6 @@ export const WORKSPACE_BOARD_COLUMN_WIDTH_DEFAULT = 308 export const WORKSPACE_BOARD_COLUMN_WIDTH_MIN = 220 export const WORKSPACE_BOARD_COLUMN_WIDTH_MAX = 520 export const WORKSPACE_BOARD_COLUMN_WIDTH_STEP = 20 -// Why: keep this aligned with the `gap-3` lane gap in WorkspaceKanbanLaneGrid; -// layout calculations need the actual rendered gap between status columns. -export const WORKSPACE_BOARD_COLUMN_GAP = 12 -export const WORKSPACE_BOARD_COLUMN_LAYOUT_DEFAULT: WorkspaceBoardColumnLayout = 'full' export const WORKSPACE_STATUS_COLOR_IDS = [ 'neutral', @@ -244,10 +235,6 @@ export function clampWorkspaceBoardOpacity(value: unknown): number { return Math.min(1, Math.max(0.2, Math.round(value * 100) / 100)) } -export function normalizeWorkspaceBoardColumnLayout(value: unknown): WorkspaceBoardColumnLayout { - return value === 'fit' ? 'fit' : WORKSPACE_BOARD_COLUMN_LAYOUT_DEFAULT -} - export function clampWorkspaceBoardColumnWidth(value: unknown): number { if (typeof value !== 'number' || !Number.isFinite(value)) { return WORKSPACE_BOARD_COLUMN_WIDTH_DEFAULT @@ -258,22 +245,6 @@ export function clampWorkspaceBoardColumnWidth(value: unknown): number { ) } -export function fitWorkspaceBoardColumnWidth(args: { - containerWidth: number - columnCount: number - capWidth: number - gap?: number -}): number { - const cap = clampWorkspaceBoardColumnWidth(args.capWidth) - if (args.columnCount <= 0 || !Number.isFinite(args.containerWidth) || args.containerWidth <= 0) { - return cap - } - const gap = args.gap ?? WORKSPACE_BOARD_COLUMN_GAP - const available = args.containerWidth - gap * Math.max(0, args.columnCount - 1) - const perColumn = Math.floor(available / args.columnCount) - return Math.min(cap, Math.max(WORKSPACE_BOARD_COLUMN_WIDTH_MIN, perColumn)) -} - export function isWorkspaceStatusId( value: string, statuses: readonly WorkspaceStatusDefinition[]