Slate: Customizable Rich Text Editor Framework

0.124.1 · active · verified Sun Apr 19

Slate is a unopinionated and completely customizable framework for building rich text editors, providing a foundational set of primitives rather than a monolithic solution. It allows developers to create bespoke editing experiences by composing plugins and extending its core data model. Currently at version `0.124.1` (core `slate` package), it maintains an active development pace with frequent patch and minor releases across its monorepo packages (e.g., `slate-react`, `slate-history`, `slate-dom`). Key differentiators include its pluggable architecture, a robust data model representing content as a nested tree, and deep integration with React for rendering. This approach enables it to be adapted for a wide range of applications, from simple note-taking to complex document authoring systems, by avoiding prescriptive UI/UX decisions.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to set up a basic Slate editor with React and TypeScript, including custom type definitions and simple bold text rendering. It shows the initialization of the editor with `createEditor`, `withReact`, and `withHistory`, and then renders it using the `Slate` provider and `Editable` component.

import React, { useMemo, useState } from 'react';
import { createEditor, Descendant } from 'slate';
import { Slate, Editable, withReact, ReactEditor } from 'slate-react';
import { withHistory } from 'slate-history';

// Define our custom editor and element types for TypeScript to enable type safety
type CustomEditor = ReactEditor;
type ParagraphElement = { type: 'paragraph'; children: CustomText[] };
type CustomText = { text: string; bold?: boolean; italic?: boolean };

declare module 'slate' {
  interface CustomTypes {
    Editor: CustomEditor;
    Element: ParagraphElement;
    Text: CustomText;
  }
}

const initialValue: Descendant[] = [
  {
    type: 'paragraph',
    children: [{ text: 'Hello, Slate!' }],
  },
  {
    type: 'paragraph',
    children: [{ text: 'This is some ' }, { text: 'bold', bold: true }, { text: ' text.' }],
  },
];

const MySimpleEditor = () => {
  // Create a Slate editor object that won't change across renders.
  // It's enhanced with React capabilities and history (undo/redo).
  const editor = useMemo(() => withHistory(withReact(createEditor())), []);
  const [value, setValue] = useState<Descendant[]>(initialValue);

  return (
    <Slate editor={editor} value={value} onChange={setValue}>
      <Editable
        placeholder="Start typing..."
        // Define a rendering function for elements
        renderElement={props => <p {...props.attributes}>{props.children}</p>}
        // Define a rendering function for leaf nodes (text with formatting)
        renderLeaf={props => {
          let children = props.children;
          if (props.leaf.bold) children = <strong>{children}</strong>;
          if (props.leaf.italic) children = <em>{children}</em>;
          return <span {...props.attributes}>{children}</span>;
        }}
        style={{ border: '1px solid #ccc', padding: '10px', minHeight: '100px' }}
      />
    </Slate>
  );
};

export default MySimpleEditor;

view raw JSON →