docs/solutions/logic-errors/2026-04-23-suggestion-node-prop-injection-must-target-elements-for-inline-voids.md
We moved date-node off direct suggestion helpers and into suggestion-driven node prop injection so the node could stay suggestion-agnostic. The first pass worked in focused tests but broke prerendering because the injection hook also ran for non-element nodes.
pnpm turbo build --filter=./apps/www failed while prerendering /cntransformProps path and an undefined element.childrentargetPlugins: [KEYS.date] guard alone. inject.nodeProps still visits text nodes, and targetPlugins only filters when an element type exists.transformProps without an explicit element guard. Runtime prerender still reached the helper with element === undefined.Constrain the suggestion injection to elements and keep the date component generic:
inject: {
isElement: true,
nodeProps: {
nodeKey: '',
styleKey: 'cssText',
transformProps: ({ editor, element, props }) => {
if (!element) return props;
const suggestionApi = editor.getApi(BaseSuggestionPlugin).suggestion;
const suggestionData = suggestionApi.suggestionData(element);
if (!suggestionData) return props;
return {
...props,
'data-inline-suggestion': suggestionData.type,
};
},
transformStyle: () => ({}) as CSSStyleDeclaration,
},
targetPlugins: [KEYS.date],
},
Then let date-node expose only a stable slot plus ancestor-aware variants:
<span
className={cn(
'w-fit cursor-pointer rounded-sm bg-muted px-1 text-muted-foreground',
'in-data-[inline-suggestion=insert]:bg-emerald-100! in-data-[inline-suggestion=insert]:text-emerald-700!',
'in-data-[inline-suggestion=remove]:bg-red-100! in-data-[inline-suggestion=remove]:text-red-700!'
)}
data-slot="date-trigger"
draggable
>
inject.nodeProps is broader than an element-only render hook. It participates in the generic render prop pipeline, so text nodes can still arrive unless the plugin opts into isElement: true. Once the injected state is guaranteed to live on element roots, the inline void component can stay decoupled and style itself through stable slots plus ancestor data attributes.
inject.nodeProps behavior that calls element helpers, set isElement: true unless the transform is intentionally text-safe.targetPlugins is meant to protect element-only logic, still add an explicit element null guard in transformProps.