.agents/skills/plate-ui/rules/component-shape.md
For node renderers already inside Plate element context:
useElement() when you need the current element objectusePath() when you need the current element pathuseNodePath() for dynamic validity state that must
survive sibling path shiftsIf a renderer forwards to PlateElement or SlateElement, keep the full
incoming props object intact and destructure from it locally:
Correct:
export function MyElement(props: PlateElementProps<TNode>) {
const { editor, element } = props;
return <PlateElement {...props} />;
}
Incorrect:
export function MyElement({
editor,
element,
...props
}: PlateElementProps<TNode>) {
return <PlateElement {...props} />;
}
That drops required renderer props from the passthrough object.
Prefer the repo’s direct patterns:
const api = editor.getApi(CommentPlugin).comment;
const tf = editor.getTransforms(CommentPlugin).comment;
Or:
const { api, editor } = useEditorPlugin(CommentPlugin);
Do not invent local wrappers like:
const getCommentApi = (editor) => ...
const getCommentTransforms = (editor) => ...
unless multiple files genuinely need the same typed adapter.
If a surface has both static/base and live renderers, keep the split explicit:
export const BaseMathKit = [
BaseInlineEquationPlugin.withComponent(InlineEquationElementStatic),
BaseEquationPlugin.withComponent(EquationElementStatic),
];
export const MathKit = [
InlineEquationPlugin.withComponent(InlineEquationElement),
EquationPlugin.withComponent(EquationElement),
];
Do not hide this behind a factory if the explicit array is clearer.
If a helper is used once, keep it in the component file.
Extract only when: