Text Editor - Navigator

Document minimap that displays heading structure for quick navigation.

#Usage

import { TextEditor } from '@primeui/vue-texteditor';
<TextEditor.Root v-model="value">
    <TextEditor.Content />
    <TextEditor.Navigator>
        <TextEditor.NavigatorTrigger>
            <NavigatorTrigger />
        </TextEditor.NavigatorTrigger>
        <TextEditor.NavigatorMenu>
            <NavigatorMenu />
        </TextEditor.NavigatorMenu>
    </TextEditor.Navigator>
</TextEditor.Root>

The Navigator is a minimap sidebar that surfaces the document's heading structure for quick navigation. Mounting <TextEditor.Navigator> enables heading tracking in the runtime. The widgets read the heading list and active entry from useNavigatorContext().

The Navigator splits into three parts. <TextEditor.Navigator> renders nothing itself and drives the heading-tracking plugin. <TextEditor.NavigatorTrigger> is the rail element — it is focusable, sets aria-haspopup="menu", and opens on hover, focus, Enter, Space, or ArrowDown. <TextEditor.NavigatorMenu> is the popover anchored to the Trigger. It uses the internal PopoverMenu, so arrow keys, Enter, and Escape drive navigation. Render heading items inside the Menu as <button role="menuitem"> so the popover picks them up.

<TextEditor.Navigator>
    <TextEditor.NavigatorTrigger>
        <NavigatorTrigger />
    </TextEditor.NavigatorTrigger>
    <TextEditor.NavigatorMenu>
        <NavigatorMenu />
    </TextEditor.NavigatorMenu>
</TextEditor.Navigator>

useNavigatorContext() exposes headings, activeIndex, menuOpen, openMenu(), closeMenu(), triggerEl, and scrollTo(pos).

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

const { headings } = useNavigatorContext();
</script>

<template>
    <div role="button" aria-label="Document outline">{{ headings.length }} headings</div>
</template>

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

const { headings, activeIndex, scrollTo } = useNavigatorContext();
</script>

<template>
    <button v-for="(h, i) in headings" :key="h.pos" role="menuitem" :aria-current="i === activeIndex ? 'true' : undefined" @click="scrollTo(h.pos)">
        {{ h.text }}
    </button>
</template>

#Alternative: inline with slot props

Trigger and Menu also expose { headings, activeIndex, scrollTo } on their default slots.

<TextEditor.Navigator>
    <TextEditor.NavigatorTrigger v-slot="{ headings }">
        <div role="button">{{ headings.length }} headings</div>
    </TextEditor.NavigatorTrigger>
    <TextEditor.NavigatorMenu v-slot="{ headings, activeIndex, scrollTo }">
        <button
            v-for="(h, i) in headings"
            :key="h.pos"
            role="menuitem"
            :aria-current="i === activeIndex ? 'true' : undefined"
            @click="scrollTo(h.pos)"
        >
            {{ h.text }}
        </button>
    </TextEditor.NavigatorMenu>
</TextEditor.Navigator>

#Example

Loading Demo...

#API

useNavigatorContext() exposes headings, activeIndex, menuOpen, openMenu, closeMenu, and scrollTo. See Slots and Contexts.