From bbd2660d078edc630de6d5bbc209c8e4d6d6c82f Mon Sep 17 00:00:00 2001 From: samuelswandi Date: Tue, 3 Feb 2026 23:37:47 -0800 Subject: [PATCH 1/3] fix(ui): add cursor-pointer to all buttons globally Instead of adding cursor-pointer to individual button classNames, set cursor: pointer on all button and [role="button"] elements via a single global CSS rule in globals.css. Also removes the now-redundant cursor-pointer class from the shared Button component. Co-authored-by: samuelswandi --- apps/desktop/src/renderer/globals.css | 5 +++++ packages/ui/src/components/ui/button.tsx | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/desktop/src/renderer/globals.css b/apps/desktop/src/renderer/globals.css index 091cacc724a..db9135ed702 100644 --- a/apps/desktop/src/renderer/globals.css +++ b/apps/desktop/src/renderer/globals.css @@ -135,6 +135,11 @@ @apply border-border antialiased; } + button, + [role="button"] { + cursor: pointer; + } + body { @apply bg-background text-foreground; } diff --git a/packages/ui/src/components/ui/button.tsx b/packages/ui/src/components/ui/button.tsx index a2fe30dbf5b..50dea30cf63 100644 --- a/packages/ui/src/components/ui/button.tsx +++ b/packages/ui/src/components/ui/button.tsx @@ -5,7 +5,7 @@ import type * as React from "react"; import { cn } from "../../lib/utils"; const buttonVariants = cva( - "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all cursor-pointer disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", { variants: { variant: { From 74216e99f80cf7d7da101f440f2befc330e3965e Mon Sep 17 00:00:00 2001 From: Kiet Ho Date: Wed, 4 Feb 2026 07:58:59 -0800 Subject: [PATCH 2/3] Fix lint --- .../routers/workspaces/procedures/status.ts | 5 +- .../TabsContent/Terminal/helpers.test.ts | 17 +- .../components/CommitInput/CommitInput.tsx | 6 +- .../RightSidebar/FilesView/FilesView.tsx | 156 +++++++++--------- 4 files changed, 96 insertions(+), 88 deletions(-) diff --git a/apps/desktop/src/lib/trpc/routers/workspaces/procedures/status.ts b/apps/desktop/src/lib/trpc/routers/workspaces/procedures/status.ts index d1eebab62d2..022713f31aa 100644 --- a/apps/desktop/src/lib/trpc/routers/workspaces/procedures/status.ts +++ b/apps/desktop/src/lib/trpc/routers/workspaces/procedures/status.ts @@ -78,7 +78,10 @@ export const createStatusProcedures = () => { const resolveIsUnnamed = () => { if (input.patch.isUnnamed !== undefined) return input.patch.isUnnamed; - if (input.patch.name !== undefined && !input.patch.preserveUnnamedStatus) + if ( + input.patch.name !== undefined && + !input.patch.preserveUnnamedStatus + ) return false; return undefined; }; diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.test.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.test.ts index 86531fc43a4..d5ef7f6bdee 100644 --- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.test.ts +++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.test.ts @@ -1,5 +1,5 @@ -import type { Terminal as XTerm } from "@xterm/xterm"; import { afterEach, beforeEach, describe, expect, it, mock } from "bun:test"; +import type { Terminal as XTerm } from "@xterm/xterm"; // Mock localStorage for Node.js test environment const mockStorage = new Map(); @@ -31,11 +31,8 @@ mock.module("renderer/lib/trpc-client", () => ({ })); // Import after mocks are set up -const { - getDefaultTerminalBg, - getDefaultTerminalTheme, - setupKeyboardHandler, -} = await import("./helpers"); +const { getDefaultTerminalBg, getDefaultTerminalTheme, setupKeyboardHandler } = + await import("./helpers"); describe("getDefaultTerminalTheme", () => { beforeEach(() => { @@ -127,7 +124,9 @@ describe("setupKeyboardHandler", () => { let handler: ((event: KeyboardEvent) => boolean) | null = null; const xterm = { - attachCustomKeyEventHandler: (next: (event: KeyboardEvent) => boolean) => { + attachCustomKeyEventHandler: ( + next: (event: KeyboardEvent) => boolean, + ) => { handler = next; }, }; @@ -162,7 +161,9 @@ describe("setupKeyboardHandler", () => { let handler: ((event: KeyboardEvent) => boolean) | null = null; const xterm = { - attachCustomKeyEventHandler: (next: (event: KeyboardEvent) => boolean) => { + attachCustomKeyEventHandler: ( + next: (event: KeyboardEvent) => boolean, + ) => { handler = next; }, }; diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/CommitInput/CommitInput.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/CommitInput/CommitInput.tsx index c554f312ac2..76d8891bd70 100644 --- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/CommitInput/CommitInput.tsx +++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/CommitInput/CommitInput.tsx @@ -234,7 +234,11 @@ export function CommitInput({ onChange={(e) => setCommitMessage(e.target.value)} className="min-h-[52px] resize-none text-[10px] bg-background" onKeyDown={(e) => { - if (e.key === "Enter" && (e.metaKey || e.ctrlKey) && !primary.disabled) { + if ( + e.key === "Enter" && + (e.metaKey || e.ctrlKey) && + !primary.disabled + ) { e.preventDefault(); primary.handler(); } diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/FilesView/FilesView.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/FilesView/FilesView.tsx index 4d368c302d3..00c5a1c5cc1 100644 --- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/FilesView/FilesView.tsx +++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/FilesView/FilesView.tsx @@ -295,73 +295,30 @@ export function FilesView() {
- {newItemMode && newItemParentPath === worktreePath && ( - - )} - - {isSearching ? ( - searchResultEntries.length > 0 ? ( -
- {searchResultEntries.map((entry) => - renameEntry?.path === entry.path ? ( - - ) : ( - - ), - )} -
- ) : ( -
- {isSearchFetching - ? "Searching files..." - : "No matching files"} -
- ) - ) : ( -
- {tree.getItems().map((item) => { - const data = item.getItemData(); - if (!data || item.getId() === "root") return null; - const showNewItemInput = - newItemMode && - data.isDirectory && - data.path === newItemParentPath; - const isRenaming = renameEntry?.path === data.path; - return ( -
- {isRenaming ? ( + {newItemMode && newItemParentPath === worktreePath && ( + + )} + + {isSearching ? ( + searchResultEntries.length > 0 ? ( +
+ {searchResultEntries.map((entry) => + renameEntry?.path === entry.path ? ( ) : ( - - )} - {showNewItemInput && ( - - )} -
- ); - })} -
- )} -
+ ), + )} +
+ ) : ( +
+ {isSearchFetching + ? "Searching files..." + : "No matching files"} +
+ ) + ) : ( +
+ {tree.getItems().map((item) => { + const data = item.getItemData(); + if (!data || item.getId() === "root") return null; + const showNewItemInput = + newItemMode && + data.isDirectory && + data.path === newItemParentPath; + const isRenaming = renameEntry?.path === data.path; + return ( +
+ {isRenaming ? ( + + ) : ( + + )} + {showNewItemInput && ( + + )} +
+ ); + })} +
+ )} +
handleNewFile(worktreePath)}> From a077ff4133b44acb42ffc0fb016027e7f81cd263 Mon Sep 17 00:00:00 2001 From: Kiet Ho Date: Wed, 4 Feb 2026 08:05:18 -0800 Subject: [PATCH 3/3] fix(desktop): resolve typecheck errors in slug check and terminal tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix property access on checkSlug response (available → status) and resolve TypeScript control flow narrowing issue in terminal handler tests. --- .../components/SlugDialog/SlugDialog.tsx | 2 +- .../routes/create-organization/page.tsx | 2 +- .../TabsContent/Terminal/helpers.test.ts | 21 +++++++++++-------- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/apps/desktop/src/renderer/routes/_authenticated/settings/organization/components/OrganizationSettings/components/SlugDialog/SlugDialog.tsx b/apps/desktop/src/renderer/routes/_authenticated/settings/organization/components/OrganizationSettings/components/SlugDialog/SlugDialog.tsx index f638d3e299d..bb4675949a2 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/settings/organization/components/OrganizationSettings/components/SlugDialog/SlugDialog.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/settings/organization/components/OrganizationSettings/components/SlugDialog/SlugDialog.tsx @@ -90,7 +90,7 @@ export function SlugDialog({ slug: slugValue, }); - setSlugAvailable(result.data?.available ?? null); + setSlugAvailable(result.data?.status ?? null); } catch (error) { console.error("[slug-dialog] Slug check failed:", error); setSlugAvailable(null); diff --git a/apps/desktop/src/renderer/routes/create-organization/page.tsx b/apps/desktop/src/renderer/routes/create-organization/page.tsx index d31ffb59a5b..d8ece12f0dc 100644 --- a/apps/desktop/src/renderer/routes/create-organization/page.tsx +++ b/apps/desktop/src/renderer/routes/create-organization/page.tsx @@ -86,7 +86,7 @@ export function CreateOrganization() { slug: slugValue, }); - setSlugAvailable(result.data?.available ?? null); + setSlugAvailable(result.data?.status ?? null); } catch (error) { console.error("[create-org] Slug check failed:", error); setSlugAvailable(null); diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.test.ts b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.test.ts index d5ef7f6bdee..1240c612aeb 100644 --- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.test.ts +++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.test.ts @@ -114,7 +114,6 @@ describe("setupKeyboardHandler", () => { afterEach(() => { // Restore navigator between tests - // @ts-expect-error - resetting global navigator for tests globalThis.navigator = originalNavigator; }); @@ -122,19 +121,21 @@ describe("setupKeyboardHandler", () => { // @ts-expect-error - mocking navigator for tests globalThis.navigator = { platform: "MacIntel" }; - let handler: ((event: KeyboardEvent) => boolean) | null = null; + const captured: { handler: ((event: KeyboardEvent) => boolean) | null } = { + handler: null, + }; const xterm = { attachCustomKeyEventHandler: ( next: (event: KeyboardEvent) => boolean, ) => { - handler = next; + captured.handler = next; }, }; const onWrite = mock(() => {}); setupKeyboardHandler(xterm as unknown as XTerm, { onWrite }); - handler?.({ + captured.handler?.({ type: "keydown", key: "ArrowLeft", altKey: true, @@ -142,7 +143,7 @@ describe("setupKeyboardHandler", () => { ctrlKey: false, shiftKey: false, } as KeyboardEvent); - handler?.({ + captured.handler?.({ type: "keydown", key: "ArrowRight", altKey: true, @@ -159,19 +160,21 @@ describe("setupKeyboardHandler", () => { // @ts-expect-error - mocking navigator for tests globalThis.navigator = { platform: "Win32" }; - let handler: ((event: KeyboardEvent) => boolean) | null = null; + const captured: { handler: ((event: KeyboardEvent) => boolean) | null } = { + handler: null, + }; const xterm = { attachCustomKeyEventHandler: ( next: (event: KeyboardEvent) => boolean, ) => { - handler = next; + captured.handler = next; }, }; const onWrite = mock(() => {}); setupKeyboardHandler(xterm as unknown as XTerm, { onWrite }); - handler?.({ + captured.handler?.({ type: "keydown", key: "ArrowLeft", altKey: false, @@ -179,7 +182,7 @@ describe("setupKeyboardHandler", () => { ctrlKey: true, shiftKey: false, } as KeyboardEvent); - handler?.({ + captured.handler?.({ type: "keydown", key: "ArrowRight", altKey: false,