diff --git a/CHANGELOG.md b/CHANGELOG.md
index b64870b5647..9bf71d444ba 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,19 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+## [8.7.4](https://github.com/ionic-team/ionic-framework/compare/v8.7.3...v8.7.4) (2025-09-17)
+
+
+### Bug Fixes
+
+* **input:** improve error text accessibility ([#30635](https://github.com/ionic-team/ionic-framework/issues/30635)) ([c339bc3](https://github.com/ionic-team/ionic-framework/commit/c339bc36827b62ef871325869a9a5db9b17ac785))
+* **overlays,picker:** remove invalid aria-hidden attribute ([#30563](https://github.com/ionic-team/ionic-framework/issues/30563)) ([49f96d7](https://github.com/ionic-team/ionic-framework/commit/49f96d7f1e9050a95e3e33a821c0467ecc0bed64)), closes [#30040](https://github.com/ionic-team/ionic-framework/issues/30040)
+* **segment-view:** scroll and select the right item when the component is in RTL context; ([#30675](https://github.com/ionic-team/ionic-framework/issues/30675)) ([66f517d](https://github.com/ionic-team/ionic-framework/commit/66f517d5b2154fff00b294a78f4107f057a580c6)), closes [#30079](https://github.com/ionic-team/ionic-framework/issues/30079)
+
+
+
+
+
## [8.7.3](https://github.com/ionic-team/ionic-framework/compare/v8.7.2...v8.7.3) (2025-08-20)
diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md
index c9a3f00a20a..8e9e8ba9851 100644
--- a/core/CHANGELOG.md
+++ b/core/CHANGELOG.md
@@ -3,6 +3,19 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+## [8.7.4](https://github.com/ionic-team/ionic-framework/compare/v8.7.3...v8.7.4) (2025-09-17)
+
+
+### Bug Fixes
+
+* **input:** improve error text accessibility ([#30635](https://github.com/ionic-team/ionic-framework/issues/30635)) ([c339bc3](https://github.com/ionic-team/ionic-framework/commit/c339bc36827b62ef871325869a9a5db9b17ac785))
+* **overlays,picker:** remove invalid aria-hidden attribute ([#30563](https://github.com/ionic-team/ionic-framework/issues/30563)) ([49f96d7](https://github.com/ionic-team/ionic-framework/commit/49f96d7f1e9050a95e3e33a821c0467ecc0bed64)), closes [#30040](https://github.com/ionic-team/ionic-framework/issues/30040)
+* **segment-view:** scroll and select the right item when the component is in RTL context; ([#30675](https://github.com/ionic-team/ionic-framework/issues/30675)) ([66f517d](https://github.com/ionic-team/ionic-framework/commit/66f517d5b2154fff00b294a78f4107f057a580c6)), closes [#30079](https://github.com/ionic-team/ionic-framework/issues/30079)
+
+
+
+
+
## [8.7.3](https://github.com/ionic-team/ionic-framework/compare/v8.7.2...v8.7.3) (2025-08-20)
diff --git a/core/Dockerfile b/core/Dockerfile
index ab667d50f97..6ccd28e99ba 100644
--- a/core/Dockerfile
+++ b/core/Dockerfile
@@ -1,5 +1,5 @@
# Get Playwright
-FROM mcr.microsoft.com/playwright:v1.54.2
+FROM mcr.microsoft.com/playwright:v1.55.0
# Set the working directory
WORKDIR /ionic
diff --git a/core/package-lock.json b/core/package-lock.json
index 00a7610f794..6e4a7454a31 100644
--- a/core/package-lock.json
+++ b/core/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@ionic/core",
- "version": "8.7.3",
+ "version": "8.7.4",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/core",
- "version": "8.7.3",
+ "version": "8.7.4",
"license": "MIT",
"dependencies": {
"@stencil/core": "4.36.2",
@@ -22,7 +22,7 @@
"@clack/prompts": "^0.11.0",
"@ionic/eslint-config": "^0.3.0",
"@ionic/prettier-config": "^2.0.0",
- "@playwright/test": "^1.54.2",
+ "@playwright/test": "^1.55.0",
"@rollup/plugin-node-resolve": "^8.4.0",
"@rollup/plugin-virtual": "^2.0.3",
"@stencil/angular-output-target": "^0.10.0",
@@ -663,9 +663,9 @@
"dev": true
},
"node_modules/@capacitor/core": {
- "version": "7.4.2",
- "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-7.4.2.tgz",
- "integrity": "sha512-akCf9A1FUR8AWTtmgGjHEq6LmGsjA2U7igaJ9PxiCBfyxKqlDbuGHrlNdpvHEjV5tUPH3KYtkze6gtFcNKPU9A==",
+ "version": "7.4.3",
+ "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-7.4.3.tgz",
+ "integrity": "sha512-wCWr8fQ9Wxn0466vPg7nMn0tivbNVjNy1yL4GvDSIZuZx7UpU2HeVGNe9QjN/quEd+YLRFeKEBLBw619VqUiNg==",
"dev": true,
"dependencies": {
"tslib": "^2.1.0"
@@ -1715,12 +1715,12 @@
}
},
"node_modules/@playwright/test": {
- "version": "1.54.2",
- "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.54.2.tgz",
- "integrity": "sha512-A+znathYxPf+72riFd1r1ovOLqsIIB0jKIoPjyK2kqEIe30/6jF6BC7QNluHuwUmsD2tv1XZVugN8GqfTMOxsA==",
+ "version": "1.55.0",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.55.0.tgz",
+ "integrity": "sha512-04IXzPwHrW69XusN/SIdDdKZBzMfOT9UNT/YiJit/xpy2VuAoB8NHc8Aplb96zsWDddLnbkPL3TsmrS04ZU2xQ==",
"dev": true,
"dependencies": {
- "playwright": "1.54.2"
+ "playwright": "1.55.0"
},
"bin": {
"playwright": "cli.js"
@@ -8593,12 +8593,12 @@
}
},
"node_modules/playwright": {
- "version": "1.54.2",
- "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.54.2.tgz",
- "integrity": "sha512-Hu/BMoA1NAdRUuulyvQC0pEqZ4vQbGfn8f7wPXcnqQmM+zct9UliKxsIkLNmz/ku7LElUNqmaiv1TG/aL5ACsw==",
+ "version": "1.55.0",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.55.0.tgz",
+ "integrity": "sha512-sdCWStblvV1YU909Xqx0DhOjPZE4/5lJsIS84IfN9dAZfcl/CIZ5O8l3o0j7hPMjDvqoTF8ZUcc+i/GL5erstA==",
"dev": true,
"dependencies": {
- "playwright-core": "1.54.2"
+ "playwright-core": "1.55.0"
},
"bin": {
"playwright": "cli.js"
@@ -8611,9 +8611,9 @@
}
},
"node_modules/playwright-core": {
- "version": "1.54.2",
- "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.54.2.tgz",
- "integrity": "sha512-n5r4HFbMmWsB4twG7tJLDN9gmBUeSPcsBZiWSE4DnYz9mJMAFqr2ID7+eGC9kpEnxExJ1epttwR59LEWCk8mtA==",
+ "version": "1.55.0",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.55.0.tgz",
+ "integrity": "sha512-GvZs4vU3U5ro2nZpeiwyb0zuFaqb9sUiAJuyrWpcGouD8y9/HLgGbNRjIph7zU9D3hnPaisMl9zG9CgFi/biIg==",
"dev": true,
"bin": {
"playwright-core": "cli.js"
@@ -11102,9 +11102,9 @@
"dev": true
},
"@capacitor/core": {
- "version": "7.4.2",
- "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-7.4.2.tgz",
- "integrity": "sha512-akCf9A1FUR8AWTtmgGjHEq6LmGsjA2U7igaJ9PxiCBfyxKqlDbuGHrlNdpvHEjV5tUPH3KYtkze6gtFcNKPU9A==",
+ "version": "7.4.3",
+ "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-7.4.3.tgz",
+ "integrity": "sha512-wCWr8fQ9Wxn0466vPg7nMn0tivbNVjNy1yL4GvDSIZuZx7UpU2HeVGNe9QjN/quEd+YLRFeKEBLBw619VqUiNg==",
"dev": true,
"requires": {
"tslib": "^2.1.0"
@@ -11863,12 +11863,12 @@
}
},
"@playwright/test": {
- "version": "1.54.2",
- "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.54.2.tgz",
- "integrity": "sha512-A+znathYxPf+72riFd1r1ovOLqsIIB0jKIoPjyK2kqEIe30/6jF6BC7QNluHuwUmsD2tv1XZVugN8GqfTMOxsA==",
+ "version": "1.55.0",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.55.0.tgz",
+ "integrity": "sha512-04IXzPwHrW69XusN/SIdDdKZBzMfOT9UNT/YiJit/xpy2VuAoB8NHc8Aplb96zsWDddLnbkPL3TsmrS04ZU2xQ==",
"dev": true,
"requires": {
- "playwright": "1.54.2"
+ "playwright": "1.55.0"
}
},
"@rollup/plugin-node-resolve": {
@@ -16812,19 +16812,19 @@
}
},
"playwright": {
- "version": "1.54.2",
- "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.54.2.tgz",
- "integrity": "sha512-Hu/BMoA1NAdRUuulyvQC0pEqZ4vQbGfn8f7wPXcnqQmM+zct9UliKxsIkLNmz/ku7LElUNqmaiv1TG/aL5ACsw==",
+ "version": "1.55.0",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.55.0.tgz",
+ "integrity": "sha512-sdCWStblvV1YU909Xqx0DhOjPZE4/5lJsIS84IfN9dAZfcl/CIZ5O8l3o0j7hPMjDvqoTF8ZUcc+i/GL5erstA==",
"dev": true,
"requires": {
"fsevents": "2.3.2",
- "playwright-core": "1.54.2"
+ "playwright-core": "1.55.0"
}
},
"playwright-core": {
- "version": "1.54.2",
- "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.54.2.tgz",
- "integrity": "sha512-n5r4HFbMmWsB4twG7tJLDN9gmBUeSPcsBZiWSE4DnYz9mJMAFqr2ID7+eGC9kpEnxExJ1epttwR59LEWCk8mtA==",
+ "version": "1.55.0",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.55.0.tgz",
+ "integrity": "sha512-GvZs4vU3U5ro2nZpeiwyb0zuFaqb9sUiAJuyrWpcGouD8y9/HLgGbNRjIph7zU9D3hnPaisMl9zG9CgFi/biIg==",
"dev": true
},
"postcss": {
diff --git a/core/package.json b/core/package.json
index c68174795bb..c37e0c2bd7e 100644
--- a/core/package.json
+++ b/core/package.json
@@ -1,6 +1,6 @@
{
"name": "@ionic/core",
- "version": "8.7.3",
+ "version": "8.7.4",
"description": "Base components for Ionic",
"keywords": [
"ionic",
@@ -44,7 +44,7 @@
"@clack/prompts": "^0.11.0",
"@ionic/eslint-config": "^0.3.0",
"@ionic/prettier-config": "^2.0.0",
- "@playwright/test": "^1.54.2",
+ "@playwright/test": "^1.55.0",
"@rollup/plugin-node-resolve": "^8.4.0",
"@rollup/plugin-virtual": "^2.0.3",
"@stencil/angular-output-target": "^0.10.0",
diff --git a/core/src/components/action-sheet/test/a11y/action-sheet.e2e.ts-snapshots/action-sheet-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/action-sheet/test/a11y/action-sheet.e2e.ts-snapshots/action-sheet-scale-md-ltr-Mobile-Chrome-linux.png
index 8a152f330e4..094a219aa3c 100644
Binary files a/core/src/components/action-sheet/test/a11y/action-sheet.e2e.ts-snapshots/action-sheet-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/action-sheet/test/a11y/action-sheet.e2e.ts-snapshots/action-sheet-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/alert/test/a11y/alert.e2e.ts-snapshots/alert-checkbox-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/alert/test/a11y/alert.e2e.ts-snapshots/alert-checkbox-scale-md-ltr-Mobile-Chrome-linux.png
index 4e8222cdfe2..82f5a675ff2 100644
Binary files a/core/src/components/alert/test/a11y/alert.e2e.ts-snapshots/alert-checkbox-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/alert/test/a11y/alert.e2e.ts-snapshots/alert-checkbox-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/alert/test/a11y/alert.e2e.ts-snapshots/alert-radio-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/alert/test/a11y/alert.e2e.ts-snapshots/alert-radio-scale-md-ltr-Mobile-Chrome-linux.png
index ef47a09dfc6..fbab7b3c127 100644
Binary files a/core/src/components/alert/test/a11y/alert.e2e.ts-snapshots/alert-radio-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/alert/test/a11y/alert.e2e.ts-snapshots/alert-radio-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/back-button/test/a11y/back-button.e2e.ts-snapshots/back-button-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/back-button/test/a11y/back-button.e2e.ts-snapshots/back-button-scale-md-ltr-Mobile-Chrome-linux.png
index 2b6d0f39bd2..f2cf349aaf3 100644
Binary files a/core/src/components/back-button/test/a11y/back-button.e2e.ts-snapshots/back-button-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/back-button/test/a11y/back-button.e2e.ts-snapshots/back-button-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/button/test/a11y/button.e2e.ts-snapshots/button-clear-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/button/test/a11y/button.e2e.ts-snapshots/button-clear-scale-md-ltr-Mobile-Chrome-linux.png
index 13dc91e2521..edf6210af61 100644
Binary files a/core/src/components/button/test/a11y/button.e2e.ts-snapshots/button-clear-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/button/test/a11y/button.e2e.ts-snapshots/button-clear-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/button/test/a11y/button.e2e.ts-snapshots/button-default-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/button/test/a11y/button.e2e.ts-snapshots/button-default-scale-md-ltr-Mobile-Chrome-linux.png
index 9d9e9a85d17..7b06b904fce 100644
Binary files a/core/src/components/button/test/a11y/button.e2e.ts-snapshots/button-default-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/button/test/a11y/button.e2e.ts-snapshots/button-default-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/button/test/a11y/button.e2e.ts-snapshots/button-small-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/button/test/a11y/button.e2e.ts-snapshots/button-small-scale-md-ltr-Mobile-Chrome-linux.png
index fd39f0f8a10..8f8583f4a11 100644
Binary files a/core/src/components/button/test/a11y/button.e2e.ts-snapshots/button-small-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/button/test/a11y/button.e2e.ts-snapshots/button-small-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/buttons/test/a11y/buttons.e2e.ts-snapshots/buttons-clear-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/buttons/test/a11y/buttons.e2e.ts-snapshots/buttons-clear-scale-md-ltr-Mobile-Chrome-linux.png
index d68ecf91bf5..20394301b2e 100644
Binary files a/core/src/components/buttons/test/a11y/buttons.e2e.ts-snapshots/buttons-clear-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/buttons/test/a11y/buttons.e2e.ts-snapshots/buttons-clear-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/buttons/test/a11y/buttons.e2e.ts-snapshots/buttons-default-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/buttons/test/a11y/buttons.e2e.ts-snapshots/buttons-default-scale-md-ltr-Mobile-Chrome-linux.png
index 88dec93214c..df4464bb826 100644
Binary files a/core/src/components/buttons/test/a11y/buttons.e2e.ts-snapshots/buttons-default-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/buttons/test/a11y/buttons.e2e.ts-snapshots/buttons-default-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/buttons/test/a11y/buttons.e2e.ts-snapshots/buttons-icon-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/buttons/test/a11y/buttons.e2e.ts-snapshots/buttons-icon-scale-md-ltr-Mobile-Chrome-linux.png
index b9b88ff84ef..a556b1b9abe 100644
Binary files a/core/src/components/buttons/test/a11y/buttons.e2e.ts-snapshots/buttons-icon-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/buttons/test/a11y/buttons.e2e.ts-snapshots/buttons-icon-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/card/test/a11y/card.e2e.ts-snapshots/card-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/card/test/a11y/card.e2e.ts-snapshots/card-scale-md-ltr-Mobile-Chrome-linux.png
index aada6cb715d..87dcc890334 100644
Binary files a/core/src/components/card/test/a11y/card.e2e.ts-snapshots/card-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/card/test/a11y/card.e2e.ts-snapshots/card-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/checkbox/test/a11y/checkbox.e2e.ts-snapshots/checkbox-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/checkbox/test/a11y/checkbox.e2e.ts-snapshots/checkbox-scale-md-ltr-Mobile-Chrome-linux.png
index fbede37e147..90d597d391b 100644
Binary files a/core/src/components/checkbox/test/a11y/checkbox.e2e.ts-snapshots/checkbox-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/checkbox/test/a11y/checkbox.e2e.ts-snapshots/checkbox-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/chip/test/a11y/chip.e2e.ts-snapshots/chip-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/chip/test/a11y/chip.e2e.ts-snapshots/chip-scale-md-ltr-Mobile-Chrome-linux.png
index c0fb06ff67b..0086d4a5bda 100644
Binary files a/core/src/components/chip/test/a11y/chip.e2e.ts-snapshots/chip-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/chip/test/a11y/chip.e2e.ts-snapshots/chip-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/content/test/standalone/content.e2e.ts-snapshots/content-standalone-md-ltr-Mobile-Chrome-linux.png b/core/src/components/content/test/standalone/content.e2e.ts-snapshots/content-standalone-md-ltr-Mobile-Chrome-linux.png
index 148717952ab..0f5e28fd3ab 100644
Binary files a/core/src/components/content/test/standalone/content.e2e.ts-snapshots/content-standalone-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/content/test/standalone/content.e2e.ts-snapshots/content-standalone-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/datetime.tsx b/core/src/components/datetime/datetime.tsx
index 2e3e111e56d..6a7d2440a8a 100644
--- a/core/src/components/datetime/datetime.tsx
+++ b/core/src/components/datetime/datetime.tsx
@@ -3,6 +3,7 @@ import { Component, Element, Event, Host, Method, Prop, State, Watch, h, writeTa
import { startFocusVisible } from '@utils/focus-visible';
import { getElementRoot, raf, renderHiddenInput } from '@utils/helpers';
import { printIonError, printIonWarning } from '@utils/logging';
+import { FOCUS_TRAP_DISABLE_CLASS } from '@utils/overlays';
import { isRTL } from '@utils/rtl';
import { createColorClasses } from '@utils/theme';
import { caretDownSharp, caretUpSharp, chevronBack, chevronDown, chevronForward } from 'ionicons/icons';
@@ -1598,7 +1599,7 @@ export class Datetime implements ComponentInterface {
forcePresentation === 'time-date'
? [this.renderTimePickerColumns(forcePresentation), this.renderDatePickerColumns(forcePresentation)]
: [this.renderDatePickerColumns(forcePresentation), this.renderTimePickerColumns(forcePresentation)];
- return {renderArray};
+ return {renderArray};
}
private renderDatePickerColumns(forcePresentation: string) {
diff --git a/core/src/components/datetime/test/a11y/datetime.e2e.ts-snapshots/datetime-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/datetime/test/a11y/datetime.e2e.ts-snapshots/datetime-scale-md-ltr-Mobile-Chrome-linux.png
index 173af1a0774..58771820175 100644
Binary files a/core/src/components/datetime/test/a11y/datetime.e2e.ts-snapshots/datetime-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/datetime/test/a11y/datetime.e2e.ts-snapshots/datetime-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-ios-ltr-Mobile-Safari-linux.png b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-ios-ltr-Mobile-Safari-linux.png
index 3437e3bc6db..2770cb15bb3 100644
Binary files a/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-ios-ltr-Mobile-Safari-linux.png and b/core/src/components/datetime/test/locale/datetime.e2e.ts-snapshots/datetime-locale-ja-JP-diff-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/input.tsx b/core/src/components/input/input.tsx
index 69281c5e899..ccb80120ca8 100644
--- a/core/src/components/input/input.tsx
+++ b/core/src/components/input/input.tsx
@@ -79,8 +79,15 @@ export class Input implements ComponentInterface {
*/
@State() hasFocus = false;
+ /**
+ * Track validation state for proper aria-live announcements
+ */
+ @State() isInvalid = false;
+
@Element() el!: HTMLIonInputElement;
+ private validationObserver?: MutationObserver;
+
/**
* The color to use from your application's color palette.
* Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`.
@@ -396,6 +403,16 @@ export class Input implements ComponentInterface {
};
}
+ /**
+ * Checks if the input is in an invalid state based on Ionic validation classes
+ */
+ private checkInvalidState(): boolean {
+ const hasIonTouched = this.el.classList.contains('ion-touched');
+ const hasIonInvalid = this.el.classList.contains('ion-invalid');
+
+ return hasIonTouched && hasIonInvalid;
+ }
+
connectedCallback() {
const { el } = this;
@@ -406,6 +423,26 @@ export class Input implements ComponentInterface {
() => this.labelSlot
);
+ // Watch for class changes to update validation state
+ if (Build.isBrowser && typeof MutationObserver !== 'undefined') {
+ this.validationObserver = new MutationObserver(() => {
+ const newIsInvalid = this.checkInvalidState();
+ if (this.isInvalid !== newIsInvalid) {
+ this.isInvalid = newIsInvalid;
+ // Force a re-render to update aria-describedby immediately
+ forceUpdate(this);
+ }
+ });
+
+ this.validationObserver.observe(el, {
+ attributes: true,
+ attributeFilter: ['class'],
+ });
+ }
+
+ // Always set initial state
+ this.isInvalid = this.checkInvalidState();
+
this.debounceChanged();
if (Build.isBrowser) {
document.dispatchEvent(
@@ -451,6 +488,12 @@ export class Input implements ComponentInterface {
this.notchController.destroy();
this.notchController = undefined;
}
+
+ // Clean up validation observer to prevent memory leaks
+ if (this.validationObserver) {
+ this.validationObserver.disconnect();
+ this.validationObserver = undefined;
+ }
}
/**
@@ -626,22 +669,22 @@ export class Input implements ComponentInterface {
* Renders the helper text or error text values
*/
private renderHintText() {
- const { helperText, errorText, helperTextId, errorTextId } = this;
+ const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
return [
-
- {helperText}
+
+ {!isInvalid ? helperText : null}
,
-
- {errorText}
+
+ {isInvalid ? errorText : null}
,
];
}
private getHintTextID(): string | undefined {
- const { el, helperText, errorText, helperTextId, errorTextId } = this;
+ const { isInvalid, helperText, errorText, helperTextId, errorTextId } = this;
- if (el.classList.contains('ion-touched') && el.classList.contains('ion-invalid') && errorText) {
+ if (isInvalid && errorText) {
return errorTextId;
}
@@ -864,7 +907,7 @@ export class Input implements ComponentInterface {
onCompositionstart={this.onCompositionStart}
onCompositionend={this.onCompositionEnd}
aria-describedby={this.getHintTextID()}
- aria-invalid={this.getHintTextID() === this.errorTextId}
+ aria-invalid={this.isInvalid ? 'true' : undefined}
{...this.inheritedAttributes}
/>
{this.clearInput && !readonly && !disabled && (
diff --git a/core/src/components/input/test/a11y/input.e2e.ts-snapshots/input-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/input/test/a11y/input.e2e.ts-snapshots/input-scale-md-ltr-Mobile-Chrome-linux.png
index cd5c32698ab..f9c0034e922 100644
Binary files a/core/src/components/input/test/a11y/input.e2e.ts-snapshots/input-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/input/test/a11y/input.e2e.ts-snapshots/input-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-hidden-slotted-label-md-ltr-Mobile-Chrome-linux.png b/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-hidden-slotted-label-md-ltr-Mobile-Chrome-linux.png
index f210e56d1ce..84852e16478 100644
Binary files a/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-hidden-slotted-label-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-hidden-slotted-label-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-slotted-label-md-ltr-Mobile-Chrome-linux.png b/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-slotted-label-md-ltr-Mobile-Chrome-linux.png
index f210e56d1ce..84852e16478 100644
Binary files a/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-slotted-label-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-slotted-label-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/validation/index.html b/core/src/components/input/test/validation/index.html
new file mode 100644
index 00000000000..2a6ad89e13f
--- /dev/null
+++ b/core/src/components/input/test/validation/index.html
@@ -0,0 +1,284 @@
+
+
+
+
+
Input - Validation
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Input - Validation Test
+
+
+
+
+
+
Screen Reader Testing Instructions:
+
+ - Enable your screen reader (VoiceOver, NVDA, JAWS, etc.)
+ - Tab through the form fields
+ - When you tab away from an empty required field, the error should be announced immediately
+ - The error text should be announced BEFORE the next field is announced
+ - Test in Chrome, Safari, and Firefox to verify consistent behavior
+
+
+
+
+
+
Required Email Field
+
+
+
+
+
Required Name Field
+
+
+
+
+
Phone Number (Pattern Validation)
+
+
+
+
+
Password (Min Length)
+
+
+
+
+
Age (Number Range)
+
+
+
+
+
Optional Field (No Validation)
+
+
+
+
+
+ Submit Form
+ Reset Form
+
+
+
+
+
+
+
diff --git a/core/src/components/item-divider/test/a11y/item-divider.e2e.ts-snapshots/item-divider-headings-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/item-divider/test/a11y/item-divider.e2e.ts-snapshots/item-divider-headings-scale-md-ltr-Mobile-Chrome-linux.png
index cf8be874a28..6efdef8be40 100644
Binary files a/core/src/components/item-divider/test/a11y/item-divider.e2e.ts-snapshots/item-divider-headings-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/item-divider/test/a11y/item-divider.e2e.ts-snapshots/item-divider-headings-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/item-divider/test/a11y/item-divider.e2e.ts-snapshots/item-divider-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/item-divider/test/a11y/item-divider.e2e.ts-snapshots/item-divider-scale-md-ltr-Mobile-Chrome-linux.png
index 167558ec8ed..36a4b4672a5 100644
Binary files a/core/src/components/item-divider/test/a11y/item-divider.e2e.ts-snapshots/item-divider-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/item-divider/test/a11y/item-divider.e2e.ts-snapshots/item-divider-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/item-sliding/test/a11y/item-sliding.e2e.ts-snapshots/item-sliding-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/item-sliding/test/a11y/item-sliding.e2e.ts-snapshots/item-sliding-scale-md-ltr-Mobile-Chrome-linux.png
index fd8582ceaf4..b15e8bf05cd 100644
Binary files a/core/src/components/item-sliding/test/a11y/item-sliding.e2e.ts-snapshots/item-sliding-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/item-sliding/test/a11y/item-sliding.e2e.ts-snapshots/item-sliding-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/item/test/a11y/item.e2e.ts-snapshots/item-buttons-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/item/test/a11y/item.e2e.ts-snapshots/item-buttons-scale-md-ltr-Mobile-Chrome-linux.png
index 8998c48f8a4..9350d2910f2 100644
Binary files a/core/src/components/item/test/a11y/item.e2e.ts-snapshots/item-buttons-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/item/test/a11y/item.e2e.ts-snapshots/item-buttons-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/item/test/a11y/item.e2e.ts-snapshots/item-detail-icon-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/item/test/a11y/item.e2e.ts-snapshots/item-detail-icon-scale-md-ltr-Mobile-Chrome-linux.png
index 8f386636a08..5d6765747e1 100644
Binary files a/core/src/components/item/test/a11y/item.e2e.ts-snapshots/item-detail-icon-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/item/test/a11y/item.e2e.ts-snapshots/item-detail-icon-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/item/test/a11y/item.e2e.ts-snapshots/item-icons-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/item/test/a11y/item.e2e.ts-snapshots/item-icons-scale-md-ltr-Mobile-Chrome-linux.png
index 75552763262..92cfcf4649c 100644
Binary files a/core/src/components/item/test/a11y/item.e2e.ts-snapshots/item-icons-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/item/test/a11y/item.e2e.ts-snapshots/item-icons-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/item/test/a11y/item.e2e.ts-snapshots/item-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/item/test/a11y/item.e2e.ts-snapshots/item-scale-md-ltr-Mobile-Chrome-linux.png
index 0a9b23a5ddc..e3ac84cde13 100644
Binary files a/core/src/components/item/test/a11y/item.e2e.ts-snapshots/item-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/item/test/a11y/item.e2e.ts-snapshots/item-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/label/test/a11y/label.e2e.ts-snapshots/label-headings-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/label/test/a11y/label.e2e.ts-snapshots/label-headings-scale-md-ltr-Mobile-Chrome-linux.png
index 0d03b926f8d..20826fa6040 100644
Binary files a/core/src/components/label/test/a11y/label.e2e.ts-snapshots/label-headings-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/label/test/a11y/label.e2e.ts-snapshots/label-headings-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/label/test/a11y/label.e2e.ts-snapshots/label-stacked-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/label/test/a11y/label.e2e.ts-snapshots/label-stacked-scale-md-ltr-Mobile-Chrome-linux.png
index 577a599c7d8..b958ef4ce54 100644
Binary files a/core/src/components/label/test/a11y/label.e2e.ts-snapshots/label-stacked-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/label/test/a11y/label.e2e.ts-snapshots/label-stacked-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/label/test/a11y/label.e2e.ts-snapshots/label-wrap-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/label/test/a11y/label.e2e.ts-snapshots/label-wrap-scale-md-ltr-Mobile-Chrome-linux.png
index ce4cc8f935b..da520d869d6 100644
Binary files a/core/src/components/label/test/a11y/label.e2e.ts-snapshots/label-wrap-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/label/test/a11y/label.e2e.ts-snapshots/label-wrap-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/list-header/test/a11y/list-header.e2e.ts-snapshots/list-header-default-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/list-header/test/a11y/list-header.e2e.ts-snapshots/list-header-default-scale-md-ltr-Mobile-Chrome-linux.png
index 05816fc84af..7c2a4571fde 100644
Binary files a/core/src/components/list-header/test/a11y/list-header.e2e.ts-snapshots/list-header-default-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/list-header/test/a11y/list-header.e2e.ts-snapshots/list-header-default-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/loading/test/a11y/loading.e2e.ts-snapshots/loading-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/loading/test/a11y/loading.e2e.ts-snapshots/loading-scale-md-ltr-Mobile-Chrome-linux.png
index 59d1c981010..45c10031cae 100644
Binary files a/core/src/components/loading/test/a11y/loading.e2e.ts-snapshots/loading-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/loading/test/a11y/loading.e2e.ts-snapshots/loading-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/menu/menu.tsx b/core/src/components/menu/menu.tsx
index 6306801ce50..4769f609914 100644
--- a/core/src/components/menu/menu.tsx
+++ b/core/src/components/menu/menu.tsx
@@ -418,6 +418,9 @@ export class Menu implements ComponentInterface, MenuI {
*/
@Method()
setOpen(shouldOpen: boolean, animated = true, role?: string): Promise
{
+ // Blur the active element to prevent it from being kept focused inside an element that will be set with aria-hidden="true"
+ (document.activeElement as HTMLElement)?.blur();
+
return menuController._setOpen(this, shouldOpen, animated, role);
}
diff --git a/core/src/components/modal/test/dark-mode/model.e2e.ts-snapshots/modal-dark-color-md-ltr-Mobile-Chrome-linux.png b/core/src/components/modal/test/dark-mode/model.e2e.ts-snapshots/modal-dark-color-md-ltr-Mobile-Chrome-linux.png
index 5fa19d7ac60..5b93a9766fc 100644
Binary files a/core/src/components/modal/test/dark-mode/model.e2e.ts-snapshots/modal-dark-color-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/modal/test/dark-mode/model.e2e.ts-snapshots/modal-dark-color-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/note/test/a11y/note.e2e.ts-snapshots/note-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/note/test/a11y/note.e2e.ts-snapshots/note-scale-md-ltr-Mobile-Chrome-linux.png
index 2dffcda2d60..836195d2734 100644
Binary files a/core/src/components/note/test/a11y/note.e2e.ts-snapshots/note-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/note/test/a11y/note.e2e.ts-snapshots/note-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/note/test/a11y/note.e2e.ts-snapshots/note-wrapping-label-scale-md-ltr-Mobile-Chrome-linux.png b/core/src/components/note/test/a11y/note.e2e.ts-snapshots/note-wrapping-label-scale-md-ltr-Mobile-Chrome-linux.png
index e70662216b3..a48900f259f 100644
Binary files a/core/src/components/note/test/a11y/note.e2e.ts-snapshots/note-wrapping-label-scale-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/note/test/a11y/note.e2e.ts-snapshots/note-wrapping-label-scale-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/picker-column-option/picker-column-option.scss b/core/src/components/picker-column-option/picker-column-option.scss
index a414a3580ed..e34a301d77d 100644
--- a/core/src/components/picker-column-option/picker-column-option.scss
+++ b/core/src/components/picker-column-option/picker-column-option.scss
@@ -3,7 +3,7 @@
// Picker Column
// --------------------------------------------------
-button {
+.picker-column-option-button {
@include padding(0);
@include margin(0);
@@ -40,6 +40,6 @@ button {
opacity: 0.4;
}
-:host(.option-disabled) button {
+:host(.option-disabled) .picker-column-option-button {
cursor: default;
}
diff --git a/core/src/components/picker-column-option/picker-column-option.tsx b/core/src/components/picker-column-option/picker-column-option.tsx
index 87b828574f8..86bed9bf3eb 100644
--- a/core/src/components/picker-column-option/picker-column-option.tsx
+++ b/core/src/components/picker-column-option/picker-column-option.tsx
@@ -124,9 +124,9 @@ export class PickerColumnOption implements ComponentInterface {
['option-disabled']: disabled,
})}
>
-