Heading

Semantic heading and subheading typography components with level-based sizing, tracking-tight styling, and dark mode support.

Preview

All heading levels

import { Heading } from '@/registry/ui-kit/tailwind-heading/react'

function Example() {
  return (
    <div className="space-y-4">
      <Heading level={1}>Heading level 1</Heading>
      <Heading level={2}>Heading level 2</Heading>
      <Heading level={3}>Heading level 3</Heading>
      <Heading level={4}>Heading level 4</Heading>
      <Heading level={5}>Heading level 5</Heading>
      <Heading level={6}>Heading level 6</Heading>
    </div>
  )
}

Subheading

import { Heading, Subheading } from '@/registry/ui-kit/tailwind-heading/react'

function Example() {
  return (
    <div className="space-y-1">
      <Heading level={2}>Account settings</Heading>
      <Subheading level={2}>Manage your account preferences and personal information.</Subheading>
    </div>
  )
}

Component API

PropDefaultDescription
level1Heading level — renders the corresponding h1–h6 element and applies the matching font size.
className""Additional CSS classes.
SubheadingMuted subheading component. Accepts the same level prop (font size is one step smaller) and renders as a p element.

Source Code

"use client";

import { forwardRef } from "react";

/* ── Size mapping ── */

const headingSizes: Record<number, string> = {
  1: "text-2xl",
  2: "text-xl",
  3: "text-lg",
  4: "text-base",
  5: "text-sm",
  6: "text-xs",
};

/* one step smaller for subheadings */
const subheadingSizes: Record<number, string> = {
  1: "text-xl",
  2: "text-lg",
  3: "text-base",
  4: "text-sm",
  5: "text-xs",
  6: "text-xs",
};

/* ── Heading ── */

interface HeadingProps extends React.HTMLAttributes<HTMLHeadingElement> {
  level?: 1 | 2 | 3 | 4 | 5 | 6;
  className?: string;
  children: React.ReactNode;
}

const Heading = forwardRef<HTMLHeadingElement, HeadingProps>(
  ({ level = 1, className = "", children, ...props }, ref) => {
    const Tag = `h${level}` as const;
    const sizeClass = headingSizes[level];

    return (
      <Tag
        ref={ref}
        className={`font-semibold tracking-tight text-zinc-900 dark:text-zinc-100 ${sizeClass} ${className}`}
        {...props}
      >
        {children}
      </Tag>
    );
  }
);
Heading.displayName = "Heading";

/* ── Subheading ── */

interface SubheadingProps extends React.HTMLAttributes<HTMLParagraphElement> {
  level?: 1 | 2 | 3 | 4 | 5 | 6;
  className?: string;
  children: React.ReactNode;
}

const Subheading = forwardRef<HTMLParagraphElement, SubheadingProps>(
  ({ level = 2, className = "", children, ...props }, ref) => {
    const sizeClass = subheadingSizes[level];

    return (
      <p
        ref={ref}
        className={`font-medium text-zinc-500 dark:text-zinc-400 ${sizeClass} ${className}`}
        {...props}
      >
        {children}
      </p>
    );
  }
);
Subheading.displayName = "Subheading";

export { Heading, Subheading };
export default Heading;