import { toast as hotToast } from 'react-hot-toast'; /** * Toast — transient confirmation of a user action. * * The app already depends on react-hot-toast (13 call sites), so this wraps it * rather than introducing a second toast system. Wrapping buys three things: * one place to set styling so toasts match the design system, a named API * (`toast.success` / `toast.error` / `toast.promise`) instead of ad-hoc option * objects, and a single default duration. * * Rule of thumb: toast for "that worked", `Alert` for "here is a condition you * need to keep seeing", `ConfirmModal` for "are you sure". */ const BASE_STYLE = { borderRadius: '12px', background: '#FFFFFF', color: 'hsl(215 25% 27%)', fontSize: '13px', fontWeight: 500, padding: '10px 14px', boxShadow: '0 12px 28px -6px rgb(16 24 40 / 0.12), 0 4px 10px -4px rgb(16 24 40 / 0.06)', border: '1px solid hsl(150 8% 87%)', maxWidth: '420px', }; const DURATIONS = { success: 2600, error: 4200, info: 3000, loading: Infinity }; const withDefaults = (options = {}) => ({ position: 'bottom-center', ...options, style: { ...BASE_STYLE, ...(options.style || {}) }, }); export const toast = { success(message, options) { return hotToast.success(message, { duration: DURATIONS.success, iconTheme: { primary: 'hsl(142 71% 36%)', secondary: '#FFFFFF' }, ...withDefaults(options), }); }, error(message, options) { return hotToast.error(message, { duration: DURATIONS.error, iconTheme: { primary: 'hsl(0 84% 60%)', secondary: '#FFFFFF' }, ...withDefaults(options), }); }, info(message, options) { return hotToast(message, { duration: DURATIONS.info, ...withDefaults(options) }); }, loading(message, options) { return hotToast.loading(message, { duration: DURATIONS.loading, ...withDefaults(options) }); }, /** * Ties a toast to an async action: loading while it runs, then success or * error. Preferred over a manual loading/dismiss pair, which leaks a spinner * whenever the promise rejects. */ promise(promise, messages, options) { return hotToast.promise( promise, { loading: messages?.loading ?? 'Working…', success: messages?.success ?? 'Done', error: messages?.error ?? 'Something went wrong', }, withDefaults(options) ); }, dismiss: hotToast.dismiss, remove: hotToast.remove, };