MCPcopy
hub / github.com/coder/mux / WorkspaceShell

Function WorkspaceShell

src/browser/components/WorkspaceShell/WorkspaceShell.tsx:106–272  ·  view source on GitHub ↗
(props)

Source from the content-addressed store, hash-verified

104);
105
106export const WorkspaceShell: React.FC<WorkspaceShellProps> = (props) => {
107 const shellRef = useRef<HTMLDivElement>(null);
108 const shellSize = useResizeObserver(shellRef);
109
110 // WorkspaceShell switches to flex-col at this breakpoint, so in that stacked mode the
111 // right sidebar doesn't need to "leave room" for ChatPane beside it.
112 const isStacked =
113 typeof window !== "undefined" && window.matchMedia("(max-width: 768px)").matches;
114
115 const [persistedLeftSidebarWidthPx] = usePersistedState<unknown>(
116 LEFT_SIDEBAR_WIDTH_KEY,
117 LEFT_SIDEBAR_DEFAULT_WIDTH_PX,
118 { listener: true }
119 );
120 const containerWidthPx = shellSize?.width ?? 0;
121 // Before ResizeObserver reports the real shell width, estimate it from the persisted left
122 // sidebar width so a wide right sidebar doesn't first paint at a viewport-wide clamp and
123 // then visibly snap narrower once the shell is measured.
124 const usableWidthPx =
125 containerWidthPx > 0
126 ? containerWidthPx
127 : estimateWorkspaceShellFallbackWidthPx({
128 viewportWidthPx: typeof window !== "undefined" ? window.innerWidth : 1200,
129 isStacked,
130 leftSidebarCollapsed: props.leftSidebarCollapsed,
131 persistedLeftSidebarWidthPx,
132 });
133
134 // Prevent ChatPane + RightSidebar from overflowing the workspace shell (which would show a
135 // horizontal scrollbar due to WorkspaceShell's `overflow-x-auto`).
136 const effectiveMaxWidthPx = isStacked
137 ? RIGHT_SIDEBAR_ABS_MAX_WIDTH_PX
138 : Math.min(
139 RIGHT_SIDEBAR_ABS_MAX_WIDTH_PX,
140 Math.max(
141 RIGHT_SIDEBAR_MIN_WIDTH_PX,
142 usableWidthPx - CHAT_PANE_MIN_WIDTH_PX - RIGHT_SIDEBAR_OVERFLOW_GUARD_PX
143 )
144 );
145
146 const sidebar = useResizableSidebar({
147 enabled: true,
148 defaultWidth: RIGHT_SIDEBAR_DEFAULT_WIDTH_PX,
149 minWidth: RIGHT_SIDEBAR_MIN_WIDTH_PX,
150 maxWidth: effectiveMaxWidthPx,
151 storageKey: RIGHT_SIDEBAR_WIDTH_KEY,
152 });
153
154 const { width: sidebarWidth, isResizing, startResize } = sidebar;
155 const addTerminalRef = useRef<((options?: TerminalSessionCreateOptions) => void) | null>(null);
156 const openTerminalPopout = useOpenTerminal();
157 const handleOpenTerminal = useCallback(
158 (options?: TerminalSessionCreateOptions) => {
159 // On mobile touch devices, always use popout since the right sidebar is hidden
160 const isMobileTouch = window.matchMedia("(max-width: 768px) and (pointer: coarse)").matches;
161 if (isMobileTouch) {
162 void openTerminalPopout(props.workspaceId, props.runtimeConfig, options);
163 } else {

Callers

nothing calls this directly

Calls 11

useResizeObserverFunction · 0.90
usePersistedStateFunction · 0.90
useResizableSidebarFunction · 0.90
useOpenTerminalFunction · 0.90
useReviewsFunction · 0.90
useWorkspaceShellStatusFunction · 0.90
getReviewImmersiveKeyFunction · 0.90
useBackgroundBashErrorFunction · 0.90
cnFunction · 0.90
openTerminalPopoutFunction · 0.85

Tested by

no test coverage detected