react-showtime
v0.3.9
Published
Animate the entry/exit of React elements during mount/unmount with CSS transitions.
Downloads
88
Readme
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-showtime
npm install react-showtime
tl;dr
- Choose between the
useShowtime
hook or theShowtime
component. The component is better for list items or if you need to listen for events (onShowing
,onHidden
). - Define your
transition
by 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
ref
to your containing element and conditionally render your item with the suppliedisMounted
boolean. - Call the hook's
show()
andhide()
functions – or toggle the component'sshow
prop – 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 start
to watch for local changes toreact-showtime
,yarn start
inexample/
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.