From 7f63fc6cebdba8abf3300a12ef6edc936775af9b Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Fri, 10 Apr 2026 22:03:39 +0700 Subject: [PATCH] Replace script status dots with colored type-aware icons Use Globe for services and SquareTerminal for scripts instead of plain status dots. Play icon for the Scripts section title. Running status uses blue instead of green. Scripts button moved before Open in Editor in the workspace header. --- .../src/components/sidebar-workspace-list.tsx | 12 ++++- .../src/components/workspace-hover-card.tsx | 36 ++++++++------- .../screens/workspace/workspace-screen.tsx | 12 ++--- .../workspace/workspace-scripts-button.tsx | 46 ++++++++----------- 4 files changed, 54 insertions(+), 52 deletions(-) diff --git a/packages/app/src/components/sidebar-workspace-list.tsx b/packages/app/src/components/sidebar-workspace-list.tsx index 24687700b..0a1066914 100644 --- a/packages/app/src/components/sidebar-workspace-list.tsx +++ b/packages/app/src/components/sidebar-workspace-list.tsx @@ -37,7 +37,8 @@ import { FolderPlus, FolderGit2, GitPullRequest, - Terminal, + Globe, + SquareTerminal, Monitor, MoreVertical, Plus, @@ -969,6 +970,9 @@ function WorkspaceRowInner({ const isDesktop = !isTouchPlatform; const showScriptsIcon = isDesktop && workspace.hasRunningScripts; + const hasRunningService = workspace.scripts.some( + (s) => s.lifecycle === "running" && (s.type ?? "service") === "service", + ); return ( @@ -1018,7 +1022,11 @@ function WorkspaceRowInner({ {showScriptsIcon ? ( - + {hasRunningService ? ( + + ) : ( + + )} ) : null} {isCreating ? Creating... : null} diff --git a/packages/app/src/components/workspace-hover-card.tsx b/packages/app/src/components/workspace-hover-card.tsx index 27f919525..a0c5298d0 100644 --- a/packages/app/src/components/workspace-hover-card.tsx +++ b/packages/app/src/components/workspace-hover-card.tsx @@ -10,7 +10,7 @@ import { useMutation } from "@tanstack/react-query"; import { Dimensions, Platform, Text, View } from "react-native"; import Animated, { FadeIn, FadeOut } from "react-native-reanimated"; import { StyleSheet, useUnistyles } from "react-native-unistyles"; -import { ExternalLink, LoaderCircle, Play, Terminal } from "lucide-react-native"; +import { ExternalLink, Globe, LoaderCircle, Play, SquareTerminal } from "lucide-react-native"; import { GitHubIcon } from "@/components/icons/github-icon"; import { DiffStat } from "@/components/diff-stat"; import { Pressable } from "react-native"; @@ -200,7 +200,7 @@ function getScriptHealthColor(input: { theme: ReturnType["theme"]; }): string { if (input.health === "healthy") { - return input.theme.colors.palette.green[500]; + return input.theme.colors.palette.blue[500]; } if (input.health === "unhealthy") { return input.theme.colors.palette.red[500]; @@ -349,7 +349,7 @@ function WorkspaceHoverCardContent({ <> - + Scripts @@ -365,7 +365,7 @@ function WorkspaceHoverCardContent({ ? getScriptHealthColor({ health: script.health, theme }) : theme.colors.foregroundMuted; } else if (isRunning) { - dotColor = theme.colors.palette.green[500]; + dotColor = theme.colors.palette.blue[500]; } else if (exitCode === 0) { dotColor = theme.colors.palette.green[500]; } else if (exitCode !== null) { @@ -402,13 +402,21 @@ function WorkspaceHoverCardContent({ > {({ hovered }) => ( <> - + {isService ? ( + + ) : ( + + )} ({ flex: 1, minWidth: 0, }, - statusDot: { - width: 8, - height: 8, - borderRadius: 4, + scriptIcon: { flexShrink: 0, - marginLeft: 2, }, checksSummaryRow: { flexDirection: "row", diff --git a/packages/app/src/screens/workspace/workspace-screen.tsx b/packages/app/src/screens/workspace/workspace-screen.tsx index dc4eaa7fa..810bf0425 100644 --- a/packages/app/src/screens/workspace/workspace-screen.tsx +++ b/packages/app/src/screens/workspace/workspace-screen.tsx @@ -2124,12 +2124,6 @@ function WorkspaceScreenContent({ serverId, workspaceId }: WorkspaceScreenProps) } right={ - {!isMobile ? ( - - ) : null} {!isMobile && workspaceDescriptor && workspaceDescriptor.scripts.length > 0 ? ( ) : null} + {!isMobile ? ( + + ) : null} {!isMobile && isGitCheckout ? ( <> {workspaceDirectory ? ( diff --git a/packages/app/src/screens/workspace/workspace-scripts-button.tsx b/packages/app/src/screens/workspace/workspace-scripts-button.tsx index 98720993a..1e3ca7943 100644 --- a/packages/app/src/screens/workspace/workspace-scripts-button.tsx +++ b/packages/app/src/screens/workspace/workspace-scripts-button.tsx @@ -1,7 +1,7 @@ import { type ReactElement } from "react"; import { Pressable, Text, View } from "react-native"; import { useMutation } from "@tanstack/react-query"; -import { ChevronDown, ExternalLink, LoaderCircle, Play, Terminal } from "lucide-react-native"; +import { ChevronDown, ExternalLink, Globe, LoaderCircle, Play, SquareTerminal } from "lucide-react-native"; import { StyleSheet, useUnistyles } from "react-native-unistyles"; import type { WorkspaceDescriptor } from "@/stores/session-store"; import { useSessionStore } from "@/stores/session-store"; @@ -20,7 +20,7 @@ function getScriptHealthColor( theme: ReturnType["theme"], ): string { if (health === "healthy") { - return theme.colors.palette.green[500]; + return theme.colors.palette.blue[500]; } if (health === "unhealthy") { return theme.colors.palette.red[500]; @@ -82,16 +82,16 @@ export function WorkspaceScriptsButton({ accessibilityLabel="Workspace scripts" > - + Scripts - {hasAnyRunning ? ( - - ) : null} @@ -114,7 +114,7 @@ export function WorkspaceScriptsButton({ ? getScriptHealthColor(script.health, theme) : theme.colors.foregroundMuted; } else if (isRunning) { - dotColor = theme.colors.palette.green[500]; + dotColor = theme.colors.palette.blue[500]; } else if (exitCode === 0) { dotColor = theme.colors.palette.green[500]; } else if (exitCode !== null) { @@ -138,12 +138,11 @@ export function WorkspaceScriptsButton({ > {({ hovered }) => ( <> - + {isService ? ( + + ) : ( + + )} ({ justifyContent: "center", gap: theme.spacing[1.5], }, - runningDot: { - width: 6, - height: 6, - borderRadius: 3, - }, scriptList: { paddingVertical: theme.spacing[1], }, @@ -293,11 +287,7 @@ const styles = StyleSheet.create((theme) => ({ scriptRowHovered: { backgroundColor: theme.colors.surface2, }, - statusDot: { - width: 8, - height: 8, - borderRadius: 4, - marginLeft: 2, + scriptIcon: { flexShrink: 0, }, scriptName: {