diff --git a/src/renderer/components/dashboard/Dashboard.tsx b/src/renderer/components/dashboard/Dashboard.tsx
index 6f8bb4ca..d95509bb 100644
--- a/src/renderer/components/dashboard/Dashboard.tsx
+++ b/src/renderer/components/dashboard/Dashboard.tsx
@@ -1,4 +1,4 @@
-import { useMemo } from "react";
+import { useMemo, type ElementType, type ReactNode } from "react";
import { motion } from "framer-motion";
import {
ArrowRight,
@@ -29,6 +29,46 @@ import { RecoveryBanner } from "./RecoveryBanner";
import { BudgetAlertBanner } from "./BudgetAlertBanner";
import { ChartSection } from "./ChartSection";
+const ATTENTION_STAGGER_MAX = 8;
+const ATTENTION_STAGGER_STEP = 0.04;
+
+function AttentionRow({
+ icon: Icon,
+ tone,
+ title,
+ subtitle,
+ onClick,
+ index,
+}: {
+ icon: ElementType;
+ tone: "warn" | "danger";
+ title: ReactNode;
+ subtitle: ReactNode;
+ onClick: () => void;
+ index: number;
+}) {
+ const iconClass = tone === "danger" ? "text-destructive" : "text-warning";
+ const bgClass = tone === "danger" ? "bg-destructive-muted" : "bg-warning-muted";
+ const delay = Math.min(index, ATTENTION_STAGGER_MAX) * ATTENTION_STAGGER_STEP;
+ return (
+
+
+
+
+
+ );
+}
+
export interface DashboardProps {
companyName?: string;
companyId?: string;
@@ -150,71 +190,48 @@ export function Dashboard(props: DashboardProps) {
{pendingApprovals.slice(0, 5).map((approval, i) => {
const requester = approval.requestedByAgentId ? agentMap.get(approval.requestedByAgentId) : undefined;
return (
- onNavigate("approvals", approval.id)}
- className="focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 flex w-full items-center gap-3 rounded-lg border border-[color:var(--destructive)] border-opacity-20 bg-warning-muted px-4 py-3 text-left transition hover:border-opacity-40"
- >
-
-
-
{approval.payloadSummary}
-
+ icon={ShieldCheck}
+ tone="warn"
+ index={i}
+ title={approval.payloadSummary}
+ subtitle={
+
{approval.type.replaceAll("_", " ")}
{requester ? by {requester.name} : null}
-
-
-
-
+
+ }
+ onClick={() => onNavigate("approvals", approval.id)}
+ />
);
})}
{failedRuns.slice(0, 3).map((run, i) => {
const agent = agentMap.get(run.agentId);
return (
- onNavigate("runs", run.id)}
- className="focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 flex w-full items-center gap-3 rounded-lg border border-[color:var(--destructive)] border-opacity-20 bg-destructive-muted px-4 py-3 text-left transition hover:border-opacity-40"
- >
-
-
-
{run.summary || "Run failed"}
-
- {agent?.name} — {run.errorMessage?.slice(0, 80) ?? "Unknown error"}
-
-
-
-
+ />
);
})}
{urgentMessages.slice(0, 3).map((msg, i) => {
const sender = agentMap.get(msg.fromAgentId);
return (
- onNavigate("communication", msg.id)}
- className="focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 flex w-full items-center gap-3 rounded-lg border border-[color:var(--destructive)] border-opacity-20 bg-warning-muted px-4 py-3 text-left transition hover:border-opacity-40"
- >
-
-
-
{msg.subject}
-
- {sender?.name ?? "Unknown"} — {msg.channel}{msg.priority === "urgent" ? " · urgent" : ""}
-
-
-
-
+ />
);
})}
@@ -233,7 +250,7 @@ export function Dashboard(props: DashboardProps) {
{activeWork.length > 0 ? (
- {activeWork.map(({ run, agent, task }) => (
+ {activeWork.map(({ run, agent, task }, i) => (
{run.status === "running" ? (
-
+ {i < 2 ? (
+
+ ) : null}
) : null}