Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Transition): allow custom animations #3438

Merged
5 changes: 4 additions & 1 deletion src/modules/Transition/Transition.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@ export interface TransitionProps extends StrictTransitionProps {

export interface StrictTransitionProps {
/** Named animation event to used. Must be defined in CSS. */
animation?: SemanticTRANSITIONS
animation?: SemanticTRANSITIONS | string

/** Primary content. */
children?: React.ReactNode

/** Whether it is directional animation event or not. Use it only for custom transitions. */
directional?: boolean

/** Duration of the CSS transition animation in milliseconds. */
duration?: number | string | TransitionPropDuration

Expand Down
11 changes: 7 additions & 4 deletions src/modules/Transition/Transition.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,14 @@ const TRANSITION_TYPE = {
export default class Transition extends Component {
static propTypes = {
/** Named animation event to used. Must be defined in CSS. */
animation: PropTypes.oneOf(SUI.TRANSITIONS),
animation: PropTypes.oneOfType([PropTypes.oneOf(SUI.TRANSITIONS), PropTypes.string]),

/** Primary content. */
children: PropTypes.element.isRequired,

/** Whether it is directional animation event or not. Use it only for custom transitions. */
directional: PropTypes.bool,

/** Duration of the CSS transition animation in milliseconds. */
duration: PropTypes.oneOfType([
PropTypes.number,
Expand Down Expand Up @@ -188,13 +191,13 @@ export default class Transition extends Component {
// ----------------------------------------

computeClasses = () => {
const { animation, children } = this.props
const { animation, directional, children } = this.props
const { animating, status } = this.state

const childClasses = _.get(children, 'props.className')
const directional = _.includes(SUI.DIRECTIONAL_TRANSITIONS, animation)
const isDirectional = _.isNil(directional) ? _.includes(SUI.DIRECTIONAL_TRANSITIONS, animation) : directional

if (directional) {
if (isDirectional) {
return cx(
animation,
childClasses,
Expand Down
5 changes: 4 additions & 1 deletion src/modules/Transition/TransitionGroup.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ export interface StrictTransitionGroupProps {
as?: any

/** Named animation event to used. Must be defined in CSS. */
animation?: SemanticTRANSITIONS
animation?: SemanticTRANSITIONS | string

/** Primary content. */
children?: React.ReactNode

/** Whether it is directional animation event or not. Use it only for custom transitions. */
directional?: boolean

/** Duration of the CSS transition animation in milliseconds. */
duration?: number | string | TransitionPropDuration
}
Expand Down
8 changes: 6 additions & 2 deletions src/modules/Transition/TransitionGroup.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@ export default class TransitionGroup extends React.Component {
as: customPropTypes.as,

/** Named animation event to used. Must be defined in CSS. */
animation: PropTypes.oneOf(SUI.TRANSITIONS),
animation: PropTypes.oneOfType([PropTypes.oneOf(SUI.TRANSITIONS), PropTypes.string]),

/** Primary content. */
children: PropTypes.node,

/** Whether it is directional animation event or not. Use it only for custom transitions. */
directional: PropTypes.bool,

/** Duration of the CSS transition animation in milliseconds. */
duration: PropTypes.oneOfType([
PropTypes.number,
Expand Down Expand Up @@ -109,13 +112,14 @@ export default class TransitionGroup extends React.Component {
}

wrapChild = (child, options = {}) => {
const { animation, duration } = this.props
const { animation, directional, duration } = this.props
const { key } = child
const { visible = true, transitionOnMount = false } = options

return (
<Transition
animation={animation}
directional={directional}
duration={duration}
key={key}
onHide={this.handleOnHide}
Expand Down
44 changes: 44 additions & 0 deletions test/specs/modules/Transition/Transition-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,20 @@ describe('Transition', () => {
wrapper.should.not.have.className('out')
})
})

it('supports custom animations', () => {
wrapperShallow(
<Transition animation='jump' transitionOnMount={false}>
<p />
</Transition>,
)

wrapper.setState({ status: Transition.ENTERING })
wrapper.should.have.className('jump')

wrapper.setState({ status: Transition.EXITING })
wrapper.should.have.className('jump')
})
})

describe('className', () => {
Expand Down Expand Up @@ -123,6 +137,36 @@ describe('Transition', () => {
})
})

describe('directional', () => {
it('adds classes when is "true"', () => {
wrapperShallow(
<Transition directional transitionOnMount={false}>
<p />
</Transition>,
)

wrapper.setState({ status: Transition.ENTERING })
wrapper.should.have.className('in')

wrapper.setState({ status: Transition.EXITING })
wrapper.should.have.className('out')
})

it('do not add classes when is "false"', () => {
wrapperShallow(
<Transition directional={false} transitionOnMount={false}>
<p />
</Transition>,
)

wrapper.setState({ status: Transition.ENTERING })
wrapper.should.have.not.className('in')

wrapper.setState({ status: Transition.EXITING })
wrapper.should.have.not.className('out')
})
})

describe('children', () => {
it('clones element', () => {
wrapperShallow(
Expand Down
3 changes: 2 additions & 1 deletion test/specs/modules/Transition/TransitionGroup-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ describe('TransitionGroup', () => {

it('passes props to children', () => {
shallow(
<TransitionGroup animation='scale' duration={1500}>
<TransitionGroup animation='scale' directional duration={1500}>
<div />
<div />
<div />
Expand All @@ -46,6 +46,7 @@ describe('TransitionGroup', () => {
.children()
.everyWhere((item) => {
item.should.have.prop('animation', 'scale')
item.should.have.prop('directional', true)
item.should.have.prop('duration', 1500)
item.type().should.equal(Transition)
})
Expand Down