Skip to content
WANCRAFT

C.133Typography & Text

Type Specimen

An interactive variable-font specimen: editable sample, live axis sliders, waterfall, glyph loupe and CSS output.

NewReactCSSTailwindadvanced

Overview

Type Specimen turns any variable font into a hands-on specimen sheet. A large sample (a real, labelled textarea) can be retyped in place, while a labelled slider is generated for every axis you pass in (weight, width, slant, optical size…) alongside size, leading and tracking. When the font has an opsz axis, optical size can follow the font size automatically. Below, tabs switch between a size waterfall, a character set whose glyphs lift under the pointer and appear magnified in a loupe with their code point, and the CSS for the current settings, ready to copy. The sliders are native range inputs with labels, value text and visible focus rings, the glyph grid uses roving focus with the arrow keys, and the whole layout adapts to its container with container queries. The demo uses the site's own variable fonts: Bricolage Grotesque (wght, wdth, opsz) and Geist (wght).

01Installation

Method 01 · Registry

CLI verified

Uses the shadcn CLI in a project initialised with shadcn init. Installs the file to components/ui/type-specimen.tsx and adds its dependencies.

npx shadcn@latest add https://wancraft.my/r/type-specimen.json

Method 02 · Copy and paste

  1. 1. No extra dependencies — React and Tailwind CSS only.
  2. 2. Copy the source from the Code tab into components/ui/type-specimen.tsx.
  3. 3. Import it and adjust props.
Dependencies
None
Peer
react ≥ 18, tailwindcss ≥ 4
Added
13 Oct 2026
Updated
—

02Usage

The default configuration. Change properties above to generate a tailored example in the Usage tab.

example.tsx
import { TypeSpecimen, type TypeAxis } from "@/components/ui/type-specimen";

export function TypeSpecimenExample() {
  const axes: TypeAxis[] = [
    { tag: "wght", name: "Weight", min: 200, max: 800, default: 500 },
    { tag: "wdth", name: "Width", min: 75, max: 100, default: 100 },
    { tag: "opsz", name: "Optical size", min: 12, max: 96, default: 72 },
  ];

  return (
    <div className="w-full max-w-4xl">
      <TypeSpecimen
        fontFamily="var(--font-bricolage)"
        fontName="Bricolage Grotesque"
        axes={axes}
      />
    </div>
  );
}

03Props

PropTypeDefaultDescription
fontFamilystring—CSS font-family used to render the specimen, e.g. a next/font variable.
fontNamestring—Display name, also used in the CSS snippet. Defaults to fontFamily.
axesTypeAxis[][]{ tag, name, min, max, default, step? } per variable axis; each becomes a labelled slider.
samplestring"Sphinx of black quartz, judge my vow"Initial, editable sample text.
sizenumber72Initial font size in px (capped by the container width).
leadingnumber1.05Initial unitless line height.
trackingnumber-0.02Initial letter spacing in em.
showWaterfall / showGlyphs / showCssbooleantrueWhich tabs appear below the sample.
waterfallnumber[][12, 16, 24, 36, 48, 64]Waterfall sizes in px.
charactersstringA–Z a–z 0–9 + symbolsCharacters in the character set grid.
accentstring"#FF7448"Slider, focus and highlight colour.
...propsHTMLAttributes<HTMLDivElement>—Forwarded to the root element.

04Features

  • 01Editable sample rendered with live font-variation-settings, size, leading and tracking
  • 02One labelled slider per axis from the axes prop (wght, wdth, slnt, opsz or custom)
  • 03Optional optical size linked to font size when the font has an opsz axis
  • 04Size waterfall, character set with hover lift and magnifying loupe (code point), CSS snippet with copy
  • 05Initial values re-sync when props change (e.g. switching fonts); Reset restores them
  • 06Container-query layout: controls sit beside the sample on wide containers, below on narrow ones
motion · tweeninput · pointerinput · keyboardinput · click

05Accessibility

  • The sample is a real <textarea> with a visually hidden label; every setting is a native range input with a <label>, an <output> and aria-valuetext including units.
  • The views are an ARIA tablist (arrow keys, Home/End) with labelled tab panels.
  • Glyph cells are buttons named with the character and its code point, navigated with roving focus (arrow keys, Home/End); the loupe updates on focus as well as hover and announces politely.
  • The hover lift only applies on devices that can hover; copy success is announced in a live region; all controls show an accent focus ring.
  • prefers-reduced-motion removes the variation and hover transitions.

06Limitations

  • Axis ranges must match the font file: values outside the font's real range are clamped by the browser, so pass the axes the font actually ships.