Skip to content
Lenso UI

Typography

A semantic typography primitive for headings, body copy, and inline code built on React Aria Components Text.

Usage

import {Typography} from "@lenso/ui";
"use client";
import { Typography } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";
const styles = stylex.create({  column: { display: "flex", flexDirection: "column", gap: 16, maxWidth: 576 },});
export function Default() {  return (    <div {...stylex.props(styles.column)}>      <Typography type="h1">Build better interfaces</Typography>      <Typography type="h2">Typography that stays semantic</Typography>      <Typography type="h3">Composable by default</Typography>      <Typography type="h4">Small heading</Typography>      <Typography>        Lenso UI Typography provides semantic typography types and native element composition.      </Typography>      <Typography color="muted" type="body-sm">        Smaller muted body copy for secondary descriptions.      </Typography>      <Typography type="code">pnpm add @lenso/ui</Typography>    </div>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

Anatomy

Typography maps visual type values to semantic elements by default.

import {Typography} from "@lenso/ui";
export default () => (  <Typography type="h1">Heading</Typography>);

Examples

Scale

"use client";// Adapted from HeroUI v3.2.6 (Apache-2.0).import { Typography } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";const scale = [  { label: "h1", meta: "36px / 600 / 1.11 / tight", sample: "Build better interfaces", type: "h1" },  {    label: "h2",    meta: "30px / 600 / 1.17 / tight",    sample: "Built for the intelligence age",    type: "h2",  },  { label: "h3", meta: "24px / 600 / 1.25 / tight", sample: "Pricing on your terms", type: "h3" },  {    label: "h4",    meta: "20px / 600 / 1.33 / tight",    sample: "Apply to the startup program",    type: "h4",  },  { label: "h5", meta: "18px / 600 / 1.39 / tight", sample: "Card titles", type: "h5" },  { label: "h6", meta: "16px / 600 / 1.50 / tight", sample: "Smaller feature headers", type: "h6" },  {    label: "body",    meta: "16px / 400 / 1.75",    sample: "Primary body text used across documentation, marketing copy, and descriptions.",    type: "body",  },  {    label: "body-sm",    meta: "14px / 400 / 1.50",    sample: "Secondary body, table cells, navigation, and sidebar items.",    type: "body-sm",  },  {    label: "body-xs",    meta: "12px / 400 / 1.25",    sample: "Captions, badges, helper text, and fine print.",    type: "body-xs",  },  { label: "code", meta: "14px / mono", sample: "pnpm add @lenso/ui", type: "code" },] as const;const styles = stylex.create({  column: { display: "flex", width: "100%", flexDirection: "column" },  row: {    display: "grid",    gridTemplateColumns: "160px 1fr",    alignItems: "center",    gap: 32,    paddingBlock: 20,    borderBlockEndWidth: { default: 1, ":last-child": 0 },    borderBlockEndStyle: "solid",    borderBlockEndColor: "var(--border)",  },  caption: { display: "flex", flexShrink: 0, flexDirection: "column", gap: 2 },  label: { fontSize: 14, lineHeight: "20px", fontWeight: 600, color: "var(--foreground)" },  meta: { fontSize: 12, lineHeight: "16px", whiteSpace: "nowrap", color: "var(--muted)" },});export function TypographyScale() {  return (    <div {...stylex.props(styles.column)}>      {scale.map((row) => (        <div key={row.label} {...stylex.props(styles.row)}>          <div {...stylex.props(styles.caption)}>            <span {...stylex.props(styles.label)}>{row.label}</span>            <span {...stylex.props(styles.meta)}>{row.meta}</span>          </div>          <Typography type={row.type}>{row.sample}</Typography>        </div>      ))}    </div>  );}export default TypographyScale;

Local adaptation source above. Derived from HeroUI v3.2.6 source.

Primitives

"use client";// Adapted from HeroUI v3.2.6 (Apache-2.0).import { Typography } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";const styles = stylex.create({  column: { display: "flex", maxWidth: 576, flexDirection: "column", gap: 16 },});export function Primitives() {  return (    <div {...stylex.props(styles.column)}>      <Typography.Heading level={1}>Dashboard</Typography.Heading>      <Typography.Paragraph>        Convenience primitives are thin wrappers over Typography, so you can choose explicit        composition without learning a second styling system.      </Typography.Paragraph>      <Typography.Paragraph color="muted" size="sm">        Paragraph supports base, sm, and xs sizes.      </Typography.Paragraph>      <Typography.Code>Typography.Code</Typography.Code>    </div>  );}export default Primitives;

Local adaptation source above. Derived from HeroUI v3.2.6 source.

  • Typography.Heading maps level={1..6} to type="h1" through type="h6".
  • Typography.Paragraph maps size="base" | "sm" | "xs" to body text styles.
  • Typography.Code maps to the inline code style.
  • Typography.Prose styles rich content passed as regular HTML children.

Prose

"use client";// Adapted from HeroUI v3.2.6 (Apache-2.0).import { Typography } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";const styles = stylex.create({  column: { display: "flex", maxWidth: 576, flexDirection: "column", gap: 12 },});export function Prose() {  return (    <Typography.Prose xstyle={styles.column}>      <h1>Prose title</h1>      <p>        Prose is for authored content where the markup is already semantic and Lenso UI applies the        default typography rhythm.      </p>      <h2>Section title</h2>      <p>        Inline code like <code>render</code> receives the same code treatment as the Typography        primitive.      </p>    </Typography.Prose>  );}export default Prose;

Local adaptation source above. Derived from HeroUI v3.2.6 source.

Render Props

"use client";// Adapted from HeroUI v3.2.6 (Apache-2.0); uses native Base UI render props.import { Typography } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";const styles = stylex.create({  column: { display: "flex", maxWidth: 576, flexDirection: "column", gap: 16 },});export function RenderProps() {  return (    <div {...stylex.props(styles.column)}>      <Typography        render={({ children, ...domProps }) => <h2 {...domProps}>{children}</h2>}        type="h1"      >        H1 visual style, h2 semantic element      </Typography>      <Typography render={({ children, ...domProps }) => <span {...domProps}>{children}</span>}>        The render prop can swap the underlying element while preserving Lenso UI props and styles.      </Typography>    </div>  );}export default RenderProps;

Local adaptation source above. Derived from HeroUI v3.2.6 source.

Use the React Aria Components-style render prop when you need to customize the rendered element.

Customization

Tailwind CSS

"use client";// Adapted from HeroUI v3.2.6 (Apache-2.0).import { Typography } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";const styles = stylex.create({  panel: {    display: "flex",    maxWidth: 448,    flexDirection: "column",    gap: 8,    borderRadius: "var(--radius-xl)",    border: "1px solid color-mix(in oklab, var(--border) 80%, transparent)",    backgroundColor: "var(--surface-secondary)",    padding: 16,  },  category: {    fontSize: 12,    fontWeight: 500,    letterSpacing: ".025em",    color: "var(--accent)",    textTransform: "uppercase",  },  title: { fontWeight: 600, letterSpacing: "-.025em", color: "var(--foreground)" },  text: { fontSize: 14, lineHeight: 1.625, color: "var(--muted)" },});export function CustomStyles() {  return (    <div {...stylex.props(styles.panel)}>      <Typography xstyle={styles.category} type="body-xs">        Changelog      </Typography>      <Typography xstyle={styles.title} type="h4">        Faster search results      </Typography>      <Typography xstyle={styles.text} type="body-sm">        Queries now return in under 200ms thanks to an improved index.      </Typography>    </div>  );}export default CustomStyles;

Local adaptation source above. Derived from HeroUI v3.2.6 source.

Global CSS

To customize the Typography component classes, you can use the @layer components directive. Learn more.

@layer components {  .typography--h1 {    @apply font-extrabold tracking-tight;  }
  .typography--code {    @apply rounded-md bg-default-100 font-mono dark:bg-default-50/20;  }}

Styling Reference

HeroUI follows the BEM methodology to ensure component variants and states are reusable and easy to customize.

CSS Classes

The Typography component uses these CSS classes (View source styles):

Base Classes [!toc]

  • .typography - Base typography primitive
  • .typography-prose - Rich prose container

Type Classes [!toc]

  • .typography--h1 through .typography--h6
  • .typography--body, .typography--body-sm, .typography--body-xs
  • .typography--code

Modifier Classes [!toc]

  • .typography--align-start, .typography--align-center, .typography--align-end, .typography--align-justify
  • .typography--color-default, .typography--color-muted
  • .typography--truncate
  • .typography--weight-normal, .typography--weight-medium, .typography--weight-semibold, .typography--weight-bold

API Reference

Typography

PropTypeDefaultDescription
type'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'body' | 'body-sm' | 'body-xs' | 'code''body'Semantic typography style.
align'start' | 'center' | 'end' | 'justify''start'Text alignment.
color'default' | 'muted''default'Text color.
weight'normal' | 'medium' | 'semibold' | 'bold'-Font weight override.
truncateboolean-Truncates the text to one line with ellipsis.
renderDOMRenderFunction-Custom render function from React Aria.
childrenReactNode-Text content.