Skip to content

Instantly share code, notes, and snippets.

@stevecastaneda
Last active May 10, 2024 19:02
Show Gist options
  • Save stevecastaneda/61c05f3ccc5c532f26cc40593bbeeb01 to your computer and use it in GitHub Desktop.
Save stevecastaneda/61c05f3ccc5c532f26cc40593bbeeb01 to your computer and use it in GitHub Desktop.

Revisions

  1. stevecastaneda revised this gist Jun 13, 2020. No changes.
  2. stevecastaneda created this gist Jun 13, 2020.
    69 changes: 69 additions & 0 deletions CSSTransition.tsx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,69 @@
    import React, { ReactNode } from "react";
    import { CSSTransition as ReactTransition } from "react-transition-group";

    interface TransitionProps {
    in?: boolean;
    timeout: number;
    enter?: string;
    enterFrom?: string;
    enterTo?: string;
    leave?: string;
    leaveFrom?: string;
    leaveTo?: string;
    children: ReactNode;
    }

    function addClasses(classes: string[], ref: React.RefObject<HTMLDivElement>) {
    ref.current?.classList.add(...classes);
    }

    function removeClasses(classes: string[], ref: React.RefObject<HTMLDivElement>) {
    ref.current?.classList.remove(...classes);
    }

    export function CSSTransition(props: TransitionProps) {
    const { enter, enterFrom, enterTo, leave, leaveFrom, leaveTo } = props;
    const nodeRef = React.useRef<HTMLDivElement>(null);

    const enterClasses = splitClasses(enter);
    const enterFromClasses = splitClasses(enterFrom);
    const enterToClasses = splitClasses(enterTo);
    const leaveClasses = splitClasses(leave);
    const leaveFromClasses = splitClasses(leaveFrom);
    const leaveToClasses = splitClasses(leaveTo);

    return (
    <ReactTransition
    in={props.in}
    nodeRef={nodeRef}
    timeout={props.timeout}
    unmountOnExit
    onEnter={() => {
    addClasses([...enterClasses, ...enterFromClasses], nodeRef);
    }}
    onEntering={() => {
    removeClasses(enterFromClasses, nodeRef);
    addClasses(enterToClasses, nodeRef);
    }}
    onEntered={() => {
    removeClasses([...enterToClasses, ...enterClasses], nodeRef);
    }}
    onExit={() => {
    addClasses([...leaveClasses, ...leaveFromClasses], nodeRef);
    }}
    onExiting={() => {
    removeClasses(leaveFromClasses, nodeRef);
    addClasses(leaveToClasses, nodeRef);
    }}
    onExited={() => {
    removeClasses([...leaveToClasses, ...leaveClasses], nodeRef);
    }}
    >
    <div ref={nodeRef}>{props.children}</div>
    </ReactTransition>
    );
    }

    function splitClasses(string: string = ""): string[] {
    return string.split(" ").filter((s) => s.length);
    }