Search the Qalma docs

Type at least two characters to get started.

Docs

Accessibility

Qalma provides structural accessibility for the primitives it owns, and leaves product UI accessibility to the components you build around the controller.

Library primitives

Primitive Accessibility behavior
<qalma-toolbar> Renders role="toolbar" and an aria-label from the label input.
button[qalmaCommand] Preserves editor selection on mouse down, disables itself through canExecute(), and sets aria-pressed only for commands with active state.
<qalma-content> Mounts the ProseMirror view after browser render. The editor view receives aria-label="Rich text editor".
ListsPlugin Handles Escape and Shift+Escape to move focus to adjacent focusable elements outside the editor, or blur when none exist.
TaskListPlugin Renders each task checkbox with aria-label="Toggle task" so it has an accessible name without a visible label.

Use native buttons for toolbar controls whenever possible. QalmaCommand targets button[qalmaCommand] specifically.

Toolbar labels

<qalma-toolbar label="Text formatting">
  <button type="button" qalmaCommand="toggleBold">Bold</button>
  <button type="button" qalmaCommand="toggleItalic">Italic</button>
</qalma-toolbar>

If a page has multiple toolbars, give each one a specific label.

Active and disabled state

QalmaCommand connects command state to native button semantics:

<button type="button" qalmaCommand="toggleBold">
  Bold
</button>

When toggleBold is active, the button gets aria-pressed="true" and .qalma-command-active. When the command cannot run, it is disabled.

Commands without active state do not get aria-pressed; this avoids announcing one-shot actions such as undo as toggles.

Mention and slash command menus are consumer-owned. The plugins provide cancelable DOM events so your menu can own keyboard behavior.

handleSlashCommandKeydown(event: Event): void {
  if (!(event instanceof CustomEvent)) {
    return;
  }

  if (event.detail.key === 'ArrowDown') {
    this.moveActiveOption(1);
    event.preventDefault();
  }
}

If your handler calls preventDefault() on the custom event, Qalma prevents the original editor keydown too.

Use normal ARIA patterns in your menu component. The docs playground uses a role="listbox" container, role="option" buttons, aria-selected, roving tabindex, and mouse-down selection preservation.

For link preview and edit UI, use dialog or popover semantics in your app. The playground link popover uses role="dialog" and aria-label="Link preview", then calls setLink, selectLink, and unsetLink on the editor controller.

Styling focus

Do not remove focus indicators without replacing them. Qalma does not style focus rings for you.

.toolbar button:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}