Skip to content

merge release-8.8.16 - #31305

Merged
brandyscarney merged 10 commits into
8.8.xfrom
release-8.8.16
Jul 29, 2026
Merged

merge release-8.8.16#31305
brandyscarney merged 10 commits into
8.8.xfrom
release-8.8.16

Conversation

@brandyscarney

Copy link
Copy Markdown
Member

v8.8.16

ShaneK and others added 10 commits July 22, 2026 14:53
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[github/codeql-action](https://redirect.github.com/github/codeql-action)
| action | patch | `v4.37.1` → `v4.37.3` |

---

### Release Notes

<details>
<summary>github/codeql-action (github/codeql-action)</summary>

###
[`v4.37.3`](https://redirect.github.com/github/codeql-action/releases/tag/v4.37.3)

[Compare
Source](https://redirect.github.com/github/codeql-action/compare/v4.37.2...v4.37.3)

No user facing changes.

###
[`v4.37.2`](https://redirect.github.com/github/codeql-action/releases/tag/v4.37.2)

[Compare
Source](https://redirect.github.com/github/codeql-action/compare/v4.37.1...v4.37.2)

- The new address format for the `config-file` input that was introduced
in CodeQL Action 4.37.0 is now enabled by default. In addition to the
format described there, the `remote=` prefix can now be used to
explicitly indicate that the input refers to a remote file. All previous
input formats continue to be accepted as well.
[#&#8203;4023](https://redirect.github.com/github/codeql-action/pull/4023)
- The CodeQL Action can now make use of [configured private
registries](https://docs.github.com/en/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries)
in Default Setup to retrieve CodeQL configuration files from remote
repositories that require authentication. This will allow customers to
store their CodeQL configuration in a single repository that can then be
referenced by Default Setup workflows in other repositories. We expect
to roll this and other, related changes out to everyone in July.
[#&#8203;4007](https://redirect.github.com/github/codeql-action/pull/4007)

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - "every weekday before 11am"
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNzUuMiIsInVwZGF0ZWRJblZlciI6IjQzLjI3NS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Issue number: internal

---------

## What is the current behavior?
When a sheet modal uses `handleBehavior="cycle"`, the host element is
focusable (`tabIndex=0`) and `onModalFocus` redirects focus to the drag
handle whenever the host is focused. `present()` moves focus to the
`.modal-wrapper` (the `role="dialog"` element) inside the shadow DOM,
but that focus event is retargeted to the host, so `onModalFocus` sees
`ev.target === el` and treats it as a direct host focus. It then bounces
focus onto the handle.

This is latent on the default `handleBehavior="none"` (the host isn't
focusable, so the redirect never runs), but reproduces on any sheet
modal that opts into `cycle`.

## What is the new behavior?
`onModalFocus` now redirects to the handle only when the host itself was
focused directly, detected by `el.shadowRoot?.activeElement` being
`null`. When `present()` focuses the dialog wrapper, `activeElement` is
the wrapper (not null), so the redirect is skipped and the dialog keeps
focus. Tabbing into the modal from outside still lands on the handle,
since the host is the focused element in that case.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

## Other information
Related to the dialog focus work in #31260 . That change is correct
under the default `handleBehavior`, but the `cycle` path was not covered
until now. Adds an e2e test to `utils/test/overlays/overlays.e2e.ts`
that presents a sheet modal with `handle-behavior="cycle"` and asserts
focus stays on the wrapper.

The same fix ships on the major-9.0 sync (#31290), where `cycle` is the
default and this bug is hit on every sheet modal.

Preview (sheet modal test page):
- iOS:
https://ionic-framework-git-fix-modal-focus-cycle-ionic1.vercel.app/src/components/modal/test/sheet?ionic:mode=ios
- MD:
https://ionic-framework-git-fix-modal-focus-cycle-ionic1.vercel.app/src/components/modal/test/sheet?ionic:mode=md
This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [chalk](https://redirect.github.com/chalk/chalk) | [`^5.3.0` →
`^6.0.0`](https://renovatebot.com/diffs/npm/chalk/5.6.2/6.0.0) |
![age](https://developer.mend.io/api/mc/badges/age/npm/chalk/6.0.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/chalk/5.6.2/6.0.0?slim=true)
|

---

### Release Notes

<details>
<summary>chalk/chalk (chalk)</summary>

###
[`v6.0.0`](https://redirect.github.com/chalk/chalk/compare/v5.6.2...661317e6f91fe7c90306c2c48ea9354562ee9146)

[Compare
Source](https://redirect.github.com/chalk/chalk/compare/v5.6.2...v6.0.0)

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - "every weekday before 11am"
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yODAuMCIsInVwZGF0ZWRJblZlciI6IjQzLjI4MC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
…when focused (#31276)

Issue number: resolves #30401

---------
## What is the current behavior?
The floating label and placeholder on `ion-select` overlap when focused
without a value

## What is the new behavior?
The placeholder is not shown when a floating label select is focused, as
that space is taken up by the label

## Does this introduce a breaking change?

- [ ] Yes
- [x] No
Issue number: internal

---------

## What is the current behavior?

The shared `dragElementBy` Playwright helper
(`core/src/utils/test/playwright/drag-element.ts`, used by every gesture
e2e test) unconditionally runs `await page.evaluate(() =>
window.getSelection()?.removeAllRanges())` between `mouse.down()` and
the drag movement. That line was added in #31260 to clear a Firefox-only
text selection, but the extra `page.evaluate()` is an awaited round-trip
that injects variable latency into the gesture path for all browsers. On
WebKit that latency messes up the gesture's timing-derived `velocityX`,
so the `item-sliding` safe-area screenshot tests in md mode settle a few
pixels off and flake randomly. Since it lives on main, the flake has
propagated to every other branch (next and major-9.0) and causes random
test failures in PRs and nightlies.

## What is the new behavior?

The selection clear now only runs on Firefox, which is the only engine
that needs it (the existing comment already scoped the problem to
Firefox). Chromium and WebKit skip the extra round-trip and get the same
drag timing they had before #31260, so the item settles
deterministically and the flake goes away. This matches the
`browserType().name() === 'webkit'` gate already used elsewhere in the
same file.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

Regression was introduced by #31260 (the `removeAllRanges` line, not the
modal a11y change itself). Verified by running in docker locally several
times.
Issue number: resolves #31296

---------

## What is the current behavior?

`StackController.destroy()` sets `this.containerEl = undefined!`, but a
transition that is still queued behind `wait()` can resolve after the
`ion-router-outlet` was destroyed (interrupted / re-entrant / cancelled
navigation during fast back-navigation). `transition()` then
dereferences the `undefined` element at `if ((containerEl as
any).commit)` and throws:

```
TypeError: undefined is not an object (evaluating 'containerEl.commit')
    at transition
```

Observed at production scale in an Ionic Angular + Capacitor app
(several hundred RUM crash events per week from a single build,
concentrated on rapid back-navigation between nested outlets).

## What is the new behavior?

- `transition()` null-checks `containerEl` (optional chaining) before
probing for `commit`.
- A transition resolving after its outlet was destroyed now takes the
method's existing fallback path and resolves `false`, instead of
throwing an unhandled `TypeError`.
- No behavior change for live outlets.

Regarding tests: there is no existing unit harness for `StackController`
(only the e2e test apps), and the defect is a timing race between a
queued transition and outlet destruction, which is impractical to
reproduce deterministically in e2e. The change is a defensive null-check
on a field that `destroy()` explicitly sets to `undefined` (with a
lint-suppressed non-null assertion). We have run this exact guard in
production via patch-package: the crash class disappears with no
observed regressions.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

## Other information

The unguarded dereference is present in v8.8.13 through latest stable
8.8.15 and `8.8.16-nightly.20260724`.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) | Type |
Update |
|---|---|---|---|---|---|
| [@playwright/test](https://playwright.dev)
([source](https://redirect.github.com/microsoft/playwright)) |
[`^1.61.1` →
`^1.62.0`](https://renovatebot.com/diffs/npm/@playwright%2ftest/1.61.1/1.62.0)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@playwright%2ftest/1.62.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@playwright%2ftest/1.61.1/1.62.0?slim=true)
| devDependencies | minor |
| mcr.microsoft.com/playwright | `v1.61.1` → `v1.62.0` |
![age](https://developer.mend.io/api/mc/badges/age/docker/mcr.microsoft.com%2fplaywright/v1.62.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/docker/mcr.microsoft.com%2fplaywright/v1.61.1/v1.62.0?slim=true)
| final | minor |
| [playwright-core](https://playwright.dev)
([source](https://redirect.github.com/microsoft/playwright)) |
[`^1.61.1` →
`^1.62.0`](https://renovatebot.com/diffs/npm/playwright-core/1.61.1/1.62.0)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/playwright-core/1.62.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/playwright-core/1.61.1/1.62.0?slim=true)
| devDependencies | minor |

---

### Release Notes

<details>
<summary>microsoft/playwright (@&#8203;playwright/test)</summary>

###
[`v1.62.0`](https://redirect.github.com/microsoft/playwright/releases/tag/v1.62.0)

[Compare
Source](https://redirect.github.com/microsoft/playwright/compare/v1.61.1...v1.62.0)

##### 🧱 New component testing model

[Component testing](https://playwright.dev/docs/test-components) moves
to a **stories and galleries** model.
A **story** wraps your component in one specific scenario — hard-coded
props, mock data, providers — and a

**gallery** page that you serve renders stories on demand. The new
[fixtures.mount()](https://playwright.dev/docs/api/class-fixtures#fixtures-mount)
fixture navigates
to the gallery, mounts a story by id, and returns a
[Locator](https://playwright.dev/docs/api/class-locator) scoped to the
story's root element:

```js
test('click should expand', async ({ mount }) => {
  const component = await mount('components/Expandable/Stateful');
  await component.getByRole('button').click();
  await expect(component.getByTestId('expanded')).toHaveValue('true');
});
```

Pass a story type as a template argument to type-check its props, and
use `update(props)` /
`unmount()` on the returned locator to re-render or tear down within a
test.

##### 🛑 Cancel operations with AbortSignal

Most operations and web-first assertions now accept a `signal` option
that takes an

[`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal),
letting you
cancel long-running actions, navigations, waits, and assertions:

```js
const controller = new AbortController();
setTimeout(() => controller.abort(), 1000);

await page.getByRole('button', { name: 'Submit' }).click({ signal: controller.signal });
await expect(page.getByText('Done')).toBeVisible({ signal: controller.signal });
```

Providing a signal does not disable the default timeout; pass `timeout:
0` to disable it.

##### 🖼️ WebP screenshots


[expect(page).toHaveScreenshot()](https://playwright.dev/docs/api/class-pageassertions#page-assertions-to-have-screenshot-1)
and
[expect(locator).toHaveScreenshot()](https://playwright.dev/docs/api/class-locatorassertions#locator-assertions-to-have-screenshot-1)
can now store snapshots in the WebP format — just give the snapshot a
`.webp` name:

```js
// Visual comparisons store the golden snapshot as lossless WebP.
await expect(page).toHaveScreenshot('homepage.webp');

// Standalone screenshots can trade quality for size with lossy WebP.
await page.screenshot({ path: 'homepage.webp', quality: 50 });
```


[page.screenshot()](https://playwright.dev/docs/api/class-page#page-screenshot)
and
[locator.screenshot()](https://playwright.dev/docs/api/class-locator#locator-screenshot)
also accept `webp` as a `type`,
where quality `100` (the default) is lossless and lower values use lossy
compression.

##### 🧩 Custom test filtering with Reporter.preprocess()

New
[reporter.preprocess()](https://playwright.dev/docs/api/class-reporter#reporter-preprocess)
hook runs after the configuration is resolved and before

[reporter.onBegin()](https://playwright.dev/docs/api/class-reporter#reporter-on-begin),
letting a reporter mark individual tests as skipped, excluded,
fixed, or failing through a
[TestRun](https://playwright.dev/docs/api/class-testrun) object:

```js
class MyReporter {
  async preprocess({ config, suite, testRun }) {
    for (const test of suite.allTests()) {
      if (shouldSkip(test))
        testRun.skip(test);
    }
  }
}
```

##### 🔁 Isolated retries

New
[testConfig.retryStrategy](https://playwright.dev/docs/api/class-testconfig#test-config-retry-strategy)
controls when failed tests are retried. The default
`'immediate'` retries as soon as a worker is free; `'isolated'` runs all
retries at the end,
one by one in a single worker, to minimize interference with the rest of
the suite:

```js
// playwright.config.ts
export default defineConfig({
  retries: 2,
  retryStrategy: 'isolated',
});
```

##### New APIs

##### Browser and Context

- New option
[`credentials`](https://playwright.dev/docs/api/class-browsercontext#browser-context-storage-state-option-credentials)
includes the context's virtual WebAuthn
[Credentials](https://playwright.dev/docs/api/class-credentials)
(passkeys) in the storage state, so they can be persisted and re-seeded
into later contexts.

##### Actions

- New `scroll` option (`"auto"` | `"none"`) on actions to opt out of
Playwright's automatic scroll-into-view.

##### Network

- New
[apiResponse.timing()](https://playwright.dev/docs/api/class-apiresponse#api-response-timing)
returns resource timing information for an API response.

##### Evaluation

- New
[locator.waitForFunction()](https://playwright.dev/docs/api/class-locator#locator-wait-for-function)
waits until a function — called with the matching element — returns a
truthy value.
-
[page.evaluate()](https://playwright.dev/docs/api/class-page#page-evaluate)
and related methods now accept functions as evaluate arguments.
-
[page.addInitScript()](https://playwright.dev/docs/api/class-page#page-add-init-script)
/
[browserContext.addInitScript()](https://playwright.dev/docs/api/class-browsercontext#browser-context-add-init-script)
now accept functions as init-script arguments.

##### Command line & MCP

- Playwright now bundles the [Playwright
MCP](https://playwright.dev/docs/getting-started-mcp) server and
[`playwright-cli`](https://playwright.dev/docs/getting-started-cli),
runnable via `npx playwright mcp` and `npx playwright cli`.

##### Reporters

- The HTML report's **Merge files** grouping — previously only a UI
toggle — can now be enabled from the config with the new `mergeFiles`
reporter option:

```js
// playwright.config.ts
export default defineConfig({
  reporter: [['html', { mergeFiles: true }]],
});
```

##### Announcements

- ⚠️ Debian 11 is not supported anymore.

##### Browser Versions

- Chromium 151.0.7922.34
- Mozilla Firefox 153.0
- WebKit 26.5

This version was also tested against the following stable channels:

- Google Chrome 151
- Microsoft Edge 151

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - "every weekday before 11am"
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yODAuMCIsInVwZGF0ZWRJblZlciI6IjQzLjI4MC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: ionitron <hi@ionicframework.com>
@github-actions github-actions Bot added package: core @ionic/core package package: angular @ionic/angular package package: vue @ionic/vue package package: react @ionic/react package labels Jul 29, 2026
@vercel

vercel Bot commented Jul 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ionic-framework Ready Ready Preview Jul 29, 2026 8:52pm

Request Review

@brandyscarney
brandyscarney marked this pull request as ready for review July 29, 2026 20:59
@brandyscarney
brandyscarney requested a review from a team as a code owner July 29, 2026 20:59
@brandyscarney
brandyscarney requested review from ShaneK and removed request for a team July 29, 2026 20:59
@brandyscarney
brandyscarney merged commit 033f6c7 into 8.8.x Jul 29, 2026
97 checks passed
@brandyscarney
brandyscarney deleted the release-8.8.16 branch July 29, 2026 20:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

package: angular @ionic/angular package package: core @ionic/core package package: react @ionic/react package package: vue @ionic/vue package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants