---
title: "Numbering Format Dropdown Menu"
description: "Add a picker for ordered-list numbering styles (decimal, alpha, roman, nested) to your Tiptap editor. More in the documentation!"
canonical_url: "https://tiptap.dev/docs/ui-components/components/numbering-format-dropdown-menu"
---

# Numbering Format Dropdown Menu

Add a picker for ordered-list numbering styles (decimal, alpha, roman, nested) to your Tiptap editor. More in the documentation!

A numbering-style picker for ordered lists. It renders a `ListButton` to toggle the ordered list alongside a dropdown of numbering styles — decimal, parenthesised, nested decimal, upper/lower alpha, upper/lower roman, and zero-padded — each shown as a small nested-list preview.

The active format is read from and applied through the **`orderedListNumbering` extension** (part of `@tiptap-pro/extension-convert-kit`), so the on-screen markers always match the format that was registered. All editor logic is exposed by the `useNumberingFormatDropdownMenu` hook, so you can build a fully custom UI on top of it.

> **Interactive demo:** [numbering format dropdown menu](https://template.tiptap.dev/preview/tiptap-ui/numbering-format-dropdown-menu)

> **Requires the orderedListNumbering extension:**
>
> This component reads and writes a `numberingFormat` id on the outermost ordered list. The matching
> level definitions (what each id renders as on screen and on export) are supplied by the extension
> config — see [Setup](#setup) below. Without it, selecting a format has no visible effect.

## Installation

Add the component via the Tiptap CLI:

```bash
npx @tiptap/cli@latest add numbering-format-dropdown-menu
```

## Setup

The component only stores a format **id** on the list; the extension owns the actual marker rendering. Configure `orderedListNumbering` (via ConvertKit) with one level definition per format id you want to offer, and the same definitions can be passed to `ExportDocx` for a faithful round-trip.

```tsx
import { ConvertKit } from '@tiptap-pro/extension-convert-kit'

const NUMBERING_FORMATS = [
  {
    id: 'decimal',
    levels: Array.from({ length: 9 }, (_v, depth) => ({
      baseStyle: ['decimal', 'lowerLetter', 'lowerRoman'][depth % 3],
      textTemplate: `%${depth + 1}.`,
    })),
  },
  // …one entry per id you offer (see NUMBERING_FORMAT_IDS)
]

const editor = useEditor({
  extensions: [
    ConvertKit.configure({
      orderedListNumbering: {
        formats: NUMBERING_FORMATS,
        defaultFormat: 'decimal',
      },
    }),
    // …
  ],
})
```

## Components

### `<NumberingFormatDropdownMenu />`

A prebuilt component that pairs an ordered-list toggle with the numbering-style dropdown.

#### Usage

```tsx
export default function MyEditor() {
  return (
    <NumberingFormatDropdownMenu
      editor={editor}
      hideWhenUnavailable={true}
      modal={false}
      onOpenChange={(isOpen) => console.log('Dropdown', isOpen ? 'opened' : 'closed')}
    />
  )
}
```

#### Props

The component also forwards any extra `Button` props (except `type`) to the dropdown trigger.

| Name                  | Type                | Default           | Description                                               |
| --------------------- | ------------------- | ----------------- | --------------------------------------------------------- |
| `editor`              | `Editor \| null`    | `undefined`       | The Tiptap editor instance.                               |
| `formats`             | `NumberingFormat[]` | `DEFAULT_FORMATS` | The numbering format ids to offer in the dropdown.        |
| `hideWhenUnavailable` | `boolean`           | `false`           | Hides the dropdown when an ordered list is not available. |
| `modal`               | `boolean`           | `true`            | Whether the dropdown traps focus as a modal.              |
| `onOpenChange`        | `(boolean) => void` | `undefined`       | Callback for when the dropdown opens or closes.           |

### `<NumberingFormatButton />`

A single format option, rendered as a small nested-list preview. Used to build the dropdown grid, or on its own.

#### Props

| Name                  | Type              | Default     | Description                                             |
| --------------------- | ----------------- | ----------- | ------------------------------------------------------- |
| `editor`              | `Editor \| null`  | `undefined` | The Tiptap editor instance.                             |
| `format`              | `NumberingFormat` | —           | The numbering format this button applies. **Required.** |
| `hideWhenUnavailable` | `boolean`         | `false`     | Hides the button when an ordered list is not available. |
| `onFormatSet`         | `() => void`      | `undefined` | Called after the format is successfully applied.        |

## Hooks

### `useNumberingFormatDropdownMenu()`

A headless hook with the full state and actions needed to build a custom numbering dropdown.

#### Usage

```tsx
function MyNumberingDropdown() {
  const {
    isVisible,
    currentFormat,
    canToggle,
    formats,
    setFormat,
    isFormatActive,
    getFormatLabel,
  } = useNumberingFormatDropdownMenu({ editor, hideWhenUnavailable: true })

  if (!isVisible) return null

  return (
    <DropdownMenu>
      <DropdownMenuTrigger disabled={!canToggle}>Numbering</DropdownMenuTrigger>
      <DropdownMenuContent>
        {formats.map((format) => (
          <DropdownMenuItem
            key={format}
            data-active-state={isFormatActive(format) ? 'on' : 'off'}
            onClick={() => setFormat(format)}
          >
            {getFormatLabel(format)}
          </DropdownMenuItem>
        ))}
      </DropdownMenuContent>
    </DropdownMenu>
  )
}
```

#### Props

| Name                  | Type                | Default           | Description                                             |
| --------------------- | ------------------- | ----------------- | ------------------------------------------------------- |
| `editor`              | `Editor \| null`    | `undefined`       | The Tiptap editor instance.                             |
| `formats`             | `NumberingFormat[]` | `DEFAULT_FORMATS` | The numbering format ids to offer.                      |
| `hideWhenUnavailable` | `boolean`           | `false`           | Hides the dropdown when an ordered list is unavailable. |

#### Return Values

| Name             | Type                                   | Description                                                      |
| ---------------- | -------------------------------------- | ---------------------------------------------------------------- |
| `isVisible`      | `boolean`                              | Whether the dropdown should be rendered.                         |
| `currentFormat`  | `string`                               | The currently applied format id (`"decimal"` when none is set).  |
| `isActive`       | `boolean`                              | Whether any of the offered formats is currently active.          |
| `canToggle`      | `boolean`                              | Whether a numbering format can be set in the current state.      |
| `formats`        | `NumberingFormat[]`                    | The offered format ids.                                          |
| `setFormat`      | `(format: NumberingFormat) => boolean` | Apply a format; returns `true` on success.                       |
| `isFormatActive` | `(format: NumberingFormat) => boolean` | Whether a given format is the active one (for an active marker). |
| `getFormatLabel` | `(format: NumberingFormat) => string`  | Human-readable preview label for a format, e.g. `"1. 2. 3."`.    |

### `useNumberingFormatButton()`

State and handlers for a single format option.

#### Props

| Name                  | Type              | Default     | Description                                   |
| --------------------- | ----------------- | ----------- | --------------------------------------------- |
| `editor`              | `Editor \| null`  | `undefined` | The Tiptap editor instance.                   |
| `format`              | `NumberingFormat` | —           | The format this button applies. **Required.** |
| `hideWhenUnavailable` | `boolean`         | `false`     | Hides the button when unavailable.            |
| `onFormatSet`         | `() => void`      | `undefined` | Called after the format is set.               |

#### Return Values

| Name              | Type            | Description                                          |
| ----------------- | --------------- | ---------------------------------------------------- |
| `isVisible`       | `boolean`       | Whether the button should be rendered.               |
| `isActive`        | `boolean`       | Whether this format is currently active.             |
| `handleSetFormat` | `() => boolean` | Applies the format; returns `true` on success.       |
| `canSet`          | `boolean`       | Whether the format can be set in the current state.  |
| `label`           | `string`        | The preview label for the format, e.g. `"1. 2. 3."`. |

## Utilities

### Format ids and labels

```tsx
import {
  NUMBERING_FORMAT_IDS,
  NUMBERING_FORMAT_LABELS,
  DEFAULT_FORMATS,
} from '@/components/tiptap-ui/numbering-format-dropdown-menu'
```

`NumberingFormat` is one of: `decimal`, `decimal-paren`, `decimal-nested`, `upper-alpha`, `lower-alpha`, `upper-roman`, `lower-roman`, `decimal-zero`. `NUMBERING_FORMAT_IDS` lists them in dropdown order; `DEFAULT_FORMATS` is the default offered set; `NUMBERING_FORMAT_LABELS` maps each id to its preview string (e.g. `"A. B. C."`).

### Editor helpers

```tsx
import {
  setNumberingFormat,
  isNumberingFormatActive,
  getCurrentNumberingFormat,
  canSetNumberingFormat,
  getFormatLabel,
} from '@/components/tiptap-ui/numbering-format-dropdown-menu'

setNumberingFormat(editor, 'upper-roman') // applies the format, returns boolean
getCurrentNumberingFormat(editor) // active format id, or null when not in a list
isNumberingFormatActive(editor, 'decimal') // boolean
canSetNumberingFormat(editor) // boolean
getFormatLabel('lower-alpha') // "a. b. c."
```

## Requirements

### Dependencies

- `@tiptap/react` — Core Tiptap React integration
- `@tiptap-pro/extension-convert-kit` — Provides the `orderedListNumbering` extension that stores and renders the format

### Referenced Components

- `use-tiptap-editor` (hook)
- `list-button` (component)
- `button` (primitive)
- `button-group` (primitive)
- `dropdown-menu` (primitive)
- `tiptap-utils` (lib)
- `chevron-down-icon` (icon)
