# Links and context menus

> Configure link behavior and add application actions to the built-in Editor context menu.



The built-in UI can create and edit hyperlinks, show a link popover, and combine SuperDoc's default context menu with application-owned actions.

## Configure both interaction surfaces [#configure-both-interaction-surfaces]

This example keeps the default menu, adds one selection-aware action, and replaces the clicked-link popover with framework-neutral DOM:

```ts
import { SuperDoc, type ContextMenuConfig, type LinkPopoverResolver } from 'superdoc';
import 'superdoc/style.css';

const resolveLinkPopover: LinkPopoverResolver = ({ href }) => ({
  type: 'external',
  render: ({ container, closePopover }) => {
    const link = document.createElement('a');
    link.href = href;
    link.target = '_blank';
    link.rel = 'noopener noreferrer';
    link.textContent = 'Open link';

    const close = document.createElement('button');
    close.type = 'button';
    close.textContent = 'Close';
    close.addEventListener('click', closePopover);
    container.append(link, close);

    return { destroy: () => close.removeEventListener('click', closePopover) };
  },
});

const contextMenu = {
  includeDefaultItems: true,
  customItems: [
    {
      id: 'application-actions',
      items: [
        {
          id: 'copy-selection-to-workflow',
          label: 'Copy selection to workflow',
          showWhen: ({ hasSelection }) => hasSelection,
          action: (_editor, { selectedText }) => void navigator.clipboard.writeText(selectedText),
        },
      ],
    },
  ],
} satisfies ContextMenuConfig;

const superdoc = new SuperDoc({
  selector: '#editor',
  document: '/contract.docx',
  modules: {
    toolbar: { groups: { center: ['link'] } },
    links: { popoverResolver: resolveLinkPopover },
    contextMenu,
  },
});

window.addEventListener('beforeunload', () => superdoc.destroy());

```

`modules.links.popoverResolver` runs synchronously when a link is clicked. Return `default` to use SuperDoc's popover, `none` to suppress it, or `external` to render with your own framework or DOM. The external renderer must return cleanup when it installs listeners or mounts a framework root.

`modules.contextMenu.customItems` adds sections to the built-in right-click and slash menu. `showWhen()` should decide whether an action is relevant from the supplied context. Keep application actions narrow and avoid reconstructing document positions from `selectionStart` or `selectionEnd`; use the Document API and public selection targets for document work.

## Separate navigation from mutation [#separate-navigation-from-mutation]

Opening a link is browser navigation. Creating, changing, and removing hyperlinks are document mutations. The built-in toolbar handles those mutations against the live selection and respects viewing mode. For programmatic hyperlink changes, use the generated Document API hyperlink operations instead of simulating toolbar clicks.

Context-menu visibility is not authorization. Server-side access and collaboration policy remain the application's responsibility.
