react-showtime v0.3.9
React Showtime ποΈΒ π₯Β π
Mount & unmount with CSS transitions
React Showtime makes it easy to apply CSS transitions to the appearance and disappearance of React elements. It automatically handles mounting and unmounting to allow time for transitions to occur.
Demo: https://react-showtime.dev/
π―βChoose between useShowtime hook and <Showtime /> component.
πβFeels familiar: useShowtime is a near-drop-in replacement for conditional rendering with a state boolean.
π
βSpecify showing styles however you like β inline, emotion, styled-components, classnames, you name it.
π¨βSensible API for defining hidden styles and custom transitions.
π©βIncluded transitions: slideFade, slide, fade, rise, scale.
πβSymmetric or asymmetric show/hide transitions.
π΄βZero dependencies. 3.4k min+gzip.
The essential insight of React Showtime is that the one-two sequence of React's useLayoutEffect and useEffect hooks is nicely suited to the one-two sequence of mounting a component with hidden CSS values and then applying showing CSS values to trigger the transition. As for hiding, transition event handlers trigger unmounting once the "hide" transition is complete.
What React Showtime is not
React Showtime is not for transitions that do not involve mounting/unmounting. It was created specifically as a shim for conditional rendering.
React Showtime is not for sophisticated animations, as it executes via CSS transition, not animation. Consider a more full-featured library like react-spring if you need keyframes or additional sophistication.
Getting Started
Installation
yarn add react-showtimenpm install react-showtimetl;dr
- Choose between the
useShowtimehook or theShowtimecomponent. The component is better for list items or if you need to listen for events (onShowing,onHidden). - Define your
transitionby describing the item's hidden styles with a CSS object literal. Or just pass the name of an included transition (slideFade,slide,fade,rise,scale). - If using the hook, attach the supplied
refto your containing element and conditionally render your item with the suppliedisMountedboolean. - Call the hook's
show()andhide()functions β or toggle the component'sshowprop β as needed.
Optionally adjust transition timing via duration, delay, easing.
You can also define asymmetric show/hide transitions (showTransition, hideTransition) and timing (showDuration, showDelay, showEasing, hideDuration, hideDelay, hideEasing).
Usage
Hook vs Component
As a rule of thumb, since you can't call hooks inside loops, use the hook when dealing with a singleton item that needs to conditionally appear or disappear (eg, a notification), and use the component whenΒ you've an indeterminate set of children that need to individually transition in and out of the DOM (eg, a list of messages).
useShowtime hook
The hook is designed to integrate with React's conditional rendering idiom. It returns an array/object containing a ref that must be attached to your element or component, an isMounted boolean that will conditionally render it, and show() and hide() functions for you to call as needed.
import React from "react";
import { useShowtime } from "react-showtime";
const HookExample = () => {
const [ref, isMounted, show, hide] = useShowtime();
// Or use object destructuring...
// const {ref, isMounted, show, hide} = useShowtime();
const toggle = () => (isMounted ? hide() : show());
return (
<div>
<button onClick={toggle}>Toggle</button>
{isMounted && <div ref={ref}>Hi there</div>}
</div>
);
};Your element or component will start off showing by default. Pass { startHidden: true } to override that.
Pass { startWithTransition: true } to automatically execute the show transition when the item initially mounts. It will be ignored if startHidden is true.
Showtime component
Showtime takes a single child component. It uses useShowtime under the hood, cloning the child and adding the ref to it.
Toggle the show boolean prop to trigger show/hide.
import React, { useState } from "react";
import { Showtime } from "react-showtime";
const ComponentExample = () => {
const [show, setShow] = useState(true);
const toggle = () => setShow((current) => !current);
return (
<div>
<button onClick={toggle}>Toggle</button>
<Showtime show={show}>
<div>Oh hi</div>
</Showtime>
</div>
);
};Pass startWithTransition={true} to automatically execute the show transition when the item initially mounts. It will be ignored if show is initially set to false.
Additional performance consideration
Since Showtime clones the child to attach its ref, it may be an expensive operation in some cases if the child component is substantially complicated. If so, provide a function that takes a ref and returns the child component instead, which may be more performant:
import React, { useState } from "react";
import { Showtime } from "react-showtime";
const ComponentExample = () => {
const [show, setShow] = useState(true);
const toggle = () => setShow((current) => !current);
return (
<div>
<button onClick={toggle}>Toggle</button>
<Showtime show={show}>
{(ref) => <div ref={ref}>Oh hi</div>}
</Showtime>
</div>
);
};However, the direct child specification is recommended for most users.
Transitions
If you accept all defaults, you'll get a slideFade transition with a 250ms duration, 16ms delay, and "ease" easing:
// Hook
const [ref, isMounted, show, hide] = useShowtime();// Component
<Showtime show={true}>...</Showtime>Included transitions
React Showtime includes a set of pre-configured transitions: slideFade, slide, fade, rise, scale.
Choose one by passing its name as the hook's sole parameter or to the component's transition prop.
// Hook
const [ref, isMounted, show, hide] = useShowtime("slide");// Component
<Showtime transition="fade" show={true}>
...
</Showtime>The hook also accepts an object instead of a string, in which case pass { transition: ... }:
const [ref, isMounted, show, hide] = useShowtime({ transition: "slide" });Timing
Adjust the transition's timing via duration, delay, and easing.
duration and delay accept integers (interpreted as milliseconds), floats (interpreted as seconds), or strings (eg, "1s" or "300ms".)
easing accepts any valid CSS transition-timing-function value.
// Hook
const [ref, isMounted, show, hide] = useShowtime({
transition: "rise",
duration: 1000,
delay: 250,
easing: "linear",
});// Component
<Showtime
show={true}
transition="scale"
duration={500}
delay={50}
easing="ease-out"
>If you need different timings across show and hide transitions, use showDuration, showDelay, showEasing, and hideDuration, hideDelay, hideEasing.
Custom transitions
To define a custom transition, pass a CSS object literal describing the item's hidden state to the transition prop(erty).
Each value can be a string, number, or object. Strings and numbers will be passed through as CSS.
As an example, here's how you might define a revolve transition, where showing would mount the item then fade it in while spinning it around the y-axis. Hiding would do the reverse.
// Hook
const [ref, isMounted, show, hide] = useShowtime({
transition: {
transform: "rotate3d(0, 1, 0, 180deg)",
opacity: 0,
},
...
});// Component
<Showtime
transition={{
transform: "rotate3d(0, 1, 0, 180deg)",
opacity: 0,
}}
...
>Per-property timing
You can pass an object instead of a string or number as a CSS property's value. It should contain { value, duration, delay, easing } properties.
value is required and will be passed through as the CSS property's value.
The other properties are optional and will be applied to that property's transition timing, overriding any inherited timing values.
In this example, the right and top CSS properties will have a 350ms transition duration and the default "ease" easing, while opacity will take 400ms using "linear" easing.
const HookExample = () => {
const [ref, isMounted, show, hide] = useShowtime({
duration: 350,
transition: {
right: "100vw",
top: "-100vh",
opacity: {
value: 0,
duration: 400,
easing: "linear",
},
},
});
// ...
};Asymmetric transitions with showTransition and hideTransition
The showTransition and hideTransition properties allow you to use different transitions for showing and hiding. This is useful if, say, a notification should slide down from above, but fade away when dismissed.
Like transition, these properties accept a string (included transition) or object (custom transition). They override transition if that's also passed in.
const HookExample = () => {
const [ref, isMounted, show, hide] = useShowtime({
showTransition: "fade",
hideTransition: {
right: "100vw",
top: "-100vh",
opacity: 0,
},
hideDuration: 350,
});
// ...
};Attaching the ref
The useShowtime hook provides a ref that must end up attached to the element you're showing/hiding. It uses the ref to directly assign CSS transition properties and hidden styles to the element, and to listen for transition events.
If you are transitioning an element directly, you can just pass the provided ref as a prop.
If you are transitioning a custom component, consider updating the component to use ref forwarding to pass the ref down to the component's outermost element.
If you are transitioning a component you cannot edit and that does not forward refs to its outermost element, attach the ref to a wrapper div.
Attaching multiple refs
There may be times when you need to attach your own ref to the element or component, along with React Showtime's ref. You can do this using a callback ref.
import React, { useRef } from "react";
import { useShowtime } from "react-showtime";
const MultipleRefsExample = () => {
const myRef = useRef();
const [showtimeRef, isMounted, show, hide] = useShowtime();
const setRefs = (node) => {
myRef.current = node;
showtimeRef.current = node;
};
const toggle = () => (isMounted ? hide() : show());
return (
<>
<button onClick={toggle}>Toggle</button>
{isMounted && <div ref={setRefs}>Hi there</div>}
</>
);
};Attaching your own ref to the Showtime component's child
If you pass a function child to the Showtime component (aka render prop), you can use a similar solution as the above to attach both your own ref and the ref Showtime supplies to the function child.
If you pass a normal JSX child to the Showtime component, the implementation is robust to any normal or callback ref you might attach yourself. Eg, in the following code, myRef will be attached as expected, along with the ref that Showtime attaches internally.
import React, { useRef } from "react";
import { Showtime } from "react-showtime";
const MultipleRefsExample = () => {
const myRef = useRef();
const [show, setShow] = useState(true);
const toggle = () => setShow((current) => !current);
return (
<>
<button onClick={toggle}>Toggle</button>
<Showtime show={show}>
<div ref={myRef}>Hi there</div>
</Showtime>
</>
);
};Events
The Showtime component accepts handlers for onHidden and onShowing. Other lifecycle events are being considered.
The useShowtime hook currently does not accept any event handlers.
API
All timing-related numbers are interpreted as milliseconds if integer, and seconds if float.
useShowtime hook
The useShowtime hook accepts a single parameter, which can be either of:
- a string referring to an included transition
- an object with the following properties:
| Name | Type | Req'd | Default | Description |
|---|---|---|---|---|
startHidden | boolean | no | false | Hide the element initially |
startWithTransition | boolean | no | false | Execute show transition on initial mount. Ignored if startHidden is true. |
transition | string or CSS Properties | no | "slideFade" | Included transition or object defining custom transition (see below) |
showTransition | string or CSS Properties | no | "slideFade" | Included transition or object defining custom transition (see below) |
hideTransition | string or CSS Properties | no | "slideFade" | Included transition or object defining custom transition (see below) |
duration | number or string | no | 250 | Transition duration |
delay | number or string | no | 16 | Transition delay |
easing | string | no | "ease" | Transition timing function |
showDuration | number or string | no | Transition duration | |
showDelay | number or string | no | Transition delay | |
showEasing | string | no | Transition timing function | |
hideDuration | number or string | no | Transition duration | |
hideDelay | number or string | no | Transition delay | |
hideEasing | string | no | Transition timing function |
Showtime component
| Name | Type | Req'd | Default | Description |
|---|---|---|---|---|
show | boolean | yes | Toggle this to show/hide the element or component | |
startWithTransition | boolean | no | false | Execute show transition on initial mount. Ignored if show initially set to false. |
transition | string or CSS Properties | no | "slideFade" | Included transition or object defining custom transition (see below) |
showTransition | string or CSS Properties | no | "slideFade" | Included transition or object defining custom transition (see below) |
hideTransition | string or CSS Properties | no | "slideFade" | Included transition or object defining custom transition (see below) |
duration | number or string | no | 250 | Transition duration |
delay | number or string | no | 16 | Transition delay |
easing | string | no | "ease" | Transition timing function |
showDuration | number or string | no | Transition duration | |
showDelay | number or string | no | Transition delay | |
showEasing | string | no | Transition timing function | |
hideDuration | number or string | no | Transition duration | |
hideDelay | number or string | no | Transition delay | |
hideEasing | string | no | Transition timing function | |
onHidden | function | no | Called when hide transition complete. | |
onShowing | function | no | Called when show transition complete. |
Transition objects
CSS Properties
| Name | Type | Req'd | Default | Description |
|---|---|---|---|---|
| Any CSS property name | string, number, or CSS Property | yes | Use camelCase for names. String and number values passed directly to style. |
CSS Property
| Name | Type | Req'd | Default | Description |
|---|---|---|---|---|
value | string or number | yes | Any CSS property name. | |
duration | number or string | no | inherited | Transition duration |
delay | number or string | no | inherited | Transition delay |
easing | string | no | inherited | Transition timing function |
Development
React Showtime was originally bootstrapped with create-react-hook using this blog post as a guiding reference.
Be sure to reflect any API changes in test fixtures, the demo app in example/, the TypeScript types in index.d.ts, and this readme.
To get started:
yarn startto watch for local changes toreact-showtime,yarn startinexample/to watch for changes to the demo site and run a dev server.
This project uses the Git Flow branching workflow. Usage of the gitflow-cjs CLI tool is recommended for releases and hotfixes.