Skip to main content

EXAMPLES

Try it. Read the code.

Working examples from the package guides. Changes here are temporary. Reset or switch examples to start again.

JavaScript / DOM

Create a small editor with bold, italic, underline, and strikethrough controls.

Integration guide

Select text, then press B, I, U, or S. Press again to remove the format, or use undo and redo.

LIVE PREVIEW

Source code

This is the code that runs in the preview.

View source on GitHub
import { Editor, readSelectionSummary, markState, watchAnswers } from '@barocss/editor-core';
import { DataStore } from '@barocss/datastore';
import { createSchema, getMinimalSchemaDefinition } from '@barocss/schema';
import { createCoreExtensions, BoldExtension, ItalicExtension, UnderlineExtension, StrikeThroughExtension } from '@barocss/extensions';
import { RendererRegistry, intoRegistry, define, defineMark, element, data, slot } from '@barocss/dsl';
import { EditorViewDOM } from '@barocss/editor-view-dom';

export function mountEditor(container: HTMLElement) {
const registry = new RendererRegistry({ global: false });
intoRegistry(registry, () => {
define('document', element('div', { style: { whiteSpace: 'pre-wrap' } }, [slot('content')]));
define('paragraph', element('p', {}, [slot('content')]));
define('inline-text', element('span', {}, [data('text', '')]));
defineMark('bold', element('strong', {}, [data('text')]));
defineMark('italic', element('em', {}, [data('text')]));
defineMark('underline', element('u', {}, [data('text')]));
defineMark('strikethrough', element('s', {}, [data('text')]));
});
const definition = getMinimalSchemaDefinition();
const schema = createSchema('quick-start', {
...definition, marks: { ...definition.marks,
underline: { name: 'underline', group: 'text-style' },
strikethrough: { name: 'strikethrough', group: 'text-style' },
},
});
const editor = new Editor({
schema, dataStore: new DataStore(undefined, schema), editable: true,
extensions: [...createCoreExtensions(), new BoldExtension(), new ItalicExtension(), new UnderlineExtension(), new StrikeThroughExtension()],
});
editor.loadDocument({ stype: 'document', content: [
{ stype: 'paragraph', content: [{ stype: 'inline-text', text: 'Start writing here.' }] },
]});
const toolbar = document.createElement('div');
toolbar.setAttribute('role', 'group');
toolbar.setAttribute('aria-label', 'Text formatting');
toolbar.style.cssText = 'display:flex;gap:4px;margin-bottom:16px';
const surface = document.createElement('div');
container.replaceChildren(toolbar, surface);
const tools = [
{ label: 'Bold', text: 'B', mark: 'bold', command: 'toggleBold' },
{ label: 'Italic', text: 'I', mark: 'italic', command: 'toggleItalic' },
{ label: 'Underline', text: 'U', mark: 'underline', command: 'toggleUnderline' },
{ label: 'Strikethrough', text: 'S', mark: 'strikethrough', command: 'toggleStrikeThrough' },
];
const buttons = tools.map(tool => {
const button = document.createElement('button');
button.type = 'button';
button.textContent = tool.text;
button.title = tool.label;
button.setAttribute('aria-label', tool.label);
button.style.cssText = 'width:34px;height:32px;border:1px solid #cbd5e1;border-radius:6px;font:600 14px system-ui';
if (tool.mark === 'italic') button.style.fontStyle = 'italic';
if (tool.mark === 'underline') button.style.textDecoration = 'underline';
if (tool.mark === 'strikethrough') button.style.textDecoration = 'line-through';
// Keep the browser's text selection when the pointer presses a button.
button.onpointerdown = event => { if (event.button === 0) event.preventDefault(); };
button.onclick = () => { void editor.executeCommand(tool.command); };
toolbar.append(button);
return button;
});
const stopWatching = watchAnswers(editor, () => {
const summary = readSelectionSummary(editor.dataStore, editor.selection);
tools.forEach((tool, index) => {
const button = buttons[index];
const state = markState(summary, tool.mark);
button.disabled = summary.empty || summary.collapsed || !editor.canExecuteCommand(tool.command);
button.setAttribute('aria-pressed', state === 'mixed' ? 'mixed' : String(state === 'on'));
button.style.background = state === 'off' ? '#fff' : '#dbeafe';
button.style.color = button.disabled ? '#94a3b8' : state === 'off' ? '#172033' : '#1d4ed8';
});
});
const view = new EditorViewDOM(editor, { container: surface, registry });
view.render();
return () => {
stopWatching();
view.destroy();
editor.destroy();
toolbar.remove();
surface.remove();
};
}

See the integration guide for installation and lifecycle details. Office examples also require the host styling setup.