Callout

Floating callout panels anchored to a DOM element (used by annotations and custom UI).

Access:

app.callout
app.getModule('callout')
app.invoke('callout.method', …)

isOpen#

Returns whether the callout panel is currently open.

Returns: boolean

app.callout.isOpen();

open#

Opens (or reopens) the callout near config.anchor. Renders optional title and custom nodes in the body, choice items as buttons in the middle, and footer actions. Emits callout:open. Outside click, Escape, and editor blur close it.

Parameters:

  • config (object) — callout content and placement
    • anchor (HTMLElement) — DOM element to position under (required for placement; in iframe mode its rect is mapped to the parent viewport)
    • title (string) — optional heading text shown at the top of the body
    • nodes (Node | string | Array) — custom body content: a Node, an HTML string, or an array of either — strings are wrapped in .rx-callout-text via innerHTML
    • items (Array) — choice buttons ({ title|label, active?, command?, params?, close? }[]); click emits callout:item, then app.invoke(command, { ...params, text, anchor }, payload) when command is set; closes unless close: false
    • actions (Array) — footer buttons ({ title|label, role?, command?, params?, close? }[]); role adds class rx-callout-action-<role>; click emits callout:action, then invokes command with params; closes unless close: false
const note = document.createElement('p');
note.textContent = 'Pick a replacement:';

app.callout.open({
    anchor: selectedEl,
    title: 'Wording',
    // Custom body: Node(s) and/or HTML strings
    nodes: [
        note,
        '<p class="hint">Suggestions come from your data.</p>'
    ],
    // Choice buttons (middle section)
    items: [
        {
            title: 'utilize → use',
            active: true,
            command: 'annotation.replaceText',
            params: { text: 'use' }
        },
        {
            title: 'utilize → employ',
            command: 'annotation.replaceText',
            params: { text: 'employ' },
            // close: false  // keep open after click
        }
    ],
    // Footer actions
    actions: [
        {
            title: 'Ignore',
            role: 'ignore',
            command: 'annotation.ignoreChoice'
        },
        {
            title: 'Ignore all',
            role: 'ignore-all',
            command: 'annotation.ignoreAll',
            params: { kind: 'wording' }
        }
    ]
});

// Listen without using command:
app.on('callout:item', ({ item, anchor }) => {
    console.log(item.title, anchor);
});

close#

Hides the callout, clears body/items/actions, and emits callout:close.

Parameters:

  • reason (any) — close reason string passed to the event (e.g. 'api', 'item', 'action', 'outsideClick', 'escape', 'blur', 'reopen')
app.callout.close();
app.callout.close({ reason: 'api' });

updatePosition#

Repositions the open callout relative to its current anchor (no-op when closed).

app.callout.updatePosition();