feat(11-02): replace 1113 old CSS variable references with Paperclip design tokens
- Replace all bg-[color:var(--old)] with bg-background/bg-card/bg-muted/bg-primary etc. - Replace all text-[color:var(--old)] with text-foreground/text-muted-foreground/text-primary etc. - Replace all border-[color:var(--line)] with border-border - Replace all inline var(--old) with var(--new) equivalents - Replace all rounded-[6px]/rounded-[8px] with rounded-lg - Replace .surface class with bg-card border border-border shadow-sm - Replace .focus-ring class with focus-visible Tailwind utilities - Replace .mono class with font-mono - Replace data-theme attribute with class-based dark mode - 99 files updated, ~1265 lines changed, zero old references remaining
This commit is contained in:
1 parent
2ed5dd3388
commit
06ea4c6aec
99 files changed
+1265
-1265
No files matched your search
@@ -61,12 +61,12 @@ export function Inbox({ items, onNavigate }: InboxProps) {
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-[8px] bg-[color:var(--accent-soft)]">
|
||||
<Bell size={20} weight="fill" className="text-[color:var(--accent)]" />
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-accent">
|
||||
<Bell size={20} weight="fill" className="text-primary" />
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="text-[18px] font-bold tracking-[-0.02em] text-[color:var(--text)]">{t("inbox.title")}</h2>
|
||||
<p className="text-[12px] text-[color:var(--muted)]">
|
||||
<h2 className="text-[18px] font-bold tracking-[-0.02em] text-foreground">{t("inbox.title")}</h2>
|
||||
<p className="text-[12px] text-muted-foreground">
|
||||
{counts.all} item{counts.all !== 1 ? "s" : ""} need{counts.all === 1 ? "s" : ""} your attention
|
||||
</p>
|
||||
</div>
|
||||
@@ -81,14 +81,14 @@ export function Inbox({ items, onNavigate }: InboxProps) {
|
||||
onClick={() => setFilter(btn.key)}
|
||||
className={`flex items-center gap-1.5 rounded-full px-3 py-1.5 text-[11px] font-medium transition ${
|
||||
filter === btn.key
|
||||
? "bg-[color:var(--accent)] text-[color:var(--text-on-accent)]"
|
||||
: "bg-[color:var(--panel-soft)] text-[color:var(--muted-strong)] hover:bg-[color:var(--line)]"
|
||||
? "bg-primary text-primary-foreground"
|
||||
: "bg-muted text-muted-foreground hover:bg-[color:var(--border)]"
|
||||
}`}
|
||||
>
|
||||
{btn.label}
|
||||
{btn.count > 0 ? (
|
||||
<span className={`rounded-full px-1.5 py-0.5 text-[9px] font-bold ${
|
||||
filter === btn.key ? "bg-[color:var(--text-on-accent)]/20 text-[color:var(--text-on-accent)]" : "bg-[color:var(--line)] text-[color:var(--muted)]"
|
||||
filter === btn.key ? "bg-[color:var(--primary-foreground)]/20 text-primary-foreground" : "bg-[color:var(--border)] text-muted-foreground"
|
||||
}`}>
|
||||
{btn.count}
|
||||
</span>
|
||||
@@ -98,10 +98,10 @@ export function Inbox({ items, onNavigate }: InboxProps) {
|
||||
</div>
|
||||
|
||||
{filteredItems.length === 0 ? (
|
||||
<div className="flex flex-col items-center justify-center rounded-[8px] border border-dashed border-[color:var(--line)] py-16 text-center">
|
||||
<Tray size={32} className="mb-3 text-[color:var(--muted)]" />
|
||||
<div className="text-[14px] font-medium text-[color:var(--muted-strong)]">{t("inbox.allClear")}</div>
|
||||
<div className="mt-1 text-[12px] text-[color:var(--muted)]">{t("inbox.noItemsNow")}</div>
|
||||
<div className="flex flex-col items-center justify-center rounded-lg border border-dashed border-border py-16 text-center">
|
||||
<Tray size={32} className="mb-3 text-muted-foreground" />
|
||||
<div className="text-[14px] font-medium text-muted-foreground">{t("inbox.allClear")}</div>
|
||||
<div className="mt-1 text-[12px] text-muted-foreground">{t("inbox.noItemsNow")}</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-1.5">
|
||||
@@ -115,10 +115,10 @@ export function Inbox({ items, onNavigate }: InboxProps) {
|
||||
initial={{ opacity: 0, y: -8 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, x: 20 }}
|
||||
className={`group flex items-center gap-3 rounded-[8px] border border-l-[3px] border-[color:var(--line)] bg-[color:var(--panel)] px-4 py-3 transition duration-150 hover:border-[color:var(--line-strong)] hover:shadow-md hover:-translate-y-px ${severityColors[item.severity] ?? ""}`}
|
||||
className={`group flex items-center gap-3 rounded-lg border border-l-[3px] border-border bg-card px-4 py-3 transition duration-150 hover:border-border hover:shadow-md hover:-translate-y-px ${severityColors[item.severity] ?? ""}`}
|
||||
>
|
||||
<div
|
||||
className="flex h-9 w-9 shrink-0 items-center justify-center rounded-[8px]"
|
||||
className="flex h-9 w-9 shrink-0 items-center justify-center rounded-lg"
|
||||
style={{ backgroundColor: config.bg }}
|
||||
>
|
||||
<Icon size={18} weight="fill" style={{ color: config.color }} />
|
||||
@@ -129,7 +129,7 @@ export function Inbox({ items, onNavigate }: InboxProps) {
|
||||
className="min-w-0 flex-1 text-left"
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="truncate text-[13px] font-medium text-[color:var(--text)]">{item.title}</span>
|
||||
<span className="truncate text-[13px] font-medium text-foreground">{item.title}</span>
|
||||
<span
|
||||
className="shrink-0 rounded-full px-2 py-0.5 text-[9px] font-bold uppercase tracking-[0.1em]"
|
||||
style={{ backgroundColor: config.bg, color: config.color }}
|
||||
@@ -137,7 +137,7 @@ export function Inbox({ items, onNavigate }: InboxProps) {
|
||||
{config.label}
|
||||
</span>
|
||||
</div>
|
||||
<div className="mt-0.5 flex items-center gap-2 text-[11px] text-[color:var(--muted)]">
|
||||
<div className="mt-0.5 flex items-center gap-2 text-[11px] text-muted-foreground">
|
||||
{item.agentName ? (
|
||||
<span className="flex items-center gap-1">
|
||||
<Robot size={10} />
|
||||
@@ -148,7 +148,7 @@ export function Inbox({ items, onNavigate }: InboxProps) {
|
||||
<span className="shrink-0 tabular-nums">{timeAgo(item.createdAt)}</span>
|
||||
</div>
|
||||
</button>
|
||||
<ArrowRight size={14} className="shrink-0 text-[color:var(--muted)] opacity-0 transition group-hover:opacity-100 group-focus-within:opacity-100" />
|
||||
<ArrowRight size={14} className="shrink-0 text-muted-foreground opacity-0 transition group-hover:opacity-100 group-focus-within:opacity-100" />
|
||||
</motion.div>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -13,10 +13,10 @@ export function PerformanceView({ metrics, onNavigate }: PerformanceProps) {
|
||||
const t = useT();
|
||||
if (!metrics) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center rounded-[8px] border border-dashed border-[color:var(--line)] py-16 text-center">
|
||||
<Target size={32} className="mb-3 text-[color:var(--muted)]" />
|
||||
<div className="text-[14px] font-medium text-[color:var(--muted-strong)]">{t("perf.noMetrics")}</div>
|
||||
<div className="mt-1 text-[12px] text-[color:var(--muted)]">{t("perf.noMetricsDesc")}</div>
|
||||
<div className="flex flex-col items-center justify-center rounded-lg border border-dashed border-border py-16 text-center">
|
||||
<Target size={32} className="mb-3 text-muted-foreground" />
|
||||
<div className="text-[14px] font-medium text-muted-foreground">{t("perf.noMetrics")}</div>
|
||||
<div className="mt-1 text-[12px] text-muted-foreground">{t("perf.noMetricsDesc")}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -48,8 +48,8 @@ export function PerformanceView({ metrics, onNavigate }: PerformanceProps) {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="rounded-[8px] border border-[color:var(--line)] bg-[color:var(--panel)] p-5">
|
||||
<div className="mb-3 text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--muted)]">Run Activity (30d)</div>
|
||||
<div className="rounded-lg border border-border bg-card p-5">
|
||||
<div className="mb-3 text-[11px] font-semibold uppercase tracking-[0.08em] text-muted-foreground">Run Activity (30d)</div>
|
||||
<div className="flex items-center gap-6">
|
||||
<div className="flex-1">
|
||||
<RunProgressBar
|
||||
@@ -60,29 +60,29 @@ export function PerformanceView({ metrics, onNavigate }: PerformanceProps) {
|
||||
</div>
|
||||
<div className="flex gap-4 text-[12px]">
|
||||
<span className="flex items-center gap-1.5">
|
||||
<span className="h-2.5 w-2.5 rounded-full bg-[color:var(--success)]" />
|
||||
<span className="text-[color:var(--muted)]">{metrics.successfulRuns} succeeded</span>
|
||||
<span className="h-2.5 w-2.5 rounded-full bg-green-600 dark:bg-green-400" />
|
||||
<span className="text-muted-foreground">{metrics.successfulRuns} succeeded</span>
|
||||
</span>
|
||||
<span className="flex items-center gap-1.5">
|
||||
<span className="h-2.5 w-2.5 rounded-full bg-[color:var(--danger)]" />
|
||||
<span className="text-[color:var(--muted)]">{metrics.failedRuns} failed</span>
|
||||
<span className="h-2.5 w-2.5 rounded-full bg-destructive" />
|
||||
<span className="text-muted-foreground">{metrics.failedRuns} failed</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section>
|
||||
<div className="mb-3 text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--muted)]">Agent Performance</div>
|
||||
<div className="overflow-x-auto rounded-[8px] border border-[color:var(--line)]">
|
||||
<div className="mb-3 text-[11px] font-semibold uppercase tracking-[0.08em] text-muted-foreground">Agent Performance</div>
|
||||
<div className="overflow-x-auto rounded-lg border border-border">
|
||||
<table className="w-full text-left">
|
||||
<thead>
|
||||
<tr className="border-b border-[color:var(--line)] bg-[color:var(--panel-soft)]">
|
||||
<th className="px-4 py-2.5 text-[11px] font-semibold uppercase tracking-[0.06em] text-[color:var(--muted)]">Agent</th>
|
||||
<th className="px-3 py-2.5 text-[11px] font-semibold uppercase tracking-[0.06em] text-[color:var(--muted)] text-right">Tasks Done</th>
|
||||
<th className="px-3 py-2.5 text-[11px] font-semibold uppercase tracking-[0.06em] text-[color:var(--muted)] text-right">Success %</th>
|
||||
<th className="px-3 py-2.5 text-[11px] font-semibold uppercase tracking-[0.06em] text-[color:var(--muted)] text-right">Runs</th>
|
||||
<th className="px-3 py-2.5 text-[11px] font-semibold uppercase tracking-[0.06em] text-[color:var(--muted)] text-right">Avg Duration</th>
|
||||
<th className="px-3 py-2.5 text-[11px] font-semibold uppercase tracking-[0.06em] text-[color:var(--muted)] text-right">Cost</th>
|
||||
<tr className="border-b border-border bg-muted">
|
||||
<th className="px-4 py-2.5 text-[11px] font-semibold uppercase tracking-[0.06em] text-muted-foreground">Agent</th>
|
||||
<th className="px-3 py-2.5 text-[11px] font-semibold uppercase tracking-[0.06em] text-muted-foreground text-right">Tasks Done</th>
|
||||
<th className="px-3 py-2.5 text-[11px] font-semibold uppercase tracking-[0.06em] text-muted-foreground text-right">Success %</th>
|
||||
<th className="px-3 py-2.5 text-[11px] font-semibold uppercase tracking-[0.06em] text-muted-foreground text-right">Runs</th>
|
||||
<th className="px-3 py-2.5 text-[11px] font-semibold uppercase tracking-[0.06em] text-muted-foreground text-right">Avg Duration</th>
|
||||
<th className="px-3 py-2.5 text-[11px] font-semibold uppercase tracking-[0.06em] text-muted-foreground text-right">Cost</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -91,30 +91,30 @@ export function PerformanceView({ metrics, onNavigate }: PerformanceProps) {
|
||||
.map((am) => (
|
||||
<tr
|
||||
key={am.agentId}
|
||||
className="border-b border-[color:var(--line)] bg-[color:var(--panel)] transition hover:bg-[color:var(--panel-soft)] cursor-pointer"
|
||||
className="border-b border-border bg-card transition hover:bg-muted cursor-pointer"
|
||||
onClick={() => onNavigate("agents", am.agentId)}
|
||||
>
|
||||
<td className="px-4 py-2.5">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex h-7 w-7 items-center justify-center rounded-full bg-[color:var(--panel-soft)] text-[10px] font-bold text-[color:var(--muted-strong)]">
|
||||
<div className="flex h-7 w-7 items-center justify-center rounded-full bg-muted text-[10px] font-bold text-muted-foreground">
|
||||
{getAgentInitials(am.agentName)}
|
||||
</div>
|
||||
<span className="text-[12px] font-medium text-[color:var(--text)]">{am.agentName}</span>
|
||||
<span className="text-[12px] font-medium text-foreground">{am.agentName}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-3 py-2.5 text-right text-[12px] font-semibold text-[color:var(--success)]">{am.tasksCompleted}</td>
|
||||
<td className="px-3 py-2.5 text-right text-[12px] font-semibold text-green-600 dark:text-green-400">{am.tasksCompleted}</td>
|
||||
<td className="px-3 py-2.5 text-right">
|
||||
<span className={`text-[12px] font-semibold ${
|
||||
am.successRate >= 80 ? "text-[color:var(--success)]"
|
||||
: am.successRate >= 50 ? "text-[color:var(--warn)]"
|
||||
: "text-[color:var(--danger)]"
|
||||
am.successRate >= 80 ? "text-green-600 dark:text-green-400"
|
||||
: am.successRate >= 50 ? "text-yellow-600 dark:text-yellow-400"
|
||||
: "text-destructive"
|
||||
}`}>
|
||||
{am.successRate}%
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-3 py-2.5 text-right text-[12px] text-[color:var(--muted)]">{am.runsTotal}</td>
|
||||
<td className="px-3 py-2.5 text-right text-[12px] text-[color:var(--muted)]">{formatDuration(am.avgRunDurationSec)}</td>
|
||||
<td className="px-3 py-2.5 text-right text-[12px] text-[color:var(--muted)]">{formatMoney(am.totalCostUsd)}</td>
|
||||
<td className="px-3 py-2.5 text-right text-[12px] text-muted-foreground">{am.runsTotal}</td>
|
||||
<td className="px-3 py-2.5 text-right text-[12px] text-muted-foreground">{formatDuration(am.avgRunDurationSec)}</td>
|
||||
<td className="px-3 py-2.5 text-right text-[12px] text-muted-foreground">{formatMoney(am.totalCostUsd)}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
|
||||
@@ -18,60 +18,60 @@ export function StandupView({ report, onNavigate }: StandupProps) {
|
||||
const t = useT();
|
||||
if (!report) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center rounded-[8px] border border-dashed border-[color:var(--line)] py-16 text-center">
|
||||
<Clock size={32} className="mb-3 text-[color:var(--muted)]" />
|
||||
<div className="text-[14px] font-medium text-[color:var(--muted-strong)]">{t("standup.noData")}</div>
|
||||
<div className="mt-1 text-[12px] text-[color:var(--muted)]">{t("standup.noDataDesc")}</div>
|
||||
<div className="flex flex-col items-center justify-center rounded-lg border border-dashed border-border py-16 text-center">
|
||||
<Clock size={32} className="mb-3 text-muted-foreground" />
|
||||
<div className="text-[14px] font-medium text-muted-foreground">{t("standup.noData")}</div>
|
||||
<div className="mt-1 text-[12px] text-muted-foreground">{t("standup.noDataDesc")}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="rounded-[8px] border border-[color:var(--line)] bg-[color:var(--panel)] p-5">
|
||||
<div className="rounded-lg border border-border bg-card p-5">
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-[8px] bg-[color:var(--accent-soft)]">
|
||||
<Heartbeat size={20} weight="fill" className="text-[color:var(--accent)]" />
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-accent">
|
||||
<Heartbeat size={20} weight="fill" className="text-primary" />
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="text-[16px] font-bold text-[color:var(--text)]">{t("standup.dailyStandup")}</h2>
|
||||
<p className="text-[12px] text-[color:var(--muted)]">
|
||||
<h2 className="text-[16px] font-bold text-foreground">{t("standup.dailyStandup")}</h2>
|
||||
<p className="text-[12px] text-muted-foreground">
|
||||
Generated {new Date(report.generatedAt).toLocaleString()}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-[14px] font-medium text-[color:var(--text)]">{report.summary}</div>
|
||||
<div className="text-[14px] font-medium text-foreground">{report.summary}</div>
|
||||
<div className="mt-3 flex gap-4">
|
||||
<div className="text-center">
|
||||
<div className="text-[18px] font-bold tabular-nums text-[color:var(--success)]">{report.agentReports.filter(r => r.tasksCompleted24h > 0).length}</div>
|
||||
<div className="text-[10px] text-[color:var(--muted)]">{t("standup.productive")}</div>
|
||||
<div className="text-[18px] font-bold tabular-nums text-green-600 dark:text-green-400">{report.agentReports.filter(r => r.tasksCompleted24h > 0).length}</div>
|
||||
<div className="text-[10px] text-muted-foreground">{t("standup.productive")}</div>
|
||||
</div>
|
||||
<div className="h-10 w-px bg-[color:var(--line)]" />
|
||||
<div className="h-10 w-px bg-[color:var(--border)]" />
|
||||
<div className="text-center">
|
||||
<div className="text-[18px] font-bold tabular-nums text-[color:var(--danger)]">{report.blockers.length}</div>
|
||||
<div className="text-[10px] text-[color:var(--muted)]">{t("standup.blockers")}</div>
|
||||
<div className="text-[18px] font-bold tabular-nums text-destructive">{report.blockers.length}</div>
|
||||
<div className="text-[10px] text-muted-foreground">{t("standup.blockers")}</div>
|
||||
</div>
|
||||
<div className="h-10 w-px bg-[color:var(--line)]" />
|
||||
<div className="h-10 w-px bg-[color:var(--border)]" />
|
||||
<div className="text-center">
|
||||
<div className="text-[18px] font-bold tabular-nums text-[color:var(--warn)]">{report.pendingApprovals}</div>
|
||||
<div className="text-[10px] text-[color:var(--muted)]">{t("standup.pendingApprovals")}</div>
|
||||
<div className="text-[18px] font-bold tabular-nums text-yellow-600 dark:text-yellow-400">{report.pendingApprovals}</div>
|
||||
<div className="text-[10px] text-muted-foreground">{t("standup.pendingApprovals")}</div>
|
||||
</div>
|
||||
<div className="h-10 w-px bg-[color:var(--line)]" />
|
||||
<div className="h-10 w-px bg-[color:var(--border)]" />
|
||||
<div className="text-center">
|
||||
<div className={`text-[18px] font-bold tabular-nums ${report.budgetUtilization > 80 ? "text-[color:var(--danger)]" : "text-[color:var(--text)]"}`}>
|
||||
<div className={`text-[18px] font-bold tabular-nums ${report.budgetUtilization > 80 ? "text-destructive" : "text-foreground"}`}>
|
||||
{report.budgetUtilization}%
|
||||
</div>
|
||||
<div className="text-[10px] text-[color:var(--muted)]">{t("standup.budgetUsed")}</div>
|
||||
<div className="text-[10px] text-muted-foreground">{t("standup.budgetUsed")}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{report.companyHighlights.length > 0 ? (
|
||||
<section>
|
||||
<div className="mb-2 text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--muted)]">{t("standup.highlights")}</div>
|
||||
<div className="mb-2 text-[11px] font-semibold uppercase tracking-[0.08em] text-muted-foreground">{t("standup.highlights")}</div>
|
||||
<div className="space-y-1.5">
|
||||
{report.companyHighlights.map((h, i) => (
|
||||
<div key={i} className="flex items-center gap-2 rounded-[6px] bg-[color:var(--success-soft)] px-3 py-2 text-[12px] text-[color:var(--success)]">
|
||||
<div key={i} className="flex items-center gap-2 rounded-lg bg-green-100 dark:bg-green-900/50 px-3 py-2 text-[12px] text-green-600 dark:text-green-400">
|
||||
<CheckCircle size={14} weight="fill" />
|
||||
{h}
|
||||
</div>
|
||||
@@ -82,10 +82,10 @@ export function StandupView({ report, onNavigate }: StandupProps) {
|
||||
|
||||
{report.blockers.length > 0 ? (
|
||||
<section>
|
||||
<div className="mb-2 text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--danger)]">Blockers</div>
|
||||
<div className="mb-2 text-[11px] font-semibold uppercase tracking-[0.08em] text-destructive">Blockers</div>
|
||||
<div className="space-y-1.5">
|
||||
{report.blockers.map((b, i) => (
|
||||
<div key={i} className="flex items-center gap-2 rounded-[6px] bg-[color:var(--danger-soft)] px-3 py-2 text-[12px] text-[color:var(--danger)]">
|
||||
<div key={i} className="flex items-center gap-2 rounded-lg bg-red-100 dark:bg-red-900/50 px-3 py-2 text-[12px] text-destructive">
|
||||
<Warning size={14} weight="fill" />
|
||||
{b}
|
||||
</div>
|
||||
@@ -95,46 +95,46 @@ export function StandupView({ report, onNavigate }: StandupProps) {
|
||||
) : null}
|
||||
|
||||
<section>
|
||||
<div className="mb-2 text-[11px] font-semibold uppercase tracking-[0.08em] text-[color:var(--muted)]">{t("standup.agentStatus")}</div>
|
||||
<div className="mb-2 text-[11px] font-semibold uppercase tracking-[0.08em] text-muted-foreground">{t("standup.agentStatus")}</div>
|
||||
<div className="space-y-2">
|
||||
{report.agentReports.map((ar) => (
|
||||
<button
|
||||
key={ar.agentId}
|
||||
type="button"
|
||||
onClick={() => onNavigate("agents", ar.agentId)}
|
||||
className="flex w-full items-center gap-3 rounded-[8px] border border-[color:var(--line)] bg-[color:var(--panel)] px-4 py-3 text-left transition hover:border-[color:var(--line-strong)] hover:shadow-sm"
|
||||
className="flex w-full items-center gap-3 rounded-lg border border-border bg-card px-4 py-3 text-left transition hover:border-border hover:shadow-sm"
|
||||
>
|
||||
<div className="relative">
|
||||
<div className={`flex h-10 w-10 items-center justify-center rounded-full text-[12px] font-bold ${
|
||||
ar.status === "running" ? "bg-[color:var(--success-soft)] text-[color:var(--success)]"
|
||||
: ar.status === "error" ? "bg-[color:var(--danger-soft)] text-[color:var(--danger)]"
|
||||
: "bg-[color:var(--panel-soft)] text-[color:var(--muted-strong)]"
|
||||
ar.status === "running" ? "bg-green-100 dark:bg-green-900/50 text-green-600 dark:text-green-400"
|
||||
: ar.status === "error" ? "bg-red-100 dark:bg-red-900/50 text-destructive"
|
||||
: "bg-muted text-muted-foreground"
|
||||
}`}>
|
||||
{getAgentInitials(ar.agentName)}
|
||||
</div>
|
||||
{ar.status === "running" ? (
|
||||
<span className="absolute -bottom-0.5 -right-0.5 flex h-3 w-3">
|
||||
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-[color:var(--success)] opacity-40" style={{ willChange: "transform" }} />
|
||||
<span className="relative inline-flex h-2 w-2 rounded-full bg-[color:var(--success)]" />
|
||||
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-green-600 dark:bg-green-400 opacity-40" style={{ willChange: "transform" }} />
|
||||
<span className="relative inline-flex h-2 w-2 rounded-full bg-green-600 dark:bg-green-400" />
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-[13px] font-semibold text-[color:var(--text)]">{ar.agentName}</span>
|
||||
<span className="text-[10px] text-[color:var(--muted)]">{ar.role}</span>
|
||||
<span className="text-[13px] font-semibold text-foreground">{ar.agentName}</span>
|
||||
<span className="text-[10px] text-muted-foreground">{ar.role}</span>
|
||||
</div>
|
||||
<div className="mt-1 flex flex-wrap gap-3 text-[11px] text-[color:var(--muted)]">
|
||||
{ar.tasksInProgress > 0 ? <span className="text-[color:var(--accent)]">{ar.tasksInProgress} in progress</span> : null}
|
||||
{ar.tasksCompleted24h > 0 ? <span className="text-[color:var(--success)]">{ar.tasksCompleted24h} done</span> : null}
|
||||
{ar.tasksBlocked > 0 ? <span className="text-[color:var(--danger)]">{ar.tasksBlocked} blocked</span> : null}
|
||||
<div className="mt-1 flex flex-wrap gap-3 text-[11px] text-muted-foreground">
|
||||
{ar.tasksInProgress > 0 ? <span className="text-primary">{ar.tasksInProgress} in progress</span> : null}
|
||||
{ar.tasksCompleted24h > 0 ? <span className="text-green-600 dark:text-green-400">{ar.tasksCompleted24h} done</span> : null}
|
||||
{ar.tasksBlocked > 0 ? <span className="text-destructive">{ar.tasksBlocked} blocked</span> : null}
|
||||
{ar.costLast24h > 0 ? <span className="tabular-nums">${ar.costLast24h.toFixed(2)}</span> : null}
|
||||
</div>
|
||||
{ar.highlights.length > 0 ? (
|
||||
<div className="mt-1 text-[10px] text-[color:var(--muted)]">{ar.highlights.join(" \u00B7 ")}</div>
|
||||
<div className="mt-1 text-[10px] text-muted-foreground">{ar.highlights.join(" \u00B7 ")}</div>
|
||||
) : null}
|
||||
</div>
|
||||
<ArrowRight size={14} className="shrink-0 text-[color:var(--muted)]" />
|
||||
<ArrowRight size={14} className="shrink-0 text-muted-foreground" />
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -10,19 +10,19 @@ import {
|
||||
import type { InboxItemType } from "@shared/types";
|
||||
|
||||
export const typeConfig: Record<InboxItemType, { icon: React.ElementType; color: string; bg: string; label: string }> = {
|
||||
pending_approval: { icon: ShieldCheck, color: "var(--warn)", bg: "var(--warn-soft)", label: "Approval" },
|
||||
failed_run: { icon: XCircle, color: "var(--danger)", bg: "var(--danger-soft)", label: "Failed Run" },
|
||||
budget_warning: { icon: CurrencyCircleDollar, color: "var(--warn)", bg: "var(--warn-soft)", label: "Budget" },
|
||||
blocked_task: { icon: Warning, color: "var(--danger)", bg: "var(--danger-soft)", label: "Blocked" },
|
||||
review_needed: { icon: Eye, color: "var(--accent)", bg: "var(--accent-soft)", label: "Review" },
|
||||
agent_message: { icon: ChatCircle, color: "var(--accent)", bg: "var(--accent-soft)", label: "Message" },
|
||||
pending_approval: { icon: ShieldCheck, color: "var(--destructive)", bg: "var(--muted-foreground)", label: "Approval" },
|
||||
failed_run: { icon: XCircle, color: "var(--destructive)", bg: "var(--destructive)", label: "Failed Run" },
|
||||
budget_warning: { icon: CurrencyCircleDollar, color: "var(--destructive)", bg: "var(--muted-foreground)", label: "Budget" },
|
||||
blocked_task: { icon: Warning, color: "var(--destructive)", bg: "var(--destructive)", label: "Blocked" },
|
||||
review_needed: { icon: Eye, color: "var(--primary)", bg: "var(--primary)", label: "Review" },
|
||||
agent_message: { icon: ChatCircle, color: "var(--primary)", bg: "var(--primary)", label: "Message" },
|
||||
};
|
||||
|
||||
export const severityColors: Record<string, string> = {
|
||||
critical: "border-l-[color:var(--danger)]",
|
||||
high: "border-l-[color:var(--warn)]",
|
||||
medium: "border-l-[color:var(--accent)]",
|
||||
low: "border-l-[color:var(--line)]",
|
||||
critical: "border-l-[color:var(--destructive)]",
|
||||
high: "border-l-[color:var(--destructive)]",
|
||||
medium: "border-l-[color:var(--primary)]",
|
||||
low: "border-l-[color:var(--border)]",
|
||||
};
|
||||
|
||||
export function CompactMetric({ label, value, tone = "default", subtitle }: {
|
||||
@@ -32,37 +32,37 @@ export function CompactMetric({ label, value, tone = "default", subtitle }: {
|
||||
subtitle?: string;
|
||||
}) {
|
||||
const toneMap = {
|
||||
default: "text-[color:var(--text)]",
|
||||
success: "text-[color:var(--success)]",
|
||||
warn: "text-[color:var(--warn)]",
|
||||
danger: "text-[color:var(--danger)]",
|
||||
accent: "text-[color:var(--accent)]",
|
||||
default: "text-foreground",
|
||||
success: "text-green-600 dark:text-green-400",
|
||||
warn: "text-yellow-600 dark:text-yellow-400",
|
||||
danger: "text-destructive",
|
||||
accent: "text-primary",
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="rounded-[8px] border border-[color:var(--line)] bg-[color:var(--panel)] px-4 py-3">
|
||||
<div className="text-[10px] font-semibold uppercase tracking-[0.08em] text-[color:var(--muted)]">{label}</div>
|
||||
<div className="rounded-lg border border-border bg-card px-4 py-3">
|
||||
<div className="text-[10px] font-semibold uppercase tracking-[0.08em] text-muted-foreground">{label}</div>
|
||||
<div className={`text-[22px] font-bold ${toneMap[tone]}`}>{value}</div>
|
||||
{subtitle ? <div className="text-[10px] text-[color:var(--muted)]">{subtitle}</div> : null}
|
||||
{subtitle ? <div className="text-[10px] text-muted-foreground">{subtitle}</div> : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function RunProgressBar({ succeeded, failed, total }: { succeeded: number; failed: number; total: number }) {
|
||||
if (total === 0) return <div className="h-3 rounded-full bg-[color:var(--panel-soft)]" />;
|
||||
if (total === 0) return <div className="h-3 rounded-full bg-muted" />;
|
||||
const successPct = (succeeded / total) * 100;
|
||||
const failPct = (failed / total) * 100;
|
||||
|
||||
return (
|
||||
<div className="flex h-3 overflow-hidden rounded-full bg-[color:var(--panel-soft)]">
|
||||
<div className="flex h-3 overflow-hidden rounded-full bg-muted">
|
||||
<motion.div
|
||||
className="h-full bg-[color:var(--success)]"
|
||||
className="h-full bg-green-600 dark:bg-green-400"
|
||||
initial={{ width: 0 }}
|
||||
animate={{ width: `${successPct}%` }}
|
||||
transition={{ duration: 0.8, ease: "easeOut" }}
|
||||
/>
|
||||
<motion.div
|
||||
className="h-full bg-[color:var(--danger)]"
|
||||
className="h-full bg-destructive"
|
||||
initial={{ width: 0 }}
|
||||
animate={{ width: `${failPct}%` }}
|
||||
transition={{ duration: 0.8, ease: "easeOut", delay: 0.2 }}
|
||||
|
||||
Reference in new issue
Block a user