feat(KB-013): complete Step 1 — add step progress component to TaskDetailModal

This commit is contained in:
gsxdsm
2026-03-29 17:53:52 -07:00
parent 478e7ffac3
commit f8203a0796
2 changed files with 109 additions and 0 deletions

View File

@@ -9,6 +9,20 @@ import { useAgentLogs } from "../hooks/useAgentLogs";
import { AgentLogViewer } from "./AgentLogViewer";
import { SteeringTab } from "./SteeringTab";
function getStepStatusColor(status: string): string {
switch (status) {
case "done":
return "var(--color-success, #3fb950)";
case "in-progress":
return "var(--todo, #58a6ff)";
case "skipped":
return "var(--text-dim, #484f58)";
case "pending":
default:
return "var(--border, #30363d)";
}
}
function formatTimestamp(iso: string): string {
const date = new Date(iso);
const now = new Date();
@@ -459,6 +473,28 @@ export function TaskDetailModal({
})()}
</div>
</div>
<div className="detail-section detail-step-progress">
<h4>Progress</h4>
{task.steps && task.steps.length > 0 ? (
<div className="step-progress-wrapper">
<div className="step-progress-bar">
{task.steps.map((step, index) => (
<div
key={index}
className={`step-progress-segment step-progress-segment--${step.status}`}
data-tooltip={`${step.name} (${step.status})`}
style={{ backgroundColor: getStepStatusColor(step.status) }}
/>
))}
</div>
<span className="step-progress-label">
{task.steps.filter(s => s.status === "done").length}/{task.steps.length} steps
</span>
</div>
) : (
<div className="step-progress-empty">(no steps defined)</div>
)}
</div>
<div className="detail-section detail-activity">
<h4>Activity</h4>
{task.log && task.log.length > 0 ? (

View File

@@ -1117,6 +1117,79 @@ body {
font-family: "SF Mono", Monaco, Consolas, monospace;
}
/* === Step Progress === */
.detail-step-progress {
margin-top: 16px;
}
.detail-step-progress h4 {
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.5px;
color: var(--text-muted);
margin-bottom: 8px;
}
.step-progress-wrapper {
display: flex;
align-items: center;
gap: 12px;
}
.step-progress-bar {
flex: 1;
display: flex;
gap: 2px;
height: 8px;
}
.step-progress-segment {
flex: 1;
height: 100%;
border-radius: 2px;
transition: filter 0.15s ease, transform 0.15s ease;
cursor: pointer;
position: relative;
}
.step-progress-segment:hover {
filter: brightness(1.2);
transform: scaleY(1.1);
}
.step-progress-segment[data-tooltip]:hover::after {
content: attr(data-tooltip);
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
background: var(--surface);
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);
}
.step-progress-label {
font-size: 11px;
font-weight: 600;
color: var(--text-muted);
font-family: "SF Mono", Monaco, Consolas, monospace;
flex-shrink: 0;
}
.step-progress-empty {
font-size: 13px;
color: var(--text-dim);
opacity: 0.7;
}
/* === Activity Timeline === */
.detail-activity {
margin-top: 20px;