Skip to content

Commit fe3c156

Browse files
koba04silvenon
authored andcommitted
feat(CSSTransition): add "done" class for appear
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.
1 parent 27271b7 commit fe3c156

File tree

2 files changed

+54
-9
lines changed

2 files changed

+54
-9
lines changed

src/CSSTransition.js

+24-8
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,11 @@ class CSSTransition extends React.Component {
9898
}
9999

100100
onEntered = (node, appearing) => {
101-
const { doneClassName } = this.getClassNames('enter');
101+
const appearClassName = this.getClassNames('appear').doneClassName;
102+
const enterClassName = this.getClassNames('enter').doneClassName;
103+
const doneClassName = appearing
104+
? `${appearClassName} ${enterClassName}`
105+
: enterClassName;
102106

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

205209
/**
206-
* The animation classNames applied to the component as it enters, exits or has finished the transition.
207-
* A single name can be provided and it will be suffixed for each stage: e.g.
210+
* The animation classNames applied to the component as it enters, exits or
211+
* has finished the transition. A single name can be provided and it will be
212+
* suffixed for each stage: e.g.
213+
*
214+
* `classNames="fade"` applies `fade-enter`, `fade-enter-active`,
215+
* `fade-enter-done`, `fade-exit`, `fade-exit-active`, `fade-exit-done`,
216+
* `fade-appear`, `fade-appear-active`, and `fade-appear-done`.
217+
*
218+
* **Note**: `fade-appear-done` and `fade-enter-done` will _both_ be applied.
219+
* This allows you to define different behavior for when appearing is done and
220+
* when regular entering is done, using selectors like
221+
* `.fade-enter-done:not(.fade-appear-done)`. For example, you could apply an
222+
* epic entrance animation when element first appears in the DOM using
223+
* [Animate.css](https://daneden.github.io/animate.css/). Otherwise you can
224+
* simply use `fade-enter-done` for defining both cases.
208225
*
209-
* `classNames="fade"` applies `fade-enter`, `fade-enter-active`, `fade-enter-done`,
210-
* `fade-exit`, `fade-exit-active`, `fade-exit-done`, `fade-appear`, and `fade-appear-active`.
211226
* Each individual classNames can also be specified independently like:
212227
*
213228
* ```js
214229
* classNames={{
215230
* appear: 'my-appear',
216231
* appearActive: 'my-active-appear',
232+
* appearDone: 'my-done-appear',
217233
* enter: 'my-enter',
218234
* enterActive: 'my-active-enter',
219235
* enterDone: 'my-done-enter',
@@ -229,8 +245,8 @@ CSSTransition.propTypes = {
229245
* import styles from './styles.css';
230246
* ```
231247
*
232-
* you might want to use camelCase in your CSS file, that way could simply spread
233-
* them instead of listing them one by one:
248+
* you might want to use camelCase in your CSS file, that way could simply
249+
* spread them instead of listing them one by one:
234250
*
235251
* ```js
236252
* classNames={{ ...styles }}
@@ -239,6 +255,7 @@ CSSTransition.propTypes = {
239255
* @type {string | {
240256
* appear?: string,
241257
* appearActive?: string,
258+
* appearDone?: string,
242259
* enter?: string,
243260
* enterActive?: string,
244261
* enterDone?: string,
@@ -273,7 +290,6 @@ CSSTransition.propTypes = {
273290
*/
274291
onEntered: PropTypes.func,
275292

276-
277293
/**
278294
* A `<Transition>` callback fired immediately after the 'exit' class is
279295
* applied.

test/CSSTransition-test.js

+30-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ describe('CSSTransition', () => {
127127

128128
onEntered={(node, isAppearing) => {
129129
expect(isAppearing).toEqual(true);
130-
expect(node.className).toEqual('appear-test-enter-done');
130+
expect(node.className).toEqual('appear-test-appear-done appear-test-enter-done');
131131
expect(count).toEqual(2);
132132
done();
133133
}}
@@ -137,6 +137,35 @@ describe('CSSTransition', () => {
137137
);
138138
});
139139

140+
it('should lose the "*-appear-done" class after leaving and entering again', (done) => {
141+
const wrapper = mount(
142+
<CSSTransition
143+
timeout={10}
144+
classNames="appear-test"
145+
in={true}
146+
appear={true}
147+
onEntered={() => {
148+
wrapper.setProps({
149+
in: false,
150+
onEntered: () => {},
151+
onExited: (node) => {
152+
expect(node.className).toBe('appear-test-exit-done')
153+
wrapper.setProps({
154+
in: true,
155+
onEntered: () => {
156+
expect(node.className).toBe('appear-test-enter-done')
157+
done()
158+
}
159+
})
160+
}
161+
})
162+
}}
163+
>
164+
<div />
165+
</CSSTransition>
166+
)
167+
})
168+
140169
it('should not be appearing in normal enter mode', done => {
141170
let count = 0;
142171
mount(

0 commit comments

Comments
 (0)