0.5.0 is the first element quality release, covering every A, B and C element. Components rebuild cleanly when moved or re-populated, keyboard and screen-reader access is fixed across the C components, and several XSS paths are closed. Themes gain a --btn-border-width hook,…
Medium-style text highlighting with private notes — engine, selection toolbar, action components, and persistence layer.
Overview
Vanilla Breeze ships a Medium-style highlighting system: select text, pick a color, optionally add a private note. Highlights persist in localStorage per page. Notes live in a panel that opens when you click the margin annotation, and the storage layer is a single private object behind a controller — easy to export, import, or wire to a sync backend later.
The system is layered. Each layer has one job and you opt into the layers you want.
Floating toolbar that appears when a user selects text in a target element. Composes action children. Detects selection, positions itself, dismisses on outside click / Escape.
<selection-menu for="article-id">…</selection-menu> with action children inside.
Inside <selection-menu>: icon button + color palette dropdown that commits a highlight via the engine. Standalone: HTML-first sugar that turns a target into a data-highlights container.
Inside <selection-menu>: highlight + open note panel in one click. Anywhere on the page: hosts the note panel UI for any highlight that requests one (margin-annotation clicks, programmatic openFor()).
<note-wc></note-wc> as a selection-menu child, OR placed once on the page so margin annotations have a panel to open.
Recipes
Read-only display of stored highlights
Just the engine, no UI. Renders highlights persisted under the page's pathname; new selections do nothing.
Read-only
<articledata-highlightsdata-highlights-readonly><p>Existing highlights from localStorage paint here.</p></article>
<articleid="post"data-highlights><p>Select text to highlight. Click a margin annotation to add a note.</p></article><selection-menufor="post"><highlight-wc></highlight-wc><note-wc></note-wc></selection-menu>
Custom colors
Define --highlight-{name} CSS tokens, then list the names on both data-highlights-colors (engine) and colors (highlight-wc swatches).
Brand palette
<style>.brand-article {--highlight-brand: #fce7f3;--highlight-accent: #ddd6fe; }</style><articleid="post"class="brand-article"data-highlightsdata-highlights-colors="brand,accent,yellow"><p>Custom palette per article.</p></article><selection-menufor="post"><highlight-wccolors="brand,accent,yellow"></highlight-wc><note-wc></note-wc></selection-menu>
Page-tools toggle for notes
Drop a note-wc with for= into the page-tools rail; clicking it opens the note panel for the first highlight on that article.
The user clicks an existing highlight (Custom Highlight API hit-test, <mark> fallback, or margin annotation)
highlights:request-note
{ id, highlight, controller }
Margin-annotation click — the convention for opening a note. <note-wc> listens at document level and opens its panel.
highlights:selected
{ text, rect }
User finishes a selection inside a target. Ignored by <selection-menu> (it has its own listener); useful for power users without selection-menu.
Engine API
The HighlightController instance is returned from initHighlights(element). Each [data-highlights] element has exactly one controller (cached).
Method / property
Purpose
getHighlights()
Snapshot of all highlights (array of { id, color, text, startOffset, endOffset, note })
removeHighlight(id)
Delete one
clearAll()
Wipe all highlights for this element
exportHighlights()
JSON string for backup / sync
importHighlights(json)
Replace highlights from JSON
findHighlightRect(id)
First viewport rect of a highlight (used by note-wc to align its panel)
colors
Active color names
element
The owning DOM element
Internal mutation methods _createFromSelection(color), _changeColor(id, color), and _updateNote(id, text) are for action components (highlight-wc, note-wc) and are not part of the documented public API.
Storage
Highlights are written to localStorage under the namespace vb-highlights with a key derived from data-highlights (or the page's pathname when the attribute has no value). Multiple articles on the same page can share a key by setting the same value.
Storage key control
<!-- Default: storage key = location.pathname --><articledata-highlights>…</article><!-- Explicit key: storage key = "blog-post-42" --><articledata-highlights="blog-post-42">…</article><!-- Two articles share one set of highlights --><articledata-highlights="shared">…</article><articledata-highlights="shared">…</article>