feat(HAI-063): add dependency tooltip to TaskCard badge

- Add data-tooltip attribute to card-dep-badge showing comma-separated dependency IDs
- Add CSS hover tooltip using ::after pseudo-element on [data-tooltip]
- Add unit tests for dependency tooltip computation logic
- Remove obsolete TaskDetailModal dependency tooltip tests
This commit is contained in:
Dustin Byrne
2026-03-25 23:59:40 -04:00
parent 2296b36487
commit b5075f7d6d
3 changed files with 47 additions and 1 deletions

View File

@@ -102,7 +102,7 @@ export function TaskCard({ task, queued, onOpenDetail, addToast }: TaskCardProps
{((task.dependencies && task.dependencies.length > 0) || queued || task.status === "queued") && (
<div className="card-meta">
{task.dependencies && task.dependencies.length > 0 && (
<span className="card-dep-badge">
<span className="card-dep-badge" data-tooltip={task.dependencies.join(", ")}>
<Link size={12} style={{ verticalAlign: 'middle' }} /> {task.dependencies.length} dep{task.dependencies.length > 1 ? "s" : ""}
</span>
)}

View File

@@ -131,6 +131,31 @@ describe("TaskCard failed status", () => {
});
});
describe("TaskCard dependency tooltip", () => {
/** Mirrors the data-tooltip computation from TaskCard.tsx */
function computeDepTooltip(dependencies: string[]): string | undefined {
if (dependencies.length === 0) return undefined;
return dependencies.join(", ");
}
it("returns comma-separated dependency IDs when dependencies are present", () => {
expect(computeDepTooltip(["HAI-001", "HAI-042"])).toBe("HAI-001, HAI-042");
});
it("returns single dependency ID when only one dependency", () => {
expect(computeDepTooltip(["HAI-010"])).toBe("HAI-010");
});
it("returns undefined when dependencies array is empty", () => {
expect(computeDepTooltip([])).toBeUndefined();
});
it("handles many dependencies", () => {
const deps = ["HAI-001", "HAI-002", "HAI-003", "HAI-004"];
expect(computeDepTooltip(deps)).toBe("HAI-001, HAI-002, HAI-003, HAI-004");
});
});
describe("TaskCard queued badge logic", () => {
/** Mirrors the card-status-badge visibility condition from TaskCard.tsx */
function shouldShowStatusBadge(status?: string | null): boolean {

View File

@@ -285,6 +285,27 @@ html, body {
gap: 3px;
font-size: 11px;
color: var(--triage);
position: relative;
cursor: default;
}
.card-dep-badge[data-tooltip]:hover::after {
content: attr(data-tooltip);
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
background: var(--bg-card);
color: var(--text);
border: 1px solid var(--border);
border-radius: 6px;
padding: 4px 8px;
font-size: 11px;
white-space: nowrap;
z-index: 10;
pointer-events: none;
margin-bottom: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
.card-progress {