Skip to content

Commit

Permalink
feat(Toast): add transition callbacks (#6674)
Browse files Browse the repository at this point in the history
* add transition callbacks to Toast

* typo modal -> toast

* add Toast Callback example

* add Toast Callback test

* modify Toast Callback test

* remove Toast Callback example

---------

Co-authored-by: Yohei Shiraishi <shiraishi@crowd-sec.com>
  • Loading branch information
ysshir and Yohei Shiraishi committed Aug 7, 2023
1 parent 717ca2b commit 57836e2
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 5 deletions.
55 changes: 51 additions & 4 deletions src/Toast.tsx
Expand Up @@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
import classNames from 'classnames';

import useTimeout from '@restart/hooks/useTimeout';
import { TransitionComponent } from '@restart/ui/types';
import { TransitionCallbacks, TransitionComponent } from '@restart/ui/types';
import ToastFade from './ToastFade';
import ToastHeader from './ToastHeader';
import ToastBody from './ToastBody';
Expand All @@ -14,12 +14,14 @@ import { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers';
import { Variant } from './types';

export interface ToastProps
extends BsPrefixProps,
extends TransitionCallbacks,
BsPrefixProps,
React.HTMLAttributes<HTMLElement> {
animation?: boolean;
autohide?: boolean;
delay?: number;
onClose?: (e?: React.MouseEvent | React.KeyboardEvent) => void;

show?: boolean;
transition?: TransitionComponent;
bg?: Variant;
Expand Down Expand Up @@ -52,7 +54,37 @@ const propTypes = {
onClose: PropTypes.func,

/**
* When `true` The modal will show itself.
* Callback fired before the toast transitions in
*/
onEnter: PropTypes.func,

/**
* Callback fired as the toast begins to transition in
*/
onEntering: PropTypes.func,

/**
* Callback fired after the toast finishes transitioning in
*/
onEntered: PropTypes.func,

/**
* Transition onExit callback when animation is not `false`
*/
onExit: PropTypes.func,

/**
* Transition onExiting callback when animation is not `false`
*/
onExiting: PropTypes.func,

/**
* Transition onExited callback when animation is not `false`
*/
onExited: PropTypes.func,

/**
* When `true` The toast will show itself.
*/
show: PropTypes.bool,

Expand Down Expand Up @@ -81,6 +113,12 @@ const Toast: BsPrefixRefForwardingComponent<'div', ToastProps> =
delay = 5000,
autohide = false,
onClose,
onEntered,
onExit,
onExiting,
onEnter,
onEntering,
onExited,
bg,
...props
},
Expand Down Expand Up @@ -140,7 +178,16 @@ const Toast: BsPrefixRefForwardingComponent<'div', ToastProps> =
return (
<ToastContext.Provider value={toastContext}>
{hasAnimation && Transition ? (
<Transition in={show} unmountOnExit>
<Transition
in={show}
onEnter={onEnter}
onEntering={onEntering}
onEntered={onEntered}
onExit={onExit}
onExiting={onExiting}
onExited={onExited}
unmountOnExit
>
{toast}
</Transition>
) : (
Expand Down
40 changes: 39 additions & 1 deletion test/ToastSpec.tsx
@@ -1,6 +1,7 @@
import * as React from 'react';
import { fireEvent, render } from '@testing-library/react';
import sinon from 'sinon';

import { expect } from 'chai';
import Toast from '../src/Toast';

const getToast = ({
Expand Down Expand Up @@ -201,4 +202,41 @@ describe('<Toast>', () => {
container.firstElementChild!.tagName.toLowerCase().should.equal('div');
container.firstElementChild!.classList.contains('my-toast');
});

it('Should pass transition callbacks to Transition', (done) => {
const increment = sinon.spy();

const Elem = () => {
const [show, setShow] = React.useState(false);
React.useEffect(() => {
setShow(true);
}, []);

return (
<Toast
show={show}
onEnter={increment}
onEntering={increment}
onEntered={() => {
increment();
setShow(false);
}}
onExit={increment}
onExiting={increment}
onExited={() => {
increment();
expect(increment.callCount).to.equal(6);
done();
}}
>
<Toast.Header />
<Toast.Body>Body</Toast.Body>
</Toast>
);
};

render(<Elem />);

clock.tick(250);
});
});

0 comments on commit 57836e2

Please sign in to comment.