---
title: List
docs:
  - route: /docs/components/list-element
    title: List Element
  - route: /docs/components/list-toolbar-button
    title: List Toolbar Button
  - route: /docs/components/todo-list-element
    title: Todo List Element
---

<ComponentPreview name="list-demo" />

<Callout>

Plate offers two approaches for implementing lists:

1. **This List plugin** - Traditional HTML-spec lists with strict nesting rules:
   - Follows standard HTML list structure (`ul`/`ol` > `li`)
   - Maintains consistent list hierarchy
   - Best for content that may be exported to HTML/markdown
   - Highest complexity

2. The [**Indent List plugin**](/docs/indent-list) - Flexible indentation-based lists:
   - More like Word/Google Docs behavior
   - Any block can be indented to create list-like structures
   - Used in the [AI editor](/editors#editor-ai)
   - Better for free-form content organization

Choose based on your needs:
- Use the **List plugin** when you need standard HTML list compatibility
- Use the **Indent List plugin** when you want more flexible indentation behavior


</Callout>

<PackageInfo>


## Features

- **HTML-compliant lists**:
  - Standard `ul`/`ol` > `li` structure
  - Proper nesting and hierarchy
  - SEO-friendly markup
  - Clean HTML/markdown export

- **List types**:
  - Unordered (bulleted) lists
  - Ordered (numbered) lists
  - Todo lists with checkboxes
  - Nested sublists

- **Drag & drop**:
  - Currently supports root-level list items only
  - Sibling and nested items drag & drop not yet supported

- **Shortcuts**:
  - Combined with the autoformat plugin, use markdown shortcuts (**`-`**, **`*`**, **`1.`**) to create lists
  - Tab/Shift+Tab for indentation control

- **Limitations (use [Indent List](/docs/indent-list) for these features)**:
  - Drag & drop only supports root-level lists
  - List items cannot be aligned

For a more flexible, Word-like approach, see the [Indent List plugin](/docs/indent-list).

</PackageInfo>

## Installation

```bash
npm install @udecode/plate-list
```

## Usage

```tsx
import { ListPlugin } from '@udecode/plate-list/react';

const plugins = [
  // ...otherPlugins,
  ListPlugin,
];
```

## Keyboard Shortcuts

<KeyTable>
  <KeyTableItem hotkey="Cmd + Opt + 4">Insert a numbered list.</KeyTableItem>
  <KeyTableItem hotkey="Cmd + Shift + 4">Insert a numbered list.</KeyTableItem>
</KeyTable>

## Plugins

### ListPlugin

- `key: 'list'`
- Contains the following element plugins:
  - `BulletedListPlugin`
  - `NumberedListPlugin`
  - `ListItemPlugin`
  - `ListItemContentPlugin`

<APIOptions>
  <APIItem name="validLiChildrenTypes" type="string[]" optional>
    Specifies valid child node types for list items, in addition to `p` and `ul`
    types.
  </APIItem>
  <APIItem name="enableResetOnShiftTab" type="boolean" optional>
    Determines whether pressing Shift+Tab should reset the list indent level.
  </APIItem>
</APIOptions>

### BulletedListPlugin

Plugin for unordered (bulleted) lists.

### NumberedListPlugin

Plugin for ordered (numbered) lists.

### ListItemPlugin

Plugin for list items.

### ListItemContentPlugin

Plugin for list item content.

## API

### editor.tf.toggle.list

Toggles a list in the editor.

<APIParameters>
<APIItem name="options" type="object">
<APISubList>
<APISubListItem parent="options" name="type" type="string">
The type of the list to toggle.
</APISubListItem>
</APISubList>

</APIItem>
</APIParameters>

### getHighestEmptyList

Finds the highest end list that can be deleted. The path of the list should be different from `diffListPath`. If the highest end list has 2 or more items, returns `liPath`. It traverses up the parent lists until:

- The list has less than 2 items.
- Its path is not equal to `diffListPath`.

<APIParameters>
  <APIItem name="editor" type="PlateEditor">
    The editor instance.
  </APIItem>
  <APIItem name="options" type="object" optional>
    <APISubList>
      <APISubListItem parent="options" name="liPath" type="Path">
        The path of the list item.
      </APISubListItem>
      <APISubListItem parent="options" name="diffListPath" type="Path" optional>
        The path of a different list.
      </APISubListItem>
    </APISubList>
  </APIItem>
</APIParameters>

<APIReturns>
  <APIItem type="Path | undefined">
    The path of the highest end list that can be deleted.
  </APIItem>
</APIReturns>

### getListItemEntry

Returns the nearest `li` and `ul`/`ol` wrapping node entries for a given path (`default = selection`).

<APIParameters>
<APIItem name="editor" type="PlateEditor">
The editor instance.
</APIItem>
<APIItem name="options" type="object">
<APISubList>
<APISubListItem
  parent="options"
  name="at"
  type="Location | null"
  optional
>
The location to retrieve the nearest entries from. If not provided, uses
the current selection.

- **Default:** `editor.selection`

</APISubListItem>
</APISubList>

</APIItem>
</APIParameters>

<APIReturns>
  <APIItem type="TElementEntry | undefined">
    The nearest `li` and `ul`/`ol` wrapping node entries.
  </APIItem>
</APIReturns>

### getListRoot

Searches upward for the root list element.

<APIParameters>
  <APIItem name="editor" type="PlateEditor">
    The editor instance.
  </APIItem>
  <APIItem name="at" type="Path | Range | Point | null" optional>
    The location to start the search from. If not provided, uses the current
    selection.

    - **Default:** `editor.selection`

  </APIItem>
</APIParameters>

<APIReturns>
  <APIItem type="TElementEntry | undefined">
    The root list element entry.
  </APIItem>
</APIReturns>

### getListTypes

Returns an array of list types supported by the editor.

<APIParameters>
  <APIItem name="editor" type="PlateEditor">
    The editor instance.
  </APIItem>
</APIParameters>

<APIReturns>
  <APIItem type="[string, string]">The list types.</APIItem>
</APIReturns>

### hasListChild

Checks if a node has a list child.

<APIParameters>
  <APIItem name="editor" type="PlateEditor">
    The editor instance.
  </APIItem>
  <APIItem name="node" type="TAncestor">
    The node to check.
  </APIItem>
</APIParameters>

<APIReturns>
<APIItem type="boolean">

`true` if the node has a list child, `false` otherwise.

</APIItem>
</APIReturns>

### indentListItems

Indents the list items in the editor.

<APIParameters>
  <APIItem name="editor" type="PlateEditor">
    The editor instance.
  </APIItem>
</APIParameters>

### insertListItem

Inserts a list item if the selection is in an li>p element.

<APIParameters>
  <APIItem name="editor" type="PlateEditor">
    The editor instance.
  </APIItem>
</APIParameters>

<APIReturns>
  <APIItem type="boolean">
    `true` if the list items were indented, `false` otherwise.
  </APIItem>
</APIReturns>

### insertTodoListItem

Inserts a todo list item if the selection is in an li>p element.

<APIParameters>
<APIItem name="editor" type="PlateEditor">
The editor instance.
</APIItem>
<APIItem name="options" type="TodoListPlugin">
<APISubList>
<APISubListItem
  parent="options"
  name="inheritCheckStateOnLineStartBreak"
  type="boolean"
  optional
>
Whether to inherit the check state of the previous line when inserting a
new todo item at the start of a line.

- **Default:** `false`

</APISubListItem>
<APISubListItem
  parent="options"
  name="inheritCheckStateOnLineEndBreak"
  type="boolean"
  optional
>
Whether to inherit the check state of the previous line when inserting a
new todo item at the end of a line.

- **Default:** `false`

</APISubListItem>
</APISubList>

</APIItem>
</APIParameters>

<APIReturns>
  <APIItem type="boolean">
    `true` if the list items were indented, `false` otherwise.
  </APIItem>
</APIReturns>

### isAcrossListItems

Checks if the selection is across blocks with list items.

<APIParameters>
  <APIItem name="editor" type="PlateEditor">
    The editor instance.
  </APIItem>
</APIParameters>

<APIReturns>
  <APIItem type="boolean">
    `true` if the selection is across blocks with list items, `false` otherwise.
  </APIItem>
</APIReturns>

### isListNested

Checks if the list is nested, i.e., its parent is a list item.

<APIParameters>
  <APIItem name="editor" type="PlateEditor">
    The editor instance.
  </APIItem>
  <APIItem name="listPath" type="Path">
    The path of the list.
  </APIItem>
</APIParameters>

<APIReturns>
  <APIItem type="boolean">
    `true` if the list is nested, `false` otherwise.
  </APIItem>
</APIReturns>

### isListRoot

Checks if a node is the root of a list.

<APIParameters>
  <APIItem name="editor" type="PlateEditor">
    The editor instance.
  </APIItem>
  <APIItem name="node" type="TElement | TText">
    The node to check.
  </APIItem>
</APIParameters>

<APIReturns>
  <APIItem type="boolean">
    `true` if the node is the root of a list, `false` otherwise.
  </APIItem>
</APIReturns>

### moveListItemDown

Moves a list item down to the next list item.

<APIParameters>
  <APIItem name="editor" type="PlateEditor">
    The editor instance.
  </APIItem>
  <APIItem name="options" type="MoveListItemDownOptions" optional>
    <APISubList>
      <APISubListItem parent="options" name="list" type="TElementEntry">
        The entry of the list node.
      </APISubListItem>
      <APISubListItem parent="options" name="listItem" type="TElementEntry">
        The entry of the list item node to move.
      </APISubListItem>
    </APISubList>
  </APIItem>
</APIParameters>

<APIReturns>
  <APIItem type="boolean">
    `true` if the list item was moved, `false` otherwise.
  </APIItem>
</APIReturns>

### moveListItemSublistItemsToListItemSublist

Moves sublist items from one list item to another list item's sublist.

<APIParameters>
<APIItem name="editor" type="PlateEditor">
The editor instance.
</APIItem>
<APIItem
  name="options"
  type="MoveListItemSublistItemsToListItemSublistOptions"
  optional
>
<APISubList>
<APISubListItem parent="options" name="fromListItem" type="TElementEntry">
The entry of the list item containing the sublist items to move.
</APISubListItem>
<APISubListItem parent="options" name="toListItem" type="TElementEntry">
The entry of the list item where the sublist items will be moved.
</APISubListItem>
<APISubListItem parent="options" name="start" type="boolean" optional>
Move the sublist items to the start of the sublist instead of the end.

- **Default:** `false`

</APISubListItem>
</APISubList>

</APIItem>
</APIParameters>

<APIReturns>
  <APIItem type="number">The number of sublist items moved.</APIItem>
</APIReturns>

### moveListItemUp

Moves a list item up.

<APIParameters>
  <APIItem name="editor" type="PlateEditor">
    The editor instance.
  </APIItem>
  <APIItem name="options" type="MoveListItemUpOptions" optional>
    <APISubList>
      <APISubListItem parent="options" name="list" type="TElementEntry">
        The entry of the list containing the list item to move.
      </APISubListItem>
      <APISubListItem parent="options" name="listItem" type="TElementEntry">
        The entry of the list item to move.
      </APISubListItem>
    </APISubList>
  </APIItem>
</APIParameters>

<APIReturns>
  <APIItem type="boolean">
    `true` if the list item was moved, `false` otherwise.
  </APIItem>
</APIReturns>

### moveListItems

Moves the selected list items up or down within their respective lists or increases/decreases their indentation level.

<APIParameters>
<APIItem name="editor" type="PlateEditor">
The editor instance.
</APIItem>
<APIItem name="options" type="MoveListItemsOptions" optional>
<APISubList>
<APISubListItem parent="options" name="increase" type="boolean" optional>
Determines whether to increase the indentation level

- **Default:** true.

</APISubListItem>
<APISubListItem
  parent="options"
  name="at"
  type="Location | Span | Undefined"
  optional
>
The location to move the list items. If not specified, the current
selection will be used.

- **Default:** `editor.selection ?? undefined`.

</APISubListItem>
<APISubListItem
  parent="options"
  name="enableResetOnShiftTab"
  type="boolean"
  optional
>
Enables resetting the indentation level to the parent list when using
Shift+Tab

- **Default:** false.

</APISubListItem>
</APISubList>

</APIItem>
</APIParameters>

<APIReturns>
  <APIItem type="boolean">
    `true` if the list items were moved, `false` otherwise.
  </APIItem>
</APIReturns>

### moveListItemsToList

Moves the list items from a sublist or a list to another list.

<APIParameters>
<APIItem name="editor" type="PlateEditor">
The editor instance.
</APIItem>
<APIItem name="options" type="MergeListItemIntoListOptions" optional>
<APISubList>
<APISubListItem
  parent="options"
  name="fromList"
  type="TElementEntry"
  optional
>
The list whose list items will be moved.
</APISubListItem>
<APISubListItem
  parent="options"
  name="fromListItem"
  type="TElementEntry"
  optional
>
The list item whose sublist items will be moved.
</APISubListItem>
<APISubListItem
  parent="options"
  name="fromStartIndex"
  type="MoveChildrenOptions['fromStartIndex']"
  optional
>
The starting index of the list items to move (default: 0).
</APISubListItem>
<APISubListItem parent="options" name="to" type="Path" optional>
The specific path where the list items will be moved to. If specified,
it overrides the `toList` and `toListIndex` options.
</APISubListItem>
<APISubListItem
  parent="options"
  name="toList"
  type="TElementEntry"
  optional
>
The list where the list items will be moved to.
</APISubListItem>
<APISubListItem
  parent="options"
  name="toListIndex"
  type="number | null"
  optional
>
The index in the destination list where the list items will be inserted.
If not specified, the list items will be inserted at the end of the
list.

- **Default:** `null`.

</APISubListItem>
<APISubListItem parent="options" name="to" type="Path" optional>
The specific path where the list items will be moved to. If specified,
it overrides the `toList` and `toListIndex` options.
</APISubListItem>
<APISubListItem
  parent="options"
  name="deleteFromList"
  type="boolean"
  optional
>
Determines whether to delete the sublist or list from which the items
are moved.

- **Default:** `true`.

</APISubListItem>
</APISubList>

</APIItem>
</APIParameters>

<APIReturns>
  <APIItem type="boolean">
    `true` if the list items were moved, `false` otherwise.
  </APIItem>
</APIReturns>

### moveListSiblingsAfterCursor

Moves the list siblings after the cursor position to a specified path.

<APIParameters>
  <APIItem name="editor" type="PlateEditor">
    The editor instance.
  </APIItem>
  <APIItem name="options" type="Object">
    <APISubList>
      <APISubListItem parent="options" name="at" type="Path">
        The path of the cursor position.
      </APISubListItem>
      <APISubListItem parent="options" name="to" type="Path">
        The path where the list siblings will be moved to.
      </APISubListItem>
    </APISubList>
  </APIItem>
</APIParameters>

<APIReturns>
  <APIItem type="number">The number of list siblings moved.</APIItem>
</APIReturns>

### removeFirstListItem

Removes the first list item if the list is not nested and the list item is not the first child.

<APIParameters>
  <APIItem name="editor" type="PlateEditor">
    The editor instance.
  </APIItem>
  <APIItem name="options" type="Object">
    <APISubList>
      <APISubListItem parent="options" name="list" type="TElementEntry">
        The list entry containing the list item.
      </APISubListItem>
      <APISubListItem parent="options" name="listItem" type="TElementEntry">
        The list item entry to be removed.
      </APISubListItem>
    </APISubList>
  </APIItem>
</APIParameters>

<APIReturns>
  <APIItem type="boolean">
    `true` if the list item was removed, `false` otherwise.
  </APIItem>
</APIReturns>

### removeListItem

Removes a list item and moves its sublist to the parent list if any.

<APIParameters>
<APIItem name="editor" type="PlateEditor">
The editor instance.
</APIItem>
<APIItem name="options" type="RemoveListItemOptions" optional>
<APISubList>
<APISubListItem parent="options" name="list" type="TElementEntry">
The list entry containing the list item.
</APISubListItem>
<APISubListItem parent="options" name="listItem" type="TElementEntry">
The list item entry to be removed.
</APISubListItem>
<APISubListItem parent="options" name="reverse" type="boolean" optional>
Whether to reverse the sublist items before moving them.

- **Default:** `true`

</APISubListItem>
</APISubList>

</APIItem>
</APIParameters>

<APIReturns>
  <APIItem type="boolean">
    `true` if the list item was removed, `false` otherwise.
  </APIItem>
</APIReturns>

### someList

Checks if the current selection is inside a list of a specific type.

<APIParameters>
  <APIItem name="editor" type="PlateEditor">
    The editor instance.
  </APIItem>
  <APIItem name="type" type="string">
    The type of list to check.
  </APIItem>
</APIParameters>

<APIReturns>
  <APIItem type="boolean">
    `true` if the selection is inside a list of the specified type, `false`
    otherwise.
  </APIItem>
</APIReturns>

### unindentListItems

Decreases the indentation level of the list items in the editor.

<APIParameters>
  <APIItem name="editor" type="PlateEditor">
    The editor instance.
  </APIItem>
  <APIItem name="options" type="UnindentListItemsOptions" optional>
    The target path at which to unindent the list items. If not provided, the
    list items will be unindented at the current selection.
  </APIItem>
</APIParameters>

### unwrapList

Removes the list formatting from the selected list items or the list items at the specified path.

<APIParameters>
  <APIItem name="editor" type="PlateEditor">
    The editor instance.
  </APIItem>
  <APIItem name="options" type="object" optional>
    <APISubList>
      <APISubListItem parent="options" name="at" type="Path" optional>
        The target path at which to remove the list formatting. If not provided,
        the list formatting will be removed from the current selection.
      </APISubListItem>
    </APISubList>
  </APIItem>
</APIParameters>

## API Components

### useListToolbarButton

A behavior hook for a list toolbar button.

<APIState>
<APIItem name="pressed" type="boolean">
The pressed state of the button.
</APIItem>

<APIItem name="nodeType" type="string">
The node type of the list.

- **Default:** `BulletedListPlugin.key`

</APIItem>
</APIState>

<APIReturns>
  <APIItem name="props" type="object">
    <APISubList>
      <APISubListItem parent="props" name="pressed" type="boolean">
        The pressed state of the button.
      </APISubListItem>
      <APISubListItem parent="props" name="onClick" type="function">
        A callback function to handle the click event of the button. It toggles
        the list of the specified node type in the editor and focuses the
        editor.
      </APISubListItem>
    </APISubList>
  </APIItem>
</APIReturns>

## API Todo List

### getTodoListItemEntry

Returns the nearest list and list item node entries for a given path (default = selection) in a todo list.

<APIParameters>
<APIItem name="editor" type="PlateEditor">
The editor instance.
</APIItem>
<APIItem name="options" type="object">
<APISubList>
<APISubListItem parent="options" name="at" type="Location | null" optional>

The location or path at which to search for the nearest list and list item nodes. Default is the current selection.

- **Default:** `editor.selection`

</APISubListItem>
</APISubList>
</APIItem>
</APIParameters>

<APIReturns>

- If a list item is found at the given location, it returns an object with the `list` and `listItem` node entries.

- If no list item is found, it returns `undefined`.

</APIReturns>

### useTodoListElement

A behavior hook a todo list item element.

<APIState>
  <APIItem name="checked" type="boolean">
    The checked state of the todo list item.
  </APIItem>
  <APIItem name="readOnly" type="boolean">
    Whether the todo list item is read-only.
  </APIItem>
  <APIItem name="element" type="TElement">
    The todo list item element.
  </APIItem>
  <APIItem name="editor" type="PlateEditor">
    The editor instance.
  </APIItem>
</APIState>

<APIReturns>
  <APIItem name="checkboxProps" type="object">
    <APISubList>
      <APISubListItem parent="checkboxProps" name="checked" type="boolean">
        The checked state of the todo list item.
      </APISubListItem>
      <APISubListItem
        parent="checkboxProps"
        name="onCheckedChange"
        type="function"
      >
        A callback function to handle the todo list item checked state change.
        It takes a boolean value as the parameter.
      </APISubListItem>
    </APISubList>
  </APIItem>
</APIReturns>
