docs/solutions/logic-errors/2026-04-04-v2-text-string-primitives-should-own-the-dom-text-boundary.md
After the zero-width policy was split and proved in Chromium, the v2 proof
surfaces were still hand-rolling ordinary text leaves with raw
<span data-slate-string> markup.
That is the same low-level seam legacy Slate already treats specially.
Leaving it ad hoc in every proof surface would have been lazy and brittle.
slate-react-v2 now owns a reusable TextString primitive:
It follows the same real boundary as legacy Slate:
<span data-slate-string>textContent in a layout effect when it driftsThe proof surfaces and matrix routes now consume that primitive instead of hand-rolled text spans.
For editable text, the DOM is not a passive output target.
Native typing, composition, spellcheck, and selection can all mutate the text node outside React’s normal one-way expectations. If the renderer surface leaves each caller to improvise a text span, it has no single place to correct stale DOM text or protect the actual text-node boundary.
Owning that boundary in one primitive is the first real v2 text-renderer seam.
For slate-react-v2 renderer/input work:
ZeroWidthStringTextStringIf a renderer/input seam is already repeated in multiple proof surfaces, it is past due to become a package primitive.