Skip to main content
react-md

Scale Transition

The scale transition is generally used for temporary elements like dropdown menus and toasts. See the CSSTransition component and useCSSTransition for additional options.

Simple Example

The transition can be enabled using the ScaleTransition component which defaults to:

The ScaleTransition requires a single child component that accepts the className prop and forwards refs like the other CSS transitions.

"use client";

import { Box } from "@react-md/core/box/Box";
import { Button } from "@react-md/core/button/Button";
import { Card } from "@react-md/core/card/Card";
import { CardContent } from "@react-md/core/card/CardContent";
import { ScaleTransition } from "@react-md/core/transition/ScaleTransition";
import { useToggle } from "@react-md/core/useToggle";
import { type ReactElement } from "react";

import styles from "./SimpleExample.module.scss";

export default function SimpleExample(): ReactElement {
  const { toggle, toggled } = useToggle();

  return (
    <Box stacked className={styles.container}>
      <Button onClick={toggle}>Toggle</Button>
      <ScaleTransition transitionIn={toggled}>
        <Card className={styles.element}>
          <CardContent>Hello, world!</CardContent>
        </Card>
      </ScaleTransition>
    </Box>
  );
}

Press Enter to start editing.

.container {
  position: relative;
}

.element {
  left: 0;
  position: absolute;
  top: 100%;
  z-index: 30;
}

Press Enter to start editing.

Vertical Example

The transition can be updated to use scaleY by enabling the vertical prop.

"use client";

import { Box } from "@react-md/core/box/Box";
import { Button } from "@react-md/core/button/Button";
import { Card } from "@react-md/core/card/Card";
import { CardContent } from "@react-md/core/card/CardContent";
import { ScaleTransition } from "@react-md/core/transition/ScaleTransition";
import { useToggle } from "@react-md/core/useToggle";
import { type ReactElement } from "react";

import styles from "./VerticalExample.module.scss";

export default function VerticalExample(): ReactElement {
  const { toggle, toggled } = useToggle();

  return (
    <Box stacked className={styles.container}>
      <Button onClick={toggle}>Toggle</Button>
      <ScaleTransition transitionIn={toggled} vertical>
        <Card className={styles.element}>
          <CardContent>Hello, world!</CardContent>
        </Card>
      </ScaleTransition>
    </Box>
  );
}

Press Enter to start editing.

.container {
  position: relative;
}

.element {
  left: 0;
  position: absolute;
  top: 100%;
  z-index: 30;
}

Press Enter to start editing.

Hidden While Exited

The default behavior for the ScaleTransition is to unmount the component while not visible. Since this causes the state of these components to reset, this means the state needs to be pushed up the tree which isn't always ideal. Instead, the ScaleTransition supports using display: none while not visible instead by setting temporary={false}.

Clicked: 0 times

"use client";

import { Box } from "@react-md/core/box/Box";
import { Button } from "@react-md/core/button/Button";
import { Card } from "@react-md/core/card/Card";
import { CardContent } from "@react-md/core/card/CardContent";
import { CardFooter } from "@react-md/core/card/CardFooter";
import { ScaleTransition } from "@react-md/core/transition/ScaleTransition";
import { Typography } from "@react-md/core/typography/Typography";
import { useToggle } from "@react-md/core/useToggle";
import { type ReactElement, useState } from "react";

import styles from "./HiddenWhileExitedExample.module.scss";

export default function HiddenWhileExitedExample(): ReactElement {
  const { toggle, toggled } = useToggle();

  return (
    <Box stacked className={styles.container}>
      <Button onClick={toggle}>Toggle</Button>
      <ScaleTransition transitionIn={toggled} temporary={false}>
        <Card className={styles.element}>
          <Content />
        </Card>
      </ScaleTransition>
    </Box>
  );
}

function Content(): ReactElement {
  const [clicked, setClicked] = useState(0);

  return (
    <>
      <CardContent>
        <Typography>{`Clicked: ${clicked} times`}</Typography>
      </CardContent>
      <CardFooter>
        <Button
          onClick={() => {
            setClicked((prev) => prev + 1);
          }}
          theme="primary"
          themeType="outline"
        >
          Click
        </Button>
      </CardFooter>
    </>
  );
}

Press Enter to start editing.

.container {
  position: relative;
}

.element {
  left: 0;
  position: absolute;
  top: 100%;
  z-index: 30;
}

Press Enter to start editing.

Scale Transition Hook Example

The useScaleTransition can be used instead of the ScaleTransition component which exposes the full API.

"use client";

import { Box } from "@react-md/core/box/Box";
import { Button } from "@react-md/core/button/Button";
import { Card } from "@react-md/core/card/Card";
import { CardContent } from "@react-md/core/card/CardContent";
import { useScaleTransition } from "@react-md/core/transition/useScaleTransition";
import { useToggle } from "@react-md/core/useToggle";
import { type ReactElement } from "react";

import styles from "./ScaleTransitionHookExample.module.scss";

export default function ScaleTransitionHookExample(): ReactElement {
  const { toggle, toggled } = useToggle();
  const { elementProps, rendered } = useScaleTransition({
    // this is the default
    // vertical: false,
    className: styles.element,
    transitionIn: toggled,
  });

  return (
    <Box stacked className={styles.container}>
      <Button onClick={toggle}>Toggle</Button>
      {rendered && (
        <Card {...elementProps}>
          <CardContent>Hello, world!</CardContent>
        </Card>
      )}
    </Box>
  );
}

Press Enter to start editing.

.container {
  position: relative;
}

.element {
  left: 0;
  position: absolute;
  top: 100%;
  z-index: 30;
}

Press Enter to start editing.