865c6c1d1e
Moves FileViewer, EditorModal, ConfirmDeleteModal, ToastNotice, MdItemList, ScopeBadge, and the shared atoms (Empty/SkeletonRows/CopyButton/formatBytes) into client/src/components/config/ so the upcoming Codex config panel can reuse them. EditorModal now takes a fetchContent callback instead of calling api.ccConfig.file itself; CcConfig.tsx supplies the Claude-specific fetcher. The moved EditorState/ConfirmDeleteState type field widens from CcArtifactType to string so non-Claude callers can use them too, with a cast at the two remaining Claude-specific call sites in CcConfig.tsx.
47 lines
1.4 KiB
TypeScript
47 lines
1.4 KiB
TypeScript
/**
|
|
* @file ToastNotice.tsx
|
|
* @description Bottom-right success/error toast for the config explorer.
|
|
* Tool-agnostic — the page owns the 5s auto-dismiss timer and passes the
|
|
* message down.
|
|
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
|
*/
|
|
|
|
import { AlertCircle, Check, X } from "lucide-react";
|
|
|
|
export type Toast = { kind: "success" | "error"; message: string } | null;
|
|
|
|
export function ToastNotice({
|
|
toast,
|
|
onDismiss,
|
|
}: {
|
|
toast: NonNullable<Toast>;
|
|
onDismiss: () => void;
|
|
}) {
|
|
const isErr = toast.kind === "error";
|
|
return (
|
|
<div className="fixed bottom-6 right-6 z-50 max-w-md">
|
|
<div
|
|
className={`rounded-lg border px-3 py-2 shadow-lg flex items-start gap-2 ${
|
|
isErr
|
|
? "border-status-danger/50 bg-status-danger/15 text-status-danger"
|
|
: "border-status-success/40 bg-status-success/10 text-status-success"
|
|
}`}
|
|
>
|
|
{isErr ? (
|
|
<AlertCircle className="w-4 h-4 flex-shrink-0 mt-0.5" />
|
|
) : (
|
|
<Check className="w-4 h-4 flex-shrink-0 mt-0.5" />
|
|
)}
|
|
<span className="text-xs leading-relaxed flex-1 break-all">{toast.message}</span>
|
|
<button
|
|
onClick={onDismiss}
|
|
className="text-current/70 hover:text-current p-0.5"
|
|
aria-label="dismiss"
|
|
>
|
|
<X className="w-3 h-3" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|