feat(ui): unify SSH workspace icon to Server across all surfaces (#1198)

SSH workspaces previously rendered as Globe in some places and Wifi in
others. Globe implies web/internet and Wifi implies wireless network
strength — neither reads as "remote machine". Use Server/ServerOff
across every SSH context for a consistent mental model. Globe remains
in true browser/web surfaces (browser pane, address bar, tabs, clone
from URL, Browser settings pane).

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
Jinjing
2026-04-27 22:31:11 -07:00
committed by GitHub
co-authored by Orca
parent 3abf68dbef
commit a110b6d794
9 changed files with 26 additions and 26 deletions
@@ -1,7 +1,7 @@
/* oxlint-disable max-lines */
import React, { useCallback, useDeferredValue, useEffect, useMemo, useRef, useState } from 'react'
import { toast } from 'sonner'
import { Globe, Plus, WifiOff } from 'lucide-react'
import { Globe, Plus, Server, ServerOff } from 'lucide-react'
import { useAppStore } from '@/store'
import { getRepoMapFromState, useAllWorktrees } from '@/store/selectors'
import {
@@ -775,9 +775,9 @@ export default function WorktreeJumpPalette(): React.JSX.Element | null {
className="shrink-0 inline-flex items-center"
>
{isSshDisconnected ? (
<WifiOff className="size-3.5 text-red-400" aria-hidden="true" />
<ServerOff className="size-3.5 text-red-400" aria-hidden="true" />
) : (
<Globe
<Server
className="size-3.5 text-muted-foreground"
aria-hidden="true"
/>
@@ -1,5 +1,5 @@
import React, { useCallback, useMemo, useState } from 'react'
import { Check, ChevronsUpDown, FolderPlus, Globe } from 'lucide-react'
import { Check, ChevronsUpDown, FolderPlus, Server } from 'lucide-react'
import { Button } from '@/components/ui/button'
import {
Command,
@@ -181,7 +181,7 @@ export default function RepoCombobox({
/>
{selectedRepo.connectionId && (
<span className="shrink-0 inline-flex items-center gap-0.5 rounded bg-muted px-1 py-0.5 text-[9px] font-medium leading-none text-muted-foreground">
<Globe className="size-2.5" />
<Server className="size-2.5" />
SSH
</span>
)}
@@ -228,7 +228,7 @@ export default function RepoCombobox({
/>
{repo.connectionId && (
<span className="shrink-0 inline-flex items-center gap-0.5 rounded bg-muted px-1 py-0.5 text-[9px] font-medium leading-none text-muted-foreground">
<Globe className="size-2.5" />
<Server className="size-2.5" />
SSH
</span>
)}
@@ -1,4 +1,4 @@
import { ArrowLeft, Globe, Search, type LucideIcon, type LucideProps } from 'lucide-react'
import { ArrowLeft, Search, Server, type LucideIcon, type LucideProps } from 'lucide-react'
import { Button } from '../ui/button'
import { Input } from '../ui/input'
@@ -134,7 +134,7 @@ export function SettingsSidebar({
<span className="truncate">{section.title}</span>
{section.isRemote && (
<span className="ml-auto inline-flex shrink-0 items-center gap-1 text-[10px] text-muted-foreground">
<Globe className="size-3" />
<Server className="size-3" />
SSH
</span>
)}
@@ -1,5 +1,5 @@
import { useState } from 'react'
import { Loader2, MonitorSmartphone, Pencil, Server, Trash2, Wifi, WifiOff } from 'lucide-react'
import { Loader2, MonitorSmartphone, Pencil, Server, ServerOff, Trash2 } from 'lucide-react'
import type {
SshTarget,
SshConnectionState,
@@ -111,7 +111,7 @@ export function SshTargetCard({
className="gap-1.5"
disabled={actionInFlight !== null}
>
<WifiOff className="size-3" />
<ServerOff className="size-3" />
Disconnect
</Button>
) : isConnecting(status) ? (
@@ -131,7 +131,7 @@ export function SshTargetCard({
{actionInFlight === 'connect' ? (
<Loader2 className="size-3 animate-spin" />
) : (
<Wifi className="size-3" />
<Server className="size-3" />
)}
Connect
</Button>
@@ -1,6 +1,6 @@
import { useCallback, useState } from 'react'
import { toast } from 'sonner'
import { Globe, Loader2, WifiOff } from 'lucide-react'
import { Loader2, Server, ServerOff } from 'lucide-react'
import {
Dialog,
DialogContent,
@@ -72,7 +72,7 @@ export function SshDisconnectedDialog({
{isConnecting ? (
<Loader2 className="size-4 text-yellow-500 animate-spin" />
) : (
<WifiOff className="size-4 text-muted-foreground" />
<ServerOff className="size-4 text-muted-foreground" />
)}
{isConnecting ? 'Reconnecting...' : 'SSH Disconnected'}
</DialogTitle>
@@ -80,7 +80,7 @@ export function SshDisconnectedDialog({
</DialogHeader>
<div className="flex items-center gap-2.5 rounded-md border border-border/50 bg-card/40 px-3 py-2">
<Globe className="size-3.5 shrink-0 text-muted-foreground" />
<Server className="size-3.5 shrink-0 text-muted-foreground" />
<div className="min-w-0 flex-1">
<span className="text-xs font-medium">{targetLabel}</span>
</div>
@@ -4,7 +4,7 @@ import { useShallow } from 'zustand/react/shallow'
import { useAppStore } from '@/store'
import { Badge } from '@/components/ui/badge'
import { Tooltip, TooltipTrigger, TooltipContent } from '@/components/ui/tooltip'
import { Bell, GitMerge, LoaderCircle, CircleCheck, CircleX, Globe, WifiOff } from 'lucide-react'
import { Bell, GitMerge, LoaderCircle, CircleCheck, CircleX, Server, ServerOff } from 'lucide-react'
import StatusIndicator from './StatusIndicator'
import CacheTimer from './CacheTimer'
import WorktreeContextMenu from './WorktreeContextMenu'
@@ -488,9 +488,9 @@ const WorktreeCard = React.memo(function WorktreeCard({
<TooltipTrigger asChild>
<span className="shrink-0 inline-flex items-center">
{isSshDisconnected ? (
<WifiOff className="size-3 text-red-400" />
<ServerOff className="size-3 text-red-400" />
) : (
<Globe className="size-3 text-muted-foreground" />
<Server className="size-3 text-muted-foreground" />
)}
</span>
</TooltipTrigger>
@@ -1,5 +1,5 @@
import React, { useCallback, useState } from 'react'
import { Loader2, MonitorSmartphone, Wifi, WifiOff } from 'lucide-react'
import { Loader2, MonitorSmartphone, Server, ServerOff } from 'lucide-react'
import { toast } from 'sonner'
import {
DropdownMenu,
@@ -174,11 +174,11 @@ export function SshStatusSegment({
{anyConnecting ? (
<Loader2 className="size-3 animate-spin text-yellow-500" />
) : overall === 'connected' ? (
<Wifi className="size-3 text-emerald-500" />
<Server className="size-3 text-emerald-500" />
) : overall === 'partial' ? (
<Wifi className="size-3 text-muted-foreground" />
<Server className="size-3 text-muted-foreground" />
) : (
<WifiOff className="size-3 text-muted-foreground" />
<ServerOff className="size-3 text-muted-foreground" />
)}
{!compact && (
<span className="text-[11px]">
@@ -7,8 +7,8 @@ import {
ChevronRight,
MemoryStick as MemoryStickIcon,
RefreshCw,
Terminal,
Wifi
Server,
Terminal
} from 'lucide-react'
import React, { useCallback, useEffect, useRef, useState } from 'react'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
@@ -705,7 +705,7 @@ function StatusBarInner(): React.JSX.Element | null {
checked={statusBarItems.includes('ssh')}
onCheckedChange={() => toggleStatusBarItem('ssh')}
>
<Wifi className="size-3.5" />
<Server className="size-3.5" />
SSH Status
</DropdownMenuCheckboxItem>
<DropdownMenuCheckboxItem
@@ -1,5 +1,5 @@
import React, { useCallback, useMemo, useState } from 'react'
import { Check, ChevronsUpDown, Globe } from 'lucide-react'
import { Check, ChevronsUpDown, Server } from 'lucide-react'
import { Button } from '@/components/ui/button'
import {
Command,
@@ -181,7 +181,7 @@ export default function RepoMultiCombobox({
/>
{repo.connectionId && (
<span className="shrink-0 inline-flex items-center gap-0.5 rounded bg-muted px-1 py-0.5 text-[9px] font-medium leading-none text-muted-foreground">
<Globe className="size-2.5" />
<Server className="size-2.5" />
SSH
</span>
)}