refactor(ui): promote BudgetBar and InlineConfirmDelete to shared ui/

BudgetBar and ConfirmDelete were only sitting in organization/helpers.tsx
but have no organization-specific behaviour. Move them under
components/ui/ and keep the old exports as re-exports so existing
importers continue to resolve. HeartbeatSection stays in helpers.tsx
because it owns agent-specific heartbeat IPC.
This commit is contained in:
ZacharyZhang-NY committed 2026-04-16 23:34:12 -04:00
1 parent 61aba41e77
commit dd007760b8
4 files changed
+51 -39

No files matched your search

@@ -1,44 +1,13 @@
import { Heartbeat, Lightning, Trash, XCircle } from "@phosphor-icons/react";
import { Heartbeat, Lightning } from "@phosphor-icons/react";
import type { AgentRecord } from "@shared/types";
import { ActionButton, Select } from "../ui";
import { formatMoney, formatTime } from "../../lib/formatters";
import { ActionButton, BudgetBar, InlineConfirmDelete, Select } from "../ui";
import { formatTime } from "../../lib/formatters";
import { unwrap } from "../../lib/desktop";
export function BudgetBar({ spent, budget }: { spent: number; budget: number }) {
const pct = budget > 0 ? Math.min((spent / budget) * 100, 100) : 0;
const overBudget = spent > budget && budget > 0;
return (
<div className="flex items-center gap-2">
<div className="h-1.5 w-20 overflow-hidden rounded-full bg-[color:var(--border)]">
<div
className={`h-full rounded-full transition-all ${overBudget ? "bg-destructive" : "bg-success"}`}
style={{ width: `${pct}%` }}
/>
</div>
<span className={`text-[11px] ${overBudget ? "text-destructive" : "text-muted-foreground"}`}>
{formatMoney(spent)} / {formatMoney(budget)}
</span>
</div>
);
}
export function ConfirmDelete({
entityLabel,
onConfirm,
onCancel,
}: {
entityLabel: string;
onConfirm: () => void;
onCancel: () => void;
}) {
return (
<div className="flex items-center gap-3 rounded-lg border border-[color:var(--destructive)] bg-destructive-muted px-4 py-3">
<span className="text-[13px] text-destructive">Delete {entityLabel}?</span>
<ActionButton label="Yes, delete" tone="danger" onClick={onConfirm} icon={Trash} />
<ActionButton label="Cancel" onClick={onCancel} icon={XCircle} />
</div>
);
}
// Re-exports kept so existing importers continue to work while BudgetBar and
// the inline-delete confirmation live in the shared UI library.
export { BudgetBar };
export const ConfirmDelete = InlineConfirmDelete;
const HEARTBEAT_INTERVALS = [
{ value: "30", label: "30 seconds" },
+19
View File
@@ -0,0 +1,19 @@
import { formatMoney } from "../../lib/formatters";
export function BudgetBar({ spent, budget }: { spent: number; budget: number }) {
const pct = budget > 0 ? Math.min((spent / budget) * 100, 100) : 0;
const overBudget = spent > budget && budget > 0;
return (
<div className="flex items-center gap-2">
<div className="h-1.5 w-20 overflow-hidden rounded-full bg-[color:var(--border)]">
<div
className={`h-full rounded-full transition-all ${overBudget ? "bg-destructive" : "bg-success"}`}
style={{ width: `${pct}%` }}
/>
</div>
<span className={`text-[11px] ${overBudget ? "text-destructive" : "text-muted-foreground"}`}>
{formatMoney(spent)} / {formatMoney(budget)}
</span>
</div>
);
}
+23
View File
@@ -1,5 +1,6 @@
import { useEffect, type ReactNode } from "react";
import { AnimatePresence, motion } from "framer-motion";
import { Trash, XCircle } from "@phosphor-icons/react";
import { ActionButton } from "./primitives";
import { useFocusTrap } from "./hooks";
@@ -137,6 +138,28 @@ export function ConfirmDialog({ open, title, message, errorMessage, onConfirm, o
);
}
/* ------------------------------------------------------------------ */
/* InlineConfirmDelete */
/* ------------------------------------------------------------------ */
export function InlineConfirmDelete({
entityLabel,
onConfirm,
onCancel,
}: {
entityLabel: string;
onConfirm: () => void;
onCancel: () => void;
}) {
return (
<div className="flex items-center gap-3 rounded-lg border border-[color:var(--destructive)] bg-destructive-muted px-4 py-3">
<span className="text-[13px] text-destructive">Delete {entityLabel}?</span>
<ActionButton label="Yes, delete" tone="danger" onClick={onConfirm} icon={Trash} />
<ActionButton label="Cancel" onClick={onCancel} icon={XCircle} />
</div>
);
}
/* ------------------------------------------------------------------ */
/* EmptyState */
/* ------------------------------------------------------------------ */
+2 -1
View File
@@ -1,5 +1,6 @@
export { Badge, SectionButton, Panel, Field, Input, TextArea, Select, ActionButton, Spinner, Eyebrow, Card } from "./primitives";
export { StatusPill, InlineNotice, ConfirmDialog, EmptyState } from "./feedback";
export { StatusPill, InlineNotice, ConfirmDialog, InlineConfirmDelete, EmptyState } from "./feedback";
export { BudgetBar } from "./BudgetBar";
export { Modal, ListFrame, ListRow } from "./layout";
export { useFocusTrap, useReducedMotion, ErrorBoundary } from "./hooks";
export { AttentionRow } from "./AttentionRow";