Element objects are a type of Node in a Slate document that contain other Element nodes or Text nodes.
interface Element {
children: Node[]
}interface Element {
children: Node[]
}Element Behavior Types
Element nodes behave differently depending on the Slate editor's schema. An element can be:
- "block" or "inline" as defined by
state.schema.isInline(element) - either "void" or "not void" as defined by
state.schema.isVoid(element)
Block vs. Inline
A "block" element can only be siblings with other "block" elements. An "inline" node can be siblings with Text nodes or other "inline" elements.
Void vs Not Void
In a not "void" element, Slate handles the rendering of its children (e.g. in a paragraph where the Text and Inline children are rendered by Slate). In a "void" element, Slate owns the DOM shell and selection anchor while app code renders only the visible content.
Voids That Support Marks
Some void elements are effectively stand-ins for text, such as with the
Mentions example, where the
mention element renders the character's name. Users might want to format Void
elements like this with bold, or set their font and size, so
state.schema.markableVoid(element) tells Slate whether or not to apply Marks
to the text children of void elements.
Rendering Void Elements
Void elements still contain a text child in the Slate document model so
selection and marks have a stable model location. The React runtime renders the
hidden anchor and browser shell for you. App renderers should use
Editable's renderVoid prop and return visible content only.
Typical rendering code will resemble this image element:
import type { RenderVoidProps } from '@platejs/slate-react'
type ImageElement = {
type: 'image'
url: string
children: [{ text: '' }]
}
const Image = ({ element }: RenderVoidProps<ImageElement>) => {
return <img alt="" src={element.url} />
}
<Editable
renderVoid={(props) => {
switch (props.element.type) {
case 'image':
return <Image {...props} />
default:
return null
}
}}
/>import type { RenderVoidProps } from '@platejs/slate-react'
type ImageElement = {
type: 'image'
url: string
children: [{ text: '' }]
}
const Image = ({ element }: RenderVoidProps<ImageElement>) => {
return <img alt="" src={element.url} />
}
<Editable
renderVoid={(props) => {
switch (props.element.type) {
case 'image':
return <Image {...props} />
default:
return null
}
}}
/>For a "markable" void such as a mention element, marks on the text child can
still be used to determine how the visible content is rendered. Selection UI is
an opt-in target subscription:
import { useElementSelected, type RenderVoidProps } from '@platejs/slate-react'
type MentionElement = {
type: 'mention'
character: string
children: [{ bold?: true; italic?: true; text: '' }]
}
const Mention = ({ element }: RenderVoidProps<MentionElement>) => {
const selected = useElementSelected()
const text = element.children[0] ?? {}
const style = {
padding: '3px 3px 2px',
margin: '0 1px',
verticalAlign: 'baseline',
display: 'inline-block',
borderRadius: '4px',
backgroundColor: '#eee',
fontSize: '0.9em',
boxShadow: selected ? '0 0 0 2px #B4D5FF' : 'none',
}
if (text.bold) {
style.fontWeight = 'bold'
}
if (text.italic) {
style.fontStyle = 'italic'
}
return (
<span
data-cy={`mention-${element.character.replace(' ', '-')}`}
style={style}
>
@{element.character}
</span>
)
}import { useElementSelected, type RenderVoidProps } from '@platejs/slate-react'
type MentionElement = {
type: 'mention'
character: string
children: [{ bold?: true; italic?: true; text: '' }]
}
const Mention = ({ element }: RenderVoidProps<MentionElement>) => {
const selected = useElementSelected()
const text = element.children[0] ?? {}
const style = {
padding: '3px 3px 2px',
margin: '0 1px',
verticalAlign: 'baseline',
display: 'inline-block',
borderRadius: '4px',
backgroundColor: '#eee',
fontSize: '0.9em',
boxShadow: selected ? '0 0 0 2px #B4D5FF' : 'none',
}
if (text.bold) {
style.fontWeight = 'bold'
}
if (text.italic) {
style.fontStyle = 'italic'
}
return (
<span
data-cy={`mention-${element.character.replace(' ', '-')}`}
style={style}
>
@{element.character}
</span>
)
}Static methods
Retrieval methods
ElementApi.matches(element: Element, props: Partial<Element>) => boolean
Check if an element matches a set of props. Note: This checks custom properties, but it does not ensure that any children are equivalent.
Check methods
ElementApi.isAncestor(value: unknown) => value is Ancestor
Check if a value implements the 'Ancestor' interface.
ElementApi.isElement(value: unknown) => value is Element
Check if a value implements the Element interface.
ElementApi.isElementList(value: unknown) => value is Element[]
Check if a value is an array of Element objects.
ElementApi.isElementProps(props: unknown) => props is Partial<Element>
Check if a value is an object that can be used as partial Element props.
ElementApi.isElementType<T Extends Element>(value: unknown, elementVal: string, ElementKey: string = 'type'): value is T
Check if a value implements the Element interface and has elementKey with selected value.
Default it check to type key value
On This Page
Element Behavior TypesBlock vs. InlineVoid vs Not VoidVoids That Support MarksRendering Void ElementsStatic methodsRetrieval methodsElementApi.matches(element: Element, props: Partial<Element>) => booleanCheck methodsElementApi.isAncestor(value: unknown) => value is AncestorElementApi.isElement(value: unknown) => value is ElementElementApi.isElementList(value: unknown) => value is Element[]ElementApi.isElementProps(props: unknown) => props is Partial<Element>ElementApi.isElementType<T Extends Element>(value: unknown, elementVal: string, ElementKey: string = 'type'): value is T