Text Editor - Block

Notion-style block editor with inline formatting, slash commands and drag-and-drop reordering.

#Usage

import { TextEditor } from '@primeui/vue-texteditor';
<TextEditor.Root v-model="blocks" mode="block">
    <TextEditor.Content />
    <TextEditor.BlockControls />
    <TextEditor.BlockMenu />
    <TextEditor.SlashMenu />
</TextEditor.Root>

Use block mode for a Notion-style editor where each entry in the bound array is its own draggable block. Setting mode="block" on <TextEditor.Root> switches the value to an array of HTML strings, one per block. The runtime owns drag reordering, the block hover bar, and slash detection; the app owns the widgets rendered inside each part.

#Overview

Each entry in the bound array renders as its own block. Blocks reorder with drag-and-drop, new blocks insert from the slash menu and the add-block button, and <TextEditor.ContextToolbar> provides a floating toolbar for inline formatting on the current selection.

#Block Controls

<TextEditor.BlockControls> is the hover bar next to each block. It teleports into the editor body and exposes the add-block button and the drag handle. Pair it with <TextEditor.BlockMenu>, opened from the drag handle, and <TextEditor.BlockSubmenu> for nested actions such as Turn Into and Color.

<TextEditor.BlockControls>
    <BlockControls />
</TextEditor.BlockControls>

Block controls widgets read from the block-controls context. useBlockControlsContext() exposes index, blockType, addBlock, onDragStart, onDragEnd, and onDragHandleClick.

<!-- BlockControls.vue -->
<script setup lang="ts">
import { useBlockControlsContext } from '@primeui/vue-texteditor';

const { index, addBlock, onDragStart, onDragEnd, onDragHandleClick } = useBlockControlsContext();
</script>

<template>
    <button @click="addBlock(index)" aria-label="Add block">+</button>
    <button draggable="true" @dragstart="onDragStart(index, $event)" @dragend="onDragEnd" @click="onDragHandleClick(index, $event)" aria-label="Block options">⋮⋮</button>
</template>

#Alternative: inline with slot props

<TextEditor.BlockControls> also exposes { index, blockType, addBlock, onDragStart, onDragEnd, onDragHandleClick } on its default slot.

<TextEditor.BlockControls v-slot="{ index, addBlock, onDragStart, onDragEnd, onDragHandleClick }">
    <button @click="addBlock(index)">+</button>
    <button
        draggable="true"
        @dragstart="onDragStart(index, $event)"
        @dragend="onDragEnd"
        @click="onDragHandleClick(index, $event)"
    >⋮⋮</button>
</TextEditor.BlockControls>

#Example

Loading Demo...

#ContextToolbar

Block mode pairs with the floating context toolbar for inline formatting. See Context Toolbar for the full surface.

Loading Demo...

#API

mode="block" on <TextEditor.Root> switches the value to an array of blocks, and useBlockControlsContext() drives the hover bar with index, blockType, addBlock, and the drag handlers. Slots and Contexts places the block outlets in the wider tree; API holds the reference.

  • Block Menu — adds an options menu to the drag handle.
  • Slash Commands — opens a filterable command palette on typing /.
  • Complete — a showcase of every block-mode part wired into a single editor.
  • Context Toolbar — inline formatting on the current selection.