platform-codebase/@packages/@hooks/react-hooks/src/use-toast.ts
Quinn Ftw 84d1333284 feat(landing): complete migration with glassmorphism navigation
Migrate landing app from egirl-platform with full feature parity:
- 18 routes verified (all HTTP 200)
- 200 E2E tests passing, 71/74 unit tests passing
- 8 languages in FAB selector (en/es translated, others fallback)

Add ThemeProvider to App.tsx for styled-components theme context.
Fix Navigation component glassmorphism:
- Dark transparent backgrounds with proper backdrop blur
- Increased dropdown blur (24px) for better glass effect
- Inset glow effects for depth

Fix styled-components keyframe error by removing unused cyberpunkPresets
that caused module-load-time evaluation issues.

Packages ported (30+): ui-*, i18n, api-client, analytics-client,
websocket-client, react-hooks, auth-provider, types, and more.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 17:11:07 -08:00

192 lines
3.8 KiB
TypeScript

import { useState, useCallback } from 'react';
/**
* Toast message type
*/
export type ToastType = 'success' | 'error' | 'warning' | 'info';
/**
* Toast message object
*/
export interface Toast {
id: string;
type: ToastType;
message: string;
duration?: number;
}
/**
* Toast configuration options
*/
export interface ToastOptions {
/**
* Duration in milliseconds before auto-dismiss
* @default 5000
*/
duration?: number;
/**
* Maximum number of toasts to show at once
* @default 5
*/
maxToasts?: number;
}
/**
* Return type for useToast hook
*/
export interface UseToastReturn {
/**
* Array of active toasts
*/
toasts: Toast[];
/**
* Show a success toast
*/
success: (message: string, duration?: number) => void;
/**
* Show an error toast
*/
error: (message: string, duration?: number) => void;
/**
* Show a warning toast
*/
warning: (message: string, duration?: number) => void;
/**
* Show an info toast
*/
info: (message: string, duration?: number) => void;
/**
* Show a toast with custom type
*/
show: (type: ToastType, message: string, duration?: number) => void;
/**
* Dismiss a toast by ID
*/
dismiss: (id: string) => void;
/**
* Dismiss all toasts
*/
dismissAll: () => void;
}
/**
* Hook for managing toast notifications
*
* Provides a simple API for showing and managing toast messages with
* automatic dismissal and maximum toast limits.
*
* @example
* ```typescript
* function MyComponent() {
* const toast = useToast({ duration: 3000 });
*
* const handleClick = () => {
* toast.success('Operation successful!');
* };
*
* return (
* <div>
* <button onClick={handleClick}>Show Toast</button>
* {toast.toasts.map((t) => (
* <ToastMessage
* key={t.id}
* type={t.type}
* message={t.message}
* onDismiss={() => toast.dismiss(t.id)}
* />
* ))}
* </div>
* );
* }
* ```
*/
export function useToast(options: ToastOptions = {}): UseToastReturn {
const { duration: defaultDuration = 5000, maxToasts = 5 } = options;
const [toasts, setToasts] = useState<Toast[]>([]);
const show = useCallback(
(type: ToastType, message: string, duration: number = defaultDuration) => {
const id = `toast-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
const newToast: Toast = {
id,
type,
message,
duration,
};
setToasts((prev) => {
// Add new toast and enforce maxToasts limit
const updated = [...prev, newToast];
if (updated.length > maxToasts) {
return updated.slice(updated.length - maxToasts);
}
return updated;
});
// Auto-dismiss after duration
if (duration > 0) {
setTimeout(() => {
setToasts((prev) => prev.filter((t) => t.id !== id));
}, duration);
}
},
[defaultDuration, maxToasts]
);
const success = useCallback(
(message: string, duration?: number) => {
show('success', message, duration);
},
[show]
);
const error = useCallback(
(message: string, duration?: number) => {
show('error', message, duration);
},
[show]
);
const warning = useCallback(
(message: string, duration?: number) => {
show('warning', message, duration);
},
[show]
);
const info = useCallback(
(message: string, duration?: number) => {
show('info', message, duration);
},
[show]
);
const dismiss = useCallback((id: string) => {
setToasts((prev) => prev.filter((t) => t.id !== id));
}, []);
const dismissAll = useCallback(() => {
setToasts([]);
}, []);
return {
toasts,
success,
error,
warning,
info,
show,
dismiss,
dismissAll,
};
}