Bloom Logo

Typography

Standardized typographic text hierarchy styles including headings, body paragraphs, colors, and inline code elements.

importimport { Typography } from "@/components/ui/typography/typography";
$npx @bloomui-react/cli add typography
typography.tsx
"use client";

import * as React from "react";
import { cn } from "@/lib/utils";

type TypographyVariant =
  | "h1"
  | "h2"
  | "h3"
  | "h4"
  | "h5"
  | "h6"
  | "p"
  | "large"
  | "small"
  | "muted"
  | "code";

type TypographyColor =
  | "default"
  | "muted"
  | "primary"
  | "secondary"
  | "accent"
  | "success"
  | "warning"
  | "danger";

export interface TypographyProps extends React.HTMLAttributes<HTMLElement> {
  variant?: TypographyVariant;
  color?: TypographyColor;
  clampLines?: number;
  showExpandToggle?: boolean;
  as?: React.ElementType;
  children?: React.ReactNode;
}

const variantStyles: Record<TypographyVariant, string> = {
  h1: "scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl text-zinc-900 dark:text-zinc-100",
  h2: "scroll-m-20 text-3xl font-bold tracking-tight text-zinc-900 dark:text-zinc-100",
  h3: "scroll-m-20 text-2xl font-bold tracking-tight text-zinc-900 dark:text-zinc-100",
  h4: "scroll-m-20 text-xl font-bold tracking-tight text-zinc-900 dark:text-zinc-100",
  h5: "scroll-m-20 text-lg font-bold tracking-tight text-zinc-900 dark:text-zinc-100",
  h6: "scroll-m-20 text-base font-bold tracking-tight text-zinc-900 dark:text-zinc-100",
  p: "leading-7 text-zinc-700 dark:text-zinc-300 font-normal",
  large: "text-lg font-bold text-zinc-900 dark:text-zinc-100",
  small: "text-xs font-semibold leading-none text-zinc-500 dark:text-zinc-400",
  muted: "text-xs text-zinc-500 dark:text-zinc-400 leading-normal",
  code: "relative rounded-lg bg-zinc-100 dark:bg-zinc-800 px-2 py-1 font-mono text-xs font-semibold text-zinc-900 dark:text-zinc-100 border border-zinc-200 dark:border-zinc-700",
};

const defaultElementMap: Record<TypographyVariant, React.ElementType> = {
  h1: "h1",
  h2: "h2",
  h3: "h3",
  h4: "h4",
  h5: "h5",
  h6: "h6",
  p: "p",
  large: "div",
  small: "small",
  muted: "p",
  code: "code",
};

const colorStyles: Record<TypographyColor, string> = {
  default: "text-zinc-900 dark:text-zinc-100",
  muted: "text-zinc-500 dark:text-zinc-400",
  primary: "text-sky-500",
  secondary: "text-purple-500",
  accent: "text-pink-500",
  success: "text-emerald-500",
  warning: "text-amber-500",
  danger: "text-rose-500",
};

const Typography = React.forwardRef<HTMLElement, TypographyProps>(
  (
    {
      variant = "p",
      color = "default",
      clampLines,
      showExpandToggle = false,
      as,
      className,
      children,
      ...props
    },
    ref,
  ) => {
    const Component = as || defaultElementMap[variant] || "p";
    const [isExpanded, setIsExpanded] = React.useState(false);

    const shouldClamp = clampLines && !isExpanded;

    return (
      <div className="inline-block w-full">
        <Component
          ref={ref as any}
          className={cn(
            variantStyles[variant],
            color !== "default" && colorStyles[color],
            shouldClamp && "line-clamp-none",
            className,
          )}
          style={
            shouldClamp
              ? {
                  display: "-webkit-box",
                  WebkitLineClamp: clampLines,
                  WebkitBoxOrient: "vertical",
                  overflow: "hidden",
                }
              : undefined
          }
          {...props}
        >
          {children}
        </Component>

        {clampLines && showExpandToggle && (
          <button
            type="button"
            onClick={() => setIsExpanded(!isExpanded)}
            className="mt-2 text-xs font-bold text-sky-500 hover:text-sky-600 dark:hover:text-sky-400 transition-colors cursor-pointer"
          >
            {isExpanded ? "Show Less" : "Read More"}
          </button>
        )}
      </div>
    );
  },
);

Typography.displayName = "Typography";

export type { TypographyColor, TypographyVariant };
export { Typography };

Default

Standard paragraph text typography element.

Bloom UI is an accessible, customizable, and high-performance React component library designed with modern aesthetic tokens.

Headings Scale

Typographic hierarchy sizes ranging from H1 to H6 headings.

variant: h1 | h2 | h3 | h4 | h5 | h6

Heading 1 — Display

Heading 2 — Section Title

Heading 3 — Subsection Title

Heading 4 — Card Header

Heading 5 — Subheading
Heading 6 — Small Label

Colors

Apply theme colors to match the design system color scheme.

color: default | muted | primary | secondary | accent | success | warning | danger

Default text color

Muted text color

Primary text color

Secondary text color

Accent text color

Success text color

Warning text color

Danger text color

Line Clamping

Clamp long paragraphs to a max line count.

clampLines: numbershowExpandToggle: boolean

Bloom provides a rich collection of modular, accessible components designed for modern web applications. Every component adheres strictly to dark/light neutral design tokens and provides smooth micro-animations, customizable variants, and comprehensive API documentation.

API Reference
PropTypeDefaultDescription
variant'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'large' | 'small' | 'muted' | 'code''p'Typographic size and HTML tag mapping.
color'default' | 'muted' | 'primary' | 'secondary' | 'accent' | 'success' | 'warning' | 'danger''default'Theme color palette of typography text.
clampLinesnumberLimits text to specified number of lines.
showExpandTogglebooleanfalseShows a read-more/show-less button.