A news story in the edit form as a stack of collapsed blocks, each with an open/close arrow, icon, type, summary and actions.
Animation: a reporter clicks +, types head, adds a Heading block and types its text.

This project is not covered by Drupal’s security advisory policy.

Write content as a stream of Drupal Canvas components, right in the regular edit form. Editors add text, images, quotes, fact boxes, live feeds and any other component your theme provides, nest them, reorder them and preview them in your site's design, without leaving the node form. The content is stored as a Canvas component tree, so Canvas renders it, JSON:API serves it as structured data, and it stays compatible with Canvas's own editor.

 Text, Figure, Heading, Image, Blockquote and Live Feed, each with an open/close arrow, its icon, type, a one-line summary and move, drag, duplicate and remove buttons. The header shows the block and word counts, Fields / Visual and Expand all.

Features

Blocks that are easy to scan and move

Each block shows an open/close arrow, its icon, its type and, when collapsed, a one-line summary of what's in it. Move up, Move down, drag, Duplicate and Remove (with Undo) sit right in the block's header, and every button names itself on hover and keyboard focus. The editor's header counts blocks and words, shows the read time, and stays at the top of the window on long stories. Blocks can start open or collapsed, and on very long content a collapsed block's fields can load the first time it's opened.

A searchable chooser

The + between blocks opens a compact chooser: a search box over every component, grouped by Canvas folder, with Canvas Patterns at the end. The highlighted component's description shows at the bottom. Type to filter, use the arrow keys, press Enter to add. Typing / in an empty text block opens it in place, and a slot that takes only one kind of component adds it straight away.

 a search box over a two-column list of components with icons, grouped under Base, with Badge highlighted.

 a reporter clicks +, types head, adds a Heading block and types its text.

Nested blocks on a dashed line

Components with slots (a live feed and its updates, a fact box and its rows, a hero and its buttons) hold their blocks on a dashed line. Only top-level blocks are drawn as cards, and the blocks inside them hang off the line, so even deep nesting stays narrow and easy to follow. The block you're working in gets dark lines, so you always know where you are. What a slot accepts, and how many, comes from core's SDC slot metadata (expected, minItems, maxItems).

 a nested Live Feed Item hangs off a dashed line, with its Time field focused.

Preview in your theme

Switch between Fields and Visual. Visual renders the content through Canvas in your site's default theme; click a block to edit it in place or in a side panel.

 the story rendered in the site's theme, with the clicked Heading block open for editing in a side panel.

In Fields view, the live preview updates as you type. In Gin and Claro it's a Preview tab in the node form's sidebar, next to Settings, so the form keeps its full width. Buttons above it switch between mobile and desktop width and open the preview in its own window, and a line above it shows the moderation state the content will be saved in. Clicking a block in the preview opens it in the form. Without a sidebar, the preview appears beside the form.

 Published.

 the Preview tab shows the story's desktop layout, scaled to fit.

Icons for every component

Each component shows an icon. A theme sets one in its component's .component.yml, from any core Icon API pack or as an SVG in the component's folder. The module ships a pack of line icons for common components. For themes you can't edit, pick icons under Configuration › Content authoring › Canvas Content Editor.

thirdPartySettings:
  canvas_content_editor:
    icon: 'canvas_content_editor:text'

 a table of components, each with its icon and an icon select list.

Starting values per content type

New blocks start with the content type's Starting values (for example a quote style or a text color made for the section your template puts the content on), and otherwise with the component's defaults for its required choices. Text, links and media start empty, so example copy never gets published by accident.

 the Blockquote component's Type set to Dark.

And on the page

The content renders through Canvas, in your theme, like any Canvas content.

The published news story in the site's article design.

How it compares

