On this page

Typography

Text

Styled text with semantic typography styles and colour roles.

Text applies Luke UI typography without adding heading semantics. It needs a Luke UI theme root. See Getting started.

The quick brown fox jumps over the lazy dog.
import { Text } from '@luke-ui/react/text';

export default () => {
	return <Text>The quick brown fox jumps over the lazy dog.</Text>;
};

Pass slot to fill a named text slot defined by a React Aria parent. Pass slot={null} to opt out of surrounding slotted text context.

Visually hidden

Set isVisuallyHidden to hide the text while keeping it available to assistive technology. Text keeps its React Aria Text root. There is no extra wrapper. Use VisuallyHidden directly when the content is not typography text, or when it must reveal on focus.

Element type

Text renders React Aria's Text component, which uses a span by default. Set elementType to choose a semantic element without changing the type treatment. Text trims Capsize space on known block elements such as p, div, headings, and blockquote, and skips it for inline or unknown element types. Use renderRoot instead of elementType when a callback must own the root element. The two props are mutually exclusive. A Text renderRoot callback must return a <span>. Use elementType for a different semantic tag. Heading supplies its resolved heading tag to its renderRoot callback.

<Text elementType="p">A paragraph of supporting copy.</Text>

<Text elementType="label">Email address</Text>

Typography

Pass typography to choose a style. body is the default. See Typography for the full style reference.

Text: Lead typography
Lead text sits at a larger size than body text.
import { Text } from '@luke-ui/react/text';

export default () => {
	return <Text typography="lead">Lead text sits at a larger size than body text.</Text>;
};

Set fontWeight only when you need to override the style's weight. Themes expose body, label, heading, and emphasis roles for that purpose.

Use a larger style such as display or heading1 for prominent content that is not a heading, such as a large status value.

Colour

Omit color to inherit the surrounding colour. Set color to primary, secondary, or a semantic role: neutral, accent, info, success, warning, or danger. Each value reads the nearest Luke UI background, such as a Box backgroundColor. On a standard surface or a subtle fill, a role keeps its hue. On a solid fill, every role reads as that fill's primary colour, because the theme guarantees contrast only for that fill's own foreground. Typography components such as Strong keep the colour around them.

Text: Colour
Surface
InheritedSecondaryDanger with emphasis
Subtle fill
InheritedSecondaryDanger with emphasis
Solid fill
InheritedSecondaryDanger with emphasis
import { Box } from '@luke-ui/react/box';
import { Strong } from '@luke-ui/react/strong';
import { Text } from '@luke-ui/react/text';
import { Comparison, ComparisonItem } from '#docs';

export default () => {
	return (
		<Comparison>
			<ComparisonItem label="Surface">
				<Box
					backgroundColor="surface.subdued"
					borderRadius="surface"
					columnGap="space.24"
					display="flex"
					flexWrap="wrap"
					padding="space.16"
					rowGap="space.8"
				>
					<Specimens />
				</Box>
			</ComparisonItem>
			<ComparisonItem label="Subtle fill">
				<Box
					backgroundColor="accent.subtle"
					borderRadius="surface"
					columnGap="space.24"
					display="flex"
					flexWrap="wrap"
					padding="space.16"
					rowGap="space.8"
				>
					<Specimens />
				</Box>
			</ComparisonItem>
			<ComparisonItem label="Solid fill">
				<Box
					backgroundColor="accent.solid"
					borderRadius="surface"
					columnGap="space.24"
					display="flex"
					flexWrap="wrap"
					padding="space.16"
					rowGap="space.8"
				>
					<Specimens />
				</Box>
			</ComparisonItem>
		</Comparison>
	);
};

function Specimens() {
	return (
		<>
			<Text>Inherited</Text>
			<Text color="secondary">Secondary</Text>
			<Text color="danger">
				Danger with <Strong>emphasis</Strong>
			</Text>
		</>
	);
}

secondary guarantees readable contrast, not visible de-emphasis. On a solid fill it can match primary. Typography props such as typography and shouldInheritFont never change the colour. Read Colour for the backgrounds Luke UI recognises.

Alignment

Set textAlign when the layout needs a different inline alignment.

Text: Alignment

Start aligned

Centre aligned

End aligned

import { Stack } from '@luke-ui/react/stack';
import { Text } from '@luke-ui/react/text';
import { vars } from '@luke-ui/react/theme';

const rowStyle = {
	backgroundColor: vars.color.background.neutral.subtle,
} as const;

export default () => {
	return (
		<Stack gap="space.8">
			<Text elementType="p" style={rowStyle} textAlign="start">
				Start aligned
			</Text>
			<Text elementType="p" style={rowStyle} textAlign="center">
				Centre aligned
			</Text>
			<Text elementType="p" style={rowStyle} textAlign="end">
				End aligned
			</Text>
		</Stack>
	);
};

Numeric glyphs

Use fontVariantNumeric to align numeric columns, format fractions and ordinals, or distinguish zero with a slash.

Text: Numeric glyphs
Tabular
111,111 888,888
Fractions
1/2 3/4 5/6
Ordinals
1st 2nd 3rd 4th
Slashed zero
012 OQR
import { Text } from '@luke-ui/react/text';
import { Comparison, ComparisonItem } from '#docs';

const variants = [
	{ label: 'Tabular', sample: '111,111 888,888', value: 'tabular-nums' },
	{ label: 'Fractions', sample: '1/2 3/4 5/6', value: 'diagonal-fractions' },
	{ label: 'Ordinals', sample: '1st 2nd 3rd 4th', value: 'ordinal' },
	{ label: 'Slashed zero', sample: '012 OQR', value: 'slashed-zero' },
] as const;

