---
title: Heading
description: A semantic heading component that renders h1-h6 elements with proper accessibility support and flexible rendering options
---

```tsx
'use client';

import { Heading } from '@/ui/heading/Heading';

export function HeadingDemo() {
  return (
    <Heading level={2} className="text-2xl font-bold">
      Welcome to Trident UI
    </Heading>
  );
}
```

## Installation

Using the CLI:

```bash
npx shadcn@latest add https://develop.trident-ui.pro.clubmed/r/heading.json
```

Or manually, copy the following code into `/ui/heading.tsx`:

```tsx
import type { ComponentPropsWithoutRef, FunctionComponent } from 'react';

export interface HeadingProps extends ComponentPropsWithoutRef<'h1'> {
  asDiv?: boolean;
  level?: 1 | 2 | 3 | 4 | 5 | 6;
}

const clampLevel = (level: number) => {
  return Math.min(Math.max(level, 1), 6);
};

export const Heading: FunctionComponent<HeadingProps> = ({
  asDiv = false,
  children,
  level = 2,
  ...attrs
}) => {
  const TagName = asDiv ? 'div' : `h${clampLevel(level)}`;

  const aria = asDiv ? { 'aria-level': level, role: 'heading' } : null;

  return (
    <TagName {...attrs} {...aria}>
      {children}
    </TagName>
  );
};
```

## Usage

```tsx showLineNumbers
import Heading from '@/docs/lib/ui/heading';

export function Component() {
  return (
    <div className="space-y-4">
      <Heading level={1} className="text-4xl font-bold">
        Main Title
      </Heading>
      <Heading level={2} className="text-2xl font-semibold">
        Section Heading
      </Heading>
      <Heading level={3} className="text-xl">
        Subsection
      </Heading>
    </div>
  );
}
```

## API Reference

### Heading

| Prop        | Type                         | Default | Description                                                                                                                                                                                                                                                                |
| ----------- | ---------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `level`     | `1 \| 2 \| 3 \| 4 \| 5 \| 6` | `2`     | The heading level to render (h1-h6). The level is automatically clamped between 1 and 6 if an invalid value is provided.                                                                                                                                                   |
| `asDiv`     | `boolean`                    | `false` | When true, renders a `<div>` element instead of a heading tag, but maintains semantic heading behavior with proper ARIA attributes (`role="heading"` and `aria-level`). Useful for styling flexibility when the semantic heading level doesn't match the visual hierarchy. |
| `children`  | `React.ReactNode`            | -       | The content to display inside the heading.                                                                                                                                                                                                                                 |
| `className` | `string`                     | -       | Additional CSS classes to apply to the heading element.                                                                                                                                                                                                                    |

The component also accepts all standard HTML attributes for h1-h6 elements (or div when `asDiv={true}`).

## Notes

- **Semantic HTML**: By default, the component renders the appropriate semantic heading element (h1-h6) based on the `level` prop, which is important for accessibility and SEO.
- **Level Clamping**: The `level` prop is automatically clamped between 1 and 6 to ensure valid HTML output.
- **Accessibility with asDiv**: When `asDiv={true}`, the component automatically adds `role="heading"` and `aria-level` attributes to maintain proper semantics for screen readers.
- **Styling Flexibility**: Use the `asDiv` prop when you need to style a heading differently from its semantic level. For example, you might need an h4 semantically but want it to look like an h2 visually.
- **No Default Styling**: The component provides no built-in styles, allowing complete control over the appearance through className or global styles.
