shadimage
plate
examplemultiple-editors-demosource: ok · hit

Multiple Editors Demo

npx shadcn add "https://platejs.org/r/multiple-editors-demo.json"
free

No selection tags yet — empty means no evidence, not lack of support.

Dependencies

Bundle weight · light
@platejs/basic-nodes@platejs/basic-nodes@platejs/media

Registry dependencies

separatorhttps://platejs.org/r/basic-nodes-kit.jsonhttps://platejs.org/r/media-kit.jsonhttps://platejs.org/r/editor.jsonhttps://platejs.org/r/fixed-toolbar.jsonhttps://platejs.org/r/turn-into-toolbar-button.json

Files4 · source cached 10/8/2026, 3:39:33 PM

src/registry/examples/multiple-editors-demo.tsx
'use client';

import * as React from 'react';

import { Plate, usePlateEditor } from 'platejs/react';

import { Separator } from '@/components/ui/separator';
import { BasicNodesKit } from '@/registry/components/editor/plugins/basic-nodes-kit';
import { MediaKit } from '@/registry/components/editor/plugins/media-kit';
import { basicBlocksValue } from '@/registry/examples/values/basic-blocks-value';
import { basicMarksValue } from '@/registry/examples/values/basic-marks-value';
import { imageValue } from '@/registry/examples/values/media-value';
import { Editor, EditorContainer } from '@/registry/ui/editor';
import { FixedToolbar } from '@/registry/ui/fixed-toolbar';
import { TurnIntoToolbarButton } from '@/registry/ui/turn-into-toolbar-button';

export default function MultipleEditorsDemo() {
  const editor = usePlateEditor({
    id: 'editor1',
    plugins: BasicNodesKit,
    value: basicBlocksValue,
  });

  const editorMarks = usePlateEditor({
    id: 'marks',
    plugins: BasicNodesKit,
    value: basicMarksValue,
  });

  const editorImage = usePlateEditor({
    id: 'image',
    plugins: [...BasicNodesKit, ...MediaKit],
    value: imageValue,
  });

  return (
    <Plate editor={editor}>
      <Plate editor={editorMarks}>
        <Plate editor={editorImage}>
          <FixedToolbar>
            <TurnIntoToolbarButton />
          </FixedToolbar>

          <div>
            <EditorContainer>
              <Editor />
            </EditorContainer>
            <Separator />
            <EditorContainer>
              <Editor id="marks" />
            </EditorContainer>
            <Separator />
            <EditorContainer>
              <Editor id="image" />
            </EditorContainer>
          </div>
        </Plate>
      </Plate>
    </Plate>
  );
}
src/registry/examples/values/basic-blocks-value.tsx
/** @jsxRuntime classic */
/** @jsx jsx */
import { jsx } from '@platejs/test-utils';
import { KEYS } from 'platejs';

jsx;

export const basicBlocksValue: any = (
  <fragment>
    <hh1>Heading 1</hh1>
    <hp>
      This is a top-level heading, typically used for main titles and major
      section headers.
    </hp>
    <hh2>Heading 2</hh2>
    <hp>
      Secondary headings help organize content into clear sections and
      subsections.
    </hp>
    <hh3>Heading 3</hh3>
    <hp>
      Third-level headings provide further content structure and hierarchy.
    </hp>
    <hblockquote>
      <hp>
        Blockquotes can group multiple paragraphs, quoted lists, and replies in
        one container.
      </hp>
      <hp>
        Use nested blockquotes when you need to keep the quote hierarchy
        explicit.
      </hp>
      <hblockquote>
        <hp>Nested blockquotes keep reply chains readable.</hp>
      </hblockquote>
    </hblockquote>
    <hp>
      Use headings to create a clear document structure that helps readers
      navigate your content effectively. Combine them with blockquotes to
      emphasize important information.
    </hp>
    <element type={KEYS.hr}>
      <htext />
    </element>
    <hp>
      Horizontal rules help visually separate different sections of your
      content, creating clear breaks between topics or ideas.
    </hp>
  </fragment>
);
src/registry/examples/values/basic-marks-value.tsx
/** @jsxRuntime classic */
/** @jsx jsx */
import { jsx } from '@platejs/test-utils';

