---
title: "Heading Button"
description: "Add a button that toggles through different heading levels in your Tiptap editor. More in the docs!"
canonical_url: "https://tiptap.dev/docs/ui-components/components/heading-button"
---

# Heading Button

Add a button that toggles through different heading levels in your Tiptap editor. More in the docs!

A fully accessible heading button for Tiptap editors. Toggle between different heading levels and paragraph text with keyboard shortcut support, level-specific icons, and tooltip integration.

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

## Installation

Add the component via the Tiptap CLI:

```bash
npx @tiptap/cli@latest add heading-button
```

## Components

### `<HeadingButton />`

A prebuilt React component that toggles heading levels in the editor with full accessibility support.

#### Usage

```tsx
import { HeadingButton } from '@/components/tiptap-ui/heading-button'
import { EditorContent, EditorContext, useEditor } from '@tiptap/react'
import { StarterKit } from '@tiptap/starter-kit'

import '@/components/tiptap-node/paragraph-node/paragraph-node.scss'

export default function MyEditor() {
  const editor = useEditor({
    immediatelyRender: false,
    extensions: [StarterKit],
    content: `
          <h1>Heading 1</h1>
          <h2>Heading 2</h2>
        `,
  })

  return (
    <EditorContext.Provider value={{ editor }}>
      <HeadingButton
        editor={editor}
        level={1}
        text="Heading 1"
        hideWhenUnavailable={true}
        showShortcut={true}
        onToggled={() => console.log(`Heading ${level} toggled!`)}
      />
      <HeadingButton
        editor={editor}
        level={2}
        text="Heading 2"
        hideWhenUnavailable={true}
        showShortcut={true}
        onToggled={() => console.log(`Heading ${level} toggled!`)}
      />

      <EditorContent editor={editor} role="presentation" />
    </EditorContext.Provider>
  )
}
```

#### Props

| Name                  | Type             | Default     | Description                                      |
| --------------------- | ---------------- | ----------- | ------------------------------------------------ |
| `editor`              | `Editor \| null` | `undefined` | The Tiptap editor instance                       |
| `level`               | `Level` (1-6)    | `required`  | The heading level (1, 2, 3, 4, 5, or 6)          |
| `text`                | `string`         | `undefined` | Optional text label for the button               |
| `hideWhenUnavailable` | `boolean`        | `false`     | Hides the button when heading is not applicable  |
| `onToggled`           | `() => void`     | `undefined` | Callback fired after a successful heading toggle |
| `showShortcut`        | `boolean`        | `false`     | Shows a keyboard shortcut badge                  |

## Hooks

### `useHeading()`

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

#### Usage

```tsx
function MyHeadingButton() {
  const { isVisible, isActive, canToggle, handleToggle, label, shortcutKeys, Icon } = useHeading({
    editor: myEditor,
    level: 3,
    hideWhenUnavailable: true,
    onToggled: () => console.log('Heading 3 toggled!'),
  })

  if (!isVisible) return null

  return (
    <button onClick={handleToggle} disabled={!canToggle} aria-label={label} aria-pressed={isActive}>
      <Icon />
      {label}
      {shortcutKeys && <HeadingShortcutBadge level={3} shortcutKeys={shortcutKeys} />}
    </button>
  )
}
```

#### Props

| Name                  | Type             | Default     | Description                                   |
| --------------------- | ---------------- | ----------- | --------------------------------------------- |
| `editor`              | `Editor \| null` | `undefined` | The Tiptap editor instance                    |
| `level`               | `Level` (1-6)    | `required`  | The heading level                             |
| `hideWhenUnavailable` | `boolean`        | `false`     | Hides the button if heading cannot be applied |
| `onToggled`           | `() => void`     | `undefined` | Callback fired after toggling heading         |

#### Return Values

| Name           | Type            | Description                              |
| -------------- | --------------- | ---------------------------------------- |
| `isVisible`    | `boolean`       | Whether the button should be rendered    |
| `isActive`     | `boolean`       | If the heading level is currently active |
| `canToggle`    | `boolean`       | If the heading can be toggled            |
| `handleToggle` | `() => boolean` | Function to toggle heading formatting    |
| `label`        | `string`        | Accessible label text for the button     |
| `shortcutKeys` | `string`        | Keyboard shortcut for the specific level |
| `Icon`         | `React.FC`      | Icon component for the heading level     |

## Utilities

### `canToggle(editor, level?, turnInto?)`

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

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

const canToggleH2 = canToggle(editor, 2) // Check if can toggle to Heading 2
const canTurnInto = canToggle(editor, 1, true) // Check if can turn into Heading 1
```

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

Checks if a heading level is currently active.

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

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

### `toggleHeading(editor, level)`

Programmatically toggles heading formatting for the current selection.

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

const success = toggleHeading(editor, 3) // Toggle Heading 3
if (success) {
  console.log('Heading toggled successfully!')
}
```

## Keyboard Shortcuts

The heading button supports level-specific keyboard shortcuts that are automatically registered:

- **Ctrl + Alt + 1**: Toggle Heading 1
- **Ctrl + Alt + 2**: Toggle Heading 2
- **Ctrl + Alt + 3**: Toggle Heading 3
- **Ctrl + Alt + 4**: Toggle Heading 4
- **Ctrl + Alt + 5**: Toggle Heading 5
- **Ctrl + Alt + 6**: Toggle Heading 6

The shortcuts are automatically registered when using either the `<HeadingButton />` component or the `useHeading()` hook. Each heading level has its own unique shortcut.

## Requirements

### Dependencies

- `@tiptap/react` - Core Tiptap React integration
- `@tiptap/starter-kit` - Basic Tiptap extensions including heading support
- `react-hotkeys-hook` - Keyboard shortcut management

### Referenced Components

- `use-tiptap-editor` (hook)
- `button` (primitive)
- `badge` (primitive)
- `tiptap-utils` (lib)
- `heading-one-icon` through `heading-six-icon` (icons)