This module is for writing the story: a stack of components in the regular edit form, stored in one field. It doesn't lay out pages or displays, so it works alongside the tools that do.

  • Paragraphs: editors see something similar, but every paragraph is its own entity with its own tables and revisions. Here, each block is one row in the node's field table. In our benchmark of the same 19-block story, saving was about 12 times faster, viewing about 3 times faster, and it used 2 tables instead of 24. Much of what Paragraphs adds through extra modules comes from Canvas here: Canvas Patterns are reusable groups of blocks, and settings like a quote's style are just component props, so there's nothing like Paragraphs behaviors to set up. What we don't have yet is a migration from Paragraphs or shared blocks that update everywhere they're used.
  • Layout Paragraphs and Mercury Editor: both store content as paragraphs and are built for page layouts with sections and columns. Here, anything that needs columns is a component with slots.
  • Gutenberg: stores the story as HTML with the block structure in comments, and its blocks are written in React. Here, every block is data (its component and its prop values), and the blocks are the same components the rest of your site uses: your theme's SDCs and any code components you've made in Canvas.
  • Canvas's own editor: this module is built on Canvas, not instead of it. Canvas's editor is a full-screen page builder for landing pages. This module is for content types like articles, where writers stay in the normal edit form with the other fields, revisions and moderation. Both use the same components and store content the same way, so they work side by side on one site.
  • Layout Builder and Display Builder: both lay out displays (and, with Display Builder, pages and Views), each in its own builder. This module edits a field you place in that layout.
  • CKEditor 5 with embeds: the least setup, but quotes and fact boxes end up as markup in one big field. Here, CKEditor 5 is still used for the text, inside each Text block, and everything else is a real component.

Requirements

  • Drupal 11.3 or later
  • Drupal Canvas 1.12. Each new Canvas minor is tested before the module allows it.
  • Media Library (core)

Getting started

  1. Install the module: composer require 'drupal/canvas_content_editor:^1.0@alpha', then enable it.
  2. Edit a content type and open Canvas Content Editor in the vertical tabs. Turn on Build content from components. Optionally keep only Body's summary, limit the allowed components, and set starting values.
  3. Print the field in your template ({{ content.field_canvas_components }}) or leave it in the view display. If a Canvas Content Template displays the content type, as in Drupal CMS site templates, place the Content components block in the template instead.

Editor settings

Under Manage form display, the widget's settings choose, per form mode:

Setting Options
Opens in Fields view, Visual view
Block style Cards (each block of the content is a card), Lines (no cards; blocks hang off dashed lines)
In Visual view, edit a block In place, In a side panel
Blocks start Open, Collapsed
Load a collapsed block's fields With the page (blocks open instantly), When it's first opened (a lighter edit form for very long content)
Live preview Shown when the editor asks for it, Shown when the form opens, Off
Live preview appears In a Preview tab in the sidebar, Beside the form
"/" opens the chooser On, Off
Word count and read time On, Off
Classes around the preview The CSS classes of the area your content sits in, so previews get its background and spacing

Accessibility

The editor is built and tested for WCAG 2.2 AA in Gin and Claro: everything works from the keyboard, the chooser is a combobox with a listbox, focus returns to the + that opened it, icon buttons name themselves on hover and focus (Esc hides the tooltip), and moving a block from the keyboard keeps focus on its controls.

Good to know

  • Editors need the use text format canvas_html_block permission for rich text props.
  • Canvas props can't be arrays of objects: use a slot with a child component (Fact box → Fact row) for repeating rows. Canvas's canvas_html_block format has no headings, so model subheads as their own component.
  • While Canvas has unpublished changes for the same entity, the editor is locked, because publishing them would overwrite edits made here.
  • The module uses some Canvas APIs marked @internal, all in one class, so it allows only the Canvas minor versions it has been tested with.
  • Updates are safe to install: they never change saved content or how an existing site behaves until a site builder changes a setting. New defaults apply to new installs only, and release notes list anything to do.
  • Automated tests (unit, kernel and browser tests) run in GitLab CI on every change.
  • The full documentation is in the module's README.

Project information

Releases