From dcebbf2deaa1b9a30648a9c92b7dc2909c2b5a47 Mon Sep 17 00:00:00 2001 From: Luccas Correa Date: Tue, 10 Feb 2026 15:49:52 -0300 Subject: [PATCH 1/4] fix: disable context menu in web view mode --- packages/super-editor/src/core/Editor.ts | 9 ++++++++- .../src/core/Editor.webLayout.test.ts | 20 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/packages/super-editor/src/core/Editor.ts b/packages/super-editor/src/core/Editor.ts index 89e2e80e67..b5c8b1e790 100644 --- a/packages/super-editor/src/core/Editor.ts +++ b/packages/super-editor/src/core/Editor.ts @@ -1486,11 +1486,18 @@ export class Editor extends EventEmitter { * Set editor options and update state. */ setOptions(options: Partial = {}): void { - this.options = { + const nextOptions = { ...this.options, ...options, }; + if (nextOptions.viewOptions?.layout === 'web') { + // Web layout mode should not surface the context menu (e.g., on mobile long-press). + nextOptions.disableContextMenu = true; + } + + this.options = nextOptions; + if ((this.options.isNewFile || !this.options.ydoc) && this.options.isCommentsEnabled) { this.options.shouldLoadComments = true; } diff --git a/packages/super-editor/src/core/Editor.webLayout.test.ts b/packages/super-editor/src/core/Editor.webLayout.test.ts index e9456d1175..3bdde82c02 100644 --- a/packages/super-editor/src/core/Editor.webLayout.test.ts +++ b/packages/super-editor/src/core/Editor.webLayout.test.ts @@ -76,6 +76,26 @@ describe('Editor Web Layout Mode', () => { }); }); + describe('context menu behavior', () => { + it('forces disableContextMenu when viewOptions.layout is "web"', () => { + const editor = createTestEditor({ + viewOptions: { layout: 'web' }, + disableContextMenu: false, + }); + + expect(editor.options.disableContextMenu).toBe(true); + }); + + it('respects disableContextMenu when viewOptions.layout is "print"', () => { + const editor = createTestEditor({ + viewOptions: { layout: 'print' }, + disableContextMenu: false, + }); + + expect(editor.options.disableContextMenu).toBe(false); + }); + }); + describe('getMaxContentSize()', () => { describe('web layout mode', () => { it('returns empty object to skip image constraints', async () => { From 9cf7271b1be12c2ba9a5e0d1c5f358ef2b1bc4f4 Mon Sep 17 00:00:00 2001 From: Luccas Correa Date: Tue, 10 Feb 2026 15:55:02 -0300 Subject: [PATCH 2/4] docs: update docs around context menu --- apps/docs/core/superdoc/configuration.mdx | 1 + apps/docs/modules/context-menu.mdx | 4 +++- packages/superdoc/src/dev/components/SuperdocDev.vue | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/docs/core/superdoc/configuration.mdx b/apps/docs/core/superdoc/configuration.mdx index ec90f44063..5b83d34646 100644 --- a/apps/docs/core/superdoc/configuration.mdx +++ b/apps/docs/core/superdoc/configuration.mdx @@ -245,6 +245,7 @@ new SuperDoc({ Use `'web'` for mobile devices and WCAG AA reflow compliance (Success Criterion 1.4.10). When set to `'web'`, the layout engine is automatically disabled. + Web layout also forces `disableContextMenu: true` to prevent long-press context menus on mobile. ```javascript viewOptions: { layout: 'web' } diff --git a/apps/docs/modules/context-menu.mdx b/apps/docs/modules/context-menu.mdx index 26675f0bae..ebf5c2745a 100644 --- a/apps/docs/modules/context-menu.mdx +++ b/apps/docs/modules/context-menu.mdx @@ -7,7 +7,8 @@ A contextual command menu triggered by right-clicking. Shows relevant actions ba ## Quick start -The context menu is **enabled by default**. Right-click anywhere in the document to open it. +The context menu is **enabled by default** in print layout. In web layout (`viewOptions.layout = 'web'`), the custom +context menu is disabled to avoid long-press menus on mobile. To disable it: @@ -35,6 +36,7 @@ new SuperDoc({ Top-level option to disable the context menu entirely + Web layout (`viewOptions.layout = 'web'`) forces this to `true`. diff --git a/packages/superdoc/src/dev/components/SuperdocDev.vue b/packages/superdoc/src/dev/components/SuperdocDev.vue index 4f67460055..46026e16c6 100644 --- a/packages/superdoc/src/dev/components/SuperdocDev.vue +++ b/packages/superdoc/src/dev/components/SuperdocDev.vue @@ -180,7 +180,7 @@ const init = async () => { documentMode: 'editing', licenseKey: 'community-and-eval-agplv3', telemetry: { - enabled: false, + enabled: true, }, comments: { visible: true, From 3763b9eea08998e055bf4d9f810930d8ab4fb02d Mon Sep 17 00:00:00 2001 From: Luccas Correa Date: Tue, 10 Feb 2026 16:44:37 -0300 Subject: [PATCH 3/4] fix: reset context menu disable when leaving web layout --- packages/super-editor/src/core/Editor.ts | 19 ++++++++++++++- .../src/core/Editor.webLayout.test.ts | 23 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/packages/super-editor/src/core/Editor.ts b/packages/super-editor/src/core/Editor.ts index b5c8b1e790..22afb1846c 100644 --- a/packages/super-editor/src/core/Editor.ts +++ b/packages/super-editor/src/core/Editor.ts @@ -253,6 +253,7 @@ export class Editor extends EventEmitter { * Guard flag to prevent double-tracking document open */ #documentOpenTracked = false; + #contextMenuForcedByLayout = false; options: EditorOptions = { element: null, @@ -1486,14 +1487,30 @@ export class Editor extends EventEmitter { * Set editor options and update state. */ setOptions(options: Partial = {}): void { + const prevLayout = this.options.viewOptions?.layout; + const prevDisableContextMenu = this.options.disableContextMenu; + const disableContextMenuProvided = Object.prototype.hasOwnProperty.call(options, 'disableContextMenu'); const nextOptions = { ...this.options, ...options, }; + const nextLayout = nextOptions.viewOptions?.layout; + const nextDisableContextMenu = disableContextMenuProvided ? options.disableContextMenu : prevDisableContextMenu; - if (nextOptions.viewOptions?.layout === 'web') { + if (nextLayout === 'web') { // Web layout mode should not surface the context menu (e.g., on mobile long-press). nextOptions.disableContextMenu = true; + this.#contextMenuForcedByLayout = nextDisableContextMenu !== true; + } else if (prevLayout === 'web') { + if (this.#contextMenuForcedByLayout && !disableContextMenuProvided) { + nextOptions.disableContextMenu = false; + } else { + nextOptions.disableContextMenu = nextDisableContextMenu; + } + this.#contextMenuForcedByLayout = false; + } else if (disableContextMenuProvided) { + nextOptions.disableContextMenu = nextDisableContextMenu; + this.#contextMenuForcedByLayout = false; } this.options = nextOptions; diff --git a/packages/super-editor/src/core/Editor.webLayout.test.ts b/packages/super-editor/src/core/Editor.webLayout.test.ts index 3bdde82c02..36a8fc5fd8 100644 --- a/packages/super-editor/src/core/Editor.webLayout.test.ts +++ b/packages/super-editor/src/core/Editor.webLayout.test.ts @@ -94,6 +94,29 @@ describe('Editor Web Layout Mode', () => { expect(editor.options.disableContextMenu).toBe(false); }); + + it('resets disableContextMenu when switching from "web" to "print" without explicit override', () => { + const editor = createTestEditor({ + viewOptions: { layout: 'web' }, + }); + + expect(editor.options.disableContextMenu).toBe(true); + + editor.setOptions({ viewOptions: { layout: 'print' } }); + + expect(editor.options.disableContextMenu).toBe(false); + }); + + it('keeps explicit disableContextMenu when switching from "web" to "print"', () => { + const editor = createTestEditor({ + viewOptions: { layout: 'web' }, + disableContextMenu: true, + }); + + editor.setOptions({ viewOptions: { layout: 'print' } }); + + expect(editor.options.disableContextMenu).toBe(true); + }); }); describe('getMaxContentSize()', () => { From 5a1c2e133140138706850ea244442d220ab33741 Mon Sep 17 00:00:00 2001 From: Luccas Correa Date: Wed, 11 Feb 2026 16:15:04 -0300 Subject: [PATCH 4/4] fix: preserve disableContextMenu across web layout toggles --- packages/super-editor/src/core/Editor.ts | 17 ++++++++------ .../src/core/Editor.webLayout.test.ts | 22 +++++++++++++++++++ 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/packages/super-editor/src/core/Editor.ts b/packages/super-editor/src/core/Editor.ts index 22afb1846c..2fdf0d9045 100644 --- a/packages/super-editor/src/core/Editor.ts +++ b/packages/super-editor/src/core/Editor.ts @@ -253,7 +253,7 @@ export class Editor extends EventEmitter { * Guard flag to prevent double-tracking document open */ #documentOpenTracked = false; - #contextMenuForcedByLayout = false; + #disableContextMenuBeforeWebLayout: boolean | undefined = undefined; options: EditorOptions = { element: null, @@ -1498,19 +1498,22 @@ export class Editor extends EventEmitter { const nextDisableContextMenu = disableContextMenuProvided ? options.disableContextMenu : prevDisableContextMenu; if (nextLayout === 'web') { + if (prevLayout !== 'web') { + this.#disableContextMenuBeforeWebLayout = nextDisableContextMenu; + } else if (disableContextMenuProvided) { + this.#disableContextMenuBeforeWebLayout = nextDisableContextMenu; + } // Web layout mode should not surface the context menu (e.g., on mobile long-press). nextOptions.disableContextMenu = true; - this.#contextMenuForcedByLayout = nextDisableContextMenu !== true; } else if (prevLayout === 'web') { - if (this.#contextMenuForcedByLayout && !disableContextMenuProvided) { - nextOptions.disableContextMenu = false; - } else { + if (disableContextMenuProvided) { nextOptions.disableContextMenu = nextDisableContextMenu; + } else { + nextOptions.disableContextMenu = this.#disableContextMenuBeforeWebLayout ?? false; } - this.#contextMenuForcedByLayout = false; + this.#disableContextMenuBeforeWebLayout = undefined; } else if (disableContextMenuProvided) { nextOptions.disableContextMenu = nextDisableContextMenu; - this.#contextMenuForcedByLayout = false; } this.options = nextOptions; diff --git a/packages/super-editor/src/core/Editor.webLayout.test.ts b/packages/super-editor/src/core/Editor.webLayout.test.ts index 36a8fc5fd8..485d3a66c3 100644 --- a/packages/super-editor/src/core/Editor.webLayout.test.ts +++ b/packages/super-editor/src/core/Editor.webLayout.test.ts @@ -117,6 +117,28 @@ describe('Editor Web Layout Mode', () => { expect(editor.options.disableContextMenu).toBe(true); }); + + it('defaults to enabled context menu after leaving web when created in web mode', () => { + const editor = createTestEditor({ + viewOptions: { layout: 'web' }, + }); + + editor.setOptions({ disableContextMenu: true }); + editor.setOptions({ viewOptions: { layout: 'print' } }); + + expect(editor.options.disableContextMenu).toBe(true); + }); + + it('does not override disableContextMenu when switching layouts if it was explicitly set before', () => { + const editor = createTestEditor({ + viewOptions: { layout: 'web' }, + }); + + editor.setOptions({ disableContextMenu: false }); + editor.setOptions({ viewOptions: { layout: 'print' } }); + + expect(editor.options.disableContextMenu).toBe(false); + }); }); describe('getMaxContentSize()', () => {