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.
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.
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.