Task Item
The TaskItem node represents an individual checkbox list item (<li data-type="taskItem">) inside a TaskList. It renders a checkbox and a content area, tracks a checked attribute, and provides keyboard shortcuts for toggling, splitting, and indenting.
You don’t need to add TaskItem manually. It is automatically included when you add TaskList via its addExtensions(). If you are using StarterKit, TaskItem is already included.
import { Editor, Document, Text, Paragraph, TaskList } from '@domternal/core';
const editor = new Editor({ element: document.getElementById('editor')!, extensions: [Document, Text, Paragraph, TaskList], content: ` <ul data-type="taskList"> <li data-type="taskItem" data-checked="false"><p>Unchecked task</p></li> <li data-type="taskItem" data-checked="true"><p>Checked task</p></li> </ul> `,});import { Component, signal } from '@angular/core';import { DomternalEditorComponent } from '@domternal/angular';import { Editor, Document, Text, Paragraph, TaskList } from '@domternal/core';
@Component({ selector: 'app-editor', imports: [DomternalEditorComponent], template: ` <domternal-editor [extensions]="extensions" [content]="content" (editorCreated)="editor.set($event)" /> `,})export class EditorComponent { editor = signal<Editor | null>(null); extensions = [Document, Text, Paragraph, TaskList]; content = '<ul data-type="taskList"><li data-type="taskItem" data-checked="false"><p>A task</p></li></ul>';}import { Domternal } from '@domternal/react';import { Document, Text, Paragraph, TaskList } from '@domternal/core';
const content = `<ul data-type="taskList"> <li data-type="taskItem" data-checked="false"><p>Unchecked task</p></li> <li data-type="taskItem" data-checked="true"><p>Checked task</p></li></ul>`;
export default function Editor() { return ( <Domternal extensions={[Document, Text, Paragraph, TaskList]} content={content} > <Domternal.Content /> </Domternal> );}TaskItem is auto-included by TaskList. Use the toggleTask command to toggle the checked state:
// Toggle the current task's checked stateeditor.commands.toggleTask();
// Check if a task item is activeeditor.isActive('taskItem'); // true or false
// TaskItem handles Enter splitting, Tab/Shift-Tab// indentation, and Mod-Enter toggle automaticallySchema
Section titled “Schema”| Property | Value |
|---|---|
| ProseMirror name | taskItem |
| Type | Node |
| Group | None (used as content of TaskList) |
| Content | block+ (one or more block nodes) |
| Defining | Yes |
| HTML tag | <li data-type="taskItem"> |
The rendered HTML structure is:
<li data-type="taskItem" data-checked="false"> <label contenteditable="false"> <input type="checkbox"> </label> <div> <!-- content goes here --> </div></li>The <label> with contenteditable="false" prevents the cursor from entering the checkbox area. The <div> wrapper holds the editable content.
Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
HTMLAttributes | Record<string, unknown> | {} | HTML attributes added to the <li> element |
nested | boolean | true | Whether nested lists are allowed inside task items |
Custom HTML attributes
Section titled “Custom HTML attributes”import { TaskItem } from '@domternal/core';
const CustomTaskItem = TaskItem.configure({ HTMLAttributes: { class: 'my-task-item' },});Attributes
Section titled “Attributes”| Attribute | Type | Default | Description |
|---|---|---|---|
checked | boolean | false | Whether the task is checked/completed |
The checked attribute is stored as data-checked="true" or data-checked="false" on the <li> element, and also controls the checked attribute on the inner <input type="checkbox">.
When splitting a task item with Enter, the checked attribute is not carried over to the new item (keepOnSplit: false). New items always start unchecked.
Commands
Section titled “Commands”| Command | Description |
|---|---|
toggleTask() | Toggle the checked state of the current task item |
// Toggle the current task's checked stateeditor.commands.toggleTask();
// With chainingeditor.chain().focus().toggleTask().run();toggleTask finds the nearest taskItem ancestor of the cursor and flips its checked attribute.
Keyboard shortcuts
Section titled “Keyboard shortcuts”| Shortcut | Behavior |
|---|---|
Enter | Split task item at cursor position |
Enter (empty item) | Lift content out of the task list (exit the list) |
Tab | Indent task item (sink into nested list) |
Shift-Tab | Outdent task item (lift out of nested list) |
Mod-Enter | Toggle checked state |
Enter behavior
Section titled “Enter behavior”The Enter key has context-dependent behavior:
- Non-empty item, cursor in middle: Splits the task item at the cursor, creating a new unchecked task item with the text after the cursor.
- Non-empty item, cursor at end: Creates a new empty unchecked task item below.
- Empty item: Lifts the content out of the task list. If the item is the last one, pressing Enter on an empty item exits the list and creates a paragraph below.
- Empty item inside a nested list within a regular list item: Escapes to the parent list level by creating a new list item at the correct depth.
Tab/Shift-Tab
Section titled “Tab/Shift-Tab”Unlike ListItem which relies on ListKeymap for Tab/Shift-Tab, TaskItem handles these shortcuts directly using ProseMirror’s sinkListItem and liftListItem commands.
JSON representation
Section titled “JSON representation”{ "type": "taskItem", "attrs": { "checked": false }, "content": [ { "type": "paragraph", "content": [ { "type": "text", "text": "Unchecked task" } ] } ]}A checked task item:
{ "type": "taskItem", "attrs": { "checked": true }, "content": [ { "type": "paragraph", "content": [ { "type": "text", "text": "Completed task" } ] } ]}Source
Section titled “Source”@domternal/core - TaskItem.ts