component — display

Eyebrow

The Label role outside a form: mono, uppercase, tracked, fg-subtle — kickers above a headline, scene labels, timecodes and counts. Written lowercase in the source; CSS sets the caps.

  • typography
  • label
  • kicker
  • eyebrow
  • caption
  • brand

use a eyebrow when

  • A kicker above a headline or a low title: "scene 01 — the studio".
  • A count beside a section heading: "04 entries".
  • A timecode or a short index: "00:01:24", "a", "b".

don't

  • Never more than one line, and never a sentence — running text is Inter at body size.
  • Not a form field's label. That is Label from Field, which is bound to its control.
  • Don't write it in capitals in the source; the utility sets the caps, and copy-paste and screen readers get what you wrote.

02 examples

Kickers, counts and timecodes

Written lowercase; the caps come from CSS. An em dash with spaces separates parts.

scene 01 — the studio

studio — issue 04

00:01:24

Beside a section heading

`as="span"` for a count that sits on the heading's baseline.

selected work

04 entries

what to use instead

by job

By what the eyebrow was doing.

Labelling a form control
  • Field — Its `Label` wears the same type and is a real `<label>`.

source

eyebrow.tsx

Copy this into your project. Resolve its dependencies from the registryDependencies in the component's API entry.

import { cn } from "@/lib/utils"

/**
 * Eyebrow — quebi design system
 *
 * The Label role outside a form: mono, uppercase, tracked, always `fg-subtle`.
 * Kickers above a headline, scene labels, timecodes, counts ("04 entries").
 * A field's label is `Label` from `@/components/field`, which wears the same
 * type but is a `<label>` bound to its control; this one labels nothing.
 *
 * Write it in lowercase in the source — the utility sets the caps, so the text
 * a screen reader or a copy-paste gets stays lowercase. Use an em dash with
 * spaces between parts ("scene 01 — the studio"). Never more than one line.
 */

type EyebrowElement = "p" | "span" | "div"

export interface EyebrowProps extends React.HTMLAttributes<HTMLElement> {
  /** The element to render. `p` (default) for a kicker on its own line, `span` inline. */
  as?: EyebrowElement
}

export function Eyebrow({ as: Element = "p", className, ...props }: EyebrowProps) {
  return <Element data-slot="eyebrow" className={cn("quebi-eyebrow m-0", className)} {...props} />
}