Heading Button
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.
Installation
Add the component via the Tiptap CLI:
npx @tiptap/cli@latest add heading-buttonComponents
<HeadingButton />
A prebuilt React component that toggles heading levels in the editor with full accessibility support.
Usage
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
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.
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 1isHeadingActive(editor, level?)
Checks if a heading level is currently active.
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 activetoggleHeading(editor, level)
Programmatically toggles heading formatting for the current selection.
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 supportreact-hotkeys-hook- Keyboard shortcut management
Referenced Components
use-tiptap-editor(hook)button(primitive)badge(primitive)tiptap-utils(lib)heading-one-iconthroughheading-six-icon(icons)