# Text

A polymorphic body text component with size, weight, tone, and alignment controls.

## Installation

```bash
npx shadcn@latest add https://reactdocs.canceydejean.dev/r/text.json
```

[Registry JSON](https://reactdocs.canceydejean.dev/r/text.json)

## Preview

```tsx
import { Text } from "@/components/ui/text/text";
import { TEXT_SIZES } from "@/components/ui/text/text.variants";

export function Preview() {
  return (
    <div className="flex flex-col gap-4">
      {TEXT_SIZES.map((size) => (
        <Text key={size} size={size}>
          Size: {size} — The quick brown fox jumps over the lazy dog.
        </Text>
      ))}
    </div>
  );
}
```


## Source

### text.tsx

```tsx
import * as React from "react";

import { cn } from "cn";

import type { TextProps } from "./text.types";
import { textVariants } from "./text.variants";

export function Text<T extends React.ElementType = "p">({
  as,
  size,
  weight,
  tone,
  align,
  className,
  ...props
}: TextProps<T>) {
  const Component = (as || "p") as React.ComponentType<Record<string, unknown>>;

  return (
    <Component
      data-slot="text"
      className={cn(textVariants({ size, weight, tone, align }), className)}
      {...props}
    />
  );
}
```


### text.types.ts

```ts
import type { VariantProps } from "class-variance-authority";

import type { textCva } from "./text.variants";
export type TextVariantProps = VariantProps<typeof textCva>;

export type TextAlign = NonNullable<TextVariantProps["align"]>;
export type TextSize = NonNullable<TextVariantProps["size"]>;
export type TextWeight = NonNullable<TextVariantProps["weight"]>;
export type TextTone = NonNullable<TextVariantProps["tone"]>;

export type TextProps<T extends React.ElementType> = {
  as?: T;
  align?: TextAlign;
  size?: TextSize;
  weight?: TextWeight;
  tone?: TextTone;
} & Omit<React.ComponentPropsWithoutRef<T>, keyof TextVariantProps>;
```


### text.variants.ts

```ts
import { cva } from "class-variance-authority";

import { cn } from "cn"

const textBase = cn("tracking-tight");

const textConfig = {
  variants: {
    size: {
      xs: "[font-size:var(--text-12)] sm:[font-size:var(--text-14)]",
      sm: "[font-size:var(--text-14)] sm:[font-size:var(--text-16)]",
      md: "[font-size:var(--text-16)] sm:[font-size:var(--text-18)]",
      lg: "[font-size:var(--text-18)] sm:[font-size:var(--text-20)]",
    },
    weight: {
      light: "font-light",
      regular: "font-normal",
      medium: "font-medium",
      semibold: "font-semibold",
      bold: "font-bold",
    },
    tone: {
      default: "text-foreground",
      muted: "text-muted-foreground",
      danger: "text-destructive",
      success: "text-green-600",
      warning: "text-yellow-600",
    },
    align: {
      left: "",
      center: "text-center",
      right: "text-right",
    },
  },
  compoundVariants: [],

  defaultVariants: {
    size: "md",
    weight: "regular",
    tone: "default",
  },
} as const;

export const textCva = cva(textBase, {
  ...textConfig,
  compoundVariants: [...textConfig.compoundVariants],
});

// Export the level variants
export const TEXT_SIZES = Object.keys(
  textConfig.variants.size,
) as (keyof typeof textConfig.variants.size)[];

// Export the size variants
export const TEXT_ALIGNMENTS = Object.keys(
  textConfig.variants.align,
) as (keyof typeof textConfig.variants.align)[];

// Export the weight variants
export const TEXT_WEIGHTS = Object.keys(
  textConfig.variants.weight,
) as (keyof typeof textConfig.variants.weight)[];

// Export the tone variants
export const TEXT_TONES = Object.keys(
  textConfig.variants.tone,
) as (keyof typeof textConfig.variants.tone)[];

export const textVariants = textCva;
```



## Usage

Use Text for paragraphs, captions, and other body copy. Set `as` to change the rendered element
when you need a `span`, `label`, or other tag.

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

export function Example() {
  return (
    <Text size="md" weight="regular" tone="muted">
      Supporting copy for the section.
    </Text>
  );
}
```

