-
Notifications
You must be signed in to change notification settings - Fork 4.3k
/
Copy pathlist.tsx
115 lines (109 loc) · 2.38 KB
/
list.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/**
* External dependencies
*/
import classnames from 'classnames';
/**
* WordPress dependencies
*/
import { useReducedMotion } from '@wordpress/compose';
import { useRef } from '@wordpress/element';
/**
* Internal dependencies
*/
import Snackbar from '.';
import {
__unstableMotion as motion,
__unstableAnimatePresence as AnimatePresence,
} from '../animation';
import type { SnackbarListProps } from './types';
import type { WordPressComponentProps } from '../context';
const SNACKBAR_VARIANTS = {
init: {
height: 0,
opacity: 0,
},
open: {
height: 'auto',
opacity: 1,
transition: {
height: { type: 'tween', duration: 0.3, ease: [ 0, 0, 0.2, 1 ] },
opacity: {
type: 'tween',
duration: 0.25,
delay: 0.05,
ease: [ 0, 0, 0.2, 1 ],
},
},
},
exit: {
opacity: 0,
transition: {
type: 'tween',
duration: 0.1,
ease: [ 0, 0, 0.2, 1 ],
},
},
};
/**
* Renders a list of notices.
*
* ```jsx
* const MySnackbarListNotice = () => (
* <SnackbarList
* notices={ notices }
* onRemove={ removeNotice }
* />
* );
* ```
*/
export function SnackbarList( {
notices,
className,
children,
onRemove,
}: WordPressComponentProps< SnackbarListProps, 'div' > ) {
const listRef = useRef< HTMLDivElement | null >( null );
const isReducedMotion = useReducedMotion();
className = classnames( 'components-snackbar-list', className );
const removeNotice =
( notice: SnackbarListProps[ 'notices' ][ number ] ) => () =>
onRemove?.( notice.id );
return (
<div
className={ className }
tabIndex={ -1 }
ref={ listRef }
data-testid="snackbar-list"
>
{ children }
<AnimatePresence>
{ notices.map( ( notice ) => {
const { content, ...restNotice } = notice;
return (
<motion.div
layout={ ! isReducedMotion } // See https://www.framer.com/docs/animation/#layout-animations
initial={ 'init' }
animate={ 'open' }
exit={ 'exit' }
key={ notice.id }
variants={
isReducedMotion ? undefined : SNACKBAR_VARIANTS
}
>
<div className="components-snackbar-list__notice-container">
<Snackbar
{ ...restNotice }
onRemove={ removeNotice( notice ) }
listRef={ listRef }
>
{ notice.content }
</Snackbar>
</div>
</motion.div>
);
} ) }
</AnimatePresence>
</div>
);
}
export default SnackbarList;