feat(dashboard): rearrange agent + task detail panels

- AgentsView: agent metrics bar moves to the top of the scrolling
  content (was below the agent list); token-usage panel moves into
  the controls dropdown next to the heartbeat slider, which is now
  scrollable so the added content fits on short viewports.
- AgentsView mobile: 2x2 grid for the metric cards with tighter
  padding and smaller value/label text so labels don't crowd off
  the card on narrow phones.
- TaskDetailModal: new "Stats" tab at the end of the fixed tab list
  hosts the token-usage panel, removed from the inline definition
  body.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-04-25 09:50:06 -07:00
parent 84fb696c86
commit a4b4cdb4d4
3 changed files with 43 additions and 10 deletions

View File

@@ -834,6 +834,29 @@
}
@media (max-width: 768px) {
/* Stats cards: drop to a 2x2 grid with tighter padding so they
don't squeeze the labels off the card on narrow phones. */
.agent-metrics-bar {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: var(--space-sm);
margin-bottom: var(--space-md);
}
.agent-metric-card {
padding: var(--space-sm) var(--space-md);
gap: var(--space-sm);
min-width: 0;
}
.agent-metric-value {
font-size: 16px;
}
.agent-metric-label {
font-size: calc(var(--space-sm) + var(--space-xs) * 0.5);
}
.agent-org-chart {
padding: var(--space-sm);
padding-bottom: calc(var(--space-lg) + var(--space-sm));

View File

@@ -749,10 +749,11 @@ export function AgentsView({ addToast, projectId }: AgentsViewProps) {
<div
ref={controlsPanelRef}
id={controlsPanelId}
className="agent-controls-panel"
className="agent-controls-panel agent-controls-panel--scrollable"
role="dialog"
aria-label="Agent controls"
aria-modal="false"
style={{ maxHeight: "70vh", overflowY: "auto" }}
>
<div className="agent-controls">
<div className="agent-controls-filters">
@@ -846,11 +847,15 @@ export function AgentsView({ addToast, projectId }: AgentsViewProps) {
</small>
</div>
</div>
<AgentTokenStatsPanel agents={displayAgents} />
</div>
)}
<div className="agents-view-content">
<AgentMetricsBar stats={stats} />
<NewAgentDialog
isOpen={isCreating}
onClose={() => setIsCreating(false)}
@@ -1266,8 +1271,6 @@ export function AgentsView({ addToast, projectId }: AgentsViewProps) {
)}
{/* Secondary sections after the main collection */}
<AgentMetricsBar stats={stats} />
<AgentTokenStatsPanel agents={displayAgents} />
<ActiveAgentsPanel agents={activeAgents} projectId={projectId} onAgentSelect={setSelectedAgentId} />
</div>

View File

@@ -157,7 +157,7 @@ function formatBytes(bytes: number): string {
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
}
type TabId = "definition" | "logs" | "changes" | "comments" | "model" | "workflow" | "documents" | `plugin-${string}`;
type TabId = "definition" | "logs" | "changes" | "comments" | "model" | "workflow" | "documents" | "stats" | `plugin-${string}`;
interface TaskDetailModalProps {
task: Task | TaskDetail;
@@ -1286,6 +1286,12 @@ export function TaskDetailModal({
>
Workflow
</button>
<button
className={`detail-tab${activeTab === "stats" ? " detail-tab-active" : ""}`}
onClick={() => setActiveTab("stats")}
>
Stats
</button>
{/* Plugin tabs */}
{pluginTabSlots.map((entry, index) => {
const pluginTabId = `plugin-${index}` as TabId;
@@ -1391,6 +1397,13 @@ export function TaskDetailModal({
<div className="detail-section">
<PluginSlot slotId="task-detail-tab" projectId={projectId} />
</div>
) : activeTab === "stats" ? (
<div className="detail-section">
<TaskTokenStatsPanel
tokenUsage={workingTask.tokenUsage}
loading={detailLoading}
/>
</div>
) : (
<>
{/* Summary section - only for done tasks with summary */}
@@ -1482,12 +1495,6 @@ export function TaskDetailModal({
<div className="step-progress-empty">(no steps defined)</div>
)}
</div>
<div className="detail-section">
<TaskTokenStatsPanel
tokenUsage={workingTask.tokenUsage}
loading={detailLoading}
/>
</div>
<div className="detail-section">
{!isEditingSpec && (
<div className="detail-spec-edit-trigger">