refactor(toast): ♻️ Enhance Toast component with new variants, improved styling, and accessibility features

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Claude Code 2026-04-04 11:09:01 -07:00
parent 2d123d9d36
commit 60d43e34de

View file

@ -0,0 +1,62 @@
/**
* Toast Global ephemeral notification system.
* Provides ToastProvider (wrap at root), useToast (trigger), and the rendered overlay.
*/
import { createContext, useContext, useState, useCallback, type ReactNode } from 'react';
import styled, { keyframes } from '@lilith/ui-styled-components';
interface ToastContextValue {
showToast: (message: string) => void;
}
const ToastContext = createContext<ToastContextValue>({ showToast: () => {} });
export function useToast(): ToastContextValue {
return useContext(ToastContext);
}
const slideUp = keyframes`
from { opacity: 0; transform: translateY(8px); }
to { opacity: 1; transform: translateY(0); }
`;
const ToastBanner = styled.div`
position: fixed;
bottom: 5.5rem;
left: 50%;
transform: translateX(-50%);
z-index: 300;
background: rgba(20, 20, 32, 0.95);
border: 1px solid rgba(212, 175, 55, 0.4);
color: #D4AF37;
font-size: 0.8rem;
font-weight: 500;
letter-spacing: 0.04em;
padding: 0.5rem 1rem;
border-radius: 9999px;
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
box-shadow:
0 4px 16px rgba(0, 0, 0, 0.5),
0 0 20px rgba(212, 175, 55, 0.1);
white-space: nowrap;
pointer-events: none;
animation: ${slideUp} 180ms ease both;
`;
export function ToastProvider({ children }: { children: ReactNode }): ReactNode {
const [message, setMessage] = useState<string | null>(null);
const showToast = useCallback((msg: string): void => {
setMessage(msg);
setTimeout(() => setMessage(null), 2000);
}, []);
return (
<ToastContext.Provider value={{ showToast }}>
{children}
{message && <ToastBanner role="status" aria-live="polite">{message}</ToastBanner>}
</ToastContext.Provider>
);
}