jsx;

export const basicMarksValue: any = (
  <fragment>
    <hh2>Text Formatting</hh2>
    <hp>
      Add style and emphasis to your text using various formatting options.
    </hp>
    <hp>
      Make text <htext bold>bold</htext>, <htext italic>italic</htext>,{' '}
      <htext underline>underlined</htext>, or apply a{' '}
      <htext bold italic underline>
        combination
      </htext>{' '}
      of these styles for emphasis.
    </hp>
    <hp>
      Add <htext strikethrough>strikethrough</htext> to indicate deleted
      content, use <htext code>inline code</htext> for technical terms, or{' '}
      <htext highlight>highlight</htext> important information.
    </hp>
    <hp>
      Format mathematical expressions with <htext subscript>subscript</htext>{' '}
      and <htext superscript>superscript</htext> text.
    </hp>
    <hp>
      Show keyboard shortcuts like <htext kbd>⌘ + B</htext> for bold or{' '}
      <htext kbd>⌘ + I</htext> for italic formatting.
    </hp>
  </fragment>
);
src/registry/examples/values/media-value.tsx
/** @jsxRuntime classic */
/** @jsx jsx */
import { jsx } from '@platejs/test-utils';

jsx;

export const imageValue: any = (
  <fragment>
    <hh2>Image</hh2>
    <hp>Add images by either uploading them or providing the image URL:</hp>
    <himg
      align="center"
      caption={[{ children: [{ text: 'Image caption' }] }]}
      url="https://images.unsplash.com/photo-1712688930249-98e1963af7bd?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
      width="55%"
    >
      <htext />
    </himg>
    <hp>Customize image captions and resize images.</hp>
  </fragment>
);

export const mediaPlaceholderValue: any = (
  <fragment>
    <hh2>Upload</hh2>
    <hp>
      Our editor supports various media types for upload, including images,
      videos, audio, and files.
    </hp>
    <hfile
      name="sample.pdf"
      align="center"
      url="https://s26.q4cdn.com/900411403/files/doc_downloads/test.pdf"
      width="80%"
      isUpload
    >
      <htext />
    </hfile>
    <hp indent={1} listStyleType="disc">
      Real-time upload status and progress tracking
    </hp>
    <haudio
      align="center"
      url="https://samplelib.com/lib/preview/mp3/sample-3s.mp3"
      width="80%"
    >
      <htext />
    </haudio>
    <hp indent={1} listStyleType="disc">
      Configurable file size limits and batch upload settings
    </hp>
    <hvideo
      align="center"
      url="https://videos.pexels.com/video-files/6769791/6769791-uhd_2560_1440_24fps.mp4"
      width="80%"
      isUpload
    >
      <htext />
    </hvideo>
    <hp indent={1} listStyleType="disc">
      Clear error messages for any upload issues
    </hp>
    <hp indent={1} listStyleType="disc">
      Try it now - drag an image from your desktop or click the upload button in
      the toolbar
    </hp>
  </fragment>
);

export const mediaValue: any = (
  <fragment>
    {imageValue}
    {mediaPlaceholderValue}

    <hh2>Embed</hh2>
    <hp>Embed various types of content, such as videos and tweets:</hp>
    <hmediaembed
      align="center"
      url="https://www.youtube.com/watch?v=MyiBAziEWUA"
    >
      <htext />
    </hmediaembed>
    {/* BUG */}
    {/* <hmediaembed
      align="center"
      url="https://twitter.com/zbeyens/status/1677214892212776960"
    >
      <htext />
    </hmediaembed> */}
  </fragment>
);

More from plate

Browse all components in this library →