Skip to content

iOS: Keep taps into the post title out of the canvas stops - #85483

Draft
ellatrix wants to merge 1 commit into
trunkfrom
fix/ios-title-tap-canvas-stop
Draft

ellatrix wants to merge 1 commit into
trunkfrom
fix/ios-title-tap-canvas-stop

Conversation

@ellatrix

Copy link
Copy Markdown
Member

What?

See wordpress-mobile/GutenbergKit#821

Makes the two canvas stops (the "Editor canvas" focus elements before and after the canvas) unselectable, so iOS can't place the caret in them.

Why?

In a canvas without an iframe, like GutenbergKit's, tapping the post title while a paragraph is selected on iOS shows the caret in the title, but typed text goes nowhere.

The canvas stops span the whole canvas with pointer-events: none (#82354). While a paragraph is selected the canvas is the editing host, so the tap moves focus from the canvas to the title. After that focus change, iOS places the caret at the tap point with a hit test that ignores pointer-events, finds the stop on top of the title, and the selection ends up outside any editable element.

With an iframe the stops live in the parent document, outside the canvas document, so the post editor in wp-admin is not affected.

How?

Adds user-select: none (and the -webkit- prefix Safari needs for inline styles) to the stops' shared style. Text selection skips them; they keep their size, focus behaviour and hint.

Testing Instructions

  1. Run GutenbergKit's editor (no iframe) with this build in an iOS simulator, with a title and two paragraphs.
  2. Tap a paragraph, then tap the title and type. The text goes into the title.
  3. Tap the other paragraph and type, then the title again. Each tap moves the caret where tapped and the text lands there.

On trunk, step 2 types nothing.

Testing Instructions for Keyboard

No change: the stops are still focusable with Tab, and Escape still parks focus on the stop with its hint.

Use of AI Tools

Investigated and written with Claude Code: reproduced in an iOS simulator running GutenbergKit's editor with an XCUITest that taps and types, traced the selection, and confirmed hiding the stops or making them unselectable fixes it. Not covered by a test here, since the iOS tests use the iframed post editor where the bug doesn't occur.

🤖 Generated with Claude Code

The canvas stops span the canvas with pointer-events: none. iOS places
the caret at a tap ignoring pointer-events, so in a canvas without an
iframe a tap into the post title landed in a stop and typing was lost.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the [Package] Block editor /packages/block-editor label Oct 23, 2026
@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

🤖 PR meta 🤖

Preview in WordPress Playground

🏷️ Labels

This pull request needs exactly one label indicating its type, and has 0.

  • Required: any label starting with [Type].
  • Found: none.

Read more about Type labels in Gutenberg. If you cannot add labels yourself, a reviewer can do it for you.

📦 Bundle size

Size Change: +14 B (0%)

Total Size: 9.07 MB

📦 View Changed
Filename Size Change
build/scripts/block-editor/index.min.js 606 kB +14 B (0%)

6e90064 Run

⚡ Performance

Show the results

Client side metrics exclude the server response time.

front-end-block-theme

Metric a615976 trunk % Change
timeToFirstByte 53 ms +13.77% -2.74% 54.25 ms +14.84% -4.06% -2.3%
largestContentfulPaint 88 ms +9.09% -2.27% 92 ms +8.7% -8.7% -4.35%
lcpMinusTtfb 33.7 ms +4.6% -2.82% 34.65 ms +15.3% -6.93% -2.74%
wpBeforeTemplate 28.59 ms +20.39% -2.1% 28.46 ms +21.57% -0.6% 0.46%
wpTemplate 20.73 ms +2.94% -3.62% 20.91 ms +4.5% -3.73% -0.86%
wpTotal 49.39 ms +13.75% -2.98% 50.66 ms +14.61% -4.22% -2.51%
wpMemoryUsage 7.68 MB +0% -0% 7.64 MB +0% -0% 0.43%
wpDbQueries 16 +0% -0% 16 +0% -0% 0%

front-end-classic-theme

Metric a615976 trunk % Change
timeToFirstByte 41.15 ms +5.83% -0.85% 45.25 ms +3.65% -0.55% -9.06%
largestContentfulPaint 88 ms +4.55% -0% 100 ms +0% -0% -12%
lcpMinusTtfb 47.15 ms +0.95% -0.53% 54.75 ms +0.46% -0.64% -13.88%
wpBeforeTemplate 26.31 ms +3.76% -0.95% 26.15 ms +2.41% -1.11% 0.61%
wpTemplate 12 ms +4.83% -1.42% 15.96 ms +1.88% -0.69% -24.81%
wpTotal 38.51 ms +5.45% -1.17% 42.42 ms +3.63% -0.9% -9.22%
wpMemoryUsage 6.26 MB +0% -0% 6.33 MB +0% -0% -1.22%
wpDbQueries 9 +0% -0% 13 +0% -0% -30.77%

media-processing

Metric a615976 trunk % Change
mediaProcessingJpeg 400.27 ms +0.91% -1.46% 401.94 ms +0.45% -0.98% -0.42%
mediaProcessingAvif 6108.22 ms +0.04% -0.54% 6068.81 ms +0.12% -0.06% 0.65%
mediaProcessingJpegToAvif 4226.26 ms +0.11% -0.44% 4195.91 ms +0.74% -0.12% 0.72%

media-upload

Metric a615976 trunk % Change
jpegUploadProcessing 1440.23 ms +37.71% -2.17% 1427.65 ms +0.28% -0.69% 0.88%
pngUploadProcessing 202.82 ms +5.22% -16.21% 175.24 ms +36.56% -3.29% 15.74%
largeJpegUploadProcessing 1406.9 ms +0.91% -0.47% 1414.24 ms +0.26% -0.54% -0.52%
multipleImageUploadProcessing 1575.59 ms +1.8% -0.99% 1573.24 ms +30.28% -0.59% 0.15%

post-editor

Metric a615976 trunk % Change
serverResponse 263.74 ms +5.23% -4.73% 294.14 ms +0.22% -1.63% -10.34%
firstPaint 300.29 ms +5.67% -22.3% 251.13 ms +33.58% -24.09% 19.58%
domContentLoaded 745.66 ms +4.67% -2.67% 805.93 ms +5.83% -4.47% -7.48%
loaded 746.49 ms +4.65% -2.66% 806.82 ms +5.86% -4.44% -7.48%
firstContentfulPaint 310.62 ms +15.55% -3.91% 376.63 ms +5% -10.93% -17.53%
firstBlock 2101.01 ms +2.33% -1.51% 2213.24 ms +4.92% -1.13% -5.07%
type 13.57 ms +1.03% -0.37% 14.57 ms +5.15% -2.06% -6.86%
typeWithoutInspector 14.49 ms +3.52% -6.35% 13.7 ms +6.86% -2.55% 5.77%
typeWithTopToolbar 16.86 ms +2.79% -4.33% 18.4 ms +6.3% -2.83% -8.37%
typeContainer 6.55 ms +10.38% -5.65% 6.54 ms +3.21% -5.5% 0.15%
focus 77.32 ms +3.82% -6.13% 80.86 ms +9.52% -1.6% -4.38%
firstFocus 149.66 ms +0% -0% 152.27 ms +0% -0% -1.71%
selectAll 365.19 ms +0.44% -1.21% 367.49 ms +3.85% -0.43% -0.63%
listViewOpen 49.39 ms +11.86% -6.82% 53.68 ms +4.99% -8.59% -7.99%
inserterOpen 28.15 ms +3.73% -3.09% 28.43 ms +13.4% -10.66% -0.98%
inserterHover 9.72 ms +7.3% -5.04% 9.33 ms +5.79% -2.68% 4.18%
inserterSearch 6.93 ms +6.2% -7.65% 6.98 ms +13.32% -8.6% -0.72%
loadPatterns 448.18 ms +4% -2.75% 452.18 ms +6.91% -2.23% -0.88%
wpTotal 256.91 ms +5.51% -4.81% 286.19 ms +0.45% -1.21% -10.23%
wpMemoryUsage 14.71 MB +0% -0% 14.68 MB +0% -0% 0.24%
wpDbQueries 55 +0% -0% 55 +0% -0% 0%

site-editor

Metric a615976 trunk % Change
serverResponse 304.2 ms +9.9% -4.16% 309.54 ms +5.45% -6.46% -1.73%
firstPaint 213.96 ms +14.14% -19.38% 213.04 ms +31.04% -12.72% 0.43%
domContentLoaded 989.95 ms +1.44% -0.81% 978.09 ms +3.46% -1.31% 1.21%
loaded 990.94 ms +1.47% -0.79% 979.16 ms +3.47% -1.31% 1.2%
firstContentfulPaint 408.7 ms +3.48% -1.06% 399.89 ms +3.14% -13.86% 2.2%
firstBlock 3512.85 ms +0.44% -0.27% 3496.93 ms +0.69% -0.77% 0.46%
type 16.14 ms +3.78% -3.9% 16.07 ms +1.06% -4.48% 0.44%
navigate 88.53 ms +19.82% -1.42% 93 ms +11.02% -6.46% -4.81%
loadPatterns 961.41 ms +4.28% -9.9% 1138.47 ms +8.68% -7.22% -15.55%
loadPages 1041.92 ms +1.29% -3.84% 1045.02 ms +5.39% -3.45% -0.3%
wpTotal 296.17 ms +10.09% -4.35% 301.27 ms +5.58% -6.62% -1.69%
wpMemoryUsage 12.73 MB +0% -0% 12.69 MB +0% -0% 0.28%
wpDbQueries 44 +2.27% -0% 44.5 +1.12% -1.12% -1.12%

6e90064 Run

🏁 Flaky tests

Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

Custom Completer: should allow newlines after multiple option completions in /test/e2e/specs/editor/various/autocomplete-and-mentions.spec.js, passed after 1 failed attempt.
Error: expect(received).toBe(expected) // Object.is equality

- Expected  - 3
+ Received  + 3

  <!-- wp:paragraph -->
  <p>🫐 test</p>
  <!-- /wp:paragraph -->

  <!-- wp:paragraph -->
- <p>🫐 test</p>
+ <p>🍎 test</p>
  <!-- /wp:paragraph -->

  <!-- wp:paragraph -->
- <p>🫐 test</p>
+ <p>🍎 test</p>
  <!-- /wp:paragraph -->

  <!-- wp:paragraph -->
- <p>🫐 test</p>
+ <p>🍎 test</p>
  <!-- /wp:paragraph -->

  <!-- wp:paragraph -->
  <p></p>
  <!-- /wp:paragraph -->

Call Log:
- Timeout 5000ms exceeded while waiting on the predicate
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/autocomplete-and-mentions.spec.js:466:6
Custom Completer: should not insert disabled options in /test/e2e/specs/editor/various/autocomplete-and-mentions.spec.js, passed after 1 failed attempt.
Error: expect(received).toBe(expected) // Object.is equality

- Expected  - 1
+ Received  + 1

  <!-- wp:paragraph -->
- <p>Sorry, we are all out of ~g grapes.</p>
+ <p>Sorry, we are all out of 🍎 grapes.</p>
  <!-- /wp:paragraph -->

Call Log:
- Timeout 5000ms exceeded while waiting on the predicate
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/autocomplete-and-mentions.spec.js:391:7
Regression: updating a specific option will only change its value and will not corrupt others in /test/e2e/specs/editor/various/core-settings.spec.js, passed after 1 failed attempt.
Error: expect(received).toStrictEqual(expected) // deep equality

- Expected  - 1
+ Received  + 1

  Array [
    "rewrite_rules",
-   "SERIALIZED DATA",
+   "",
  ]
    at forEach (/home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/core-settings.spec.js:46:26)
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/core-settings.spec.js:43:35
Undo restores the post selection when another synced entity is loaded (RTC WebSocket) in /test/e2e/specs/editor/collaboration/collaboration-undo-redo.spec.ts, passed after 1 failed attempt.
Error: expect(received).toMatchObject(expected)

- Expected  - 2
+ Received  + 2

  Object {
    "attributeKey": "content",
    "blockIndex": 0,
    "content": "abcdef",
-   "endOffset": 3,
-   "offset": 3,
+   "endOffset": 6,
+   "offset": 6,
  }

Call Log:
- Timeout 5000ms exceeded while waiting on the predicate
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/collaboration/collaboration-undo-redo.spec.ts:363:5
Undo restores the post selection when another synced entity is loaded in /test/e2e/specs/editor/collaboration/collaboration-undo-redo.spec.ts, passed after 1 failed attempt.
Error: expect(received).toMatchObject(expected)

- Expected  - 2
+ Received  + 2

  Object {
    "attributeKey": "content",
    "blockIndex": 0,
    "content": "abcdef",
-   "endOffset": 3,
-   "offset": 3,
+   "endOffset": 6,
+   "offset": 6,
  }

Call Log:
- Timeout 5000ms exceeded while waiting on the predicate
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/collaboration/collaboration-undo-redo.spec.ts:363:5
should be immediately saved on indentation in /test/e2e/specs/editor/blocks/list.spec.js, passed after 1 failed attempt.
Error: expect(received).toBe(expected) // Object.is equality

- Expected  - 1
+ Received  + 1

@@ -1,8 +1,8 @@
  <!-- wp:list -->
  <ul class="wp-block-list"><!-- wp:list-item -->
- <li>one<!-- wp:list -->
+ <li>ne<!-- wp:list -->
  <ul class="wp-block-list"><!-- wp:list-item -->
  <li></li>
  <!-- /wp:list-item --></ul>
  <!-- /wp:list --></li>
  <!-- /wp:list-item --></ul>

Call Log:
- Timeout 5000ms exceeded while waiting on the predicate
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/blocks/list.spec.js:694:52
should change the indented list type in /test/e2e/specs/editor/blocks/list.spec.js, passed after 1 failed attempt.
TimeoutError: locator.click: Timeout 10000ms exceeded.
Call log:
  - waiting for locator('role=toolbar[name="Block tools"i]').locator('role=button[name="Indent"]')

    at Editor.clickBlockToolbarButton (/home/runner/work/gutenberg/gutenberg/packages/e2e-test-utils-playwright/src/editor/click-block-toolbar-button.ts:17:15)
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/blocks/list.spec.js:727:3
should format text across blocks in /test/e2e/specs/editor/various/multi-block-selection.spec.js, passed after 1 failed attempt.
Error: expect(received).toMatchObject(expected)

- Expected  - 1
+ Received  + 1

@@ -1,9 +1,9 @@
  Array [
    Object {
      "attributes": Object {
-       "content": "ab",
+       "content": "b",
      },
      "name": "core/paragraph",
    },
    Object {
      "attributes": Object {

Call Log:
- Timeout 5000ms exceeded while waiting on the predicate
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/multi-block-selection.spec.js:2170:41
should gradually multi-select in /test/e2e/specs/editor/various/multi-block-selection.spec.js, passed after 1 failed attempt.
Error: expect(received).toMatchObject(expected)

- Expected  - 3
+ Received  + 7

  Array [
    Object {
-     "name": "core/column",
+     "attributes": Object {
+       "content": "1",
+       "dropCap": false,
      },
-   Object {
-     "name": "core/column",
+     "clientId": "58df1cf1-f311-410f-9cfb-a91f1b97c995",
+     "innerBlocks": Array [],
+     "isValid": true,
+     "name": "core/paragraph",
    },
  ]

Call Log:
- Timeout 5000ms exceeded while waiting on the predicate
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/multi-block-selection.spec.js:1151:5
should indent and outdent multi-selected items with Tab in /test/e2e/specs/editor/blocks/list.spec.js, passed after 1 failed attempt.
Error: expect(received).toBe(expected) // Object.is equality

- Expected  - 1
+ Received  + 1

@@ -1,8 +1,8 @@
  <!-- wp:list -->
  <ul class="wp-block-list"><!-- wp:list-item -->
- <li>one<!-- wp:list -->
+ <li>ne<!-- wp:list -->
  <ul class="wp-block-list"><!-- wp:list-item -->
  <li>two</li>
  <!-- /wp:list-item -->

  <!-- wp:list-item -->

Call Log:
- Timeout 5000ms exceeded while waiting on the predicate
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/blocks/list.spec.js:1118:52
should merge a following sibling list into the outermost list with Delete from a nested item (#77245) in /test/e2e/specs/editor/blocks/list.spec.js, passed after 1 failed attempt.
Error: expect(received).toMatchObject(expected)

- Expected  - 2
+ Received  + 2

@@ -8,11 +8,11 @@
          "innerBlocks": Array [
            Object {
              "innerBlocks": Array [
                Object {
                  "attributes": Object {
-                   "content": "b‸",
+                   "content": "b",
                  },
                  "name": "core/list-item",
                },
              ],
              "name": "core/list",
@@ -25,11 +25,11 @@
    },
    Object {
      "innerBlocks": Array [
        Object {
          "attributes": Object {
-           "content": "1",
+           "content": "‸1",
          },
          "innerBlocks": Array [
            Object {
              "innerBlocks": Array [
                Object {

Call Log:
- Timeout 5000ms exceeded while waiting on the predicate
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/blocks/list.spec.js:2854:41
should replace the selection across blocks with an inline image in /test/e2e/specs/editor/various/multi-block-selection.spec.js, passed after 1 failed attempt.
Error: expect(received).toMatchObject(expected)

- Expected  - 1
+ Received  + 1

@@ -1,9 +1,9 @@
  Array [
    Object {
      "attributes": Object {
-       "content": "ab",
+       "content": "b",
      },
      "name": "core/paragraph",
    },
    Object {
      "attributes": Object {

Call Log:
- Timeout 5000ms exceeded while waiting on the predicate
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/multi-block-selection.spec.js:2372:41
should restore an older revision in /test/e2e/specs/editor/various/revisions.spec.js, passed after 1 failed attempt.
Error: expect(received).toMatchObject(expected)

- Expected  - 1
+ Received  + 1

  Array [
    Object {
      "attributes": Object {
-       "content": "Original content - Updated content - Autosaved",
+       "content": "Original content",
      },
      "name": "core/paragraph",
    },
  ]

Call Log:
- Timeout 5000ms exceeded while waiting on the predicate
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/revisions.spec.js:146:5
should update the URL from the last navigation if only varies in the URL fragment in /test/e2e/specs/interactivity/router-navigate.spec.ts, passed after 1 failed attempt.
Error: expect(locator).toHaveText(expected) failed

Locator:  getByTestId('title')
Expected: "Link 1"
Received: "Main"
Timeout:  5000ms

Call log:
  - Expect "toHaveText" getByTestId('title') with timeout 5000ms
  - waiting for getByTestId('title')
    14 × locator resolved to <h2 data-testid="title">Main</h2>
       - unexpected value "Main"

    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/interactivity/router-navigate.spec.ts:160:25

6e90064 Run

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Package] Block editor /packages/block-editor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant