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:
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" },
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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 */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
@@ -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";
|
||||
|
||||
Reference in new issue
Block a user