Plate
PlateEditorsTemplates
GitHub16kGitHub
DiscordDiscord
  • Feature Kits
  • Plugin
    • Plugin Methods
    • Plugin Shortcuts
    • Plugin Context
    • Plugin Components
    • Plugin Rules
    • Editing Behavior
    • Plugin Input Rules
  • Editor
    • Editor Methods
    • Controlled Value
  • Authored Changes
  • Performance
  • Static Rendering
  • HTML
  • Markdown
  • Form
  • TypeScript
  • Debugging
  • Unit Testing
  • Browser
  • Troubleshooting
  • Locations
  • Transactions
  • Serializing
  • Roots
  • Document Meta
  • Clipboard and Paste
  • Decorations, annotations, and widgets
  • Schema
  • History
  • Pagination
  • Annotations
  • DOM Coverage
  • External Text Views
  • Virtualized Rendering

Plugin Components

PreviousNext

Render Plate plugin nodes with React components.

Plugin components are the React rendering layer for Plate node plugins. Use Plate UI components first when the registry already has the node you need, then customize with EditorElement or EditorLeaf and bind it through .configure({ component }). This page shows the one component binding path.

Start with Plate UI

Plate UI components are copied into your app. That makes them the fastest path for production styling and the safest starting point for customization.

Start hereUse when
Plate UIYou want registry components copied into your app.
Feature Kits
Plugin ContextPlugin Rules

On This Page

Start with Plate UIComponent primitivesEditorElementEditorLeafRegister componentsExisting pluginComponent with consumer overridesIntrinsic componentsStylingAPI Reference
Build your editor
Production-ready AI template and reusable components.
Get all-access
You want plugin groups that already wire components, shortcuts, and options.
This pageYou are writing or replacing a component by hand.

The package owns plugin behavior. Your app owns copied component files and their styles.

Component primitives

Use EditorElement for element nodes and EditorLeaf for mark or leaf nodes. Both components merge editor attributes and node props, className, and style onto the rendered DOM element.

Render children

Always render children. Plate needs the children in the DOM even when the element is void or the visible UI comes from surrounding controls.

EditorElement

Element components render block, inline, and void element nodes.

components/editor/blockquote.tsx
'use client';
 
import type { BlockquotePlugin } from 'platejs/react';
import { type EditorElementProps, EditorElement } from 'platejs/react';
 
export function BlockquoteElement({
  children,
  ...props
}: EditorElementProps<typeof BlockquotePlugin>) {
  return (
    <EditorElement
      as="blockquote"
      className="my-1 border-l-2 pl-6 italic"
      {...props}
    >
      {children}
    </EditorElement>
  );
}
components/editor/blockquote.tsx
'use client';
 
import type { BlockquotePlugin } from 'platejs/react';
import { type EditorElementProps, EditorElement } from 'platejs/react';
 
export function BlockquoteElement({
  children,
  ...props
}: EditorElementProps<typeof BlockquotePlugin>) {
  return (
    <EditorElement
      as="blockquote"
      className="my-1 border-l-2 pl-6 italic"
      {...props}
    >
      {children}
    </EditorElement>
  );
}

EditorElement renders a div by default. Pass as when the node should render as a specific HTML element.

EditorLeaf

Leaf components render marked and decorated text ranges.

components/editor/code.tsx
'use client';
 
import type { CodePlugin } from 'platejs/react';
import { type EditorLeafProps, EditorLeaf } from 'platejs/react';
 
export function CodeLeaf({
  children,
  ...props
}: EditorLeafProps<typeof CodePlugin>) {
  return (
    <EditorLeaf
      as="code"
      className="whitespace-pre-wrap rounded-md bg-muted px-[0.3em] py-[0.2em] font-mono text-sm"
      {...props}
    >
      {children}
    </EditorLeaf>
  );
}
components/editor/code.tsx
'use client';
 
import type { CodePlugin } from 'platejs/react';
import { type EditorLeafProps, EditorLeaf } from 'platejs/react';
 
