Skip to content

Editor: Expose editor components as reusable pieces #2761

@aduth

Description

@aduth

Previously: #2065

The current implementation of the editor is very specific to the post editor screen, but we will want to support cases where parts of the editor can be used in different contexts. A component like <VisualEditorBlockList />, for example, would be a very useful substitute for how someone might currently otherwise use a single TinyMCE instance on a page. To support this, we would still need block values to be coordinated through editor state, ideally in a manner less specific to managing a post entity.

Proposal:

Expose a number of Editor components, the root of which an <Editor> component serves as the interface through which changes are surfaced and state is initialized:

<Editor>
	<header>
		<Editor.UndoRedo />
	</header>
	<Editor.BlockList />
	<Editor.InserterButton />
	<aside>
		<Editor.BlockInspector />
	</aside>
</Editor>

How changes are surfaced should be guided by use-cases. It may be that Editor accepts a single onChange prop which is invoked with the string of content, but it could be that a consumer would need more raw access to actions as they are dispatched. Further, frequent serializations will likely have a negative impact on performance.

One option is for the consumer to initialize the Redux store themselves, thus having access to applying their own middlewares or store enhancers to gain access to raw changes as they occur.

const store = createEditorStore( /* ...enhancers */ );

const editor = <Editor store={ store } />;

// ...later

const content = getContent( store.getState() );

In this model, a post editor would separately manage post properties such as visibility, author, terms, etc, and the underlying <Editor /> would hold responsibility for maintaining the value of a post's content.

This would also bring alignment between blocks and editor, and I suggest we eliminate the distinction. It could be that the Editor component receives a configuration of blocks, a subset of all registered options (#2065), or that blocks are registered to the editor instance itself. In either case, I see block registration being specific to the idea of an editor.

const editor = createEditorInstance();

editor.registerBlock( /* ... */ );

I think it's important that we don't become excessively granular by artificially separating concepts. Where we currently distinguish editor from blocks, we should instead distinguish editor (and blocks) from post editing.

- /blocks
/editor
+ /post-editor

Metadata

Metadata

Assignees

Labels

FrameworkIssues related to broader framework topics, especially as it relates to javascriptGeneral InterfaceParts of the UI which don't fall neatly under other labels.

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions