WebberUI

Type Scale Playground

An interactive modular type scale playground: pick a ratio or drag the slider, and every level on the page recomputes and reflows in sync with a spring animation.

Loading preview…
npx shadcn@latest add https://webberui.com/r/type-scale-playground.json

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

1.25
16
1.1
1.8
<TypeScalePlayground />

Installation

npx shadcn@latest add https://webberui.com/r/type-scale-playground.json

Or, once registries are configured in components.json, install it as @webberui/type-scale-playground.

Usage

import { TypeScalePlayground } from "@/components/ui/type-scale-playground";

<TypeScalePlayground defaultRatio={1.25} />

Controlled mode

Providing ratio puts it in controlled mode, with onRatioChange receiving the user's input:

const [ratio, setRatio] = React.useState(1.333);

<TypeScalePlayground ratio={ratio} onRatioChange={setRatio} />

Custom layout

Use levels to define the demo levels from largest to smallest; each level's font size is baseSize × ratio^step:

<TypeScalePlayground
  baseSize={18}
  levels={[
    { key: "h1", step: 4, text: "Product headline", weight: 700, label: "H1" },
    { key: "h2", step: 2, text: "Section subhead", weight: 600, label: "H2" },
    { key: "body", step: 0, text: "Body paragraph.", label: "Body" },
    { key: "note", step: -1, text: "Footnote.", muted: true, label: "Note" },
  ]}
/>

Props

PropTypeDefaultDescription
rationumberControlled ratio value; providing it enables controlled mode
defaultRationumber1.25Initial ratio in uncontrolled mode
onRatioChange(ratio: number) => voidCallback when the ratio changes (already clamped and rounded to three decimal places)
presetsScalePreset[]six named ratiosList of named ratio presets
minnumber1.1Minimum ratio the slider allows
maxnumber1.8Maximum ratio the slider allows
baseSizenumber16Base font size (the pixel size at step 0)
levelsTypeLevel[]a five-level demo layoutCustom type levels
showControlsbooleantrueWhether to show the preset and slider control bar

ScalePreset

FieldTypeDescription
labelstringDisplay name
valuenumberRatio value

TypeLevel

FieldTypeDescription
keystringUnique key
stepnumberStep relative to the base (font size = baseSize × ratio^step)
textstringSample text
labelstringLevel label (badge on the right)
weightnumberFont weight
trackingstringTracking (the CSS value for letter-spacing)
uppercasebooleanWhether to upper-case it
mutedbooleanWhether to display it in the secondary colour

How it works

  • Modular type scale: every level's font size is computed as baseSize × ratio^step. Change the ratio and all levels recompute together — the big sizes grow fast and the small ones grow slowly, so the contrast opens and closes with it.
  • Spring synchronization: when the ratio changes, every level's size transitions with the same set of spring parameters and naturally re-wraps and reflows as it grows, demonstrating real layout breathing.
  • Two modes: leaving out ratio is uncontrolled (internal state); passing ratio is controlled, syncing external state through onRatioChange.
  • Presets and slider: six common ratios are built in (Minor Third through Golden), and the slider also allows stepless adjustment between min and max.

Accessibility

  • The ratio slider is role="slider" with aria-valuemin / aria-valuemax / aria-valuenow / aria-valuetext, and supports arrow keys (±0.01), PageUp/PageDown (±0.1), and Home/End keyboard operation.
  • The presets are real <button>s, marking the currently selected ratio with aria-pressed.
  • The sample text is readable content; the pixel badges on the right are hidden from assistive technology (aria-hidden).
  • When the user has "reduce motion" enabled at the system level, the font sizes jump straight to their target values, the thumb does not bounce, and there is no transition animation.

On this page