diff --git a/src/components/close.tsx b/src/components/close.tsx new file mode 100644 index 0000000..86bf4d0 --- /dev/null +++ b/src/components/close.tsx @@ -0,0 +1,35 @@ +import { styled } from 'goober'; + +export interface CloseTheme { + primary?: string; + secondary?: string; +} + +export const CloseIcon = styled('div')` + width: 20px; + opacity: 1; + height: 20px; + border-radius: 10px; + background: ${(p) => p.primary || 'transparent'};; + position: relative; + transform: rotate(45deg); + transition: background-color 200ms ease-out; + + &:after, + &:before { + content: ''; + animation-delay: 150ms; + position: absolute; + border-radius: 3px; + opacity: 1; + background: ${(p) => p.secondary || '#000'}; + bottom: 9px; + left: 4px; + height: 2px; + width: 12px; + } + + &:before { + transform: rotate(90deg); + } +`; diff --git a/src/components/toast-bar.tsx b/src/components/toast-bar.tsx index 72cd3ad..2ede29e 100644 --- a/src/components/toast-bar.tsx +++ b/src/components/toast-bar.tsx @@ -4,6 +4,7 @@ import { styled, keyframes } from 'goober'; import { Toast, ToastPosition, resolveValue, Renderable } from '../core/types'; import { ToastIcon } from './toast-icon'; import { prefersReducedMotion } from '../core/utils'; +import { CloseIcon } from "./close"; const enterAnimation = (factor: number) => ` 0% {transform: translate3d(0,${factor * -200}%,0) scale(.6); opacity:.5;} @@ -49,6 +50,7 @@ interface ToastBarProps { icon: Renderable; message: Renderable; }) => Renderable; + onDismiss: () => void; } const getAnimationStyle = ( @@ -70,8 +72,9 @@ const getAnimationStyle = ( }; export const ToastBar: React.FC = React.memo( - ({ toast, position, style, children }) => { + ({ toast, position, style, children, onDismiss }) => { const animationStyle: React.CSSProperties = toast.height + ? getAnimationStyle( toast.position || position || 'top-center', toast.visible @@ -84,6 +87,7 @@ export const ToastBar: React.FC = React.memo( {resolveValue(toast.message, toast)} ); + const closeIcon = !!toast.canDismiss ? : null; return ( = React.memo( <> {icon} {message} + {closeIcon} )} diff --git a/src/components/toaster.tsx b/src/components/toaster.tsx index 16182fa..4c505ee 100644 --- a/src/components/toaster.tsx +++ b/src/components/toaster.tsx @@ -6,6 +6,7 @@ import { ToastPosition, ToastWrapperProps, } from '../core/types'; +import { toast } from "../core/toast"; import { useToaster } from '../core/use-toaster'; import { prefersReducedMotion } from '../core/utils'; import { ToastBar } from './toast-bar'; @@ -131,7 +132,13 @@ export const Toaster: React.FC = ({ ) : children ? ( children(t) ) : ( - + { + toast.dismiss(t.id); + }} + /> )} ); diff --git a/src/core/toast.ts b/src/core/toast.ts index 8a71eb0..f2b2985 100644 --- a/src/core/toast.ts +++ b/src/core/toast.ts @@ -30,6 +30,7 @@ const createToast = ( pauseDuration: 0, ...opts, id: opts?.id || genId(), + canDismiss: opts?.canDismiss, }); const createHandler = diff --git a/src/core/types.ts b/src/core/types.ts index cd6f67a..92199be 100644 --- a/src/core/types.ts +++ b/src/core/types.ts @@ -52,6 +52,7 @@ export interface Toast { createdAt: number; visible: boolean; height?: number; + canDismiss?: boolean; } export type ToastOptions = Partial< @@ -65,6 +66,7 @@ export type ToastOptions = Partial< | 'style' | 'position' | 'iconTheme' + | 'canDismiss' > >;