Display
text-2xl (24px)Page title
text-xl (17px)Section title
text-lg (15px)Heading
text-base (13px)Body
text-base (13px)Body sm
text-sm (12px)Body secondary
text-base (13px)Success
text-base (13px)Error
text-base (13px)import { Text } from "@cloudflare/kumo";
export function TextVariantsDemo() {
return (
<div className="grid w-full grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
<div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
<Text variant="display" as="h1">
Display
</Text>
<Text variant="mono-secondary">text-2xl (24px)</Text>
</div>
<div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
<Text variant="page-title" as="h2">
Page title
</Text>
<Text variant="mono-secondary">text-xl (17px)</Text>
</div>
<div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
<Text variant="section-title" as="h3">
Section title
</Text>
<Text variant="mono-secondary">text-lg (15px)</Text>
</div>
<div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
<Text variant="heading" as="h4">
Heading
</Text>
<Text variant="mono-secondary">text-base (13px)</Text>
</div>
<div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
<Text>Body</Text>
<Text variant="mono-secondary">text-base (13px)</Text>
</div>
<div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
<Text size="sm">Body sm</Text>
<Text variant="mono-secondary">text-sm (12px)</Text>
</div>
<div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
<Text variant="secondary">Body secondary</Text>
<Text variant="mono-secondary">text-base (13px)</Text>
</div>
<div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
<Text variant="mono">Monospace</Text>
<Text variant="mono-secondary">text-sm (12px)</Text>
</div>
<div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
<Text variant="mono-secondary">Monospace secondary</Text>
<Text variant="mono-secondary">text-sm (12px)</Text>
</div>
<div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
<Text variant="success">Success</Text>
<Text variant="mono-secondary">text-base (13px)</Text>
</div>
<div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
<Text variant="error">Error</Text>
<Text variant="mono-secondary">text-base (13px)</Text>
</div>
</div>
);
}Installation
Barrel
import { Text } from "@cloudflare/kumo";Granular
import { Text } from "@cloudflare/kumo/components/text";Usage
import { Text } from "@cloudflare/kumo";
export default function Example() {
return <Text>Your content here</Text>;
}Heading variants
Heading variants are role-based. Reach for the one that describes what the text is, not how big you want it:
variant="display"— hero / prominent moments (24px semibold)variant="page-title"— the single title of a page or dialog (17px medium)variant="section-title"— card / panel / section heading (15px medium)variant="heading"— inline / row / list-item heading (13px medium)
heading is the small, most-used one — reach for it before adding extra
weight or size to body text.
Semantic HTML
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.
// Heading variants REQUIRE `as` — TypeScript will flag usages missing it
<Text variant="display">Welcome</Text> // Doesn't compile
// Real section headings (contribute to the document outline)
<Text variant="display" as="h1">Welcome</Text>
<Text variant="page-title" as="h1">Account settings</Text>
<Text variant="section-title" as="h2">General</Text>
<Text variant="heading" as="h3">API tokens</Text>
// Decorative heading-styled text that is NOT a section heading
<Text variant="display" as="span">Big card label</Text>
// Visually one size, semantically another
<Text variant="display" as="h3">Visually large, but semantically h3</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.
Restrictions
The size prop is intentionally restricted to the body, secondary, success, and error variants.
<Text size="sm">Body</Text>
<Text variant="secondary" size="sm">Body secondary</Text>
<Text variant="success">Success</Text>
<Text variant="error">Error</Text>Monospace variants (mono and mono-secondary) always render at 12px and
do not accept a size prop.
<Text variant="mono">Monospace</Text>Heading variants (display, page-title, section-title, heading) don’t
accept size — the size is part of the role.
The bold prop follows the same shape: it applies only to copy variants
(body, secondary, success, error), where it bumps weight to
font-medium (500) for inline emphasis. Heading variants already carry
their role’s weight, and monospace stays regular by design — both type
bold as never so consumers get a compile error rather than a silent
no-op. For structural hierarchy inside a document outline reach for
variant="heading" instead of bold.
<Text bold>Important detail</Text>
<Text variant="secondary" bold>Muted but bumped</Text>Deprecated variants
The numeric heading names still work but emit a warning in development. Migrate call sites to the role-based names:
heading1→displayheading2→page-titleheading3→section-title
Truncate
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.
This is a long piece of text that will be truncated with an ellipsis when it overflows its container.
import { Text } from "@cloudflare/kumo";
export function TextTruncateDemo() {
return (
<div className="w-64 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
<Text truncate>
This is a long piece of text that will be truncated with an ellipsis
when it overflows its container.
</Text>
</div>
);
}<Text truncate>This is a long piece of text that will be truncated...</Text>API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "display" | "page-title" | "section-title" | "heading" | "heading1" | "heading2" | "heading3" | "body" | "secondary" | "success" | "error" | "mono" | "mono-secondary" | "body" | Text style variant. Heading variants (role-based, weight-first hierarchy): - `"display"` — Hero / prominent moments (24px semibold) - `"page-title"` — The single title of a page or dialog (17px medium) - `"section-title"` — Card / panel / section heading (15px medium) - `"heading"` — Inline / row / list-item heading (13px medium) Body variants: - `"body"` — Default body text (13px) - `"secondary"` — Muted text for secondary information - `"success"` — Success state text - `"error"` — Error state text - `"mono"` — Monospace text for code - `"mono-secondary"` — Muted monospace text Deprecated (use the role-based names above): - `"heading1"` → use `"display"` - `"heading2"` → use `"page-title"` - `"heading3"` → use `"section-title"` |
| size | "sm" | "base" | "xs" | "lg" | "base" | Text size (only applies to body/secondary/success/error variants). - `"sm"` — 12px (caption / helper text) - `"base"` — 13px (default body) - `"xs"` — **Deprecated.** Use `"sm"` instead. - `"lg"` — **Deprecated.** Use `"base"` instead. |
| bold | boolean | - | Bumps body copy weight to `font-medium` (500). Only applies to copy variants (`body`, `secondary`, `success`, `error`); heading variants already carry their role's weight and disallow this prop at the type level. For structural hierarchy inside a document outline reach for `variant="heading"` instead — `bold` is for inline emphasis. |
| truncate | boolean | - | Whether to truncate overflowing text with an ellipsis. Adds `truncate min-w-0` classes. |
| as | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "span" | "label" | "dt" | "dd" | "li" | "figcaption" | "legend" | "pre" | "code" | "em" | "strong" | "small" | "abbr" | "time" | - | The HTML element to render. Accepts headings (`"h1"`–`"h6"`), block text (`"p"`, `"pre"`), inline text (`"span"`, `"code"`, `"em"`, `"strong"`, `"small"`, `"abbr"`, `"time"`), form-related (`"label"`, `"legend"`), list/definition (`"dt"`, `"dd"`, `"li"`), and `"figcaption"`. - **Required** for heading variants (`"display"`, `"page-title"`, `"section-title"`, `"heading"`) — pick the element that reflects this text's place in the document outline, or `"span"` for decorative heading-styled text that is not a section heading. - **Optional** for body variants (defaults to `"p"`) and monospace variants (defaults to `"span"`). |
| children | ReactNode | - | Text content. |