Text

Body text with variants, sizes, weights, and truncation.

import { Text } from "@ps1ui/core";

Variants

body — default foreground

muted — secondary information

subtle — tertiary information

primary — brand green

accent — warm highlight

danger — destructive or error

<Text variant="body">body — default foreground</Text>
<Text variant="muted">muted — secondary information</Text>
<Text variant="subtle">subtle — tertiary information</Text>
<Text variant="primary">primary — brand green</Text>
<Text variant="accent">accent — warm highlight</Text>
<Text variant="danger">danger — destructive or error</Text>

Sizes

size xl

size lg

size md

size sm

size xs

<Text size="xl">size xl</Text>
<Text size="lg">size lg</Text>
<Text size="md">size md</Text>
<Text size="sm">size sm</Text>
<Text size="xs">size xs</Text>

Truncate

A single line that is far too long for its box gets an ellipsis.

<div style={{ maxWidth: "16rem" }}>
  <Text truncate>
    A single line that is far too long for its box gets an ellipsis.
  </Text>
</div>

Leading / trailing slots

1,204

main

opens in a new tab

24%

<Text leading="">1,204</Text>
<Text variant="muted" leading="">main</Text>
<Text variant="primary" trailing="">opens in a new tab</Text>
<Text variant="accent" leading="" trailing="%">24</Text>

Leading / trailing slots (icon component)

Both slots accept any ReactNode, so an icon component drops in the same way — this docs page cannot render the JSX form directly (Astro cannot serialise React children passed as a prop), but the pattern above is how consumers use it in real .tsx code. Decorative icons should carry aria-hidden so the accessible name stays the label text alone.

import { IconStar } from "your-icon-library";

<Text leading={<IconStar aria-hidden />}>1,204</Text>

Adorned + truncate

a-very-long-file-name-that-will-not-fit.tsx

<div style={{ maxWidth: "14rem" }}>
  <Text truncate leading="">
    a-very-long-file-name-that-will-not-fit.tsx
  </Text>
</div>

Passing leading or trailing turns the Text into a flex row and wraps its children in a label box; without either prop nothing changes, so an ordinary paragraph keeps rendering exactly as before. The row is meant for a single line — pair it with truncate rather than letting a multi-line paragraph centre its icon against the whole block.

Props

PropTypeDefaultDescription
as"p" | "span" | "div" | "label" | "strong" | "em" | "small""p"

Element to render.

variant"body" | "muted" | "subtle" | "primary" | "accent" | "danger""body"

Color variant.

size"xs" | "sm" | "md" | "lg" | "xl""sm"

Font size on the type scale.

weight"regular" | "medium" | "semibold" | "bold"

Font weight.

truncatebooleanfalse

Truncate overflowing text with an ellipsis instead of wrapping.

leadingReactNode

Leading element (typically an icon) rendered before children with a shared inline gap.

trailingReactNode

Trailing element (typically an icon) rendered after children with a shared inline gap.

Also accepts the attributes of the element rendered via as (default: <p>).