# Text

> Body-copy primitive. Polymorphic element, token-driven size scale, Lato by default, terminal semantics for tone.

- Category: primitive
- Status: stable (since 0.3.0)
- A11y pattern: https://www.w3.org/WAI/ARIA/apg/patterns/
- Tokens: --font-sans, --foreground-primary, --foreground-secondary
- Playground: https://design.freecodecamp.org/playground#text
- npm dependencies: `react@>=18 <20`
- Registry dependencies: [theme](https://design.freecodecamp.org/registry/theme.md)
- Files:
  - `Text.tsx` → `src/ui/text/Text.tsx` (raw: https://design.freecodecamp.org/registry/text/Text.tsx)
  - `text.css` → `src/ui/text/text.css` (raw: https://design.freecodecamp.org/registry/text/text.css)

## Install (copy source)

1. Ensure the theme is installed once per project - tokens.css + base.css imported globally, fonts available. See https://design.freecodecamp.org/registry/theme.md and https://design.freecodecamp.org/registry/starter.md.
2. Copy the files below into `src/ui/text/` (adjust to your project layout) and import the CSS once from your global stylesheet, e.g. `@import './ui/text/text.css';`.
3. Colors, spacing and type come from tokens - tailor the component by editing the copied source; recolour by editing tokens.css, not the component CSS.

## Usage

Text is the body-copy primitive. It renders a `<p>` by default, swaps to
any inline or block element via `as`, and exposes four size steps, two
weights, and three tones - every other styling decision comes from
tokens.

## Accessibility

Pure styling wrapper - no ARIA. Use semantic elements via `as` when the
content demands it (`small` for legal text, `span` inside inline flow,
etc.).

## Example

```tsx
import { Text } from './ui/text/Text';

<Text size="lg">Large body - section ledes and emphasis.</Text>
<Text>Default body - eighteen pixels minimum.</Text>
<Text size="sm" tone="muted">Caption - annotations, metadata, footnotes.</Text>
```

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `as` | `enum` | no | `p` |  |
| `size` | `enum` | no | `base` |  |
| `weight` | `enum` | no | `regular` |  |
| `tone` | `enum` | no | `default` |  |

## Source: Text.tsx

```tsx
import React, { forwardRef } from 'react';

export type TextAs = 'p' | 'span' | 'div' | 'small';
export type TextSize = 'xs' | 'sm' | 'base' | 'lg';
export type TextWeight = 'regular' | 'bold';
export type TextTone = 'default' | 'secondary' | 'muted';

export interface TextProps extends React.HTMLAttributes<HTMLElement> {
  as?: TextAs;
  size?: TextSize;
  weight?: TextWeight;
  tone?: TextTone;
}

export const Text = forwardRef<HTMLElement, TextProps>(
  (
    {
      as = 'p',
      size = 'base',
      weight = 'regular',
      tone = 'default',
      className = '',
      children,
      ...rest
    },
    ref
  ) => {
    const classes = [
      'text',
      size !== 'base' && `text--${size}`,
      weight !== 'regular' && `text--${weight}`,
      tone !== 'default' && `text--${tone}`,
      className
    ]
      .filter(Boolean)
      .join(' ');
    return React.createElement(
      as,
      { ref, className: classes, ...rest },
      children
    );
  }
);
Text.displayName = 'Text';
```

## Source: text.css

```css
.text {
  font-family: var(--font-sans, 'Lato', system-ui, sans-serif);
  font-size: 1rem;
  line-height: 1.55;
  color: var(--foreground-primary);
  margin: 0 0 0.5rem;
}
.text--xs {
  font-size: 0.75rem;
}
.text--sm {
  font-size: 0.875rem;
}
.text--lg {
  font-size: 1.125rem;
}
.text--bold {
  font-weight: 700;
}
.text--secondary {
  color: var(--foreground-secondary);
}
.text--muted {
  color: var(--foreground-secondary);
  opacity: 0.7;
}
```

## HTML / vanilla variant

```html
<p class="text text--lg">Large body</p>
<p class="text">Default body</p>
<p class="text text--sm text--muted">Caption</p>
```

Interactive behaviours for plain HTML come from the vanilla runtime (data-uikit-* attributes): https://design.freecodecamp.org/registry/vanilla.md - or download https://design.freecodecamp.org/cdn/uikit.global.js once and self-host it (do not hotlink).

## For coding agents

This library is distributed as copyable source, not an npm package. Start at https://design.freecodecamp.org/registry/starter.md, discover components via https://design.freecodecamp.org/llms.txt, and copy files into the consuming project. Keep token names intact; recolour by editing the copied tokens.css.
