Mark Button
A fully accessible mark button for Tiptap editors. Easily toggle text formatting marks like bold, italic, strikethrough, and more with keyboard shortcut support and flexible customization options.
Installation
Add the component via the Tiptap CLI:
npx @tiptap/cli@latest add mark-buttonComponents
<MarkButton />
A prebuilt React component that toggles mark formatting for a specific mark type.
Usage
import { useEditor, EditorContent, EditorContext } from '@tiptap/react'
import { StarterKit } from '@tiptap/starter-kit'
import { Underline } from '@tiptap/extension-underline'
import { Superscript } from '@tiptap/extension-superscript'
import { Subscript } from '@tiptap/extension-subscript'
import { MarkButton } from '@/components/tiptap-ui/mark-button'
import '@/components/tiptap-node/code-block-node/code-block-node.scss'
import '@/components/tiptap-node/paragraph-node/paragraph-node.scss'
export default function MyEditor() {
const editor = useEditor({
immediatelyRender: false,
extensions: [StarterKit, Underline, Superscript, Subscript],
content: `
<p>
<strong>Bold</strong> for emphasis with <code>**</code> or <code>⌘+B</code> or the <code>B</code> button.
</p>
<p>
<em>Italic</em> for subtle nuances with <code>*</code> or <code>⌘+I</code> or the <code>I</code> button.
</p>
<p>
<s>Strikethrough</s> to show revisions with <code>~~</code> or the <code>~~S~~</code> button.
</p>
<p>
<code>Code</code> for code snippets with <code>:</code> or <code>⌘+⇧+C</code> or the <code>C</code> button.
</p>
<p>
<u>Underline</u> for emphasis with <code>⌘+U</code> or the <code>U</code> button.
</p>
<p>
<sup>Superscript</sup> for footnotes with <code>⌘+.</code> or the <code>.</code> button.
</p>
<p>
<sub>Subscript</sub> for chemical formulas with <code>⌘+,</code> or the <code>,</code> button.
</p>
`,
})
return (
<EditorContext.Provider value={{ editor }}>
<MarkButton
editor={editor}
type="bold"
text="Bold"
hideWhenUnavailable={true}
showShortcut={true}
onToggled={() => console.log('Mark toggled!')}
/>
<MarkButton type="italic" />
<MarkButton type="strike" />
<MarkButton type="code" />
<MarkButton type="underline" />
<MarkButton type="superscript" />
<MarkButton type="subscript" />
<EditorContent editor={editor} role="presentation" />
</EditorContext.Provider>
)
}Props
| Name | Type | Default | Description |
|---|---|---|---|
editor | Editor | null | undefined | The Tiptap editor instance |
type | Mark | required | The type of mark ("bold", "italic", "strike", etc.) |
text | string | undefined | Optional text label for the button |
hideWhenUnavailable | boolean | false | Hides the button when mark toggle is not available |
onToggled | () => void | undefined | Callback fired after a successful mark toggle |
showShortcut | boolean | false | Shows a keyboard shortcut badge (if available) |
Hooks
useMark()
A custom hook to build your own mark button with full control over rendering and behavior.
Usage
import { useMark } from '@/components/tiptap-ui/mark-button'
import { parseShortcutKeys } from '@/lib/tiptap-utils'
import { Badge } from '@/components/tiptap-ui-primitive/badge'
function MyMarkButton() {
const { isVisible, isActive, canToggle, handleMark, label, shortcutKeys, Icon } = useMark({
editor: myEditor,
type: 'bold',
hideWhenUnavailable: true,
onToggled: () => console.log('Mark toggled!'),
})
if (!isVisible) return null
return (
<button
onClick={handleMark}
disabled={!canToggle}
aria-label={label}
aria-pressed={isActive}
title={label}
>
<Icon />
{label}
{shortcutKeys && <Badge>{parseShortcutKeys({ shortcutKeys })}</Badge>}
</button>
)
}Props
| Name | Type | Default | Description |
|---|---|---|---|
editor | Editor | null | undefined | The Tiptap editor instance |
type | Mark | required | The type of mark to toggle |
hideWhenUnavailable | boolean | false | Hides the button if mark toggle is not available |
onToggled | () => void | undefined | Callback fired after a successful mark toggle |
Return Values
| Name | Type | Description |
|---|---|---|
isVisible | boolean | Whether the button should be rendered |
isActive | boolean | If the specific mark type is currently active |
canToggle | boolean | If the mark toggle is currently allowed |
handleMark | () => boolean | Function to toggle mark formatting, returns success |
label | string | Formatted display name (e.g., "Bold", "Italic") |
shortcutKeys | string | Keyboard shortcut for the specific mark type |
Icon | React.FC | Icon component for the mark button |
Utilities
canToggleMark(editor, type)
Checks if a specific mark type can be toggled in the current editor state.
Parameters:
editor:Editor | null- The Tiptap editor instancetype:Mark- The mark type to check
Returns: boolean - Whether the mark can be toggled
import { canToggleMark } from '@/components/tiptap-ui/mark-button'
const canToggle = canToggleMark(editor, 'bold') // Check if bold can be toggledtoggleMark(editor, type)
Programmatically toggles mark formatting for the specified type.
Parameters:
editor:Editor | null- The Tiptap editor instancetype:Mark- The mark type to toggle
Returns: boolean - Whether the toggle was successful
import { toggleMark } from '@/components/tiptap-ui/mark-button'
const success = toggleMark(editor, 'italic')
if (success) {
console.log('Italic mark toggled successfully!')
}isMarkActive(editor, type)
Checks if a specific mark type is currently active.
Parameters:
editor:Editor | null- The Tiptap editor instancetype:Mark- The mark type to check
Returns: boolean - Whether the mark is active
import { isMarkActive } from '@/components/tiptap-ui/mark-button'
const active = isMarkActive(editor, 'underline')getFormattedMarkName(type)
Gets the formatted display name for a mark type.
Parameters:
type:Mark- The mark type
Returns: string - The formatted name (e.g., "Bold", "Italic")
import { getFormattedMarkName } from '@/components/tiptap-ui/mark-button'
const name = getFormattedMarkName('bold') // Returns "Bold"
const name2 = getFormattedMarkName('superscript') // Returns "Superscript"shouldShowButton(props)
Determines if the mark button should be shown based on editor state and configuration.
Parameters:
props:objecteditor:Editor | null- The Tiptap editor instancetype:Mark- The mark typehideWhenUnavailable:boolean- Whether to hide when unavailable
Returns: boolean - Whether the button should be shown
import { shouldShowButton } from '@/components/tiptap-ui/mark-button'
const shouldShow = shouldShowButton({
editor,
type: 'bold',
hideWhenUnavailable: true,
})Keyboard Shortcuts
Each mark type has its own keyboard shortcut:
- Cmd/Ctrl + B: Toggle bold
- Cmd/Ctrl + I: Toggle italic
- Cmd/Ctrl + U: Toggle underline
- Cmd/Ctrl + Shift + S: Toggle strikethrough
- Cmd/Ctrl + E: Toggle code
- Cmd/Ctrl + .: Toggle superscript
- Cmd/Ctrl + ,: Toggle subscript
The shortcuts are automatically registered when using either the <MarkButton /> component or the useMark() hook.
Requirements
Dependencies
@tiptap/react- Core Tiptap React integration@tiptap/starter-kit- Basic Tiptap extensions including mark support@tiptap/extension-underline- Underline mark extension@tiptap/extension-superscript- Superscript mark extension@tiptap/extension-subscript- Subscript mark extensionreact-hotkeys-hook- Keyboard shortcut management
Referenced Components
use-tiptap-editor(hook)button(primitive)badge(primitive)tiptap-utils(lib)bold-icon(icon)italic-icon(icon)underline-icon(icon)strike-icon(icon)code-2-icon(icon)superscript-icon(icon)subscript-icon(icon)