export default () => {
	return (
		<Comparison>
			{variants.map((variant) => (
				<ComparisonItem key={variant.value} label={variant.label}>
					<Text elementType="div" fontVariantNumeric={variant.value}>
						{variant.sample}
					</Text>
				</ComparisonItem>
			))}
		</Comparison>
	);
};

Trimming

Block text trims space above capitals and below the baseline by default. That makes vertical spacing more predictable in cards and other bounded layouts. Inline text skips trim so its pseudo-elements cannot interrupt the surrounding line. Set shouldDisableTrim explicitly when you need to override the element-type inference.

Text: Trimming
Aa
import { Box } from '@luke-ui/react/box';
import { CheckboxField } from '@luke-ui/react/checkbox-field';
import { Stack } from '@luke-ui/react/stack';
import { Text } from '@luke-ui/react/text';
import { vars } from '@luke-ui/react/theme';
import { useState } from 'react';

const lineBoxStyle = {
	backgroundColor: vars.color.background.surface.subdued,
	borderBlock: `${vars.borderWidth.thin} dashed ${vars.color.border.decorative}`,
} as const;

export default () => {
	const [isTrimmed, setIsTrimmed] = useState(true);

	return (
		<Stack gap="space.16">
			<CheckboxField isSelected={isTrimmed} label="Trim text" onChange={setIsTrimmed} />
			<Box paddingInline="space.12" style={lineBoxStyle}>
				<Text elementType="div" shouldDisableTrim={!isTrimmed} typography="display">
					Aa
				</Text>
			</Box>
		</Stack>
	);
};

Truncation

Use lineClamp to constrain text to one line or up to five lines. Text truncates overflow with an ellipsis. It disables trimming automatically when you set lineClamp.

Text: Truncation
Short lines are easier to scan than long ones, which is why well-set text rarely stretches edge to edge on a wide screen, no matter how much room is available.
Short lines are easier to scan than long ones, which is why well-set text rarely stretches edge to edge on a wide screen, no matter how much room is available.
import { Stack } from '@luke-ui/react/stack';
import { Text } from '@luke-ui/react/text';

export default () => {
	return (
		<Stack gap="space.16">
			<Text elementType="div" lineClamp>
				Short lines are easier to scan than long ones, which is why well-set text rarely stretches
				edge to edge on a wide screen, no matter how much room is available.
			</Text>
			<Text elementType="div" lineClamp={2}>
				Short lines are easier to scan than long ones, which is why well-set text rarely stretches
				edge to edge on a wide screen, no matter how much room is available.
			</Text>
		</Stack>
	);
};

Transform and decoration

Use textTransform and textDecoration when the content calls for them. These props affect the rendered text only, so avoid using uppercase styling as a substitute for a clear label.

Text: Transform and decoration
Uppercase textUnderlined text
import { Stack } from '@luke-ui/react/stack';
import { Text } from '@luke-ui/react/text';

export default () => {
	return (
		<Stack gap="space.12">
			<Text textTransform="uppercase">Uppercase text</Text>
			<Text textDecoration="underline">Underlined text</Text>
		</Stack>
	);
};

API

TextProps also accepts compatible DOM and ARIA attributes and event handlers for its rendered element.

NameTypeDefault
color
"accent" |⁠ "danger" |⁠ "info" |⁠ "neutral" |⁠ "primary" |⁠ "secondary" |⁠ "success" |⁠ "warning" |⁠ undefined—

Sets text colour from the nearest Luke UI background. On a solid background, every semantic role reads as that background's primary colour. Omit it to inherit the surrounding colour.

fontStyle
"default" |⁠ "inherit" |⁠ "italic" |⁠ "normal" |⁠ undefined'default'

Sets font style.

fontVariantNumeric
"default" |⁠ "diagonal-fractions" |⁠ "normal" |⁠ "ordinal" |⁠ "slashed-zero" |⁠ "tabular-nums" |⁠ undefined'default'

Sets numeric glyph style.

fontWeight
"body" |⁠ "emphasis" |⁠ "heading" |⁠ "label" |⁠ undefined—

Sets the semantic font-weight role. When omitted, the selected typography style supplies its weight.

isVisuallyHidden
booleanfalse

Hides text visually while keeping it accessible.

lineClamp
1 |⁠ 2 |⁠ 3 |⁠ 4 |⁠ 5 |⁠ boolean |⁠ undefined—

Clamps text lines. true clamps to 1 line; numeric values clamp to 1–5.

shouldDisableTrim
boolean |⁠ undefined—

Turns cap-height trim on or off. When omitted, trimming is disabled for inline or unknown element types. Line clamp always disables trim.

shouldInheritFont
boolean |⁠ undefinedfalse

Makes text inherit its surrounding font styles. Colour always inherits unless color is set.

textAlign
"center" |⁠ "end" |⁠ "start" |⁠ undefined'start'

Sets text alignment.

textDecoration
"inherit" |⁠ "line-through" |⁠ "none" |⁠ "underline" |⁠ undefined'none'

Sets text decoration.

textTransform
"capitalize" |⁠ "default" |⁠ "inherit" |⁠ "lowercase" |⁠ "none" |⁠ "uppercase" |⁠ undefined'none'

Sets text transform.

textWrap
"balance" |⁠ "default" |⁠ "pretty" |⁠ undefined'default'

Sets text wrapping behavior.

typography
"body" |⁠ "caption" |⁠ "display" |⁠ "heading1" |⁠ "heading2" |⁠ "heading3" |⁠ "heading4" |⁠ "label" |⁠ "lead" |⁠ undefined'body'

Applies a complete typography style: family, size, weight, line height, letter spacing, and trim.