HyMarkdownEditor
Usage examples on this page are written for Lit / plain HTML (
<hy-markdown-editor>). The same component ships asHyMarkdownEditorin@whitespaceux/harmony-react(native React 19), with typed wrappers for Angular, Solid, Svelte, and Vue. The API reference below applies to all frameworks.
Markdown editor with a CodeMirror 6 source pane and a unified-pipeline preview, presented either as a single pane with a Source ⇄ Preview toggle or as a side-by-side split.
The view prop picks the layout strategy. The default view="single" shows one pane with a Source ⇄ Preview eye toggle. view="auto" makes it responsive — a container query renders source + preview side-by-side when the editor is wide and collapses back to the single-pane toggle when it is narrow. view="split" pins the side-by-side layout with a draggable hy-splitter handle so the panes can be resized. In any split layout the preview refreshes live (debounced) as you type.
Examples
Basic (single pane with Source ⇄ Preview toggle)
<hy-markdown-editor label="Description" placeholder="Type Markdown..."></hy-markdown-editor>Responsive (auto split when wide, eye toggle when narrow)
<hy-markdown-editor view="auto" label="Notes" value="# Live preview"></hy-markdown-editor>Pinned side-by-side split
<hy-markdown-editor view="split" label="Notes" value="# Live preview"></hy-markdown-editor>Mode-locked preview
<hy-markdown-editor mode="preview" no-mode-toggle value="# Hello"></hy-markdown-editor>Autofocus inside a dialog (overlay-discovery contract)
<hy-dialog>
<hy-markdown-editor autofocus autoselect value="# Existing"></hy-markdown-editor>
</hy-dialog>API
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
editorView | — | EditorView | null | — | Access the live CM6 view. Public for tests / advanced consumers (e.g. wiring custom keymap extensions). Returns null before the widget has mounted (SSR, pre-firstUpdated). |
uniqueId | unique-id | string | '' | — |
value | value | string | '' | — |
mode | mode | 'source' | 'preview' | 'source' | — |
view | view | 'auto' | 'single' | 'split' | 'single' | Pane layout strategy — single (default) | auto | split. Reflected so the container-query split rules in the stylesheet can branch on it. See MarkdownEditorView. The mode toggle still governs which pane shows in single-pane layouts; in a split layout both panes are visible and the toggle is hidden. |
noModeToggle | no-mode-toggle | boolean | false | — |
placeholder | placeholder | string | '' | — |
label | label | string | '' | — |
disabled | disabled | boolean | false | — |
autofocus | autofocus | boolean | false | Focus the source pane on first connect. Per .claude/rules/focus.md, this is primarily the marker overlay containers (dialog, drawer, popover) discover on show; secondarily a page-load focus shortcut with the same UX caveats as native HTML autofocus. |
autoselect | autoselect | boolean | false | Pre-select the source-pane contents after autofocus (or after .focus() followed by .select()). Mirrors text-area / text-input. |
name | name | string | '' | Form-field name. Set when the editor participates in a <form>. |
required | required | boolean | false | Marks the editor as required for form validation. |
readonly | readonly | boolean | false | Read-only: source pane is non-editable but still focusable. |
spellcheck | spellcheck | boolean | true | Override the default spellcheck="true" on the source pane. Note this shadows the inherited HTMLElement.spellcheck boolean — the inner textarea reads from this property only. |
maxlength | maxlength | number | null | null | Maximum character length of the markdown source. |
minlength | minlength | number | null | null | Minimum character length of the markdown source. |
uploadImage | — | ImageUploadHandler | undefined | — | Host-provided async upload hook. When set, the image dialog gains a drop/pick upload affordance (an embedded hy-file-upload); the host wires this to its asset store (e.g. Supabase Storage behind the Clerk session). When absent, the image dialog is URL-only. Library-side property, not an attribute — the consuming app injects the function. |
acceptedImageTypes | accepted-image-types | string | 'image/*' | accept filter forwarded to the embedded hy-file-upload. Defaults to image/*. |
maxImageBytes | max-image-bytes | number | null | null | Max upload size in bytes, forwarded to hy-file-upload's max-size. |
Events
| Event | Detail | Description |
|---|---|---|
input | — | Detail { value: string }. Fired on every keystroke. |
change | — | Detail { value: string }. Fired on blur after the value changed. |
mode-change | — | Detail { mode, previous }. Fired when the mode-toggle button is clicked. Not fired for programmatic el.mode = ... assignment. |
image-upload-start | — | Detail { file: File }. Fired when a picked/dropped image starts uploading via the uploadImage callback. |
image-upload-error | — | Detail { file: File, message: string }. Fired when the uploadImage callback rejects. |
Slots
| Slot | Description |
|---|---|
extra-tools | Extra toolbar items, rendered in the toolbar's trailing cluster next to the mode toggle. Use for primary actions anchored to the editing surface (e.g. Save / Cancel on an editable document). Only visible while the toolbar is — source / split mode; hidden in single-pane preview. React mirror: the extraTools prop. |
CSS Parts
| Part | Description |
|---|---|
base | Outer wrapper. |
toolbar | Top bar holding the formatting controls and mode toggle. |
format-tools | Leading group of formatting controls (source mode only). |
mode-toggle | The Source ⇄ Preview toggle button. |
body | The editing / preview surface. |
source | The source pane (CodeMirror 6 mount). |
preview | The preview pane. |
preview-skeleton | Loading placeholder shown while the cold preview pipeline loads. |
live-region | Screen-reader announcement region for mode pivots. |
image-dialog | The insert-image dialog (hy-dialog). |
CSS Custom Properties
| Property | Description |
|---|---|
--hy-markdown-editor-min-height | Minimum height of the body. Defaults to 12rem. |
--hy-markdown-editor-padding-vertical | Vertical padding inside source / preview. Defaults to --hy-padding-form-md. |
--hy-markdown-editor-padding-horizontal | Horizontal padding inside source / preview. Defaults to --hy-padding-layout-lg. |
--hy-markdown-editor-toolbar-padding-vertical | Vertical padding inside the toolbar. Defaults to --hy-padding-form-sm. |
--hy-markdown-editor-toolbar-divider-height | Height of the vertical toolbar separator. Defaults to --hy-icon-size-lg. |
--hy-markdown-editor-gap | Gap between toolbar items. Defaults to --hy-gap-form-sm. |
--hy-markdown-editor-radius | Border radius of the outer wrapper. Defaults to --hy-radius-form-md. |
--hy-markdown-editor-border-width | Border width. Defaults to --hy-stroke-sm. |
--hy-markdown-editor-border-color | Border color. Defaults to --hy-border-default-rest. |
--hy-markdown-editor-background | Background color. Defaults to --hy-background-surface-base. |
--hy-markdown-editor-foreground | Foreground / text color. Defaults to --hy-foreground-default-rest. |
--hy-markdown-editor-font-family | Source-pane font family. Defaults to --hy-code-sm-font-family. |
Methods
focus()
Focus the CM6 editor. No-op when the source pane can't be shown (single-pane preview) or before mount.
select()
Select the entire source-pane content. No-op when the source pane can't be shown.