{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "plugin-components-docs",
  "title": "Plugin Components",
  "description": "Render Plate plugin nodes with React components.",
  "files": [
    {
      "path": "../../content/docs/(guides)/plugin-components.mdx",
      "content": "---\ntitle: Plugin Components\ndescription: Render Plate plugin nodes with React components.\n---\n\nPlugin components are the React rendering layer for Plate node plugins. Use\nPlate UI components first when the registry already has the node you need, then\ncustomize with `PlateElement`, `PlateLeaf`, `.withComponent`, or the editor\n`components` map. This page shows which registration path to use.\n\n## Start with Plate UI\n\nPlate UI components are copied into your app. That makes them the fastest path\nfor production styling and the safest starting point for customization.\n\n| Start here | Use when |\n| --- | --- |\n| [Plate UI](/docs/installation/plate-ui) | You want registry components copied into your app. |\n| [Feature Kits](/docs/feature-kits) | You want plugin groups that already wire components, shortcuts, and options. |\n| This page | You are writing or replacing a component by hand. |\n\nThe package owns plugin behavior. Your app owns copied component files and their\nstyles.\n\n## Component Primitives\n\nUse `PlateElement` for element nodes and `PlateLeaf` for mark or leaf nodes.\nBoth components merge Slate attributes, Plate node props, `className`, and\n`style` onto the rendered DOM element.\n\n<Callout type=\"info\" title=\"Render children\">\n  Always render `children`. Slate needs the children in the DOM even when the\n  element is void or the visible UI comes from surrounding controls.\n</Callout>\n\n### PlateElement\n\nElement components render block, inline, and void element nodes.\n\n```tsx title=\"components/ui/blockquote-node.tsx\" showLineNumbers\n'use client';\n\nimport { type PlateElementProps, PlateElement } from 'platejs/react';\n\nexport function BlockquoteElement({\n  children,\n  ...props\n}: PlateElementProps) {\n  return (\n    <PlateElement\n      as=\"blockquote\"\n      className=\"my-1 border-l-2 pl-6 italic\"\n      {...props}\n    >\n      {children}\n    </PlateElement>\n  );\n}\n```\n\n`PlateElement` renders a `div` by default. Pass `as` when the node should render\nas a specific HTML element.\n\n### PlateLeaf\n\nLeaf components render marks and decorated text ranges.\n\n```tsx title=\"components/ui/code-node.tsx\" showLineNumbers\n'use client';\n\nimport { type PlateLeafProps, PlateLeaf } from 'platejs/react';\n\nexport function CodeLeaf({ children, ...props }: PlateLeafProps) {\n  return (\n    <PlateLeaf\n      as=\"code\"\n      className=\"whitespace-pre-wrap rounded-md bg-muted px-[0.3em] py-[0.2em] font-mono text-sm\"\n      {...props}\n    >\n      {children}\n    </PlateLeaf>\n  );\n}\n```\n\n`PlateLeaf` renders a `span` by default. Use it for plugins with\n`node.isLeaf: true`.\n\n## Register Components\n\nUse the narrowest registration path that fits the job.\n\n### withComponent\n\nUse `.withComponent()` when you only need to attach a React component to a\nplugin.\n\n```tsx title=\"components/editor/plugins.tsx\" showLineNumbers\nimport {\n  BlockquotePlugin,\n  CodePlugin,\n} from '@platejs/basic-nodes/react';\n\nimport { BlockquoteElement } from '@/components/ui/blockquote-node';\nimport { CodeLeaf } from '@/components/ui/code-node';\n\nexport const plugins = [\n  BlockquotePlugin.withComponent(BlockquoteElement),\n  CodePlugin.withComponent(CodeLeaf),\n];\n```\n\n`.withComponent(Component)` sets both `node.component` and `render.node` for the\nplugin.\n\n### node.component\n\nUse `node.component` inside `.configure()` when the same plugin call also owns\nrules, shortcuts, options, or parser behavior.\n\n```tsx title=\"components/editor/plugins.tsx\" showLineNumbers\nimport { CodeRules } from '@platejs/basic-nodes';\nimport { CodePlugin } from '@platejs/basic-nodes/react';\n\nimport { CodeLeaf } from '@/components/ui/code-node';\n\nexport const plugins = [\n  CodePlugin.configure({\n    inputRules: [CodeRules.markdown()],\n    node: { component: CodeLeaf },\n    shortcuts: { toggle: { keys: 'mod+e' } },\n  }),\n];\n```\n\nDuring plugin resolution, Plate keeps `node.component` and `render.node` in sync.\n\n### Editor components\n\nUse the editor `components` option when a single editor owns the component map.\nThis is useful for replacing several components in one place.\n\n```tsx title=\"components/editor.tsx\" showLineNumbers\nimport {\n  BlockquotePlugin,\n  CodePlugin,\n} from '@platejs/basic-nodes/react';\nimport { Plate, usePlateEditor } from 'platejs/react';\n\nimport { BlockquoteElement } from '@/components/ui/blockquote-node';\nimport { CodeLeaf } from '@/components/ui/code-node';\nimport { Editor, EditorContainer } from '@/components/ui/editor';\n\nexport function AppEditor() {\n  const editor = usePlateEditor({\n    components: {\n      [BlockquotePlugin.key]: BlockquoteElement,\n      [CodePlugin.key]: CodeLeaf,\n    },\n    plugins: [BlockquotePlugin, CodePlugin],\n  });\n\n  return (\n    <Plate editor={editor}>\n      <EditorContainer>\n        <Editor />\n      </EditorContainer>\n    </Plate>\n  );\n}\n```\n\nThe keys are plugin keys, not file names or component names.\n\n## Render Without a Custom Component\n\nUse `render.as` when the default `PlateElement` or `PlateLeaf` wrapper is enough\nand you only need a different HTML tag.\n\n```ts title=\"quote-plugin.ts\" showLineNumbers\nimport { createPlatePlugin } from 'platejs/react';\n\nexport const QuotePlugin = createPlatePlugin({\n  key: 'quote',\n  node: {\n    isElement: true,\n    type: 'quote',\n  },\n  render: {\n    as: 'blockquote',\n  },\n});\n```\n\nReach for a custom component once you need classes, nested controls, popovers,\ntoolbars, resize handles, or plugin options inside the render tree.\n\n## Styling\n\nPrefer component-local styles. Plate also adds a `slate-<node-type>` class while\nrendering plugin nodes, so global CSS can target stable node types when you need\neditor-wide styling.\n\n```css title=\"app/globals.css\"\n.slate-p {\n  margin-block: 0.25rem;\n}\n\n.slate-code {\n  border-radius: 0.375rem;\n  font-family: var(--font-mono);\n}\n```\n\nUse global selectors sparingly. Component files are easier to copy, inspect, and\nreplace from the registry.\n\n## API Reference\n\n| API | Use for | Notes |\n| --- | --- | --- |\n| `PlateElement` | Element nodes. | Defaults to `div`; accepts `as`, `className`, `style`, and Plate render props. |\n| `PlateLeaf` | Leaf and mark nodes. | Defaults to `span`; use with plugins where `node.isLeaf` is true. |\n| `plugin.withComponent(Component)` | Simple component attachment. | Sets `node.component` and `render.node`. |\n| `plugin.configure({ node: { component } })` | Component plus plugin config. | Plate syncs `node.component` to `render.node` during resolution. |\n| `render.as` | Default wrapper with a different tag. | Works when no custom `render.node` component is set. |\n| `components` | Editor-wide component overrides. | Merged into the root plugin's component overrides. |\n| `override.components` | Advanced plugin-level component overrides. | Higher-priority plugins win when a target already has a component. |\n\nFor plugin method details, see [Plugin Methods](/docs/plugin-methods). For static\nrendering components, see [Static Rendering](/docs/static).\n",
      "type": "registry:file",
      "target": "content/docs/plate/(guides)/plugin-components.mdx"
    }
  ],
  "type": "registry:file"
}