---
title: "Mark Button"
description: "Integrate a button that toggles through text marks like bold, italics and underline. More in the docs!"
canonical_url: "https://tiptap.dev/docs/ui-components/components/mark-button"
---

# Mark Button

Integrate a button that toggles through text marks like bold, italics and underline. More in the docs!

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.

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

## Installation

Add the component via the Tiptap CLI:

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

## Components

### `<MarkButton />`

A prebuilt React component that toggles mark formatting for a specific mark type.

#### Usage

```tsx
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

```tsx
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 instance
- `type`: `Mark` - The mark type to check

**Returns:** `boolean` - Whether the mark can be toggled

```tsx
import { canToggleMark } from '@/components/tiptap-ui/mark-button'

const canToggle = canToggleMark(editor, 'bold') // Check if bold can be toggled
```

### `toggleMark(editor, type)`

Programmatically toggles mark formatting for the specified type.

**Parameters:**

- `editor`: `Editor | null` - The Tiptap editor instance
- `type`: `Mark` - The mark type to toggle

**Returns:** `boolean` - Whether the toggle was successful

```tsx
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 instance
- `type`: `Mark` - The mark type to check

**Returns:** `boolean` - Whether the mark is active

```tsx
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")

```tsx
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`: `object`
  - `editor`: `Editor | null` - The Tiptap editor instance
  - `type`: `Mark` - The mark type
  - `hideWhenUnavailable`: `boolean` - Whether to hide when unavailable

**Returns:** `boolean` - Whether the button should be shown

```tsx
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 extension
- `react-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)
