@@ -5,12 +5,13 @@ import { keyframes, styled } from "styled-components";
5
5
import { toastsEventEmitter } from "./toastEmitter" ;
6
6
7
7
export interface ToastContextProps {
8
- createToast : ( toast : ToastProps ) => void ;
8
+ createToast : ( toast : ToastProps , align ?: ToastAlignment ) => void ;
9
9
}
10
10
export const ToastContext = createContext < ToastContextProps > ( {
11
11
createToast : ( ) => null ,
12
12
} ) ;
13
13
14
+ export type ToastAlignment = "start" | "end" ;
14
15
export type ToastType = "danger" | "warning" | "default" | "success" ;
15
16
export interface ToastProps {
16
17
id ?: string ;
@@ -20,6 +21,7 @@ export interface ToastProps {
20
21
/** Time in milliseconds the toast will be visible */
21
22
duration ?: number ;
22
23
actions ?: Array < ButtonProps & { altText : string } > ;
24
+ align ?: ToastAlignment ;
23
25
}
24
26
25
27
const ToastIcon = styled ( Icon ) < { $type ?: ToastType } > `
@@ -99,6 +101,7 @@ const ToastHeader = styled(RadixUIToast.Title)`
99
101
100
102
const ToastDescriptionContainer = styled . div `
101
103
display: flex;
104
+ flex-direction: column;
102
105
justify-content: space-between;
103
106
width: 100%;
104
107
align-items: flex-end;
@@ -123,7 +126,7 @@ const Title = styled.div`
123
126
flex: 1;
124
127
` ;
125
128
126
- const Toast = ( {
129
+ export const Toast = ( {
127
130
type,
128
131
title,
129
132
description,
@@ -167,8 +170,14 @@ const Toast = ({
167
170
{ actions . length > 0 && (
168
171
< ToastDescriptionContent >
169
172
{ actions . map ( ( { altText, ...btnProps } ) => (
170
- < RadixUIToast . Action altText = { altText } >
171
- < Button { ...btnProps } />
173
+ < RadixUIToast . Action
174
+ altText = { altText }
175
+ asChild
176
+ key = { altText }
177
+ >
178
+ < div >
179
+ < Button { ...btnProps } />
180
+ </ div >
172
181
</ RadixUIToast . Action >
173
182
) ) }
174
183
</ ToastDescriptionContent >
@@ -179,7 +188,7 @@ const Toast = ({
179
188
) ;
180
189
} ;
181
190
182
- const Viewport = styled ( RadixUIToast . Viewport ) < { $align : "start" | "end" } > `
191
+ const Viewport = styled ( RadixUIToast . Viewport ) < { $align : ToastAlignment } > `
183
192
--viewport-padding: 25px;
184
193
position: fixed;
185
194
bottom: 0;
@@ -203,23 +212,29 @@ const Viewport = styled(RadixUIToast.Viewport)<{ $align: "start" | "end" }>`
203
212
outline: none;
204
213
` ;
205
214
206
- export interface ToastProviderProps extends RadixUIToast . ToastProps {
207
- align ?: "start" | "end" ;
215
+ export interface ToastProviderProps extends RadixUIToast . ToastProviderProps {
216
+ align ?: ToastAlignment ;
208
217
}
209
218
210
219
export const ToastProvider = ( {
211
220
children,
212
221
align = "end" ,
213
222
...props
214
223
} : ToastProviderProps ) => {
215
- const [ toasts , setToasts ] = useState < Map < string , ToastProps > > ( new Map ( ) ) ;
224
+ const [ toasts , setToasts ] = useState < Record < ToastAlignment , Map < string , ToastProps > > > ( {
225
+ start : new Map ( ) ,
226
+ end : new Map ( ) ,
227
+ } ) ;
216
228
217
229
useEffect ( ( ) => {
218
230
const listener = ( toast : ToastProps ) => {
219
231
setToasts ( currentToasts => {
220
- const newMap = new Map ( currentToasts ) ;
221
- newMap . set ( toast ?. id ?? String ( Date . now ( ) ) , toast ) ;
222
- return newMap ;
232
+ const alignment = toast . align ?? "end" ;
233
+ const newToasts = { ...currentToasts } ;
234
+ const map = new Map ( newToasts [ alignment ] ) ;
235
+ map . set ( toast ?. id ?? String ( Date . now ( ) ) , toast ) ;
236
+ newToasts [ alignment ] = map ;
237
+ return newToasts ;
223
238
} ) ;
224
239
} ;
225
240
@@ -231,30 +246,36 @@ export const ToastProvider = ({
231
246
const onClose = ( id : string ) => ( open : boolean ) => {
232
247
if ( ! open ) {
233
248
setToasts ( currentToasts => {
234
- const newMap = new Map ( currentToasts ) ;
235
- newMap . delete ( id ) ;
236
- return newMap ;
249
+ const newToasts = { ...currentToasts } ;
250
+ const map = new Map ( newToasts [ align ] ) ;
251
+ map . delete ( id ) ;
252
+ newToasts [ align ] = map ;
253
+ return newToasts ;
237
254
} ) ;
238
255
}
239
256
} ;
257
+
240
258
const value = {
241
- createToast : ( toast : ToastProps ) => {
259
+ createToast : ( toast : ToastProps , toastAlign : ToastAlignment = align ) => {
242
260
setToasts ( currentToasts => {
243
- const newMap = new Map ( currentToasts ) ;
244
- newMap . set ( toast ?. id ?? String ( Date . now ( ) ) , toast ) ;
245
- return newMap ;
261
+ const newToasts = { ...currentToasts } ;
262
+ const map = new Map ( newToasts [ toastAlign ] ) ;
263
+ map . set ( toast ?. id ?? String ( Date . now ( ) ) , toast ) ;
264
+ newToasts [ toastAlign ] = map ;
265
+ return newToasts ;
246
266
} ) ;
247
267
} ,
248
268
} ;
249
269
250
270
return (
251
271
< RadixUIToast . Provider
252
272
swipeDirection = { align === "start" ? "left" : "right" }
273
+ key = { `toast-provider-${ align } ` }
253
274
{ ...props }
254
275
>
255
276
< ToastContext . Provider value = { value } >
256
277
{ children }
257
- { Array . from ( toasts ) . map ( ( [ id , toast ] ) => (
278
+ { Array . from ( toasts [ align ] ) . map ( ( [ id , toast ] ) => (
258
279
< Toast
259
280
key = { id }
260
281
{ ...toast }
0 commit comments