Skip to content

Roll Value

A value that rolls to its new text instead of swapping: up for a later one, down for an earlier one.

$npx shadcn@latest add https://framebrick.co/r/roll-value.json

From the Metuo template, see it in context.

$129/month

Installation

$ npx shadcn@latest add https://framebrick.co/r/roll-value.json

Usage

import { RollValue } from "@/components/ui/roll-value";

// every value it can show, and which one shows now
<p className="text-5xl font-semibold">
  <RollValue items={["$129", "$1,049"]} index={yearly ? 1 : 0} />
</p>

Props

PropTypeDefaultDescription
itemsReactNode[]—Every value it can show, in order. They are all in the page, one above the other.
indexnumber—Which of them shows now. A later one than before rolls up, an earlier one rolls down.
gapnumber10Space between two values in the column, in px. It only shows while it rolls.
classNamestring—Classes for the window: the text size and weight go here, or text-right to align the narrower values.
  • It is Metuo's price roll: the price sits in a window one line tall over a column holding both periods, and the billing switch rolls the column up one line (69 px for a 32 px price) with Framer's spring, bounce 0, 0.4 s; "/month" turns into "/year" beside it the same way. Going back rolls down.
  • It sizes itself from the text: the window is one line tall (1lh, the line height it inherits) and as wide as the widest value, so what is beside it never moves. It needs the lh unit: Chrome 109, Safari 16.4 or Firefox 120.
  • Plain CSS: no animation library and no JavaScript, so it works as it is on a server page, and the right value is in the server's HTML. The spring is a CSS linear() curve sampled from the spring itself, within 1% of it; a browser without linear() gets cubic-bezier(0.22, 1, 0.36, 1). With reduced motion it changes at once.
  • Only the value at index is read to assistive technology (the others are aria-hidden and inert), and nothing is announced when it changes: the control that changed it says what it did, or give this an aria-live of its own.
  • It is not Text Rotator, which cycles through its texts by itself on a timer; this one goes where it is told.

AI prompt

Paste into v0, Lovable, Bolt or Claude to rebuild this component in your own project.

Create a React + Tailwind CSS component called RollValue — plain CSS, no JavaScript and no animation library, so it works in a server component.
- Props: items (ReactNode[], every value it can show), index (which one shows), gap (px, 10), className and the span attributes. Clamp the index to the items.
- A span (relative inline-block h-[1lh] overflow-hidden align-bottom) with --i (the index) and --gap set inline, holding a flex flex-col column (gap-(--gap)) with one block h-[1lh] whitespace-nowrap span per item; the items that are not at the index are aria-hidden and inert.
- The column's transform is translateY(calc(var(--i) * -1 * (1lh + var(--gap)))) with transition-transform over 400ms and an easing from the custom property --roll-ease: cubic-bezier(0.22,1,0.36,1), replaced by a 30-stop linear() list sampled from a spring with bounce 0 and duration 0.4s inside supports-[transition-timing-function:linear(0,1)]; motion-reduce:transition-none.

Be the first to know

Get new templates and components first

One short email when we release a template or a free component. No spam — unsubscribe anytime.

We use your email only for Framebrick updates. Privacy policy