@@ -3,6 +3,7 @@ import * as style from './style.css';
33import 'add-css:./style.css' ;
44import { linkRef } from 'shared/prerendered-app/util' ;
55import { cleanSet } from '../util/clean-modify' ;
6+ import { animateTo } from '../util' ;
67
78interface Props {
89 icon : VNode ;
@@ -19,12 +20,8 @@ export default class Modal extends Component<Props, State> {
1920
2021 componentDidMount ( ) {
2122 if ( ! this . dialogElement ) throw new Error ( 'Modal missing' ) ;
22- // Once a transition ends, check if the modal should be closed (not just hidden)
23- // dialog.close() instantly hides the modal, so we call it AFTER fading it out i.e. on transition end
24- this . dialogElement . addEventListener ( 'transitionend' , ( event ) => {
25- event . stopPropagation ( ) ;
26- this . _closeOnTransitionEnd ( ) ;
27- } ) ;
23+
24+ // Set inert by default
2825 this . dialogElement . inert = true ;
2926
3027 // Prevent events from leaking through the dialog
@@ -36,16 +33,10 @@ export default class Modal extends Component<Props, State> {
3633
3734 private _closeOnTransitionEnd = ( ) => {
3835 // If modal does not exist
39- // Or if it's not being closed at the moment
40- if (
41- ! this . dialogElement ||
42- ! this . dialogElement . classList . contains ( style . modalClosing )
43- )
44- return ;
36+ if ( ! this . dialogElement ) return ;
4537
4638 this . dialogElement . close ( ) ;
47- this . dialogElement . classList . remove ( style . modalClosing ) ;
48- this . dialogElement . setAttribute ( 'inert' , 'enabled' ) ;
39+ this . dialogElement . inert = true ;
4940 this . setState ( { shown : false } ) ;
5041 } ;
5142
@@ -55,15 +46,41 @@ export default class Modal extends Component<Props, State> {
5546
5647 this . dialogElement . inert = false ;
5748 this . dialogElement . showModal ( ) ;
49+ // animate modal opening
50+ animateTo (
51+ this . dialogElement ,
52+ [
53+ { opacity : 0 , transform : 'translateY(50px)' } ,
54+ { opacity : 1 , transform : 'translateY(0px)' } ,
55+ ] ,
56+ { duration : 250 , easing : 'ease' } ,
57+ ) ;
58+ // animate modal::backdrop
59+ animateTo ( this . dialogElement , [ { opacity : 0 } , { opacity : 1 } ] , {
60+ duration : 250 ,
61+ easing : 'linear' ,
62+ pseudoElement : '::backdrop' ,
63+ } ) ;
5864 this . setState ( { shown : true } ) ;
5965 }
6066
6167 private _hideModal ( ) {
6268 if ( ! this . dialogElement || ! this . dialogElement . open )
6369 throw Error ( 'Modal missing / hidden' ) ;
6470
65- // Make the modal fade out
66- this . dialogElement . classList . add ( style . modalClosing ) ;
71+ // animate modal closing
72+ const anim = animateTo (
73+ this . dialogElement ,
74+ { opacity : 0 , transform : 'translateY(50px)' } ,
75+ { duration : 250 , easing : 'ease' } ,
76+ ) ;
77+ // animate modal::backdrop
78+ animateTo ( this . dialogElement , [ { opacity : 0 } ] , {
79+ duration : 250 ,
80+ easing : 'linear' ,
81+ pseudoElement : '::backdrop' ,
82+ } ) ;
83+ anim . onfinish = this . _closeOnTransitionEnd ;
6784 }
6885
6986 private _onKeyDown ( e : KeyboardEvent ) {
0 commit comments