Skip to content

Commit 99759d1

Browse files
authored
🤖 fix: restore workspace name truncation in sidebar (#942)
The TooltipWrapper component added in cf61afe was missing `min-w-0` in inline mode, which broke the flex truncation chain. Long workspace names caused the sidebar to become horizontally scrollable instead of properly truncating. **Changes:** - Added `min-w-0` to TooltipWrapper inline mode to preserve truncation - Replaced flexbox with CSS Grid (`grid-cols-[auto_1fr_auto]`) for the workspace row - this guarantees the middle column truncates properly without complex nested flex chains - Added `LongWorkspaceNames` story with git status indicators to catch future truncation regressions - Default `createdAt` to `Date.now()` in mockFactory to prevent workspaces from being hidden by age filters in stories _Generated with `mux`_
1 parent 894a7ce commit 99759d1

File tree

4 files changed

+63
-7
lines changed

4 files changed

+63
-7
lines changed

src/browser/components/Tooltip.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export const TooltipWrapper: React.FC<TooltipWrapperProps> = ({ inline = false,
4646
<TooltipContext.Provider value={{ isHovered, setIsHovered, triggerRef }}>
4747
<span
4848
ref={triggerRef}
49-
className={cn("relative", inline ? "inline-flex items-center" : "block")}
49+
className={cn("relative", inline ? "inline-flex min-w-0 items-center" : "block")}
5050
onMouseEnter={handleMouseEnter}
5151
onMouseLeave={handleMouseLeave}
5252
>

src/browser/components/WorkspaceListItem.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -145,11 +145,11 @@ const WorkspaceListItemInner: React.FC<WorkspaceListItemProps> = ({
145145
data-workspace-id={workspaceId}
146146
>
147147
<div className="flex min-w-0 flex-1 flex-col gap-1">
148-
<div className="flex min-w-0 items-center gap-1.5">
148+
<div className="grid min-w-0 grid-cols-[auto_1fr_auto] items-center gap-1.5">
149149
<RuntimeBadge runtimeConfig={metadata.runtimeConfig} isWorking={canInterrupt} />
150150
{isEditing ? (
151151
<input
152-
className="bg-input-bg text-input-text border-input-border font-inherit focus:border-input-border-focus -mx-1 min-w-0 flex-1 rounded-sm border px-1 text-left text-[13px] outline-none"
152+
className="bg-input-bg text-input-text border-input-border font-inherit focus:border-input-border-focus min-w-0 rounded-sm border px-1 text-left text-[13px] outline-none"
153153
value={editingName}
154154
onChange={(e) => setEditingName(e.target.value)}
155155
onKeyDown={handleRenameKeyDown}
@@ -163,7 +163,7 @@ const WorkspaceListItemInner: React.FC<WorkspaceListItemProps> = ({
163163
<TooltipWrapper inline>
164164
<span
165165
className={cn(
166-
"text-foreground -mx-1 min-w-0 flex-1 truncate rounded-sm px-1 text-left text-[14px] transition-colors duration-200",
166+
"text-foreground block truncate text-left text-[14px] transition-colors duration-200",
167167
!isDisabled && "cursor-pointer"
168168
)}
169169
onDoubleClick={(e) => {
@@ -187,7 +187,7 @@ const WorkspaceListItemInner: React.FC<WorkspaceListItemProps> = ({
187187
</TooltipWrapper>
188188
)}
189189

190-
<div className="ml-auto flex items-center gap-1">
190+
<div className="flex items-center gap-1">
191191
{!isCreating && (
192192
<>
193193
<GitStatusIndicator
@@ -199,7 +199,7 @@ const WorkspaceListItemInner: React.FC<WorkspaceListItemProps> = ({
199199

200200
<TooltipWrapper inline>
201201
<button
202-
className="text-muted hover:text-foreground col-start-1 flex h-5 w-5 shrink-0 cursor-pointer items-center justify-center border-none bg-transparent p-0 text-base opacity-0 transition-all duration-200 hover:rounded-sm hover:bg-white/10"
202+
className="text-muted hover:text-foreground flex h-5 w-5 cursor-pointer items-center justify-center border-none bg-transparent p-0 text-base opacity-0 transition-all duration-200 hover:rounded-sm hover:bg-white/10"
203203
onClick={(e) => {
204204
e.stopPropagation();
205205
void onRemoveWorkspace(workspaceId, e.currentTarget);

src/browser/stories/App.sidebar.stories.tsx

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,61 @@ export const ManyWorkspaces: AppStory = {
141141
),
142142
};
143143

144+
/** Long workspace names - tests truncation and prevents horizontal scroll regression */
145+
export const LongWorkspaceNames: AppStory = {
146+
render: () => (
147+
<AppWithMocks
148+
setup={() => {
149+
const workspaces = [
150+
createWorkspace({
151+
id: "ws-short",
152+
name: "main",
153+
projectName: "my-app",
154+
}),
155+
createWorkspace({
156+
id: "ws-medium",
157+
name: "feature/user-authentication",
158+
projectName: "my-app",
159+
}),
160+
createWorkspace({
161+
id: "ws-long",
162+
name: "feature/implement-oauth2-authentication-with-google-provider",
163+
projectName: "my-app",
164+
}),
165+
createWorkspace({
166+
id: "ws-very-long",
167+
name: "bugfix/fix-critical-memory-leak-in-websocket-connection-handler-that-causes-oom",
168+
projectName: "my-app",
169+
}),
170+
createSSHWorkspace({
171+
id: "ws-ssh-long",
172+
name: "deploy/production-kubernetes-cluster-rolling-update-with-zero-downtime",
173+
projectName: "my-app",
174+
host: "very-long-hostname.internal.company-infrastructure.example.com",
175+
}),
176+
];
177+
178+
// Set up git status to verify GitStatusIndicator remains visible
179+
const gitStatus = new Map<string, GitStatusFixture>([
180+
["ws-short", { ahead: 1 }],
181+
["ws-medium", { dirty: 3 }],
182+
["ws-long", { ahead: 2, behind: 1 }],
183+
["ws-very-long", { dirty: 5, ahead: 3 }],
184+
["ws-ssh-long", { behind: 2 }],
185+
]);
186+
187+
expandProjects(["/home/user/projects/my-app"]);
188+
189+
return createMockORPCClient({
190+
projects: groupWorkspacesByProject(workspaces),
191+
workspaces,
192+
executeBash: createGitStatusExecutor(gitStatus),
193+
});
194+
}}
195+
/>
196+
),
197+
};
198+
144199
/** All git status indicator variations */
145200
export const GitStatusVariations: AppStory = {
146201
render: () => (

src/browser/stories/mockFactory.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ export function createWorkspace(
5858
projectName: opts.projectName,
5959
namedWorkspacePath: `/home/user/.mux/src/${opts.projectName}/${safeName}`,
6060
runtimeConfig: opts.runtimeConfig ?? DEFAULT_RUNTIME_CONFIG,
61-
createdAt: opts.createdAt,
61+
// Default to current time so workspaces aren't filtered as "old" by age-based UI
62+
createdAt: opts.createdAt ?? new Date().toISOString(),
6263
};
6364
}
6465

0 commit comments

Comments
 (0)