W9-5: Tooltip sweep — HelpTip helper + per-view decode (#533)

* [W9-5a] Tooltip sweep foundation: HelpTip helper + shared cryptic badges

HelpTip: DRY wrapper over the verbose 3-element Radix Tooltip pattern so a
broad sweep stays a one-line wrap per site (falsy label short-circuits to the
bare child). Unit-tested (3 cases).

TaskStatusBadge + AgentStateBadge: the panel's most cryptic, most-frequent
elements (15 task lifecycle states, 11 agent states) had no explanation
anywhere. Add a per-state tooltip via HelpTip, with the canonical text in one
description map and exported as taskStatusDescription / agentStateDescription
so the per-view inline renderers (kanban, task header) reuse it instead of
re-declaring. This is part 1 of the W9-5 tooltip sweep; the per-view inline
surfaces follow in subsequent PRs.

* [W9-5b] Per-view tooltip sweep: decode cryptic badges, icon-only buttons, status dots

35 HelpTip additions across 22 panel components, reusing the W9-5a
helper plus taskStatusDescription/agentStateDescription. Tipped:
task-id/commit-hash/branch/PR badges, severity/origin/status badges,
priority (P0-P3), migration/shared flags, MegaTask umbrella badge,
Review Gate / For Resumption / Confidential note badges, icon-only
view/delete/edit/clear/show-hide buttons, semver bump + gate-state
badges, ahead-not-pushed badge. Skipped self-explanatory labeled
buttons and elements already carrying title=.

---------

Co-authored-by: Renn F <rennf93@users.noreply.github.com>
This commit is contained in:
Renzo F
2026-07-15 04:34:17 +02:00
committed by GitHub
co-authored by Renn F
parent f07e2420a8
commit b7f2d84c77
26 changed files with 438 additions and 207 deletions
@@ -1,4 +1,5 @@
import { Badge } from "@/components/ui/badge";
import { HelpTip } from "@/components/ui/help-tip";
import {
Clock,
RefreshCw,
@@ -53,12 +54,32 @@ const stateIcons: Record<string, React.ReactNode> = {
terminated: <Square className="h-4 w-4" />,
};
const stateDescriptions: Record<string, string> = {
active: "Agent is actively working a task.",
running: "Agent is running — currently executing.",
ready: "Agent is ready and waiting for work.",
starting: "Agent container is starting up.",
idle: "Agent is idle — no task currently claimed.",
waiting_long: "Agent has been waiting a long time; may need attention.",
paused: "Agent is paused; can resume.",
stopped: "Agent container is stopped; can be restarted.",
terminated: "Agent container has been terminated.",
offline: "Agent is offline.",
error: "Agent hit an error state; needs attention.",
};
interface AgentStateBadgeProps {
state: AgentStateString | string;
showIcon?: boolean;
size?: "sm" | "md" | "lg";
}
/** Plain-language explanation for an agent state. Reused by the shared badge
* and by inline agent-state renderers. Empty for an unknown state. */
export function agentStateDescription(state: string): string {
return stateDescriptions[state] ?? "";
}
export function AgentStateBadge({
state,
showIcon = true,
@@ -74,10 +95,12 @@ export function AgentStateBadge({
const icon = stateIcons[state] || <Square className="h-4 w-4" />;
return (
<Badge className={`${color} text-white ${sizeClasses[size]}`}>
{showIcon && <span className="mr-1">{icon}</span>}
{state.replace(/_/g, " ")}
</Badge>
<HelpTip label={stateDescriptions[state]}>
<Badge className={`${color} text-white ${sizeClasses[size]}`}>
{showIcon && <span className="mr-1">{icon}</span>}
{state.replace(/_/g, " ")}
</Badge>
</HelpTip>
);
}