Text
Body-text primitive with token-driven sans family and a size/tone/weight scale; polymorphic via `as`. Install Text from the VLLNT UI registry with the shadcn CLI.
Body-text primitive with token-driven sans family and a size/tone/weight scale; polymorphic via as. Part of the core family in VLLNT UI, it ships as a
machine-readable registry entry — copy the source directly into your app with
the shadcn CLI and own it, no runtime dependency on a component library.
Preview
Switch between light and dark to inspect the embedded Storybook preview.
Installation
Add Text to your project with the shadcn CLI. The source lands in your codebase, ready to adapt:
pnpm dlx shadcn@latest add https://ui.vllnt.ai/r/text.jsonSource
import { createElement } from "react";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "../../lib/utils";
/**
* Body-text scale for the {@link Text} primitive. Exposed so consumers can
* compose the same token-driven styles onto bespoke elements.
*/
export const textVariants = cva(
"font-[family-name:var(--font-sans)] text-foreground",
{
defaultVariants: {
size: "base",
tone: "default",
weight: "normal",
},
variants: {
size: {
base: "text-[length:var(--font-size-body)] leading-[var(--line-height-body)]",
caption:
"text-[length:var(--font-size-caption)] leading-[var(--line-height-caption)]",
lead: "text-[length:var(--font-size-body-lg)] leading-[var(--line-height-body-lg)]",
small:
"text-[length:var(--font-size-body-sm)] leading-[var(--line-height-body-sm)]",
},
tone: {
default: "",
muted: "text-muted-foreground",
},
weight: {
medium: "font-medium",
normal: "font-normal",
semibold: "font-semibold",
},
},
},
);
/** HTML element the {@link Text} primitive renders as. */
export type TextElement = "div" | "label" | "p" | "span";
/** Props for {@link Text}. */
export type TextProps = React.HTMLAttributes<HTMLElement> &
VariantProps<typeof textVariants> & {
as?: TextElement;
ref?: React.Ref<HTMLElement>;
};
/**
* Body text whose family, scale, and weight come from theme-overridable tokens
* (`--font-sans`, `--font-size-body*`). Polymorphic via `as`. Forwards `ref` to
* the rendered element.
*
* Use `tone="muted"` on the default `background`; on `muted`/`card` surfaces the
* muted foreground can fall below WCAG AA contrast for body text.
*
* @example
* <Text size="lead" tone="muted">Intro copy</Text>
*/
const Text = ({
as = "p",
className,
ref,
size,
tone,
weight,
...props
}: TextProps) =>
createElement(as, {
className: cn(textVariants({ size, tone, weight }), className),
ref,
...props,
});
Text.displayName = "Text";
export { Text };
Stories
Explore every variant and state in the interactive Storybook:
Preview
Switch between light and dark to inspect the embedded Storybook preview.