First Commit
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import React, { createContext, useCallback, useContext, useMemo, useState } from "react";
|
||||
|
||||
import { Alert, Button, Snackbar } from "@mui/material";
|
||||
|
||||
type Severity = "success" | "info" | "warning" | "error";
|
||||
|
||||
type Toast = {
|
||||
open: boolean;
|
||||
message: string;
|
||||
severity: Severity;
|
||||
actionLabel?: string;
|
||||
onAction?: () => void;
|
||||
};
|
||||
|
||||
type ToastApi = {
|
||||
toast: (
|
||||
message: string,
|
||||
severity?: Severity,
|
||||
action?: { label: string; onClick: () => void },
|
||||
) => void;
|
||||
};
|
||||
|
||||
const ToastContext = createContext<ToastApi | null>(null);
|
||||
|
||||
export function ToastProvider({ children }: { children: React.ReactNode }) {
|
||||
const [t, setT] = useState<Toast>({ open: false, message: "", severity: "info" });
|
||||
|
||||
const toast = useCallback(
|
||||
(message: string, severity: Severity = "info", action?: { label: string; onClick: () => void }) => {
|
||||
setT({
|
||||
open: true,
|
||||
message,
|
||||
severity,
|
||||
actionLabel: action?.label,
|
||||
onAction: action?.onClick,
|
||||
});
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const value = useMemo(() => ({ toast }), [toast]);
|
||||
|
||||
return (
|
||||
<ToastContext.Provider value={value}>
|
||||
{children}
|
||||
<Snackbar
|
||||
open={t.open}
|
||||
autoHideDuration={3500}
|
||||
onClose={() => setT((p) => ({ ...p, open: false }))}
|
||||
anchorOrigin={{ vertical: "bottom", horizontal: "right" }}
|
||||
>
|
||||
<Alert
|
||||
onClose={() => setT((p) => ({ ...p, open: false }))}
|
||||
severity={t.severity}
|
||||
variant="filled"
|
||||
sx={{ maxWidth: 420 }}
|
||||
action={
|
||||
t.actionLabel && t.onAction ? (
|
||||
<Button
|
||||
color="inherit"
|
||||
size="small"
|
||||
onClick={() => {
|
||||
setT((p) => ({ ...p, open: false }));
|
||||
t.onAction?.();
|
||||
}}
|
||||
>
|
||||
{t.actionLabel}
|
||||
</Button>
|
||||
) : undefined
|
||||
}
|
||||
>
|
||||
{t.message}
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
</ToastContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useToast(): ToastApi {
|
||||
const v = useContext(ToastContext);
|
||||
if (!v) throw new Error("useToast must be used within ToastProvider");
|
||||
return v;
|
||||
}
|
||||
Reference in New Issue
Block a user