---
layout: ~/layouts/MdxDocLayout.astro
title: "Text"
description: "A typography component for various heading and copy styles."
sourceFile: "components/text"
---

import ComponentExample from "~/components/docs/ComponentExample.astro";
import ComponentSection from "~/components/docs/ComponentSection.astro";
import PropsTable from "~/components/docs/PropsTable.astro";
import { Text } from "@cloudflare/kumo";
import {
  TextVariantsDemo,
  TextTruncateDemo,
} from "~/components/demos/TextDemo";

{/* Hero Demo */}

<ComponentSection>
  <ComponentExample demo="TextVariantsDemo">
    <TextVariantsDemo client:visible />
  </ComponentExample>
</ComponentSection>

{/* Installation */}

<ComponentSection>

## Installation

### Barrel

```tsx
import { Text } from "@cloudflare/kumo";
```

### Granular

```tsx
import { Text } from "@cloudflare/kumo/components/text";
```

</ComponentSection>

{/* Usage */}

<ComponentSection>

## Usage

```tsx
import { Text } from "@cloudflare/kumo";

export default function Example() {
  return <Text>Your content here</Text>;
}
```

<section class="mt-8 space-y-4">
  <Text variant="heading3" as="h3">Semantic HTML</Text>
  <Text>
    The `variant` prop controls visual styling only—it does not determine the HTML element rendered.
    Heading variants **require** the `as` prop to avoid silently excluding real section headings from
    the document outline. Body and monospace variants have sensible defaults (`<p>` and `<span>`
    respectively) and accept `as` optionally.
  </Text>

```tsx
// Heading variants REQUIRE `as` — TypeScript will flag usages missing it
<Text variant="heading1">Page Title</Text> // Doesn't compile

// Real section headings (contribute to the document outline)
<Text variant="heading1" as="h1">Page Title</Text>
<Text variant="heading2" as="h2">Section Title</Text>

// Decorative heading-styled text that is NOT a section heading
<Text variant="heading1" as="span">Big bold card label</Text>

// Visually one size, semantically another
<Text variant="heading1" as="h3">Visually large, but semantically h3</Text>
```

  <Text>
    The `as` prop accepts: `"h1"` through `"h6"`, `"p"`, and `"span"`.
    Body variants default to `"p"`, monospace variants default to `"span"`,
    and heading variants have no default — you must choose explicitly.
  </Text>
</section>

<section class="mt-8 space-y-4">
  <Text variant="heading3" as="h3">Restrictions</Text>
  <Text>
    The `bold` and `size` props are intentionally restricted to the `base`, `secondary`, `success`, and `error` text variants.
  </Text>

```tsx
<Text size="sm" bold>Body</Text>
<Text variant="secondary" bold>Body secondary</Text>
<Text variant="success" size="lg">Success</Text>
<Text variant="error">Error</Text>
```

<Text>
  Monospace variants (`mono` and `mono-secondary`) can only set `size` to `lg`
  and cannot use the `bold` prop:
</Text>

```tsx
<Text variant="mono">Monospace</Text>
<Text variant="mono" size="lg">Monospace</Text>
<Text variant="mono" bold>Monospace</Text> // Doesn't compile
```

<Text>
  Headings (i.e. `heading1`, `heading2` and `heading3` variants) cannot use
  these props at all:
</Text>

```tsx
<Text variant="heading1" bold>
  Heading 1
</Text> // Doesn't compile
```

</section>

</ComponentSection>

{/* Truncate */}

<ComponentSection>

## Truncate

<Text>
  Use the `truncate` prop to clip overflowing text with an ellipsis. This adds `truncate min-w-0` classes, which is useful when `Text` is inside a flex or grid container.
</Text>

<ComponentExample demo="TextTruncateDemo">
  <TextTruncateDemo client:visible />
</ComponentExample>

```tsx
<Text truncate>This is a long piece of text that will be truncated...</Text>
```

</ComponentSection>

{/* API Reference */}

<ComponentSection>

## API Reference

  <PropsTable component="Text" />
</ComponentSection>
