vue3-highlight-text-color

Vue 3 component for creating and restoring persistent text highlights.
614 16
Install
npm install vue3-highlight-text-color
Latest Version:1.2.0
Vue:3
License:MIT
Last Updated:Sep 28, 2026
Links: GitHub  ·  npm
Maintainer: alivadi

vue3-highlight-text-color

A Vue 3 component for selecting text, assigning it a colour, and restoring the saved highlights later. Highlight positions are stored as character offsets in the source HTML's textContent, so the saved data is serializable and does not depend on the rendered highlight spans.

Installation

pnpm add vue3-highlight-text-color

Vue is a peer dependency; install Vue 3 in the consuming application as usual.

Vue 3 usage

<script setup lang="ts">
import { ref } from "vue";
import {
  subtractMarkerRange,
  TextHighlighter,
  type Marker,
  type MarkerRange,
  type NewMarker,
} from "vue3-highlight-text-color";
import "vue3-highlight-text-color/style.css";

const article = "<p>Select any part of this <strong>HTML text</strong>.</p>";
const highlights = ref<Marker[]>([]);

function addHighlight(highlight: NewMarker) {
  highlights.value.push({ ...highlight, id: crypto.randomUUID() });
}

function removeHighlight(range: MarkerRange) {
  highlights.value = subtractMarkerRange(highlights.value, range);
}
</script>

<template>
  <TextHighlighter
    :text="article"
    :text-id="1"
    :markers="highlights"
    :colors="['#99f6e4', '#bae6fd', '#ddd6fe']"
    @handle-new-highlight="addHighlight"
    @handle-remove-highlight="removeHighlight"
  />
</template>

API

TextHighlighter props

Prop Type Description
text string Source HTML to display and annotate.
textId number Stable identifier of this document.
markers readonly Marker[] Persisted highlights for this and other documents.
colors readonly string[] Optional CSS colours shown in the picker.

Events

Event Payload Description
handle-new-highlight NewMarker Emitted after a user chooses a colour for a selection. Persist it with an id.
handle-remove-highlight MarkerRange Emitted for the selected range to remove.

Slots

color-picker replaces the default colour picker while preserving the library's selection, popup positioning, dismissal, and marker creation.

Slot prop Type Description
colors readonly string[] Resolved colors prop, or the default palette.
chooseColor (color: string) => void Creates a highlight for the active selection.
removeHighlight () => void Removes highlights intersecting the active selection.
close () => void Closes the picker without changing highlights.
<TextHighlighter :text="article" :text-id="1" :markers="highlights">
  <template #color-picker="{ colors, chooseColor, close }">
    <div class="my-picker">
      <button
        v-for="color in colors"
        :key="color"
        class="my-square-swatch"
        :style="{ backgroundColor: color }"
        @click="chooseColor(color)"
      />
      <button @click="close">Cancel</button>
    </div>
  </template>
</TextHighlighter>

Data types

type TextRange = { start: number; end: number };

type NewMarker = {
  textId: number;
  color: string;
  range: TextRange;
};

type Marker = NewMarker & { id: string | number };
type MarkerRange = Pick<NewMarker, "textId" | "range">;

Styling highlights

Each generated highlight exposes its saved colour as --vth-highlight-color. The following variables can be set on a parent element to adapt marker styling without relying on generated class names:

Variable Purpose
--vth-highlight-background Background for all highlights; defaults to each marker's saved colour.
--vth-highlight-foreground Text colour in a highlight.
--vth-highlight-border-radius Corner radius for highlights.
--vth-highlight-code-background Background for highlights nested in <code>.
--vth-highlight-code-foreground Text colour for highlights nested in <code>.
--vth-highlight-code-border-radius Corner radius for highlights nested in <code>.
--vth-highlight-code-padding-inline Horizontal padding for highlights nested in <code>.
.article {
  --vth-highlight-foreground: #172033;
  --vth-highlight-border-radius: 0.2em;
}

.article code {
  --vth-highlight-code-background: #dbeafe;
  --vth-highlight-code-foreground: #1e3a8a;
  --vth-highlight-code-padding-inline: 0.15em;
}

When highlights overlap, the last matching item in markers has visual priority. subtractMarkerRange(markers, range) returns a new marker list and does not mutate its inputs.

Compatibility

This package is a Vue 3 UI component. It requires Vue 3 and a browser DOM; it is not directly usable as a React component or as a vanilla JavaScript widget. React and non-Vue applications would need a framework-specific adapter or a separate headless package. The stored Marker format can still be shared between such adapters.

The package ships ESM, CommonJS, TypeScript declarations, and a separate CSS entry point. It targets modern browsers and requires Node.js 22.13.0+ for development and build tooling.

Security

text is assigned as HTML. Sanitize untrusted content before passing it to the component.

Development and release checks

pnpm install
pnpm dev
pnpm check
pnpm pack:check

pnpm dev starts the playground at http://localhost:5173. pnpm check runs type checks for the library and playground, the test suite, and the production build. pnpm pack:check previews the exact npm tarball.

Project resources

License

MIT

Related Packages

@cocoar/vue-document-viewer

Universal document viewer for Vue 3 — PDFs, images, and more, with annotations a...

5,423 0
@skaile/forge-annotation-inbox

Annotation toolbar whose notes reach coding agents with SFC source locations: fr...

255 0
@commentkit/comment-kit

Figma-style comments for any website. Clients pin feedback with an automatic scr...

2,888
@meanhq/mean

Connects your web app's dev server to Mean, so annotations on your running app c...

415 2
vitepress-jsdoc

A bridge between Vitepress and JSDoc-style commented codebases for hassle-free d...

20,143 24

Version History

Version Released Vue License
1.2.0 ^3.3.4 MIT
1.1.0 ^3.3.4 MIT
1.0.0 ^3.3.4 MIT
0.0.1 3.3.4 MIT