ContentEditor.Toolbar with no children is one row of the everyday
controls (variant="compact"): the block type as a menu naming the block at
the selection, the marks and the link, the two lists, and every insertable
block under one « Insert » menu. Undo, redo, indent and outdent are marked
secondary by their features and stay on their keys. variant="full" lays
every item out as its own control, grouped in a fixed order: history, text,
block, list, insert, table.
An item is a Toggle when it knows whether it is active, a ghost Button
otherwise, with a Tooltip carrying its label and its keys, and a Popover
when it opens a form. An item that requires a capability the host did not
wire (image upload) is absent, not disabled. ContentEditor.ToolbarMenu
folds any run of items into one menu when you compose the row yourself.
The row scrolls sideways when the groups outgrow it, the way a phone's
keyboard bar does; pass wrap to let the groups wrap onto several rows
instead.
Compose the groups by hand for a narrower toolbar:
const items = FEATURES.flatMap((feature) => feature.toolbar ?? []);
<ContentEditor.Toolbar>
<ContentEditor.ToolbarGroup items={items.filter((item) => item.group === "text")} />
<ContentEditor.ToolbarGroup items={items.filter((item) => item.group === "block")} />
</ContentEditor.Toolbar>The floating toolbar
ContentEditor.FloatingToolbar shows the features' floating items above a
text selection, flipped below when the top has no room. It follows the
editor's own selection rather than the DOM's, so it stays over the selected
text while the link form inside it holds focus.
The slash menu
Typing / opens the registry's slash items, filtered on the host's labels
and each item's keywords, on the kit's Command. The menu is the slash
feature: an editor built without it has none.
Single line
mode="single-line" drops every block feature and holds one paragraph: Enter
is swallowed, a seed of several blocks is folded into its first.
createInlineContentFeatures() is the matching feature set.
API
ContentEditor.Root
| Prop | Type | Default | |
|---|---|---|---|
children | ReactNode | required | |
features | ContentRegistry | readonly ContentFeature[] | required | The features this editor offers. createContentFeatures returns the
ones this package ships; add your own, drop what you do not want,
reorder them. Either the list or a registry built from it. |
onChange | (value: Value) => void | required | Called with the whole next document on every edit, keystrokes included. |
value | Value | null | required | The document being edited, plain serialisable data; null is empty. |
className | string | — | |
generateNodeId | (() => string) | newContentNodeId | Node-id factory, injectable for deterministic tests. |
labels | ContentEditorLabelsInput | — | |
mode | ContentEditorMode | "block" | block is the full editor. inline drops every block feature (marks and
links only). single-line is inline with one paragraph and Enter as a
submit rather than a break. |
onUploadImage | ((file: File) => Promise<ContentUploadedImage>) | — | Delegated image upload: receives the picked file, resolves with its url. Omit to hide every image affordance. |
readOnly | boolean | false | |
theme | ContentEditorThemeInput | — |
Plus the DOM props of the element it renders. Source: content-editor/components/root.tsx.
ContentEditor.Canvas
| Prop | Type | Default | |
|---|---|---|---|
placeholder | string | — | Shown in the empty document; defaults to the chrome.placeholder label. |
as | ElementType<any, keyof IntrinsicElements> | — | |
autoFocusOnEditable | boolean | — | Autofocus when it becomes editable (readOnly false -> readOnly true) |
decorate | ((options: { editor: PlateEditor; entry: NodeEntry; }) => TRange[]) | null | — | |
disabled | boolean | — | |
disableDefaultStyles | boolean | — | |
onDOMBeforeInput | ((event: InputEvent) => void) | — | |
renderChunk | RenderChunkFn | — | |
renderEditable | ((editable: ReactElement<any, string | JSXElementConstructor<any>>) => ReactNode) | — | R enders the editable content. |
renderElement | RenderElementFn | — | |
renderLeaf | RenderLeafFn | — | |
renderPlaceholder | ((props: { attributes: { contentEditable: boolean; 'data-slate-placeholder': boolean; ref: (instance: any) => void | (() => VoidOrUndefinedOnly); style: CSSProperties; dir?: "rtl" | undefined; }; children: any; }) => Element) | — | |
renderText | RenderTextFn | — | |
role | string | — | |
scrollSelectionIntoView | ((editor: Editor, domRange: Range) => void) | — | |
style | CSSProperties | — |
Plus the DOM props of the element it renders. Source: content-editor/components/canvas.tsx.
ContentEditor.Toolbar
| Prop | Type | Default | |
|---|---|---|---|
children | ReactNode | — | Compose groups by hand; without children every registry item is shown. |
className | string | — | |
variant | "compact" | "full" | "compact" | compact (the default) is one row of the everyday controls: the block
type as a menu, the marks, the lists, everything insertable under one
« Insert » menu; undo, redo and indent stay on their keys. full lays
every item out as its own control, grouped. |
wrap | boolean | false | Wrap the groups onto several rows instead of scrolling one row sideways. Off by default: on a phone, wrapped groups leave a ragged block of rows and hairlines above the document, while one row scrolls the way a phone keyboard bar does. |
Plus the DOM props of the element it renders. Source: content-editor/components/toolbar.tsx.
ContentEditor.FloatingToolbar
| Prop | Type | Default | |
|---|---|---|---|
className | string | — |
Plus the DOM props of the element it renders. Source: content-editor/components/floating-toolbar.tsx.