Skip to content

Commit

Permalink
feat(CSSTransition): add "done" class for appear
Browse files Browse the repository at this point in the history
This is not a breaking change because it doesn't remove the
`*-enter-done` class name after appearing is done, instead
`*-appear-done` is added in addition to that class, which provides you
with a bit more control in case you wanted to define a specific
animation only when an element first appears in the DOM, not every time
it enters.

Closes #383.
Closes #327.

Changes came from #383, but had to rebase to resolve conflicts and make
modifications informed by the discussion in #327.
  • Loading branch information
koba04 authored and silvenon committed Apr 6, 2019
1 parent 27271b7 commit fe3c156
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 9 deletions.
32 changes: 24 additions & 8 deletions src/CSSTransition.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,11 @@ class CSSTransition extends React.Component {
}

onEntered = (node, appearing) => {
const { doneClassName } = this.getClassNames('enter');
const appearClassName = this.getClassNames('appear').doneClassName;
const enterClassName = this.getClassNames('enter').doneClassName;
const doneClassName = appearing
? `${appearClassName} ${enterClassName}`
: enterClassName;

this.removeClasses(node, appearing ? 'appear' : 'enter');
addClass(node, doneClassName);
Expand Down Expand Up @@ -203,17 +207,29 @@ CSSTransition.propTypes = {
...Transition.propTypes,

/**
* The animation classNames applied to the component as it enters, exits or has finished the transition.
* A single name can be provided and it will be suffixed for each stage: e.g.
* The animation classNames applied to the component as it enters, exits or
* has finished the transition. A single name can be provided and it will be
* suffixed for each stage: e.g.
*
* `classNames="fade"` applies `fade-enter`, `fade-enter-active`,
* `fade-enter-done`, `fade-exit`, `fade-exit-active`, `fade-exit-done`,
* `fade-appear`, `fade-appear-active`, and `fade-appear-done`.
*
* **Note**: `fade-appear-done` and `fade-enter-done` will _both_ be applied.
* This allows you to define different behavior for when appearing is done and
* when regular entering is done, using selectors like
* `.fade-enter-done:not(.fade-appear-done)`. For example, you could apply an
* epic entrance animation when element first appears in the DOM using
* [Animate.css](https://daneden.github.io/animate.css/). Otherwise you can
* simply use `fade-enter-done` for defining both cases.
*
* `classNames="fade"` applies `fade-enter`, `fade-enter-active`, `fade-enter-done`,
* `fade-exit`, `fade-exit-active`, `fade-exit-done`, `fade-appear`, and `fade-appear-active`.
* Each individual classNames can also be specified independently like:
*
* ```js
* classNames={{
* appear: 'my-appear',
* appearActive: 'my-active-appear',
* appearDone: 'my-done-appear',
* enter: 'my-enter',
* enterActive: 'my-active-enter',
* enterDone: 'my-done-enter',
Expand All @@ -229,8 +245,8 @@ CSSTransition.propTypes = {
* import styles from './styles.css';
* ```
*
* you might want to use camelCase in your CSS file, that way could simply spread
* them instead of listing them one by one:
* you might want to use camelCase in your CSS file, that way could simply
* spread them instead of listing them one by one:
*
* ```js
* classNames={{ ...styles }}
Expand All @@ -239,6 +255,7 @@ CSSTransition.propTypes = {
* @type {string | {
* appear?: string,
* appearActive?: string,
* appearDone?: string,
* enter?: string,
* enterActive?: string,
* enterDone?: string,
Expand Down Expand Up @@ -273,7 +290,6 @@ CSSTransition.propTypes = {
*/
onEntered: PropTypes.func,


/**
* A `<Transition>` callback fired immediately after the 'exit' class is
* applied.
Expand Down
31 changes: 30 additions & 1 deletion test/CSSTransition-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ describe('CSSTransition', () => {

onEntered={(node, isAppearing) => {
expect(isAppearing).toEqual(true);
expect(node.className).toEqual('appear-test-enter-done');
expect(node.className).toEqual('appear-test-appear-done appear-test-enter-done');
expect(count).toEqual(2);
done();
}}
Expand All @@ -137,6 +137,35 @@ describe('CSSTransition', () => {
);
});

it('should lose the "*-appear-done" class after leaving and entering again', (done) => {
const wrapper = mount(
<CSSTransition
timeout={10}
classNames="appear-test"
in={true}
appear={true}
onEntered={() => {
wrapper.setProps({
in: false,
onEntered: () => {},
onExited: (node) => {
expect(node.className).toBe('appear-test-exit-done')
wrapper.setProps({
in: true,
onEntered: () => {
expect(node.className).toBe('appear-test-enter-done')
done()
}
})
}
})
}}
>
<div />
</CSSTransition>
)
})

it('should not be appearing in normal enter mode', done => {
let count = 0;
mount(
Expand Down

0 comments on commit fe3c156

Please sign in to comment.