---
title: "Heading Dropdown Menu"
description: "Integrate a dropdown menu from which you can select a heading. Add this UI component to your Editor."
canonical_url: "https://tiptap.dev/docs/ui-components/components/heading-dropdown-menu"
---

# Heading Dropdown Menu

Integrate a dropdown menu from which you can select a heading. Add this UI component to your Editor.

A fully accessible heading dropdown menu for Tiptap editors. Easily select and apply heading levels (H1-H6) with a clean dropdown interface and flexible customization options.

> **Interactive demo:** [heading dropdown menu](https://template.tiptap.dev/preview/tiptap-ui/heading-dropdown-menu)

## Installation

Add the component via the Tiptap CLI:

```bash
npx @tiptap/cli@latest add heading-dropdown-menu
```

## Components

### `<HeadingDropdownMenu />`

A prebuilt React component that provides a dropdown menu for selecting heading levels.

#### Usage

```tsx
export default function MyEditor() {
  return (
    <HeadingDropdownMenu
      editor={editor}
      levels={[1, 2, 3, 4, 5, 6]}
      hideWhenUnavailable={true}
      portal={false}
      onOpenChange={(isOpen) => console.log('Dropdown', isOpen ? 'opened' : 'closed')}
    />
  )
}
```

#### Props

| Name                  | Type                | Default         | Description                                        |
| --------------------- | ------------------- | --------------- | -------------------------------------------------- |
| `editor`              | `Editor \| null`    | `undefined`     | The Tiptap editor instance                         |
| `levels`              | `Level[]`           | `[1,2,3,4,5,6]` | Available heading levels to show in dropdown       |
| `hideWhenUnavailable` | `boolean`           | `false`         | Hides the dropdown when headings are not available |
| `portal`              | `boolean`           | `false`         | Whether to render the dropdown menu in a portal    |
| `onOpenChange`        | `(boolean) => void` | `undefined`     | Callback for when the dropdown opens or closes     |

## Hooks

### `useHeadingDropdownMenu()`

A custom hook to build your own heading dropdown menu with full control over rendering and behavior.

#### Usage

```tsx
function MyHeadingDropdown() {
  const { isVisible, activeLevel, isActive, canToggle, levels, label, Icon } =
    useHeadingDropdownMenu({
      editor: myEditor,
      levels: [1, 2, 3],
      hideWhenUnavailable: true,
    })

  if (!isVisible) return null

  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <button disabled={!canToggle} aria-label={label} aria-pressed={isActive}>
          <Icon />
          {label}
          <ChevronDownIcon />
        </button>
      </DropdownMenuTrigger>
      <DropdownMenuContent>
        {levels.map((level) => (
          <DropdownMenuItem key={level}>
            <HeadingButton editor={editor} level={level} text={`Heading ${level}`} />
          </DropdownMenuItem>
        ))}
      </DropdownMenuContent>
    </DropdownMenu>
  )
}
```

#### Props

| Name                  | Type             | Default         | Description                                      |
| --------------------- | ---------------- | --------------- | ------------------------------------------------ |
| `editor`              | `Editor \| null` | `undefined`     | The Tiptap editor instance                       |
| `levels`              | `Level[]`        | `[1,2,3,4,5,6]` | Available heading levels to show in dropdown     |
| `hideWhenUnavailable` | `boolean`        | `false`         | Hides the dropdown if headings cannot be applied |

#### Return Values

| Name          | Type                 | Description                                  |
| ------------- | -------------------- | -------------------------------------------- |
| `isVisible`   | `boolean`            | Whether the dropdown should be rendered      |
| `activeLevel` | `Level \| undefined` | Currently active heading level (1-6)         |
| `isActive`    | `boolean`            | If any heading is currently active           |
| `canToggle`   | `boolean`            | If heading formatting is currently allowed   |
| `levels`      | `Level[]`            | Array of available heading levels            |
| `label`       | `string`             | Accessible label text for the dropdown       |
| `Icon`        | `React.FC`           | Icon component for the current heading state |

## Utilities

### `getActiveHeadingLevel(editor, levels?)`

Gets the currently active heading level from the available levels.

```tsx
import { getActiveHeadingLevel } from '@/components/tiptap-ui/heading-dropdown-menu'

const activeLevel = getActiveHeadingLevel(editor, [1, 2, 3]) // Returns active level or undefined
```

### Individual Heading Functions

The heading dropdown menu leverages functions from the heading button component:

#### `isHeadingActive(editor, level?)`

Checks if a specific heading level is active, or if any heading is active.

```tsx
import { isHeadingActive } from '@/components/tiptap-ui/heading-button'

const isH1Active = isHeadingActive(editor, 1) // Check if H1 is active
const isAnyHeadingActive = isHeadingActive(editor) // Check if any heading is active
```

#### `canToggle(editor)`

Checks if heading formatting can be toggled in the current editor state.

```tsx
import { canToggle } from '@/components/tiptap-ui/heading-button'

const canApplyHeading = canToggle(editor)
```

## Keyboard Shortcuts

Individual heading levels support keyboard shortcuts when using `HeadingButton` components:

- **Cmd/Ctrl + Alt + 1**: Toggle H1
- **Cmd/Ctrl + Alt + 2**: Toggle H2
- **Cmd/Ctrl + Alt + 3**: Toggle H3
- **Cmd/Ctrl + Alt + 4**: Toggle H4
- **Cmd/Ctrl + Alt + 5**: Toggle H5
- **Cmd/Ctrl + Alt + 6**: Toggle H6

The dropdown itself doesn't register shortcuts but provides access to all heading options in one interface.

## Requirements

### Dependencies

- `@tiptap/react` - Core Tiptap React integration
- `@tiptap/starter-kit` - Basic Tiptap extensions including heading support

### Referenced Components

- `use-tiptap-editor` (hook)
- `use-heading-dropdown-menu` (hook)
- `heading-button` (component)
- `button` (primitive)
- `dropdown-menu` (primitive)
- `card` (primitive)
- `chevron-down-icon` (icon)
- `heading-icon` (icon)
- `heading-one-icon` (icon)
- `heading-two-icon` (icon)
- `heading-three-icon` (icon)
- `heading-four-icon` (icon)
- `heading-five-icon` (icon)
- `heading-six-icon` (icon)
