Skip to content

Commit cb882ad

Browse files
authored
improvement(sidebar): allow dragging the sidebar slightly narrower than the default (#7820)
* improvement(sidebar): allow dragging the sidebar slightly narrower than the default * fix(sidebar): clamp the default width fallback to the viewport maximum
1 parent d21b6e8 commit cb882ad

6 files changed

Lines changed: 36 additions & 11 deletions

File tree

‎apps/sim/app/layout.tsx‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
120120
}
121121
122122
// Sidebar width. Mirror getMaxSidebarWidth() in stores/sidebar/store.ts:
123-
// 30% of the viewport capped at 400px, and never below the 256px
123+
// 30% of the viewport capped at 400px, and never below the 224px
124124
// minimum, so a narrow window yields a width >= MIN instead of a
125125
// sub-minimum sliver.
126126
var defaultSidebarWidth = 256;
@@ -149,11 +149,11 @@ export default function RootLayout({ children }: { children: React.ReactNode })
149149
// collapsed, because the desktop hover-peek renders the sidebar at
150150
// its restore width while --sidebar-width still reads collapsed.
151151
var width = state && state.sidebarWidth;
152-
var maxSidebarWidth = Math.max(256, Math.min(400, window.innerWidth * 0.3));
152+
var maxSidebarWidth = Math.max(224, Math.min(400, window.innerWidth * 0.3));
153153
var expandedWidth =
154154
typeof width === 'number' && isFinite(width)
155-
? Math.min(Math.max(width, 256), maxSidebarWidth)
156-
: defaultSidebarWidth;
155+
? Math.min(Math.max(width, 224), maxSidebarWidth)
156+
: Math.min(defaultSidebarWidth, maxSidebarWidth);
157157
document.documentElement.style.setProperty(
158158
'--sidebar-expanded-width',
159159
expandedWidth + 'px'

‎apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workflow-list/components/workflow-item/avatars/avatars.tsx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ export function Avatars({ workflowId }: AvatarsProps) {
3333

3434
/**
3535
* Scale the max visible avatars between MIN_COUNT and MAX_COUNT as the sidebar
36-
* widens.
36+
* widens past its default width.
3737
*/
3838
const maxVisible = useMemo(() => {
39-
const widthDelta = sidebarWidth - SIDEBAR_WIDTH.MIN
39+
const widthDelta = sidebarWidth - SIDEBAR_WIDTH.DEFAULT
4040
const additionalAvatars = Math.floor(widthDelta / AVATAR_CONFIG.WIDTH_PER_AVATAR)
4141
const calculated = AVATAR_CONFIG.MIN_COUNT + additionalAvatars
4242
return Math.max(AVATAR_CONFIG.MIN_COUNT, Math.min(AVATAR_CONFIG.MAX_COUNT, calculated))

‎apps/sim/app/workspace/[workspaceId]/w/components/sidebar/sidebar.tsx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -824,7 +824,7 @@ export const Sidebar = memo(function Sidebar() {
824824

825825
const handleOpenSettings = (section: SettingsSection) => {
826826
if (!isCollapsedRef.current) {
827-
setSidebarWidth(SIDEBAR_WIDTH.MIN)
827+
setSidebarWidth(SIDEBAR_WIDTH.DEFAULT)
828828
}
829829
navigateToSettings({ section })
830830
}
@@ -898,7 +898,7 @@ export const Sidebar = memo(function Sidebar() {
898898
const navigateToPage = useCallback(
899899
(path: string) => {
900900
if (!isCollapsedRef.current) {
901-
setSidebarWidth(SIDEBAR_WIDTH.MIN)
901+
setSidebarWidth(SIDEBAR_WIDTH.DEFAULT)
902902
}
903903
router.push(path)
904904
},

‎apps/sim/stores/constants.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ export const CONTENT_WINDOW_GAP = 0
2929
/** Sidebar width constraints */
3030
export const SIDEBAR_WIDTH = {
3131
DEFAULT: 256,
32-
MIN: 256,
32+
/** Narrowest the expanded rail can be dragged — slightly under the default */
33+
MIN: 224,
3334
/** Width when sidebar is collapsed to icon-only mode */
3435
COLLAPSED: 48,
3536
/**

‎apps/sim/stores/sidebar/store.test.ts‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,15 @@ describe('sidebar width CSS variables', () => {
5454
expect(widthVars()).toEqual({ width: '300px', expanded: '300px' })
5555
})
5656

57+
it('allows narrowing below the default down to the minimum', () => {
58+
useSidebarStore.getState().setSidebarWidth(SIDEBAR_WIDTH.MIN)
59+
expect(useSidebarStore.getState().sidebarWidth).toBe(SIDEBAR_WIDTH.MIN)
60+
expect(SIDEBAR_WIDTH.MIN).toBeLessThan(SIDEBAR_WIDTH.DEFAULT)
61+
62+
useSidebarStore.getState().setSidebarWidth(SIDEBAR_WIDTH.MIN - 1)
63+
expect(useSidebarStore.getState().sidebarWidth).toBe(SIDEBAR_WIDTH.MIN)
64+
})
65+
5766
it('keeps the expanded variable at the restore width while collapsed', () => {
5867
useSidebarStore.getState().setSidebarWidth(300)
5968
useSidebarStore.getState().toggleCollapsed()
@@ -93,6 +102,21 @@ describe('sidebar width CSS variables', () => {
93102

94103
expect(widthVars().expanded).toBe(`${SIDEBAR_WIDTH.MIN}px`)
95104
})
105+
106+
it('clamps the default fallback to a viewport maximum below the default', () => {
107+
const innerWidth = window.innerWidth
108+
window.innerWidth = 800
109+
try {
110+
useSidebarStore.setState({ isCollapsed: false, sidebarWidth: Number.NaN })
111+
112+
useSidebarStore.getState().syncWidth()
113+
114+
expect(widthVars().expanded).toBe(`${getMaxSidebarWidth(800)}px`)
115+
expect(getMaxSidebarWidth(800)).toBeLessThan(SIDEBAR_WIDTH.DEFAULT)
116+
} finally {
117+
window.innerWidth = innerWidth
118+
}
119+
})
96120
})
97121

98122
describe('getMaxSidebarWidth', () => {

‎apps/sim/stores/sidebar/store.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ export function getMaxSidebarWidth(viewportWidth: number): number {
2121

2222
/** Clamps an expanded sidebar width into the valid range for the current viewport. */
2323
function clampSidebarWidth(width: number): number {
24-
if (!Number.isFinite(width)) return SIDEBAR_WIDTH.DEFAULT
24+
const target = Number.isFinite(width) ? width : SIDEBAR_WIDTH.DEFAULT
2525
const max =
2626
typeof window === 'undefined' ? Number.POSITIVE_INFINITY : getMaxSidebarWidth(window.innerWidth)
27-
return Math.min(Math.max(width, SIDEBAR_WIDTH.MIN), max)
27+
return Math.min(Math.max(target, SIDEBAR_WIDTH.MIN), max)
2828
}
2929

3030
/**

0 commit comments

Comments
 (0)