Skip to content

chore(git): sync with main#31290

Merged
ShaneK merged 17 commits into
major-9.0from
sync-major-9.0-with-main
Jul 23, 2026
Merged

chore(git): sync with main#31290
ShaneK merged 17 commits into
major-9.0from
sync-major-9.0-with-main

Conversation

@ShaneK

@ShaneK ShaneK commented Jul 23, 2026

Copy link
Copy Markdown
Member

Sync major-9.0 with main.

renovate Bot and others added 16 commits July 9, 2026 16:09
This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [@capacitor/core](https://capacitorjs.com)
([source](https://redirect.github.com/ionic-team/capacitor)) | [`8.4.0`
→
`8.4.1`](https://renovatebot.com/diffs/npm/@capacitor%2fcore/8.4.0/8.4.1)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@capacitor%2fcore/8.4.1?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@capacitor%2fcore/8.4.0/8.4.1?slim=true)
|

---

### Release Notes

<details>
<summary>ionic-team/capacitor (@&#8203;capacitor/core)</summary>

###
[`v8.4.1`](https://redirect.github.com/ionic-team/capacitor/blob/HEAD/CHANGELOG.md#841-2026-06-19)

[Compare
Source](https://redirect.github.com/ionic-team/capacitor/compare/8.4.0...8.4.1)

##### Bug Fixes

- **cli:** make SPM dependency patch work on prereleases
([#&#8203;8508](https://redirect.github.com/ionic-team/capacitor/issues/8508))
([6048e90](https://redirect.github.com/ionic-team/capacitor/commit/6048e90171afa0229a3c25b52a23c377c6bb804c))
- **cli:** patch Capacitor SPM dependency version in plugins
([#&#8203;8492](https://redirect.github.com/ionic-team/capacitor/issues/8492))
([28bb2c6](https://redirect.github.com/ionic-team/capacitor/commit/28bb2c687069dfdd6aa7abc866004a1c6388d103))

</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:eyJjcmVhdGVkSW5WZXIiOiI0My4yMzEuMSIsInVwZGF0ZWRJblZlciI6IjQzLjIzMS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

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

---------

## What is the current behavior?
`ionic-react`'s `IonTabBar` tries to reference
`this.props.onIonTabsWillChange` and `this.props.onIonTabsDidChange`,
which do not exist, causing the `onIonTabsWillChange` and
`onIonTabsDidChange` events to never fire.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Update usage of `this.props.onIonTabsWillChange` to
`this.props.tabsContext.tabBarProps.onIonTabsWillChange`
- Update usage of `this.props.onIonTabsDidChange` to
`this.props.tabsContext.tabBarProps.onIonTabsDidChange`
- Add check to make sure `this.props.tabsContext` is truthy before using
it
- `onIonTabsWillChange` and `onIonTabsDidChange` fire as expected

## Does this introduce a breaking change?

- [ ] Yes
- [x] No
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [actions/setup-node](https://redirect.github.com/actions/setup-node) |
action | minor | `v6.4.0` → `v6.5.0` |

---

### Release Notes

<details>
<summary>actions/setup-node (actions/setup-node)</summary>

###
[`v6.5.0`](https://redirect.github.com/actions/setup-node/compare/v6.4.0...v6.5.0)

[Compare
Source](https://redirect.github.com/actions/setup-node/compare/v6.4.0...v6.5.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:eyJjcmVhdGVkSW5WZXIiOiI0My4yNTkuMiIsInVwZGF0ZWRJblZlciI6IjQzLjI1OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [@capacitor/core](https://capacitorjs.com)
([source](https://redirect.github.com/ionic-team/capacitor)) | [`8.4.1`
→
`8.4.2`](https://renovatebot.com/diffs/npm/@capacitor%2fcore/8.4.1/8.4.2)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@capacitor%2fcore/8.4.2?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@capacitor%2fcore/8.4.1/8.4.2?slim=true)
|

---

### Release Notes

<details>
<summary>ionic-team/capacitor (@&#8203;capacitor/core)</summary>

###
[`v8.4.2`](https://redirect.github.com/ionic-team/capacitor/blob/HEAD/CHANGELOG.md#842-2026-07-14)

[Compare
Source](https://redirect.github.com/ionic-team/capacitor/compare/8.4.1...8.4.2)

##### Bug Fixes

- **android:** explicitly grant URI permissions for image capture intent
([#&#8203;8526](https://redirect.github.com/ionic-team/capacitor/issues/8526))
([6f2d328](https://redirect.github.com/ionic-team/capacitor/commit/6f2d3283897a375d09ca9ec8784a9f0d65f0a530))

</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:eyJjcmVhdGVkSW5WZXIiOiI0My4yNTkuMiIsInVwZGF0ZWRJblZlciI6IjQzLjI1OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [actions/setup-node](https://redirect.github.com/actions/setup-node) |
action | major | `v6.5.0` → `v7.0.0` |
| [actions/setup-node](https://redirect.github.com/actions/setup-node) |
action | major | `v6` → `v7` |

---

### Release Notes

<details>
<summary>actions/setup-node (actions/setup-node)</summary>

###
[`v7.0.0`](https://redirect.github.com/actions/setup-node/compare/v6.5.0...v7.0.0)

[Compare
Source](https://redirect.github.com/actions/setup-node/compare/v7.0.0...v7.0.0)

###
[`v7`](https://redirect.github.com/actions/setup-node/compare/v6.5.0...v7.0.0)

[Compare
Source](https://redirect.github.com/actions/setup-node/compare/v6.5.0...v7.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 these
updates 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:eyJjcmVhdGVkSW5WZXIiOiI0My4yNTkuMiIsInVwZGF0ZWRJblZlciI6IjQzLjI1OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
|
[@capacitor/status-bar](https://redirect.github.com/ionic-team/capacitor-plugins)
| [`8.0.2` →
`8.0.3`](https://renovatebot.com/diffs/npm/@capacitor%2fstatus-bar/8.0.2/8.0.3)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@capacitor%2fstatus-bar/8.0.3?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@capacitor%2fstatus-bar/8.0.2/8.0.3?slim=true)
|

---

### Release Notes

<details>
<summary>ionic-team/capacitor-plugins
(@&#8203;capacitor/status-bar)</summary>

###
[`v8.0.3`](https://redirect.github.com/ionic-team/capacitor-plugins/releases/tag/%40capacitor/status-bar%408.0.3)

[Compare
Source](https://redirect.github.com/ionic-team/capacitor-plugins/compare/@capacitor/status-bar@8.0.2...@capacitor/status-bar@8.0.3)

**Note:** Version bump only for package
[@&#8203;capacitor/status-bar](https://redirect.github.com/capacitor/status-bar)

</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:eyJjcmVhdGVkSW5WZXIiOiI0My4yNTkuMiIsInVwZGF0ZWRJblZlciI6IjQzLjI1OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
… enter the modal (#31260)

Issue number: internal

---------

## What is the current behavior?
When a modal is opened with Android TalkBack enabled, the screen reader
cannot enter or navigate the modal's content. On present, focus is moved
to the modal host, but the host is role-less. The `role="dialog"`,
`aria-modal`, and the label live on the inner `.ion-overlay-wrapper` so
assistive technologies have no dialog to land on.

## What is the new behavior?
- `present()` now focuses the overlay's `[role="dialog"]` element (the
wrapper) instead of the role-less host, falling back to the host when
the role is on the host (action-sheet, loading).
- The modal wrapper gets `tabIndex="-1"` so it can receive that
programmatic focus (an element with only `role="dialog"` is not
focusable). Its focus ring is suppressed since the focus is
programmatic, not keyboard-driven.
- Clears text selection when gestures start to prevent Firefox from
interrupting swipe-to-close and sheet gestures.
- Adds an e2e test to `modal/test/a11y/modal.e2e.ts` to verify no
visible outline added to the wrapper.
- Adds e2e tests to `utils/test/overlays/overlays.e2e.ts` to verify the
focus is on the wrapper instead of the host for all modals.
- Fixes Playwright test helper to clear text selection immediately after
`mouse.down()` to prevent the selection from blocking gesture detection
in the test environment.

---------

Co-authored-by: Brandy Smith <brandyscarney@users.noreply.github.com>
Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
…s attachShadow (#30967)

Issue number: related to #29751

## What is the current behavior?

In Angular SSR environments using a server DOM that does not implement
native `attachShadow` (for example Domino), Ionic server hydration can
fail with:

`TypeError: this.attachShadow is not a function`

This occurs in the server hydrate path used by `@ionic/angular-server`
when calling `hydrateDocument(...)` with the current default behavior.

## What is the new behavior?

This PR adds a capability check in
`packages/angular-server/src/ionic-server-module.ts` and applies a
conditional fallback only when `attachShadow` is unavailable:

- if `attachShadow` is supported:
  - keep existing behavior (`clientHydrateAnnotations: false`)
- if `attachShadow` is not supported:
  - use `serializeShadowRoot: 'scoped'`
  - use `clientHydrateAnnotations: true`

This keeps the current behavior for environments with native
`attachShadow`, while providing a compatible SSR path for Domino-like
environments.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

## Other information

The change is intentionally scoped to `@ionic/angular-server`
integration logic and does not modify component behavior or the existing
`excludeComponents` list.

I could not run the full Ionic test/lint suite locally in my current
Windows environment setup, so this PR relies on CI for full validation.

Note: this PR addresses the `attachShadow` SSR crash path in
`@ionic/angular-server` by applying a conditional fallback.

From upstream investigation, there is also a Stencil runtime fix in `>=
4.40.0` related to non-shadow component patching
(`children`/`childNodes`) that may affect Angular client hydration
behavior. So full end-to-end resolution of all symptoms may also depend
on the Stencil bump tracked separately.

Co-authored-by: ShaneK <shane@shanessite.net>
Issue number: FW-6928

---------

<!-- Following up FW-6926: review reusable actions and pin them to
commit SHAs for supply-chain security. -->

## What is the current behavior?

Several third-party GitHub Actions in our workflows and composite
actions
were still referenced by mutable tags (`@v6`/`@v7`/`@v8`/`@v4`). A
mutable
tag can be repointed by the action author — or an attacker who gains
write
access to the action repo — to arbitrary code, which then runs with the
workflow's permissions and secrets (notably in the release pipeline).

## What is the new behavior?

All remaining unpinned third-party actions are now pinned to a
full-length
commit SHA with a `# vX.Y.Z` comment, matching the convention already
used
across the repo (e.g. `actions/checkout@9c091bb… # v7.0.0`). Each action
keeps its current major, pinned to the latest patch of that major. Every
SHA was independently verified against its upstream tag.

File | Action | Pinned to
-- | -- | --
actions/build-angular/action.yml | actions/setup-node | 820762786… #
v7.0.0
actions/upload-archive/action.yml | actions/upload-artifact |
043fb46d1… # v7.0.1
actions/test-core-screenshot/action.yml | actions/upload-artifact |
043fb46d1… # v7.0.1
actions/download-archive/action.yml | actions/download-artifact |
3e5f45b2c… # v8.0.1
actions/update-reference-screenshots/action.yml |
actions/download-artifact | 3e5f45b2c… # v8.0.1
codeql-analysis.yml (init + analyze) | github/codeql-action |
7188fc363… # v4.37.1
conventional-commit.yml | amannn/action-semantic-pull-request |
48f256284… # v6.1.1
label.yml | actions/labeler | b8dd2d9be… # v6.2.0


Local `uses: ./…` composite/reusable refs are intentionally left
unchanged
(same-repo, no external supply-chain risk).

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

No behavioural change — this only pins which upstream commit CI
executes.

## Other information

- No major-version upgrades; that's deferred as a separate maintenance
concern.
- Follow-ups considered but out of scope: a CI guard to block
reintroducing
unpinned actions, and a `github-actions` Dependabot entry to keep the
pins
  bumped.
# Conflicts:
#	core/package-lock.json
#	packages/react-router/package-lock.json
#	packages/react/package-lock.json
#	packages/react/package.json
#	packages/vue-router/package-lock.json
#	packages/vue/package-lock.json
#	packages/vue/package.json
@ShaneK
ShaneK requested a review from a team as a code owner July 23, 2026 12:53
@ShaneK
ShaneK requested a review from thetaPC July 23, 2026 12:53
@vercel

vercel Bot commented Jul 23, 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, Comment Jul 23, 2026 2:20pm

Request Review

@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 23, 2026
When a sheet modal defaults handleBehavior to "cycle" (the new default on
major-9.0), the host becomes focusable and onModalFocus redirects focus to
the drag handle. present() (from #31260) focuses the shadow-DOM dialog
wrapper for screen readers, but that focus event is retargeted to the host
at the shadow boundary, so onModalFocus saw ev.target === el and bounced
focus onto the handle. The wrapper never kept focus, which failed the
"focus the sheet modal wrapper on present" e2e on Firefox.

Guard the redirect on el.shadowRoot.activeElement being null, which is true
only when the host itself was focused directly (e.g. tabbing into the
modal). When present() focuses the wrapper, activeElement is the wrapper, so
the redirect is skipped and the dialog focus is left intact. Tabbing to the
handle from outside still works.
@ShaneK
ShaneK merged commit a334b43 into major-9.0 Jul 23, 2026
94 of 96 checks passed
@ShaneK
ShaneK deleted the sync-major-9.0-with-main branch July 23, 2026 15:00
pull Bot pushed a commit to goldtoad6/ionic-framework that referenced this pull request Jul 23, 2026
…1293)

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 ionic-team#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 (ionic-team#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
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.

6 participants