From e3bb924af36211d3bb9510f370231786db8537a3 Mon Sep 17 00:00:00 2001 From: Kiet Ho Date: Thu, 23 Apr 2026 18:07:13 -0700 Subject: [PATCH 1/3] feat(desktop): show PR state as sidebar workspace icon Replace the host-type icon in the v2 dashboard sidebar with a PR state icon (open/merged/closed/draft), colored by state, when a workspace has an associated pull request. Clicking the icon opens the PR on GitHub. Drop the now-redundant bottom-right PR badge, and make the diff stats only colorize when the workspace is active. --- .../DashboardSidebarExpandedWorkspaceRow.tsx | 104 +++++++++++------- .../DashboardSidebarWorkspaceDiffStats.tsx | 15 ++- .../DashboardSidebarWorkspaceIcon.tsx | 44 +++++++- 3 files changed, 113 insertions(+), 50 deletions(-) diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx index 058c6d27f02..a441a573ac8 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx @@ -10,12 +10,12 @@ import { import { HiMiniXMark } from "react-icons/hi2"; import type { DiffStats } from "renderer/hooks/host-service/useDiffStats"; import { HotkeyLabel } from "renderer/hotkeys"; +import { electronTrpc } from "renderer/lib/electron-trpc"; import { RenameInput } from "renderer/screens/main/components/WorkspaceSidebar/RenameInput"; import type { DashboardSidebarWorkspace } from "../../../../types"; import { getCreationStatusText } from "../../utils/getCreationStatusText"; import { DashboardSidebarWorkspaceDiffStats } from "../DashboardSidebarWorkspaceDiffStats"; import { DashboardSidebarWorkspaceIcon } from "../DashboardSidebarWorkspaceIcon"; -import { DashboardSidebarWorkspaceStatusBadge } from "../DashboardSidebarWorkspaceStatusBadge"; interface DashboardSidebarExpandedWorkspaceRowProps extends ComponentPropsWithoutRef<"div"> { @@ -67,6 +67,7 @@ export const DashboardSidebarExpandedWorkspaceRow = forwardRef< } = workspace; const showsStandaloneActiveStripe = accentColor == null; const localRef = useRef(null); + const openUrl = electronTrpc.external.openUrl.useMutation(); useEffect(() => { if (isActive) { @@ -120,36 +121,72 @@ export const DashboardSidebarExpandedWorkspaceRow = forwardRef< -
- -
+ {pullRequest ? ( + + ) : ( +
+ +
+ )}
-

- {hostType === "local-device" - ? "Local workspace" - : hostType === "remote-device" - ? hostIsOnline === false - ? "Remote workspace — device offline" - : "Remote workspace" - : "Cloud workspace"} -

-

- {hostType === "local-device" - ? "Running on this device" - : hostType === "remote-device" - ? hostIsOnline === false - ? "The associated device isn't reachable right now" - : "Running on a paired device" - : "Hosted in the cloud"} -

+ {pullRequest ? ( + <> +

+ PR #{pullRequest.number} — {pullRequest.state} +

+

+ Click to open on GitHub +

+ + ) : ( + <> +

+ {hostType === "local-device" + ? "Local workspace" + : hostType === "remote-device" + ? hostIsOnline === false + ? "Remote workspace — device offline" + : "Remote workspace" + : "Cloud workspace"} +

+

+ {hostType === "local-device" + ? "Running on this device" + : hostType === "remote-device" + ? hostIsOnline === false + ? "The associated device isn't reachable right now" + : "Running on a paired device" + : "Hosted in the cloud"} +

+ + )}
@@ -233,15 +270,6 @@ export const DashboardSidebarExpandedWorkspaceRow = forwardRef< {branch} - - {pullRequest && ( - - )} diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceDiffStats/DashboardSidebarWorkspaceDiffStats.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceDiffStats/DashboardSidebarWorkspaceDiffStats.tsx index 06d431aa2c9..f6ca2c3861f 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceDiffStats/DashboardSidebarWorkspaceDiffStats.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceDiffStats/DashboardSidebarWorkspaceDiffStats.tsx @@ -1,5 +1,3 @@ -import { cn } from "@superset/ui/utils"; - interface DashboardSidebarWorkspaceDiffStatsProps { additions: number; deletions: number; @@ -13,14 +11,15 @@ export function DashboardSidebarWorkspaceDiffStats({ }: DashboardSidebarWorkspaceDiffStatsProps) { return (
- +{additions} - −{deletions} + + +{additions} + + + −{deletions} +
); diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceIcon/DashboardSidebarWorkspaceIcon.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceIcon/DashboardSidebarWorkspaceIcon.tsx index fb9df6f6d4f..2b74ccb6432 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceIcon/DashboardSidebarWorkspaceIcon.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceIcon/DashboardSidebarWorkspaceIcon.tsx @@ -1,10 +1,20 @@ import { cn } from "@superset/ui/utils"; import { HiExclamationTriangle } from "react-icons/hi2"; -import { LuCloud, LuCloudOff } from "react-icons/lu"; +import { + LuCircleDot, + LuCloud, + LuCloudOff, + LuGitMerge, + LuGitPullRequest, + LuGitPullRequestDraft, +} from "react-icons/lu"; import { AsciiSpinner } from "renderer/screens/main/components/AsciiSpinner"; import { StatusIndicator } from "renderer/screens/main/components/StatusIndicator"; import type { ActivePaneStatus } from "shared/tabs-types"; -import type { DashboardSidebarWorkspaceHostType } from "../../../../types"; +import type { + DashboardSidebarWorkspaceHostType, + DashboardSidebarWorkspacePullRequest, +} from "../../../../types"; interface DashboardSidebarWorkspaceIconProps { hostType: DashboardSidebarWorkspaceHostType; @@ -13,6 +23,7 @@ interface DashboardSidebarWorkspaceIconProps { variant: "collapsed" | "expanded"; workspaceStatus?: ActivePaneStatus | null; creationStatus?: "preparing" | "generating-branch" | "creating" | "failed"; + pullRequestState?: DashboardSidebarWorkspacePullRequest["state"] | null; } const OVERLAY_POSITION = { @@ -20,6 +31,20 @@ const OVERLAY_POSITION = { expanded: "-top-0.5 -right-0.5", } as const; +const PR_ICON_BY_STATE = { + open: LuGitPullRequest, + merged: LuGitMerge, + closed: LuCircleDot, + draft: LuGitPullRequestDraft, +} as const; + +const PR_COLOR_BY_STATE = { + open: "text-emerald-500", + merged: "text-purple-500", + closed: "text-destructive", + draft: "text-muted-foreground", +} as const; + export function DashboardSidebarWorkspaceIcon({ hostType, hostIsOnline, @@ -27,13 +52,24 @@ export function DashboardSidebarWorkspaceIcon({ variant, workspaceStatus = null, creationStatus, + pullRequestState = null, }: DashboardSidebarWorkspaceIconProps) { const overlayPosition = OVERLAY_POSITION[variant]; const iconColor = isActive ? "text-foreground" : "text-muted-foreground"; const isRemoteDeviceOffline = hostType === "remote-device" && hostIsOnline === false; - const renderHostIcon = () => { + const renderPrimaryIcon = () => { + if (pullRequestState) { + const PrIcon = PR_ICON_BY_STATE[pullRequestState]; + return ( + + ); + } + if (hostType === "local-device") { return ( ) : ( - renderHostIcon() + renderPrimaryIcon() )} {workspaceStatus && workspaceStatus !== "working" && ( From 5443909b74b97a0e677be09df081f85eafa41915 Mon Sep 17 00:00:00 2001 From: Kiet Ho Date: Thu, 23 Apr 2026 18:17:11 -0700 Subject: [PATCH 2/3] fix(desktop): address PR review comments on sidebar PR icon - Stop keydown propagation on the PR icon button so keyboard activation (Enter/Space) does not also trigger the parent row's workspace click. - Use hover:bg-foreground/10 on the PR icon button so hover is visible even when the row is active (which already has bg-muted). - Humanize PR state in the icon tooltip (Open/Merged/Closed/Draft). - Drop the stale rounded class from the diff-stats container now that its background is gone. - Use LuGitPullRequestClosed instead of LuCircleDot for closed PRs. --- .../DashboardSidebarExpandedWorkspaceRow.tsx | 24 ++++++++++++++++--- .../DashboardSidebarWorkspaceDiffStats.tsx | 2 +- .../DashboardSidebarWorkspaceIcon.tsx | 4 ++-- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx index a441a573ac8..f268426407f 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx @@ -12,11 +12,24 @@ import type { DiffStats } from "renderer/hooks/host-service/useDiffStats"; import { HotkeyLabel } from "renderer/hotkeys"; import { electronTrpc } from "renderer/lib/electron-trpc"; import { RenameInput } from "renderer/screens/main/components/WorkspaceSidebar/RenameInput"; -import type { DashboardSidebarWorkspace } from "../../../../types"; +import type { + DashboardSidebarWorkspace, + DashboardSidebarWorkspacePullRequest, +} from "../../../../types"; import { getCreationStatusText } from "../../utils/getCreationStatusText"; import { DashboardSidebarWorkspaceDiffStats } from "../DashboardSidebarWorkspaceDiffStats"; import { DashboardSidebarWorkspaceIcon } from "../DashboardSidebarWorkspaceIcon"; +const PR_STATE_LABEL: Record< + DashboardSidebarWorkspacePullRequest["state"], + string +> = { + open: "Open", + merged: "Merged", + closed: "Closed", + draft: "Draft", +}; + interface DashboardSidebarExpandedWorkspaceRowProps extends ComponentPropsWithoutRef<"div"> { workspace: DashboardSidebarWorkspace; @@ -128,8 +141,13 @@ export const DashboardSidebarExpandedWorkspaceRow = forwardRef< event.stopPropagation(); openUrl.mutate(pullRequest.url); }} + onKeyDown={(event) => { + if (event.key === "Enter" || event.key === " ") { + event.stopPropagation(); + } + }} aria-label={`Open pull request #${pullRequest.number}`} - className="relative mr-2.5 flex size-5 shrink-0 cursor-pointer items-center justify-center rounded hover:bg-muted" + className="relative mr-2.5 flex size-5 shrink-0 cursor-pointer items-center justify-center rounded hover:bg-foreground/10" >

- PR #{pullRequest.number} — {pullRequest.state} + PR #{pullRequest.number} — {PR_STATE_LABEL[pullRequest.state]}

Click to open on GitHub diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceDiffStats/DashboardSidebarWorkspaceDiffStats.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceDiffStats/DashboardSidebarWorkspaceDiffStats.tsx index f6ca2c3861f..aeb04771f3a 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceDiffStats/DashboardSidebarWorkspaceDiffStats.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceDiffStats/DashboardSidebarWorkspaceDiffStats.tsx @@ -11,7 +11,7 @@ export function DashboardSidebarWorkspaceDiffStats({ }: DashboardSidebarWorkspaceDiffStatsProps) { return (

diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceIcon/DashboardSidebarWorkspaceIcon.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceIcon/DashboardSidebarWorkspaceIcon.tsx index 2b74ccb6432..91f64d61b4e 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceIcon/DashboardSidebarWorkspaceIcon.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceIcon/DashboardSidebarWorkspaceIcon.tsx @@ -1,11 +1,11 @@ import { cn } from "@superset/ui/utils"; import { HiExclamationTriangle } from "react-icons/hi2"; import { - LuCircleDot, LuCloud, LuCloudOff, LuGitMerge, LuGitPullRequest, + LuGitPullRequestClosed, LuGitPullRequestDraft, } from "react-icons/lu"; import { AsciiSpinner } from "renderer/screens/main/components/AsciiSpinner"; @@ -34,7 +34,7 @@ const OVERLAY_POSITION = { const PR_ICON_BY_STATE = { open: LuGitPullRequest, merged: LuGitMerge, - closed: LuCircleDot, + closed: LuGitPullRequestClosed, draft: LuGitPullRequestDraft, } as const; From 59559284ee84b2abe16d92497f75af2aad526eda Mon Sep 17 00:00:00 2001 From: Kiet Ho Date: Thu, 23 Apr 2026 18:30:27 -0700 Subject: [PATCH 3/3] chore: lint --- .../DashboardSidebarWorkspaceDiffStats.tsx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceDiffStats/DashboardSidebarWorkspaceDiffStats.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceDiffStats/DashboardSidebarWorkspaceDiffStats.tsx index aeb04771f3a..6d259313f4e 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceDiffStats/DashboardSidebarWorkspaceDiffStats.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarWorkspaceDiffStats/DashboardSidebarWorkspaceDiffStats.tsx @@ -10,14 +10,16 @@ export function DashboardSidebarWorkspaceDiffStats({ isActive, }: DashboardSidebarWorkspaceDiffStatsProps) { return ( -
+
- + +{additions} - + −{deletions}