export function CodeLeaf({
  children,
  ...props
}: EditorLeafProps<typeof CodePlugin>) {
  return (
    <EditorLeaf
      as="code"
      className="whitespace-pre-wrap rounded-md bg-muted px-[0.3em] py-[0.2em] font-mono text-sm"
      {...props}
    >
      {children}
    </EditorLeaf>
  );
}

EditorLeaf renders a span by default. Use it for plugins that declare schema.mark.

Register components

Declare component in a new Plate plugin, or include it in the existing descriptor's single terminal .configure() call.

Existing plugin

Use .configure({ component }) to attach a React component to a plugin.

components/editor/plugins.tsx
import {
  BlockquotePlugin,
  CodePlugin,
} from 'platejs/react';
 
import { BlockquoteElement } from '@/components/editor/blockquote';
import { CodeLeaf } from '@/components/editor/code';
 
export const plugins = [
  BlockquotePlugin.configure({ component: BlockquoteElement }),
  CodePlugin.configure({ component: CodeLeaf }),
];
components/editor/plugins.tsx
import {
  BlockquotePlugin,
  CodePlugin,
} from 'platejs/react';
 
import { BlockquoteElement } from '@/components/editor/blockquote';
import { CodeLeaf } from '@/components/editor/code';
 
export const plugins = [
  BlockquotePlugin.configure({ component: BlockquoteElement }),
  CodePlugin.configure({ component: CodeLeaf }),
];

Component with consumer overrides

When the same plugin also needs rules, shortcuts, initial state, or input rules, put every override in that same terminal .configure() call.

components/editor/plugins.tsx
import { CodeRules } from 'platejs';
import { CodePlugin } from 'platejs/react';
 
import { CodeLeaf } from '@/components/editor/code';
 
export const plugins = [
  CodePlugin.configure({
    component: CodeLeaf,
    inputRules: [CodeRules.markdown()],
    shortcuts: { toggle: { keys: 'mod+e' } },
  }),
];
components/editor/plugins.tsx
import { CodeRules } from 'platejs';
import { CodePlugin } from 'platejs/react';
 
import { CodeLeaf } from '@/components/editor/code';
 
export const plugins = [
  CodePlugin.configure({
    component: CodeLeaf,
    inputRules: [CodeRules.markdown()],
    shortcuts: { toggle: { keys: 'mod+e' } },
  }),
];

Intrinsic components

Bind an HTML tag directly when the default EditorElement or EditorLeaf behavior is enough.

quote-plugin.ts
import { schema } from 'platejs';
import { definePlugin } from 'platejs/react';
 
export const QuotePlugin = definePlugin('quote', {
  component: 'blockquote',
  schema: {
    element: { content: schema.content.text({ default: 'text', min: 1 }) },
  },
});
quote-plugin.ts
import { schema } from 'platejs';
import { definePlugin } from 'platejs/react';
 
export const QuotePlugin = definePlugin('quote', {
  component: 'blockquote',
  schema: {
    element: { content: schema.content.text({ default: 'text', min: 1 }) },
  },
});

Reach for a custom component once you need classes, nested controls, popovers, toolbars, resize handles, or plugin state inside the render tree.

Styling

Prefer component-local styles. Plate also adds a editor-<node-type> class while rendering plugin nodes, so global CSS can target stable node types when you need editor-wide styling.

app/globals.css
.editor-paragraph {
  margin-block: 0.25rem;
}
 
.editor-code {
  border-radius: 0.375rem;
  font-family: var(--font-mono);
}
app/globals.css
.editor-paragraph {
  margin-block: 0.25rem;
}
 
.editor-code {
  border-radius: 0.375rem;
  font-family: var(--font-mono);
}

Use global selectors sparingly. Component files are easier to copy, inspect, and replace from the registry.

API Reference

APIUse forNotes
EditorElementElement nodes.Defaults to div; accepts as, className, style, and Plate render props.
EditorLeafMarked and decorated text.Defaults to span; use with plugins that declare schema.mark.
plugin.configure({ component: Component })Ordinary node component binding.Include the component and every consumer override in the same terminal call.
plugin.configure({ component: 'tag' })Default wrapper with an intrinsic tag.Accepts an HTML tag such as 'blockquote', 'strong', or 'code'.

For plugin method details, see Plugin Methods. For static rendering components, see Static Rendering.