Text flip

Cycle through words or phrases in place, flipping the next one in as the current one flips out.

Rotates a set of words in a sentence or heading, like the framework names in this site's hero. Works in React, Vue, Svelte, Solid, Preact and vanilla JS.

  • Flips on a timer, or on demand with next, prev and goTo
  • Sizes to the widest item, so the text around it never shifts
  • Hides every item but the current one from assistive technology
  • Renders the first item as plain text until hydrated, so server-rendered markup reads fine
  • Respects reduced motion

Installation

in the preview, then copy the prompt into Claude Code, Cursor or another coding agent, or add the component yourself with the shadcn CLI or by hand.

Prompt for your coding agent
Show prompt
Add the text flip from isbatak-labs to this project. It cycles through words or phrases in place, flipping the next one in as the current one flips out. Use the React version styled with Panda CSS and built on the Zag state machine. Docs: https://isbatak-labs.vercel.app/components/prototypes/text-flip.md

1. Install it with the shadcn CLI. Swap `pnpm dlx` for `npx`, `yarn dlx` or `bunx` to match the project's lockfile:

pnpm dlx shadcn@latest add https://isbatak-labs.vercel.app/r/text-flip-basic-react-panda.json

This installs `@isbatak/zag-text-flip` and `@zag-js/react`, plus `@isbatak/panda-text-flip` as a dev dependency, and adds the component to `src/components/text-flip-basic/`. If the CLI can't run here, install those packages yourself and write the files listed in https://isbatak-labs.vercel.app/r/text-flip-basic-react-panda.json (each entry has its content and target path).

2. Finish the setup:

- Panda CSS: add `"@isbatak/panda-text-flip"` to the presets in the Panda config (or import `textFlipPreset` from it if the config already imports its presets), then run `panda codegen`. If the project doesn't use Panda CSS, stop and tell me to pick the CSS version in the docs instead.

3. Ask me where the text flip should go and which words it should cycle through, and suggest a spot if one stands out. Then render it there: copy the installed component, give it a name that fits, replace the items with mine (each item needs its zero-based `index`), and keep the timing options that fit (`interval`, `autoplay`).

4. Start the dev server, check that the words flip in place on a timer without shifting the text around them, then stop it. If you can't run it, tell me how to check it myself.
pnpm dlx shadcn@latest add https://isbatak-labs.vercel.app/r/text-flip-basic-react-panda.json

This installs the dependencies and adds the component to src/components/text-flip-basic/. It imports the recipe from styled-system/recipes.

Add "@isbatak/panda-text-flip" to presets in your Panda config, or import textFlipPreset from it and add that instead.

Examples

Scroll to an example to load it in the preview, and open the code view there for the full source. The settings button in the preview changes the example live, and the snippet under it follows. Each example is its own registry item, so you can add it with the CLI the same way.

Every item needs its zero-based index, in the order the items flip.

Controls

The machine exposes next, prev, goTo, play and pause, and playing tells you whether the timer is running. Wire them to buttons to let people step through the items or stop the animation. With Ark UI, create the machine with useTextFlip and pass it to TextFlip.RootProvider so the buttons outside the root can use it.

const service = useMachine(textFlip.machine, {})

Timing

Set interval to the time in milliseconds each item stays before the next one flips in. The default is 2000. Set autoplay to false to start paused, and defaultIndex to start on another item.

const service = useMachine(textFlip.machine, {
  interval: 1000,
})

Styling

The root is an inline grid and every item sits in the same cell, so the root is as wide as the widest item. Each item gets data-state set to visible for the first item before any flip, entering for the current item, exiting for the one it replaced and hidden for the rest. The Panda recipe animates entering and exiting with a blurred slide, and turns the animation off when people prefer reduced motion.

Accessibility

Items that aren't shown get aria-hidden, so screen readers only read the current one, and they don't announce each flip. When the words are decoration, like a list of supported frameworks, hide the root with aria-hidden and put the full list in visually hidden text next to it.

Props

PropTypeDefault
idsElementIds
The ids of the elements in the text flip. Useful for composition.
—
intervalnumber
The time in milliseconds each item stays before the next one flips in.
2000
autoplayboolean
Whether the items start flipping on their own.
true
defaultIndexnumber
The index of the item shown first.
0
onIndexChange(details: IndexChangeDetails) => void
Function called when the shown item changes.
—
idstring
The unique identifier of the machine.
—
getRootNode() => ShadowRoot | Document | Node
A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron.
—

API

PropertyType
indexnumber
The index of the shown item.
playingboolean
Whether the items are flipping on their own.
next() => void
Show the next item, wrapping around after the last one.
prev() => void
Show the previous item, wrapping around before the first one.
goTo(index: number) => void
Show the item at the given index.
play() => void
Start flipping on a timer.
pause() => void
Stop flipping on a timer.
getItemState(props: ItemProps) => ItemState
Returns whether an item is shown, flipping in, flipping out or hidden.