Skip to main content

Overview

SlateElement is the fundamental building block of content within Yoopta Editor blocks. Each element represents a piece of structured content with a type, unique ID, children, and optional properties. Yoopta Editor extends Slate.js’s element structure with additional fields for enhanced functionality.

Type Definition

type SlateElement<K extends string = string, T = any> = {
  id: string;
  type: K;
  children: Descendant[];
  props?: PluginElementProps<T>;
};

Properties

id
string
required
Unique identifier for the element. Generated automatically when elements are created.
type
string
required
Element type identifier in kebab-case format (e.g., "paragraph", "heading-one", "list-item"). This differs from block types which use PascalCase.
children
Descendant[]
required
Array of child nodes, which can be other elements or text nodes. From Slate.js’s Descendant type.Text nodes have the structure:
{ text: string; bold?: boolean; italic?: boolean; ... }
props
PluginElementProps<T>
Optional properties object containing element configuration and metadata.

SlateElementTextNode

Text nodes within elements support various formatting marks:
type SlateElementTextNode = {
  text: string;
  bold?: boolean;
  italic?: boolean;
  underline?: boolean;
  code?: boolean;
  strike?: boolean;
  highlight?: any;
};

Examples

Basic Paragraph Element

const paragraphElement: SlateElement = {
  id: "elem-uuid-1",
  type: "paragraph",
  children: [
    { text: "This is plain text. " },
    { text: "This is bold.", bold: true },
    { text: " This is italic.", italic: true }
  ],
  props: {
    nodeType: "block"
  }
};

Heading Element

const headingElement: SlateElement = {
  id: "heading-elem-1",
  type: "heading-one",
  children: [
    { text: "Chapter 1: Introduction" }
  ],
  props: {
    nodeType: "block"
  }
};
const linkElement: SlateElement = {
  id: "link-elem-1",
  type: "link",
  children: [
    { text: "Visit our website" }
  ],
  props: {
    nodeType: "inline",
    url: "https://example.com",
    target: "_blank",
    rel: "noopener noreferrer"
  }
};

Image Element (Void)

const imageElement: SlateElement = {
  id: "image-elem-1",
  type: "image",
  children: [{ text: "" }], // Void elements require an empty text child
  props: {
    nodeType: "void",
    src: "https://example.com/image.jpg",
    alt: "Description of image",
    width: 800,
    height: 600
  }
};

Code Block Element

const codeElement: SlateElement = {
  id: "code-elem-1",
  type: "code",
  children: [
    { text: "function hello() {\n" },
    { text: "  console.log('Hello, world!');\n" },
    { text: "}" }
  ],
  props: {
    nodeType: "block",
    language: "javascript",
    theme: "github-dark"
  }
};

List Item Element

const listItemElement: SlateElement = {
  id: "list-item-elem-1",
  type: "bulleted-list",
  children: [
    { text: "First item" }
  ],
  props: {
    nodeType: "block"
  }
};

Usage

Getting Elements

import { Elements } from '@yoopta/editor';

// Get element by path within a block
const element = editor.getElement({
  blockId: 'block-id',
  path: [0] // First element in the block
});

// Using Elements API
const element2 = Elements.getElement(editor, {
  blockId: 'block-id',
  path: [0]
});

Creating Elements with editor.y

// Create a block element
const paragraph = editor.y('paragraph', {
  children: [
    editor.y.text('Hello, world!')
  ]
});

// Create an inline element (e.g., link)
const link = editor.y.inline('link', {
  props: { url: 'https://example.com' },
  children: [
    editor.y.text('Click here')
  ]
});

// Create a text node with marks
const boldText = editor.y.text('Bold text', { bold: true });
const italicText = editor.y.text('Italic text', { italic: true });

Updating Elements

import { Elements } from '@yoopta/editor';

// Update element properties
editor.updateElement({
  blockId: 'block-id',
  path: [0],
  options: {
    props: {
      nodeType: 'block',
      customProp: 'new value'
    }
  }
});

Inserting Elements

import { Elements } from '@yoopta/editor';

// Insert a new element
const newElement = editor.y('paragraph', {
  children: [
    editor.y.text('New paragraph')
  ]
});

editor.insertElement({
  blockId: 'block-id',
  element: newElement,
  path: [1] // Insert at index 1
});

Deleting Elements

import { Elements } from '@yoopta/editor';

// Delete an element
editor.deleteElement({
  blockId: 'block-id',
  path: [0]
});

Element Structure Builder (editor.y)

The editor.y utility provides a convenient way to create elements:
// Block element
editor.y(type: string, options?: ElementStructureOptions)

// Inline element
editor.y.inline(type: string, options?: ElementStructureOptions)

// Text node
editor.y.text(text: string, marks?: TextNodeOptions)

ElementStructureOptions

type ElementStructureOptions = {
  props?: Record<string, any>;
  children?: Descendant[];
};

TextNodeOptions

type TextNodeOptions = {
  bold?: boolean;
  italic?: boolean;
  underline?: boolean;
  code?: boolean;
  strike?: boolean;
  highlight?: any;
};

Working with Children

// Get element children
const children = editor.getElementChildren({
  blockId: 'block-id',
  path: [0]
});

// Check if element is empty
const isEmpty = editor.isElementEmpty({
  blockId: 'block-id',
  path: [0]
});

// Iterate through children
const element = editor.getElement({ blockId: 'block-id', path: [0] });
if (element) {
  element.children.forEach((child) => {
    if ('text' in child) {
      console.log('Text node:', child.text);
    } else {
      console.log('Element node:', child.type);
    }
  });
}

Element Types by Plugin

Different plugins define different element types:
  • paragraph - Paragraph plugin
  • heading-one, heading-two, heading-three - Headings plugin
  • blockquote - Blockquote plugin
  • bulleted-list - Bulleted list plugin
  • numbered-list - Numbered list plugin
  • todo-list - Todo list plugin
  • image - Image plugin
  • video - Video plugin
  • file - File plugin
  • callout - Callout plugin
  • code - Code plugin
  • table - Table plugin
  • accordion - Accordion plugin

Node Types

The nodeType property determines how an element behaves:
type PluginElementNodeType = 'block' | 'inline' | 'void' | 'inlineVoid';
  • block: Standard block-level elements (paragraphs, headings, lists)
  • inline: Inline elements that flow with text (links, mentions)
  • void: Non-editable block elements (images, videos, embeds)
  • inlineVoid: Non-editable inline elements (inline images, badges)

Type Safety

import type { SlateElement, SlateElementTextNode } from '@yoopta/editor';

// Type-safe element creation
function createParagraph(text: string): SlateElement {
  return {
    id: generateId(),
    type: 'paragraph',
    children: [{ text }],
    props: { nodeType: 'block' }
  };
}

// Type guard for text nodes
function isTextNode(node: any): node is SlateElementTextNode {
  return 'text' in node;
}

See Also

Build docs developers (and LLMs) love