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-button
Components
<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 1
isHeadingActive(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 active
toggleHeading(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-icon
throughheading-six-icon
(icons)