Skip to content

merge release-9.0.9 - #31625

Merged
ShaneK merged 13 commits into
9.0.xfrom
release-9.0.9
Oct 21, 2026
Merged

ShaneK merged 13 commits into
9.0.xfrom
release-9.0.9

Conversation

@ShaneK

@ShaneK ShaneK commented Oct 21, 2026

Copy link
Copy Markdown
Member

Release 9.0.9

brandyscarney and others added 13 commits October 14, 2026 12:10
… while it floats (#31567)

Issue number: internal

---------

## What is the current behavior?
An input, select, or textarea with an extremely long overflowing label
with `label-placement="floating"` overflows its container when going
from a resting to a floating state:


https://github.com/user-attachments/assets/7fc7f1e3-07d6-4461-ad63-261f2ebcf57f

## What is the new behavior?


https://github.com/user-attachments/assets/aae95b06-5cdf-4b9e-81ee-48e3e6b3fb39

- The label's `max-width` now transitions along with its `transform`, so
the label reveals more of its text gradually as it scales down instead
of showing its full floating width while still at its resting size.
- With `fill="outline"`, the label stays positioned relative to the
control in both its resting and floating states, so its `max-width`
always resolves against the same width and can animate without jumping.
- The start container controller now also measures the end container and
is renamed to `createStartEndContainerController`. The combined start
and end width is written to `--internal-start-end-container-width`,
which the outline floating label uses to size itself to the full width
of the notch.
- Adds `$form-control-label-transition-easing` so the label's color,
transform, and `max-width` transitions share one easing.
- Adds an e2e test per component that steps through the label's
transitions and checks that the label never extends past the field.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

## Other information

Previews:
-
[Input](https://ionic-framework-git-fw-7683-ionic1.vercel.app/src/components/input/test/slot)
-
[Select](https://ionic-framework-git-fw-7683-ionic1.vercel.app/src/components/select/test/slot)
-
[Textarea](https://ionic-framework-git-fw-7683-ionic1.vercel.app/src/components/textarea/test/slot)

---------

Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
…31552)

Issue number: resolves #29793

---------

## What is the current behavior?

Currently, swipe to go back on `ion-nav` and `ion-router-outlet` starts
the back transition as soon as the gesture starts. With animations
disabled, through either the `animated` prop or the global config,
there's no progress animation for the swipe to drive, so the transition
completes instantly. The previous page gets its enter lifecycle events
even when the swipe is abandoned, and a completed swipe never navigates.

## What is the new behavior?

With animations disabled, the swipe now waits until it's released to
decide whether to go back. A completed swipe goes back without an
animation and an abandoned one does nothing. For `ion-router-outlet`,
core calls the swipe handler's `onStart` and `onEnd(true)` on release,
so Angular, React and Vue didn't need changes. The host also ignores
pointer events during the swipe, the same way a swipe-driven transition
does, so releasing doesn't click whatever is under the pointer.

## Does this introduce a breaking change?

- [ ] Yes
- [X] No

## Other information

[Relevant test screen
(Angular)](https://ionic-framework-git-fw-7757-ionic1.vercel.app/angular/standalone/swipe-animated-disabled?ionic:mode=ios)

## Current dev build
```
9.0.7-dev.11791478996.1b854592
```
This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [@stencil/angular-output-target](https://stenciljs.com/)
([source](https://redirect.github.com/stenciljs/output-targets)) |
[`1.4.1` →
`1.5.2`](https://renovatebot.com/diffs/npm/@stencil%2fangular-output-target/1.4.1/1.5.2)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@stencil%2fangular-output-target/1.5.2?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@stencil%2fangular-output-target/1.4.1/1.5.2?slim=true)
|
| [@stencil/vue-output-target](https://stenciljs.com/)
([source](https://redirect.github.com/stenciljs/output-targets)) |
[`0.14.2` →
`0.14.6`](https://renovatebot.com/diffs/npm/@stencil%2fvue-output-target/0.14.2/0.14.6)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@stencil%2fvue-output-target/0.14.6?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@stencil%2fvue-output-target/0.14.2/0.14.6?slim=true)
|

---

### Release Notes

<details>
<summary>stenciljs/output-targets
(@&#8203;stencil/angular-output-target)</summary>

###
[`v1.5.2`](https://redirect.github.com/stenciljs/output-targets/compare/@stencil/angular-output-target@1.5.1...@stencil/angular-output-target@1.5.2)

[Compare
Source](https://redirect.github.com/stenciljs/output-targets/compare/@stencil/angular-output-target@1.5.1...@stencil/angular-output-target@1.5.2)

###
[`v1.5.1`](https://redirect.github.com/stenciljs/output-targets/compare/@stencil/angular-output-target@1.5.0...@stencil/angular-output-target@1.5.1)

[Compare
Source](https://redirect.github.com/stenciljs/output-targets/compare/@stencil/angular-output-target@1.5.0...@stencil/angular-output-target@1.5.1)

###
[`v1.5.0`](https://redirect.github.com/stenciljs/output-targets/compare/@stencil/angular-output-target@1.4.1...@stencil/angular-output-target@1.5.0)

[Compare
Source](https://redirect.github.com/stenciljs/output-targets/compare/@stencil/angular-output-target@1.4.1...@stencil/angular-output-target@1.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.

👻 **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:eyJjcmVhdGVkSW5WZXIiOiI0NC43OS4xIiwidXBkYXRlZEluVmVyIjoiNDQuMTY0LjEiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbXX0=-->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Brandy Smith <6577830+brandyscarney@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/) |
|---|---|---|---|
| [vitest](https://vitest.dev)
([source](https://redirect.github.com/vitest-dev/vitest/tree/HEAD/packages/vitest))
| [`5.0.4` →
`5.0.5`](https://renovatebot.com/diffs/npm/vitest/5.0.4/5.0.5) |
![age](https://developer.mend.io/api/mc/badges/age/npm/vitest/5.0.5?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vitest/5.0.4/5.0.5?slim=true)
|

---

### Release Notes

<details>
<summary>vitest-dev/vitest (vitest)</summary>

###
[`v5.0.5`](https://redirect.github.com/vitest-dev/vitest/releases/tag/v5.0.5)

[Compare
Source](https://redirect.github.com/vitest-dev/vitest/compare/v5.0.4...v5.0.5)

#####    🐞 Bug Fixes

- Keep vite default `fs.deny` with api token file  -  by
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa), **Hiroshi
Ogawa** and **Claude Opus 5.5** in
[#&#8203;11578](https://redirect.github.com/vitest-dev/vitest/issues/11578)
[<samp>(28dc1)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/28dc1edfb)
- Handle quoted file names in `--changed`  -  by
[@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in
[#&#8203;11583](https://redirect.github.com/vitest-dev/vitest/issues/11583)
[<samp>(14921)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/14921e962)
- Add `data` to the `import.meta.hot` stub  -  by
[@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in
[#&#8203;11590](https://redirect.github.com/vitest-dev/vitest/issues/11590)
[<samp>(3a828)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/3a8289ac3)
- Set `skip` in `skipIf`, ignore `undefined` options  -  by
[@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in
[#&#8203;11591](https://redirect.github.com/vitest-dev/vitest/issues/11591)
[<samp>(d523a)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/d523a15f2)
- Skip builtin loading in async leak detector  -  by
[@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in
[#&#8203;11598](https://redirect.github.com/vitest-dev/vitest/issues/11598)
[<samp>(fe86a)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/fe86a64c6)
- Keep the import frame in native loader errors  -  by
[@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in
[#&#8203;11599](https://redirect.github.com/vitest-dev/vitest/issues/11599)
[<samp>(9697b)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/9697b3894)
- Run hook cleanups when a later hook fails  -  by
[@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in
[#&#8203;11605](https://redirect.github.com/vitest-dev/vitest/issues/11605)
[<samp>(6c5a4)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/6c5a44720)
- Release mocks of finished test files  -  by
[@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in
[#&#8203;11607](https://redirect.github.com/vitest-dev/vitest/issues/11607)
[<samp>(e9c3d)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/e9c3d72f0)
- Abort all running tests on cancel  -  by
[@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in
[#&#8203;11606](https://redirect.github.com/vitest-dev/vitest/issues/11606)
[<samp>(6621a)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/6621a72d6)
- **browser**:
- Ignore synthetic pagehide events  -  by
[@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in
[#&#8203;11582](https://redirect.github.com/vitest-dev/vitest/issues/11582)
[<samp>(ca081)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/ca0813584)
- Run plugin buildStart on server creation  -  by
[@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in
[#&#8203;11593](https://redirect.github.com/vitest-dev/vitest/issues/11593)
[<samp>(ea611)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/ea611e44c)
- Drop late connections of closed sessions  -  by
[@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in
[#&#8203;11600](https://redirect.github.com/vitest-dev/vitest/issues/11600)
[<samp>(f161e)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/f161e6df2)
- Wait 30s for the browser to close  -  by
[@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in
[#&#8203;11601](https://redirect.github.com/vitest-dev/vitest/issues/11601)
[<samp>(6498b)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/6498b666a)
- Run global setup once with instances  -  by
[@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in
[#&#8203;11596](https://redirect.github.com/vitest-dev/vitest/issues/11596)
[<samp>(8dd67)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/8dd67c262)
- **reporter**:
- End reason `&#&#8203;39;failed&#&#8203;39;` on worker crash  -  by
[@&#8203;AriPerkkio](https://redirect.github.com/AriPerkkio) in
[#&#8203;11568](https://redirect.github.com/vitest-dev/vitest/issues/11568)
[<samp>(6ae8e)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/6ae8e89ff)

#####     [View changes on
GitHub](https://redirect.github.com/vitest-dev/vitest/compare/v5.0.4...v5.0.5)

</details>

---

### Configuration

📅 **Schedule**: (UTC)

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

🚦 **Automerge**: Enabled.

♻ **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:eyJjcmVhdGVkSW5WZXIiOiI0NC4xNjQuMSIsInVwZGF0ZWRJblZlciI6IjQ0LjE2NC4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

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

| Package | Type | Update | Change |
|---|---|---|---|
|
[github/codeql-action](https://redirect.github.com/github/codeql-action)
| action | minor | `v4.38.3` → `v4.39.0` |

---

### Release Notes

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

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

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

- *Breaking change*: Bump the minimum required CodeQL bundle version to
2.20.7.
[#&#8203;4205](https://redirect.github.com/github/codeql-action/pull/4205)
- The `codeql-action/analyze` step now validates that a correct argument
for the `checkout_path` input has been provided. The `checkout_path`
input must be set to the path where the repository that is being
analyzed is checked out at on the runner, if that path is something
other than the workspace root. If the path does not point to a
repository checkout or is different from the path that was used by
`codeql-action/init`, then the CodeQL Action now produces a warning.
[#&#8203;4148](https://redirect.github.com/github/codeql-action/pull/4148)
- Resolved an issue with third-party caching implementations that
prevented caches from being restored correctly.
[#&#8203;4206](https://redirect.github.com/github/codeql-action/pull/4206)
- The `codeql-action/start-proxy` step that is used in Code Scanning
Default Setup now finds CodeQL releases using the same logic as
`codeql-action/init`. This primarily benefits customers who are using
GitHub instances other than `github.com` where the
`codeql-action/start-proxy` step may previously have been unable to
locate recent releases and ended up using outdated versions of the
private registry authentication proxy as a result.
[#&#8203;4198](https://redirect.github.com/github/codeql-action/pull/4198)

</details>

---

### Configuration

📅 **Schedule**: (UTC)

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

🚦 **Automerge**: Enabled.

♻ **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:eyJjcmVhdGVkSW5WZXIiOiI0NC4xNjQuMSIsInVwZGF0ZWRJblZlciI6IjQ0LjE2NC4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

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

---------

## What is the current behavior?

In v8, using `ion-tab-bar` without `ion-tabs` throws in Vue because
`IonTabBar` injects `tabBarData` with no default and reads `.value` off
`undefined`. Clicking a tab button then throws again in the native event
handler. This was already fixed in v9 by the strict type checking chore
in #31320, which gave the injection a `null` default and guarded it, but
nothing tests the standalone case in a browser.

## What is the new behavior?

This adds a `/tabs-standalone` page to the Vue test app with an
`ion-tab-bar` that has no `ion-tabs` or `ion-router-outlet` around it,
where the app tracks the active tab itself and navigates by calling
`router.push` from the tab buttons. The new Playwright spec checks that
clicking moves the selected state, runs the app's own `@click`, doesn't
change the URL, logs no errors or warnings, and that `router.push` from
a tab button navigates.

## Does this introduce a breaking change?

- [ ] Yes
- [X] No

## Other information

I checked that the spec catches the original bug by patching the built
`@ionic/vue` back to the v8 `inject("tabBarData")`. Both tests fail with
the errors from the issue, and they pass on this branch. This is
test-only, so the v8 behavior is unchanged. We aren't backporting the
fix since it isn't critical.

The follow-up request in the issue for a page animation when switching
tabs by method isn't covered here and is out of scope for the issue it's
in.
### Summary
Fixes #31594.

In `packages/angular/src/standalone/navigation/tabs.ts`, `IonTabs` was
importing `IonTabBar` and `IonTab` from `../directives/proxies`. Because
`directives/proxies` is the barrel that re-exports every component
proxy, bundlers pulling `IonTabs` into the root route included all
lazy-route Ionic components into the initial chunk, defeating standalone
tree-shaking and component code-splitting.

### Fix
Import `IonTab` from `../directives/ion-tab` and `IonTabBar` from
`../directives/ion-tab-bar` directly, matching per-component entry
points and preventing the entire proxies barrel from bundling into
initial route chunks.
Issue number: resolves #30777, resolves #27975

---------

## What is the current behavior?

Currently, when `ion-datetime` is inside a modal or popover (usually
through `ion-datetime-button`), cancelling or dismissing the overlay
leaves the unconfirmed selection in place. The `cancel()` method only
emits `ionCancel` and closes the overlay, so reopening the datetime
shows the cancelled date as selected even though `value` never changed.

## What is the new behavior?

The datetime now listens for its parent overlay's dismiss event and
resets its selection to `value` unless the overlay was dismissed with
the `datetime-confirm` role. That covers the Cancel button, backdrop
taps, swipes and hardware back. The reset skips the month animation
since the overlay has already animated out, otherwise cancelling a
selection in another month left the calendar stuck on that month when
reopened. Calling `cancel()` on an inline datetime now restores the
committed selection right away.

## Does this introduce a breaking change?

- [ ] Yes
- [X] No

## Other information

There was an earlier attempt at this in #27976 that called `reset()`
from `cancel()`, which was closed until the design was settled. This
reprocesses `value` directly instead, so it doesn't pick up the clearing
behavior of `reset()`.

This changes behavior in a few edge cases:
- Calling `cancel()` without closing an overlay now resets the
selection, where before it only emitted `ionCancel`.
- If `canDismiss` blocks the dismiss, the selection stays, since the
user is still in the picker.
- An unconfirmed selection is now discarded the next time the overlay
opens, so calling `confirm()` or `reset()` from a dismiss handler works
the same as on `main`. Browsing to another month without picking a day
isn't reset either, which also matches `main`.

Use the "Popover - Custom" and "Modal - Custom" examples, pick a date,
cancel, then reopen:
- [Relevant test screen
(iOS)](https://ionic-framework-git-fw-7061-ionic1.vercel.app/src/components/datetime-button/test/overlays?ionic:mode=ios)
- [Relevant test screen
(MD)](https://ionic-framework-git-fw-7061-ionic1.vercel.app/src/components/datetime-button/test/overlays?ionic:mode=md)
…1583)

Issue number: resolves #30617

---------

## What is the current behavior?

Currently, replacing a page inside a tab stack breaks going back in two
different ways. Calling `useIonRouter().replace()` shows a back button
that does nothing, because `replace()` sends the `root` direction, which
clears the location history but leaves `pushedByRoute` set. Calling
`navigate(path, 'forward', 'replace')` after switching tabs does the
opposite, so the URL goes back but the replaced page stays on screen.
That one happens because the back button calls `router.go(-3)` and the
router assumes the page we left is only one entry ahead.

## What is the new behavior?

Now `replace()` uses the `none` direction, so it keeps the pages beneath
the one it replaced and still doesn't animate, the same as a plain
`router.replace()`. The router also uses the real history delta to find
the page we left, and an explicit `navigate(url, 'root', 'replace')` no
longer shows a back button since there's nothing to go back to.

## Does this introduce a breaking change?

- [ ] Yes
- [X] No

## Other information

This does change `replace()` for apps that relied on it clearing the
history. That only started in 9.0, when #31142 made the router respect
the caller's direction, and those apps can switch to `navigate(url,
'root', 'replace')`. I updated the `useIonRouter` docs in ionic-docs to
match here: ionic-team/ionic-docs#4794
…ound (#31591)

Issue number: N/A

---------

## What is the current behavior?

The `visible` docs on `ion-backdrop` only say "If `true`, the backdrop
will be visible." Developers read that as "hides the backdrop," but
`visible="false"` only removes the default background: the backdrop
still blocks interaction, and custom background styles on `ion-backdrop`
still apply. This has been reported as a bug several times (#26953,
#29177, #30742).

## What is the new behavior?

- Documents that `visible` controls only the default background, not
whether the backdrop blocks interaction or overrides a custom
background. The wording matches `showBackdrop` on `ion-modal` and
`ion-popover`.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

## Other information

The Properties table on the docs site is generated from this JSDoc, so
it updates on the next API sync.
@ShaneK
ShaneK requested a review from a team as a code owner October 21, 2026 18:23
@ShaneK
ShaneK requested review from thetaPC and removed request for a team October 21, 2026 18:23
@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 Oct 21, 2026
@vercel

vercel Bot commented Oct 21, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated
ionic-framework Ready Ready Preview Oct 21, 2026 6:27pm UTC

Request Review

@ShaneK
ShaneK merged commit 0d9f688 into 9.0.x Oct 21, 2026
134 of 155 checks passed
@ShaneK
ShaneK deleted the release-9.0.9 branch October 21, 2026 18:46

This branch was successfully deployed

1 active deployment
Preview — ae6e2bb8 Deployed Oct 21, 2026 by vercel[bot]
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