Files
krow_talent_app/src/components/ds/toast.js
2026-08-07 23:53:15 +05:30

81 lines
2.4 KiB
JavaScript

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,
};