| ... | ... | @@ -45,12 +45,15 @@ import { |
| 45 | 45 | CircleCheckIcon, |
| 46 | 46 | CircleDashedIcon, |
| 47 | 47 | ClockIcon, |
| 48 | EyeIcon, |
| 48 | 49 | FolderIcon, |
| 49 | 50 | GitBranchIcon, |
| 51 | MessageCircleQuestionIcon, |
| 50 | 52 | PinIcon, |
| 51 | 53 | PinOffIcon, |
| 52 | 54 | PlusIcon, |
| 53 | 55 | SettingsIcon, |
| 56 | ShieldQuestionIcon, |
| 54 | 57 | SquarePenIcon, |
| 55 | 58 | TerminalIcon, |
| 56 | 59 | Undo2Icon, |
| ... | ... | @@ -1088,8 +1091,6 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { |
| 1088 | 1091 | // switching sidebars must not light up every historical thread as unread. |
| 1089 | 1092 | const isUnread = hasUnseenCompletion({ ...thread, lastVisitedAt }); |
| 1090 | 1093 | const status = resolveSidebarThreadStatus(thread); |
| 1091 | | const isInFlight = |
| 1092 | | status === "working" || status === "monitoring" || status === "approval" || status === "input"; |
| 1093 | 1094 | // A woken thread reappears at its original position (the sort is |
| 1094 | 1095 | // deliberately static), so the pill has to carry the weight. Snoozing is |
| 1095 | 1096 | // an explicit act, so the pill clears only when the user re-engages: |
| ... | ... | @@ -1123,35 +1124,32 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { |
| 1123 | 1124 | icon: "working" as const, |
| 1124 | 1125 | // No shimmer: a label that animates forever is noise in a sidebar |
| 1125 | 1126 | // full of them (and repaints every vsync on high-refresh displays). |
| 1126 | | // Working is a background state, so it rests at the dim end of what |
| 1127 | | // the old pulse cycled through; only the thread you have open gets |
| 1128 | | // the label at full strength. |
| 1129 | | className: cn("text-sky-600 dark:text-sky-400", !props.isActive && "opacity-75"), |
| 1127 | className: "text-sky-600 dark:text-sky-400", |
| 1130 | 1128 | } |
| 1131 | 1129 | : status === "monitoring" |
| 1132 | 1130 | ? { |
| 1133 | 1131 | // Monitoring is calm background presence, not active progress |
| 1134 | 1132 | // (monitoring-pill D6), so it keeps the label at full strength. |
| 1135 | 1133 | label: "Monitoring", |
| 1136 | | icon: null, |
| 1137 | | className: "text-sky-600 dark:text-sky-400", |
| 1134 | icon: "monitoring" as const, |
| 1135 | className: "text-foreground dark:text-white", |
| 1138 | 1136 | } |
| 1139 | 1137 | : status === "approval" |
| 1140 | 1138 | ? { |
| 1141 | 1139 | label: "Approval", |
| 1142 | | icon: null, |
| 1140 | icon: "approval" as const, |
| 1143 | 1141 | className: "text-amber-700 dark:text-amber-300", |
| 1144 | 1142 | } |
| 1145 | 1143 | : status === "input" |
| 1146 | 1144 | ? { |
| 1147 | 1145 | label: "Input", |
| 1148 | | icon: null, |
| 1146 | icon: "input" as const, |
| 1149 | 1147 | className: "text-indigo-600 dark:text-indigo-300", |
| 1150 | 1148 | } |
| 1151 | 1149 | : status === "failed" |
| 1152 | 1150 | ? { |
| 1153 | 1151 | label: "Failed", |
| 1154 | | icon: null, |
| 1152 | icon: "failed" as const, |
| 1155 | 1153 | className: "text-red-700 dark:text-red-300", |
| 1156 | 1154 | } |
| 1157 | 1155 | : isWoke |
| ... | ... | @@ -1396,10 +1394,6 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { |
| 1396 | 1394 | : shouldRecede |
| 1397 | 1395 | ? "text-sidebar-muted-foreground/75 hover:bg-sidebar-row-hover hover:text-sidebar-foreground" |
| 1398 | 1396 | : "bg-transparent text-sidebar-foreground hover:bg-sidebar-row-hover", |
| 1399 | | isInFlight && |
| 1400 | | !props.isActive && |
| 1401 | | !isSelected && |
| 1402 | | "opacity-70 transition-opacity hover:opacity-100", |
| 1403 | 1397 | isFileDragOver && "ring-1 ring-inset ring-primary/70", |
| 1404 | 1398 | // The hover tint must not clobber an active/selected row's own surface. |
| 1405 | 1399 | isFileDragOver && !props.isActive && !isSelected && "bg-sidebar-row-hover", |
| ... | ... | @@ -1462,7 +1456,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { |
| 1462 | 1456 | "truncate", |
| 1463 | 1457 | shouldRecede |
| 1464 | 1458 | ? "text-secondary-label" |
| 1465 | | : isUnread || isWoke |
| 1459 | : isUnread || isWoke || status === "input" |
| 1466 | 1460 | ? "text-foreground" |
| 1467 | 1461 | : status === "failed" |
| 1468 | 1462 | ? "text-foreground/95" |
| ... | ... | @@ -1472,7 +1466,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { |
| 1472 | 1466 | "truncate group-focus-within/sidebar-row:text-foreground group-hover/sidebar-row:text-foreground", |
| 1473 | 1467 | shouldRecede |
| 1474 | 1468 | ? "text-secondary-label/70" |
| 1475 | | : props.isActive || isWoke |
| 1469 | : props.isActive || isWoke || status === "input" |
| 1476 | 1470 | ? "text-foreground" |
| 1477 | 1471 | : isUnread |
| 1478 | 1472 | ? "text-muted-foreground" |
| ... | ... | @@ -1814,6 +1808,14 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { |
| 1814 | 1808 | > |
| 1815 | 1809 | {topStatus.icon === "working" ? ( |
| 1816 | 1810 | <CircleDashedIcon aria-hidden className="size-4 shrink-0" /> |
| 1811 | ) : topStatus.icon === "input" ? ( |
| 1812 | <MessageCircleQuestionIcon aria-hidden className="size-4 shrink-0" /> |
| 1813 | ) : topStatus.icon === "approval" ? ( |
| 1814 | <ShieldQuestionIcon aria-hidden className="size-4 shrink-0" /> |
| 1815 | ) : topStatus.icon === "failed" ? ( |
| 1816 | <CircleAlertIcon aria-hidden className="size-4 shrink-0" /> |
| 1817 | ) : topStatus.icon === "monitoring" ? ( |
| 1818 | <EyeIcon aria-hidden className="size-4 shrink-0" /> |
| 1817 | 1819 | ) : topStatus.icon === "done" ? ( |
| 1818 | 1820 | <CircleCheckIcon aria-hidden className="size-4 shrink-0" /> |
| 1819 | 1821 | ) : null} |