diff --git a/src/renderer/components/inbox/Inbox.tsx b/src/renderer/components/inbox/Inbox.tsx index dc9c6cd3..cfe7c30c 100644 --- a/src/renderer/components/inbox/Inbox.tsx +++ b/src/renderer/components/inbox/Inbox.tsx @@ -8,7 +8,7 @@ import { import type { InboxItem, InboxItemType, SectionId } from "@shared/types"; import { timeAgo } from "../../lib/formatters"; import { useT } from "../../i18n"; -import { typeConfig, severityBorderClass } from "./inbox-helpers"; +import { typeConfig } from "./inbox-helpers"; import { AttentionRow } from "../ui"; interface InboxProps { @@ -104,12 +104,15 @@ export function Inbox({ items, onNavigate }: InboxProps) {
{t("inbox.noItemsNow")}
) : ( -
+
{filteredItems.map((item, i) => { const config = typeConfig[item.type]; const Icon = config.icon; - const title = {item.title}; + const isUrgent = item.severity === "critical" || item.severity === "high"; + const title = ( + {item.title} + ); const subtitle = ( {item.agentName ? ( @@ -119,6 +122,9 @@ export function Inbox({ items, onNavigate }: InboxProps) { ) : null} {item.subtitle.slice(0, 80)} + {isUrgent ? ( + ); @@ -127,11 +133,9 @@ export function Inbox({ items, onNavigate }: InboxProps) { key={item.id} index={i} icon={Icon} - iconColor={config.color} - iconTileBg={config.bg} - iconWeight="fill" - rowBgClass="bg-card" - borderAccentClass={`border-l-[3px] border-border hover:shadow-md hover:-translate-y-px ${severityBorderClass(item.severity)}`} + tone="info" + iconWeight={isUrgent ? "bold" : "regular"} + variant="line" title={title} subtitle={subtitle} onClick={() => handleItemClick(item)} diff --git a/src/renderer/components/inbox/inbox-helpers.tsx b/src/renderer/components/inbox/inbox-helpers.tsx index 275f7a46..a39346be 100644 --- a/src/renderer/components/inbox/inbox-helpers.tsx +++ b/src/renderer/components/inbox/inbox-helpers.tsx @@ -10,27 +10,15 @@ import { import type { InboxItemType } from "@shared/types"; import { Card } from "../ui"; -export const typeConfig: Record = { - 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 typeConfig: Record = { + pending_approval: { icon: ShieldCheck, label: "Approval" }, + failed_run: { icon: XCircle, label: "Failed Run" }, + budget_warning: { icon: CurrencyCircleDollar, label: "Budget" }, + blocked_task: { icon: Warning, label: "Blocked" }, + review_needed: { icon: Eye, label: "Review" }, + agent_message: { icon: ChatCircle, label: "Message" }, }; -export const severityColors: Record = { - 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 severityBorderClass(severity: string | null | undefined): string { - if (!severity) return "border-l-[color:var(--border)]"; - return severityColors[severity] ?? "border-l-[color:var(--border)]"; -} - export function CompactMetric({ label, value, tone = "default", subtitle }: { label: string; value: string | number; diff --git a/src/renderer/components/ui/AttentionRow.tsx b/src/renderer/components/ui/AttentionRow.tsx index 8f203568..2a9bf31e 100644 --- a/src/renderer/components/ui/AttentionRow.tsx +++ b/src/renderer/components/ui/AttentionRow.tsx @@ -6,6 +6,7 @@ const ATTENTION_STAGGER_MAX = 8; const ATTENTION_STAGGER_STEP = 0.04; export type AttentionTone = "warn" | "danger" | "info" | "neutral"; +export type AttentionVariant = "card" | "line"; export interface AttentionRowProps { icon: ElementType; @@ -21,6 +22,7 @@ export interface AttentionRowProps { borderAccentClass?: string; showArrow?: boolean; iconWeight?: "fill" | "bold" | "regular"; + variant?: AttentionVariant; } const toneIconClass: Record = { @@ -51,30 +53,53 @@ export function AttentionRow({ borderAccentClass, showArrow = true, iconWeight, + variant = "card", }: AttentionRowProps) { const iconClass = iconColor ? "" : toneIconClass[tone]; - const bgClass = rowBgClass ?? toneBgClass[tone]; const delay = Math.min(index, ATTENTION_STAGGER_MAX) * ATTENTION_STAGGER_STEP; - const borderClass = borderAccentClass ?? "border-[color:var(--destructive)] border-opacity-20 hover:border-opacity-40"; const isButton = typeof onClick === "function"; - const commonClass = `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 ${borderClass} ${bgClass} px-4 py-3 text-left transition`; - const iconElement = iconTileBg ? ( -
- -
- ) : ( - - ); + const chromeClass = + variant === "line" + ? "border-b border-border/60 hover:bg-muted/40 px-2 py-3" + : (() => { + const bgClass = rowBgClass ?? toneBgClass[tone]; + const borderClass = + borderAccentClass ?? + "border-[color:var(--destructive)] border-opacity-20 hover:border-opacity-40"; + return `rounded-lg border ${borderClass} ${bgClass} px-4 py-3`; + })(); + const commonClass = `focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 flex w-full items-center gap-3 text-left transition ${chromeClass}`; + + const iconElement = + variant === "card" && iconTileBg ? ( +
+ +
+ ) : ( + + ); + + const titleWeightClass = variant === "line" ? "" : "font-medium"; const inner = ( <> {iconElement}
-
{title}
+
{title}
{subtitle ?
{subtitle}
: null}
{rightMeta}