Skip to content

merge release-9.0.5 - #31476

Merged
ShaneK merged 10 commits into
9.0.xfrom
release-9.0.5
Sep 23, 2026
Merged

ShaneK merged 10 commits into
9.0.xfrom
release-9.0.5

Conversation

@ShaneK

@ShaneK ShaneK commented Sep 23, 2026

Copy link
Copy Markdown
Member

Release 9.0.5

thetaPC and others added 10 commits September 16, 2026 11:18
)

Issue number: resolves #30626 

---------

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->
The native `button` inside `ion-button` is not being updated with the
aria-attributes if it changes on `ion-button` after initial render,
including `aria-description`. Additionally, the same dynamic is
happening with other button like elements, including `ion-card` and
`ion-item`.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->
The native `button` inside `ion-button` updates with the aria attributes
if it changes on `ion-button`. Changes include:
- Add 2 helper functions to [helpers.ts](http://helpers.ts/)
    - A mutation observer watching for all attribute changes.
- One which watches only for aria attribute changes, which calls the
mutation observer.
- Add 4 tests to
[button.e2e.ts](https://github.com/ionic-team/ionic-framework/blob/main/core/src/components/button/test/a11y/button.e2e.ts)
in a11y:
- One which loops through each aria attribute (imported from the helper)
using `ariaAttributes`
- One which specifically tests `aria-disabled` since it is managed in
`render()` separately. Render forced with prop change.
   - One which looks at detaching and reattaching behavior
- One which tests the helper strips, sets, accepts empty strings, and
can process removeAttribute
- Update
[button.tsx](https://github.com/ionic-team/ionic-framework/blob/main/core/src/components/button/button.tsx)
to:
- Add import of new helpers watchForAriaAttributeChanges, type
AttributeWatcher from '@utils/helpers'
   - Add `private ariaWatcher?: AttributeWatcher;` to class Button
- Add `private didLoad = false;` for conditional use in
`connectedCallback`and use in added `componentDidLoad` for starting the
watcher after initial component load
- Remove previous [watch
block](https://github.com/ionic-team/ionic-framework/blob/b4b2603210b313fc2f2ee2c88b9112751e24b338/core/src/components/button/button.tsx#L161-L181)
since now handled by helper
- In `item.tsx`,
- Add `ariaWatcher` and `watchForAriaAttributeChanges`, replicating
functionality of the watch block, only applying to `aria-label`
currently
- Use existing`private didLoad = false;` for conditional use in
`connectedCallback`and use in existing `componentDidLoad` for starting
the watcher after initial component load
- In `item.e2e.test`, add tests to ensure:
  - native element updates aria-label when host attribute changes
  - aria-label sync survives detach and reattach
- helper strips host attribute and syncs native element through set,
empty, and remove
- In `card.tsx`,
- Add `ariaWatcher` and `watchForAriaAttributeChanges`, replicating
functionality of the watch block, only applying to `aria-label`
currently
- Add `private didLoad = false;` for conditional use in
`connectedCallback`and use in added `componentDidLoad` for starting the
watcher after initial component load
- In `card.e2e.test`, add tests to ensure:
  - native element updates aria-label when host attribute changes
  - aria-label sync survives detach and reattach
- helper strips host attribute and syncs native element through set,
empty, and remove

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

---------

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

---------

## What is the current behavior?

Several dependencies throughout the repo have postcss as a dependency.
While it doesn't affect users, a vulnerability in postcss causes
dependabot to log high severity alerts.

## What is the new behavior?

- Bumped dependencies in vue and vue-router that were on the old
postcss.
- Added overrides for ng18, ng19, and ng20 test apps, which are stuck on
older versions.
- Ran `npm update` for all other packages that inherited postcss. This
has a few side effects:
- Bumps the `lockFileVersion` from 2 to 3, which accounts for most of
the diff in the package-lock files.
- Bumps the `react-router` from 5 to 6 in the React 18 test app
package-lock.

## Does this introduce a breaking change?

- [ ] Yes
- [X] No

## Other information

Core uses old versions of stylelint and stylelint-order that cannot be
easily updated, and these use an old postcss with the vulnerability.

---------

Co-authored-by: @anupamme

---------

Co-authored-by: Maria Hutt <thetaPC@users.noreply.github.com>
Issue number: internal

---------

## What is the current behavior?

The Vue package has two warnings that are printed regardless of the
configured log level.

## What is the new behavior?

- Export `printIonWarning` and `printIonError` from core, enabling
packages to log messages with Ionic's configured log level.
- Use `printIonWarning` in the Vue package instead of `console.warn`
directly. This checks the log level before printing.

## Does this introduce a breaking change?

- [ ] Yes
- [X] No
Issue number: resolves #30919

---------

Supersedes #31047, which this builds on. @KanhaiyaPandey is credited as
co-author on the commit.

## What is the current behavior?

When a CSS `zoom` other than `1` applies to the popover, `ion-popover`
renders incorrectly: it is positioned away from its trigger, and with
`size="cover"` it is given the wrong width. This affects a documented
workflow — adjusting the `html` zoom is the approach Ionic's
documentation recommends for dynamic font scaling on Chrome for Android.

The zoom factor is effectively applied twice. Geometry APIs
(`getBoundingClientRect()` on the trigger, content and arrow, plus
`clientX`/`clientY` for `reference="event"`) report values in the zoomed
coordinate space. Those values are written straight into the inline
`top`/`left`/`--width` styles on `.popover-content`, which are
interpreted in the unzoomed layout space and then re-scaled by the
browser.

## What is the new behavior?

- The effective zoom is read from the **popover's own context** via
`currentCSSZoom`, not from `document.documentElement`. This picks up a
zoom applied anywhere above the popover and accounts for zoom
accumulated across several ancestors. Where the property is unavailable,
it falls back to the ratio between the element's bounding rect and its
`offsetWidth`; differences below a small tolerance are treated as no
zoom, since `offsetWidth` is integer-rounded and would otherwise report
a phantom zoom.
- Every rect-derived measurement is normalized by that factor: trigger
and content rects, arrow dimensions, the `size="cover"` width, and the
pointer coordinates used by `reference="event"`.
- `innerWidth`/`innerHeight` are scaled into the same space. They are
not affected by CSS `zoom`, so leaving them alone made the offscreen
adjustment clamp against a viewport larger than the space actually
available, letting the popover render past the edge of the screen.
- Behavior is unchanged when no zoom is applied: the detected factor is
exactly `1` and every normalization is a division by `1`.

This mirrors how Floating UI addressed the same problem in
floating-ui/floating-ui#3492 — `Element.currentCSSZoom` as both the
value and the feature detector, with a default of `1` on engines that
lack it. Their fix also had to scale the overflow bounds inside
`detectOverflow()`, which is the same class of issue as the
`innerWidth`/`innerHeight` point above.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

The new `zoom` parameters on the popover positioning helpers are
optional and default to `1`. Those helpers are internal to the component
and are not part of the public API.

## Other information

**Tests**

Eight E2E tests in `core/src/components/popover/test/zoom/`, covering
the review points raised on #31047:

| Scenario | Covers |
|---|---|
| Zoom on `body`; accumulated zoom (`html` 1.2 × `body` 1.25) | zoom
applied at levels other than `documentElement` |
| `size="cover"` width matches the trigger | sizing, not just
positioning |
| `reference="event"` anchors to the pointer | pointer coordinates |
| Arrow centred on the trigger (ios) | arrow positioning |
| Popover stays within the viewport | offscreen adjustment |
| Zoomed out (`0.8`) and zoomed in (`1.5`) | factors either side of 1 |

All eight fail against `main` and pass with this change, so each one
covers the regression rather than merely passing.

These are functional assertions rather than screenshots: what is being
verified is the popover's geometry relative to its trigger, and both
boxes are read in the same coordinate space, so the relationship holds
at any zoom level. No screenshot baselines are added.

Unit tests in `core/src/components/popover/test/util.spec.ts` cover the
zoom detection itself — the `currentCSSZoom` path, the `offsetWidth`
fallback, the rounding tolerance — and the normalization of content,
trigger and arrow measurements.

**Verification**

The spec suite passes in full: 82 files, 714 tests, no failures.

The zoom tests are not skipped for any browser and pass on all three
browser projects — Chromium, Firefox and WebKit — in both `ios` and `md`
modes. Assertions use a 2px tolerance to absorb sub-pixel differences
between engines.

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: KanhaiyaPandey <kanhaiyapandey2232@gmail.com>
This PR contains the following updates:

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

---

### Release Notes

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

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

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

- The CodeQL Action now has experimental support for CodeQL releases for
which per-language bundles are available. Per-language bundles support
analysis for a single language and are therefore smaller than the
combined bundles that allow analysis for all supported languages. As a
result, per-language bundles take up less space on disk and are faster
to download. We expect to roll this change out to everyone in the coming
weeks.
[#&#8203;4146](https://redirect.github.com/github/codeql-action/pull/4146)

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

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/) |
|---|---|---|---|
|
[@types/node](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node)
([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node))
| [`24.13.5` →
`24.13.6`](https://renovatebot.com/diffs/npm/@types%2fnode/24.13.5/24.13.6)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/24.13.6?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/24.13.5/24.13.6?slim=true)
|

---

### 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:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMDMuMCIsInVwZGF0ZWRJblZlciI6IjQ0LjEwMy4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
…1460)

Issue number: resolves #30933

---------

## What is the current behavior?

Currently, an `ion-datetime` in a modal or popover sometimes opens with
a blank calendar on iOS 26. The host is missing `datetime-ready`, so
`.calendar-body` stays at `opacity: 0`. It doesn't happen every time,
and when it does the calendar stays blank until the overlay is reopened.

The `ion-datetime` component runs two IntersectionObservers on the same
root and target, one that adds `datetime-ready` and one that removes it.
WebKit reports an element that is still on screen as not intersecting,
and it doesn't deliver that entry to every observer, so the removing
observer tears the ready state down and the adding one never hears the
recovery.

## What is the new behavior?

The hidden-state observer now checks the host before tearing anything
down. An overlay hides its contents with `display: none`, which leaves
the host without a layout box, so a host that still has one is on screen
and the entry is wrong. The `hasBeenIntersecting` flag added in #31108
is gone, because the same check covers the synthetic "not intersecting"
entry that `observe()` fires when the host mounts offscreen. Both
callbacks also read the last entry instead of the first, since a batched
callback's first entry can be stale.

## Does this introduce a breaking change?

- [ ] Yes
- [X] No

## Other information

I reproduced this on an iOS 26.2 simulator, opening and dismissing the
modal in a loop and checking `datetime-ready` after each open. Four
extra observers on the same root and target recorded 54, 52, 54, 52
events over 25 cycles, which is where the per-observer delivery claim
comes from.

Same machine and everything, 150 cycles each:

| build | blank calendar |
| --- | --- |
| main | 7 (4.7%) |
| this branch | 0 |

The e2e test stubs `IntersectionObserver` to report hidden while the
datetime is on screen, since the WebKit misbehavior can't be forced on
demand. It fails on all three browsers without the fix. The open/close
cycle test guards against regressions but won't reproduce the glitch on
its own.

[Relevant test screen -
iOS](https://ionic-framework-git-fix-30933-ionic1.vercel.app/src/components/datetime-button/test/overlays?ionic:mode=ios)
@ShaneK
ShaneK requested a review from a team as a code owner September 23, 2026 18:51
@ShaneK
ShaneK requested review from brandyscarney and removed request for a team September 23, 2026 18:51
@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 Sep 23, 2026
@vercel

vercel Bot commented Sep 23, 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 Sep 23, 2026 6:56pm UTC

Request Review

@ShaneK
ShaneK merged commit ffa7041 into 9.0.x Sep 23, 2026
107 checks passed
@ShaneK
ShaneK deleted the release-9.0.5 branch September 23, 2026 19:04

This branch was successfully deployed

1 active deployment
Preview 15d51760 Deployed Sep 23, 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.

6 participants