diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index e44acd31374..98905a6c843 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -20,10 +20,10 @@ body:
id: affected-versions
attributes:
label: Ionic Framework Version
- description: Which version(s) of Ionic Framework does this issue impact? [Ionic Framework 1.x to 6.x are no longer supported](https://ionicframework.com/docs/reference/support#framework-maintenance-and-support-status). For extended support, considering visiting [Ionic's Enterprise offering](https://ionic.io/enterprise).
+ description: Which version(s) of Ionic Framework does this issue impact? [Ionic Framework 1.x to 7.x are no longer supported](https://ionicframework.com/docs/reference/support#framework-maintenance-and-support-status).
options:
- - v7.x
- v8.x
+ - v9.x
- Nightly
multiple: true
validations:
diff --git a/.github/workflows/actions/build-angular-server/action.yml b/.github/workflows/actions/build-angular-server/action.yml
index e21a39669bf..70c65316883 100644
--- a/.github/workflows/actions/build-angular-server/action.yml
+++ b/.github/workflows/actions/build-angular-server/action.yml
@@ -19,10 +19,25 @@ runs:
run: npm run sync
shell: bash
working-directory: ./packages/angular-server
+ - name: ποΈ Lint
+ run: npm run lint
+ shell: bash
+ working-directory: ./packages/angular-server
+ # No Typecheck step here. Unlike the rollup-built packages, which report
+ # type errors as warnings and still exit 0, ng-packagr fails the build on
+ # them, so the Build step below already covers this.
- name: ποΈ Build
run: npm run build.prod
shell: bash
working-directory: ./packages/angular-server
+ - name: Clean core package.json
+ run: git checkout ./package.json
+ shell: bash
+ working-directory: ./core
+ - name: π Check Diff
+ run: git diff --exit-code
+ shell: bash
+ working-directory: ./packages/angular-server
- uses: ./.github/workflows/actions/upload-archive
with:
name: ionic-angular-server
diff --git a/.github/workflows/actions/build-angular/action.yml b/.github/workflows/actions/build-angular/action.yml
index 12e1db1f5dc..121fa6f7da9 100644
--- a/.github/workflows/actions/build-angular/action.yml
+++ b/.github/workflows/actions/build-angular/action.yml
@@ -23,6 +23,9 @@ runs:
run: npm run lint
shell: bash
working-directory: ./packages/angular
+ # No Typecheck step here. Unlike the rollup-built packages, which report
+ # type errors as warnings and still exit 0, ng-packagr fails the build on
+ # them, so the Build step below already covers this.
- name: ποΈ Build
run: npm run build
shell: bash
@@ -39,4 +42,4 @@ runs:
with:
name: ionic-angular
output: ./packages/angular/AngularBuild.zip
- paths: ./packages/angular/dist
+ paths: ./packages/angular/dist ./packages/angular/css
diff --git a/.github/workflows/actions/build-core-stencil-prerelease/action.yml b/.github/workflows/actions/build-core-stencil-prerelease/action.yml
index 4597514ec1f..e35474df669 100644
--- a/.github/workflows/actions/build-core-stencil-prerelease/action.yml
+++ b/.github/workflows/actions/build-core-stencil-prerelease/action.yml
@@ -1,10 +1,14 @@
name: 'Build Ionic Core with Stencil Prerelease'
description: 'Build Ionic Core with a Prerelease Build of Stencil'
inputs:
- stencil-version:
+ stencil-core-version:
description: 'The NPM tag of @stencil/core to install.'
type: string
required: true
+ stencil-react-output-target-version:
+ description: 'The NPM tag of @stencil/react-output-target to install.'
+ type: string
+ required: true
runs:
using: 'composite'
steps:
@@ -13,13 +17,17 @@ runs:
with:
node-version: 24.x
- - name: πΈοΈ Install Dependencies
+ - name: πΈοΈ Install Core Dependencies
run: npm ci
working-directory: ./core
shell: bash
- - name: π¦ Install Stencil ${{ inputs.stencil-version }}
+ - name: π¦ Install Stencil Core ${{ inputs.stencil-core-version }}
+ working-directory: ./core
+ run: npm i @stencil/core@${{ inputs.stencil-core-version }}
+ shell: bash
+ - name: π¦ Install Stencil React Output Target ${{ inputs.stencil-react-output-target-version }}
working-directory: ./core
- run: npm i @stencil/core@${{ inputs.stencil-version }}
+ run: npm i @stencil/react-output-target@${{ inputs.stencil-react-output-target-version }}
shell: bash
- name: ποΈ Build Core
run: npm run build -- --ci --debug --verbose
@@ -29,8 +37,16 @@ runs:
run: npm run test.lazy-imports
working-directory: ./core
shell: bash
+ - name: πΈοΈ Install React Package Dependencies
+ run: npm ci
+ working-directory: ./packages/react
+ shell: bash
+ - name: ποΈ Lint React Package
+ run: npm run lint
+ working-directory: ./packages/react
+ shell: bash
- uses: ./.github/workflows/actions/upload-archive
with:
name: ionic-core
output: core/CoreBuild.zip
- paths: core/dist core/components core/src/foundations core/css core/hydrate core/loader core/src/components.d.ts core/package.json
+ paths: core/dist core/components core/src/foundations core/css core/hydrate core/loader core/src/components.d.ts core/package.json packages/react/src/components/components.ts
diff --git a/.github/workflows/actions/build-core/action.yml b/.github/workflows/actions/build-core/action.yml
index 3538e29072b..dca2a5c5134 100644
--- a/.github/workflows/actions/build-core/action.yml
+++ b/.github/workflows/actions/build-core/action.yml
@@ -37,4 +37,4 @@ runs:
output: core/CoreBuild.zip
# Include generated proxy files from Stencil output targets so
# framework builds can detect when they need to be updated
- paths: core/dist core/components core/src/foundations core/css core/hydrate core/loader core/src/components.d.ts core/api.txt packages/angular/src/directives/proxies.ts packages/angular/src/directives/proxies-list.ts packages/angular/standalone/src/directives/proxies.ts packages/vue/src/proxies.ts packages/react/src/components/proxies.ts packages/react/src/components/inner-proxies.ts packages/react/src/components/routing-proxies.ts
+ paths: core/dist core/components core/src/foundations core/css core/hydrate core/loader core/src/components.d.ts core/api.txt packages/angular/src/lazy/directives/proxies.ts packages/angular/src/lazy/directives/proxies-list.ts packages/angular/src/standalone/directives packages/vue/src/proxies.ts packages/react/src/components/components.ts packages/react/src/components/inner-proxies.ts packages/react/src/components/routing-proxies.ts
diff --git a/.github/workflows/actions/build-react-router/action.yml b/.github/workflows/actions/build-react-router/action.yml
index b104ebd429d..bb2cbb27eea 100644
--- a/.github/workflows/actions/build-react-router/action.yml
+++ b/.github/workflows/actions/build-react-router/action.yml
@@ -28,10 +28,22 @@ runs:
run: npm run lint
shell: bash
working-directory: ./packages/react-router
+ # The rollup build reports type errors as warnings and still succeeds, so
+ # this step is what keeps the package type-clean.
+ - name: π Typecheck
+ run: npm run typecheck
+ shell: bash
+ working-directory: ./packages/react-router
- name: ποΈ Build
run: npm run build
shell: bash
working-directory: ./packages/react-router
+ - name: Clean package.json updates
+ run: git checkout ./core/package.json ./packages/react/package.json
+ shell: bash
+ - name: π Check Diff
+ run: git diff --exit-code
+ shell: bash
- uses: ./.github/workflows/actions/upload-archive
with:
name: ionic-react-router
diff --git a/.github/workflows/actions/build-react/action.yml b/.github/workflows/actions/build-react/action.yml
index 5335ea47af2..b7d3ac6b99a 100644
--- a/.github/workflows/actions/build-react/action.yml
+++ b/.github/workflows/actions/build-react/action.yml
@@ -23,6 +23,12 @@ runs:
run: npm run lint
shell: bash
working-directory: ./packages/react
+ # The rollup build reports type errors as warnings and still succeeds, so
+ # this step is what keeps the package type-clean.
+ - name: π Typecheck
+ run: npm run typecheck
+ shell: bash
+ working-directory: ./packages/react
- name: ποΈ Build
run: npm run build
shell: bash
@@ -31,16 +37,14 @@ runs:
run: npm run test.spec
shell: bash
working-directory: ./packages/react
- - name: Clean core package.json
- run: git checkout ./package.json
- shell: bash
- working-directory: ./core
- - name: π Check Diff
- run: git diff --exit-code
- shell: bash
- working-directory: ./packages/react
- uses: ./.github/workflows/actions/upload-archive
with:
name: ionic-react
output: packages/react/ReactBuild.zip
- paths: packages/react/dist packages/react/css
+ paths: packages/react/dist packages/react/css packages/react/package.json
+ - name: Clean package.json updates
+ run: git checkout ./core/package.json ./packages/react/package.json
+ shell: bash
+ - name: π Check Diff
+ run: git diff --exit-code
+ shell: bash
diff --git a/.github/workflows/actions/build-vue-router/action.yml b/.github/workflows/actions/build-vue-router/action.yml
index bf47bb0dec3..68972ef2324 100644
--- a/.github/workflows/actions/build-vue-router/action.yml
+++ b/.github/workflows/actions/build-vue-router/action.yml
@@ -28,14 +28,22 @@ runs:
run: npm run lint
shell: bash
working-directory: ./packages/vue-router
+ # The rollup build reports type errors as warnings and still succeeds, so
+ # this step is what keeps the package type-clean.
+ - name: π Typecheck
+ run: npm run typecheck
+ shell: bash
+ working-directory: ./packages/vue-router
- name: ποΈ Build
run: npm run build
shell: bash
working-directory: ./packages/vue-router
- - name: π§ͺ Test Spec
- run: npm run test.spec
+ - name: Clean package.json updates
+ run: git checkout ./core/package.json
+ shell: bash
+ - name: π Check Diff
+ run: git diff --exit-code
shell: bash
- working-directory: ./packages/vue-router
- uses: ./.github/workflows/actions/upload-archive
with:
name: ionic-vue-router
diff --git a/.github/workflows/actions/build-vue/action.yml b/.github/workflows/actions/build-vue/action.yml
index 4a7375786d2..22c731e99ad 100644
--- a/.github/workflows/actions/build-vue/action.yml
+++ b/.github/workflows/actions/build-vue/action.yml
@@ -23,18 +23,22 @@ runs:
run: npm run lint
shell: bash
working-directory: ./packages/vue
+ # The rollup build reports type errors as warnings and still succeeds, so
+ # this step is what keeps the package type-clean.
+ - name: π Typecheck
+ run: npm run typecheck
+ shell: bash
+ working-directory: ./packages/vue
- name: ποΈ Build
run: npm run build
shell: bash
working-directory: ./packages/vue
- - name: Clean core package.json
- run: git checkout ./package.json
+ - name: Clean package.json updates
+ run: git checkout ./core/package.json ./packages/react/package.json
shell: bash
- working-directory: ./core
- name: π Check Diff
run: git diff --exit-code
shell: bash
- working-directory: ./packages/vue
- uses: ./.github/workflows/actions/upload-archive
with:
name: ionic-vue
diff --git a/.github/workflows/actions/test-core-clean-build/action.yml b/.github/workflows/actions/test-core-clean-build/action.yml
index 25c9a202652..f6275acbee5 100644
--- a/.github/workflows/actions/test-core-clean-build/action.yml
+++ b/.github/workflows/actions/test-core-clean-build/action.yml
@@ -12,10 +12,9 @@ runs:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- - name: Clean core package.json
- run: git checkout ./package.json
+ - name: Clean package.json updates
+ run: git checkout ./core/package.json ./packages/react/package.json
shell: bash
- working-directory: ./core
- name: π Check Diff
run: |
git diff --exit-code || {
diff --git a/.github/workflows/actions/test-react-router-e2e/action.yml b/.github/workflows/actions/test-react-router-e2e/action.yml
index 663ae0be575..beea150b549 100644
--- a/.github/workflows/actions/test-react-router-e2e/action.yml
+++ b/.github/workflows/actions/test-react-router-e2e/action.yml
@@ -32,6 +32,10 @@ runs:
run: npm install
shell: bash
working-directory: ./packages/react-router/test/build/${{ inputs.app }}
+ - name: π¦ Install Playwright Browsers
+ run: npx playwright install chromium
+ shell: bash
+ working-directory: ./packages/react-router/test/build/${{ inputs.app }}
- name: π Sync Built Changes
run: npm run sync
shell: bash
@@ -40,7 +44,13 @@ runs:
run: npm run build
shell: bash
working-directory: ./packages/react-router/test/build/${{ inputs.app }}
- - name: π§ͺ Run Tests
+ - name: π§ͺ Run Cypress Tests
run: npm run e2e
shell: bash
working-directory: ./packages/react-router/test/build/${{ inputs.app }}
+ - name: π Run Playwright Tests
+ run: npx playwright test --retries=2
+ env:
+ CI: true
+ shell: bash
+ working-directory: ./packages/react-router/test/build/${{ inputs.app }}
diff --git a/.github/workflows/actions/test-vue-e2e/action.yml b/.github/workflows/actions/test-vue-e2e/action.yml
index 5f7de702d08..2316e019a46 100644
--- a/.github/workflows/actions/test-vue-e2e/action.yml
+++ b/.github/workflows/actions/test-vue-e2e/action.yml
@@ -32,6 +32,10 @@ runs:
run: npm install
shell: bash
working-directory: ./packages/vue/test/build/${{ inputs.app }}
+ - name: π¦ Install Playwright Browsers
+ run: npx playwright install chromium
+ shell: bash
+ working-directory: ./packages/vue/test/build/${{ inputs.app }}
- name: π Sync
run: npm run sync
shell: bash
@@ -44,3 +48,9 @@ runs:
run: npm run test:e2e
shell: bash
working-directory: ./packages/vue/test/build/${{ inputs.app }}
+ - name: π Run Playwright Tests
+ run: npx playwright test --retries=2
+ env:
+ CI: true
+ shell: bash
+ working-directory: ./packages/vue/test/build/${{ inputs.app }}
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 540d873c5db..683f9de2004 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -140,7 +140,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- apps: [ng16, ng17, ng18, ng19, ng20]
+ apps: [ng18, ng19, ng20, ng21, ng22, ng22-zone]
needs: [build-angular, build-angular-server]
runs-on: ubuntu-latest
steps:
@@ -176,7 +176,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- apps: [reactrouter5]
+ apps: [reactrouter6-react18, reactrouter6-react19]
needs: [build-react, build-react-router]
runs-on: ubuntu-latest
steps:
@@ -198,7 +198,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- apps: [react17, react18, react19]
+ apps: [react18, react19]
needs: [build-react, build-react-router]
runs-on: ubuntu-latest
steps:
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index f17a5f9a264..df238d50502 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -15,7 +15,7 @@ jobs:
security-events: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- - uses: github/codeql-action/init@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7
+ - uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9
with:
languages: javascript
- - uses: github/codeql-action/analyze@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7
+ - uses: github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4.37.9
diff --git a/.github/workflows/migrate.yml b/.github/workflows/migrate.yml
new file mode 100644
index 00000000000..54990664544
--- /dev/null
+++ b/.github/workflows/migrate.yml
@@ -0,0 +1,93 @@
+name: 'Ionic Migrate'
+
+# Lint, test, and build the @ionic/migrate CLI.
+#
+# The workflow always triggers (no trigger-level `paths` filter) so the
+# `verify-migrate` gate always reports a status and can be marked a required
+# check: a path-filtered *trigger* would skip the whole workflow on unrelated
+# PRs, and a required check that never runs blocks merges forever. Instead the
+# `changes` job detects whether the package was touched and the heavy job runs
+# only then; `verify-migrate` reports success either way (skipped == fine).
+on:
+ pull_request:
+ branches: [ '**' ]
+ merge_group:
+ workflow_dispatch:
+
+# Lint/test/build only reads the repo; keep the token least-privilege.
+permissions:
+ contents: read
+
+concurrency:
+ group: migrate-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ changes:
+ runs-on: ubuntu-latest
+ outputs:
+ migrate: ${{ steps.filter.outputs.migrate }}
+ steps:
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ # Full history so the PR base commit is reachable for the diff below.
+ fetch-depth: 0
+ - name: Detect migrate changes
+ id: filter
+ shell: bash
+ run: |
+ # Fail the step (not the else branch) if git diff itself errors, so a
+ # broken detector can't masquerade as "package untouched".
+ set -euo pipefail
+ # Only pull_request runs get the path optimization. merge_group and
+ # manual dispatch run the (fast) tests unconditionally, so the merge
+ # queue never blocks on a check that was skipped by a stale diff.
+ if [ "${{ github.event_name }}" != "pull_request" ]; then
+ echo "migrate=true" >> "$GITHUB_OUTPUT"
+ exit 0
+ fi
+ base="${{ github.event.pull_request.base.sha }}"
+ changed="$(git diff --name-only "$base" HEAD)"
+ if echo "$changed" \
+ | grep -qE '^(packages/migrate/|\.github/workflows/migrate\.yml$)'; then
+ echo "migrate=true" >> "$GITHUB_OUTPUT"
+ else
+ echo "migrate=false" >> "$GITHUB_OUTPUT"
+ fi
+
+ test-migrate:
+ needs: changes
+ if: ${{ needs.changes.outputs.migrate == 'true' }}
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: ./packages/migrate
+ steps:
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
+ with:
+ node-version: 24.x
+ cache: 'npm'
+ cache-dependency-path: packages/migrate/package-lock.json
+ - name: Install Dependencies
+ run: npm ci
+ - name: Lint
+ run: npm run lint
+ - name: Test
+ run: npm test
+ - name: Build
+ run: npm run build
+
+ # Always-running required gate. See header comment for why this exists.
+ # Green when the package was untouched (test-migrate skipped) or tests pass;
+ # red when detection failed or the tests actually failed.
+ verify-migrate:
+ if: ${{ always() }}
+ needs: [ changes, test-migrate ]
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check results
+ # changes.result != 'success' catches a failed/cancelled detector,
+ # whose skipped test-migrate would otherwise slip through as green.
+ if: ${{ needs.changes.result != 'success' || needs.test-migrate.result == 'failure' || needs.test-migrate.result == 'cancelled' }}
+ run: exit 1
diff --git a/.github/workflows/release-ionic.yml b/.github/workflows/release-ionic.yml
index 9671a057c28..e8b7030966d 100644
--- a/.github/workflows/release-ionic.yml
+++ b/.github/workflows/release-ionic.yml
@@ -81,13 +81,12 @@ jobs:
version: ${{ inputs.version }}
preid: ${{ inputs.preid }}
working-directory: 'packages/angular'
- folder: './dist'
- name: Cache Built @ionic/angular
uses: ./.github/workflows/actions/upload-archive
with:
name: ionic-angular
output: packages/angular/AngularBuild.zip
- paths: packages/angular/dist
+ paths: packages/angular/dist packages/angular/css
release-react:
needs: [release-core]
diff --git a/.github/workflows/release-migrate.yml b/.github/workflows/release-migrate.yml
new file mode 100644
index 00000000000..d119e6830de
--- /dev/null
+++ b/.github/workflows/release-migrate.yml
@@ -0,0 +1,72 @@
+name: 'Release @ionic/migrate'
+
+on:
+ workflow_call:
+ inputs:
+ tag:
+ description: 'Which npm tag should this be published to?'
+ required: true
+ type: string
+
+permissions:
+ contents: read
+ id-token: write
+
+jobs:
+ release-migrate:
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: ./packages/migrate
+ steps:
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ - name: π’ Configure Node for Publish
+ uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
+ with:
+ node-version: 24.x
+ registry-url: 'https://registry.npmjs.org'
+ scope: '@ionic'
+ cache: 'npm'
+ cache-dependency-path: packages/migrate/package-lock.json
+ - name: π¦ Install latest npm
+ run: npm install -g npm@latest
+ shell: bash
+ - name: πΈοΈ Install Dependencies
+ run: npm ci
+ shell: bash
+ - name: π Resolve Version
+ id: resolve-version
+ run: |
+ set -euo pipefail
+ version="$(node -p "require('./package.json').version")"
+ echo "version=$version" >> "$GITHUB_OUTPUT"
+ echo "Releasing @ionic/migrate@$version to the '${{ inputs.tag }}' tag"
+ shell: bash
+ - name: π§ Ensure Version Is Unpublished
+ run: |
+ set -euo pipefail
+ version="${{ steps.resolve-version.outputs.version }}"
+ # `npm view` exits non-zero both for an unpublished version and for a
+ # package that does not exist yet, and the latter is the expected state
+ # on the very first release. So inspect stdout rather than the exit
+ # code: empty output means the version is free to publish.
+ if [ -n "$(npm view "@ionic/migrate@$version" version 2>/dev/null || true)" ]; then
+ echo "::error::@ionic/migrate@$version is already published. Bump the version in packages/migrate/package.json."
+ exit 1
+ fi
+ shell: bash
+ - name: π Lint
+ run: npm run lint
+ shell: bash
+ - name: π§ͺ Test
+ run: npm test
+ shell: bash
+ - name: ποΈ Run Build
+ run: npm run build
+ shell: bash
+ # `--access public` is not passed here because publishConfig.access in
+ # package.json already sets it; a scoped package would otherwise default to
+ # restricted on its first publish.
+ - name: π Publish to NPM
+ run: npm publish --tag ${{ inputs.tag }} --provenance
+ shell: bash
diff --git a/.github/workflows/release-orchestrator.yml b/.github/workflows/release-orchestrator.yml
index a0c05cbcd58..67964f340d5 100644
--- a/.github/workflows/release-orchestrator.yml
+++ b/.github/workflows/release-orchestrator.yml
@@ -15,6 +15,7 @@ on:
options:
- dev
- production
+ - migrate
version:
description: 'Which version should be published? (Only for production releases)'
required: false
@@ -28,7 +29,7 @@ on:
- premajor
- prerelease
tag:
- description: 'Which npm tag should this be published to? (Only for production releases)'
+ description: 'Which npm tag should this be published to? (Only for production and migrate releases)'
required: false
type: choice
default: latest
@@ -68,6 +69,16 @@ jobs:
uses: ./.github/workflows/dev-build.yml
secrets: inherit
+ run-migrate:
+ if: ${{ github.event_name == 'workflow_dispatch' && inputs.release-type == 'migrate' }}
+ permissions:
+ contents: read
+ id-token: write
+ uses: ./.github/workflows/release-migrate.yml
+ secrets: inherit
+ with:
+ tag: ${{ inputs.tag }}
+
run-production:
if: ${{ github.event_name == 'workflow_dispatch' && inputs.release-type == 'production' }}
permissions:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index b4228d33841..bb552039012 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -135,11 +135,13 @@ jobs:
"/npm/@ionic/core@6/dist/ionic/ionic.esm.js",
"/npm/@ionic/core@7/dist/ionic/ionic.esm.js",
"/npm/@ionic/core@8/dist/ionic/ionic.esm.js",
+ "/npm/@ionic/core@9/dist/ionic/ionic.esm.js",
"/npm/@ionic/core@latest/dist/ionic/ionic.esm.js",
"/npm/@ionic/core@next/dist/ionic/ionic.esm.js",
"/npm/@ionic/core@6/css/ionic.bundle.css",
"/npm/@ionic/core@7/css/ionic.bundle.css",
"/npm/@ionic/core@8/css/ionic.bundle.css",
+ "/npm/@ionic/core@9/css/ionic.bundle.css",
"/npm/@ionic/core@latest/css/ionic.bundle.css"
"/npm/@ionic/core@next/css/ionic.bundle.css"
]}'
diff --git a/.github/workflows/stencil-nightly.yml b/.github/workflows/stencil-nightly.yml
index a9be239edfa..4348122bb98 100644
--- a/.github/workflows/stencil-nightly.yml
+++ b/.github/workflows/stencil-nightly.yml
@@ -9,11 +9,16 @@ on:
- cron: '00 06 * * 1-5'
workflow_dispatch:
inputs:
- npm_release_tag:
+ npm_release_tag_core:
required: true
type: string
- description: What version should be pulled from NPM?
+ description: What stencil/core version should be pulled from NPM?
default: nightly
+ npm_release_tag_react_output_target:
+ required: true
+ type: string
+ description: What stencil/react-output-target version should be pulled from NPM?
+ default: latest
# When pushing a new commit we should
# cancel the previous test run to not
@@ -29,7 +34,9 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: ./.github/workflows/actions/build-core-stencil-prerelease
with:
- stencil-version: ${{ inputs.npm_release_tag || 'nightly' }}
+ stencil-core-version: ${{ inputs.npm_release_tag_core || 'nightly' }}
+ stencil-react-output-target-version: ${{ inputs.npm_release_tag_react_output_target || 'latest' }}
+
test-core-clean-build:
needs: [build-core-with-stencil-nightly]
@@ -52,7 +59,7 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: ./.github/workflows/actions/test-core-spec
with:
- stencil-version: ${{ inputs.npm_release_tag || 'nightly' }}
+ stencil-version: ${{ inputs.npm_release_tag_core || 'nightly' }}
test-core-screenshot:
strategy:
@@ -150,7 +157,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- apps: [ng16, ng17, ng18, ng19, ng20]
+ apps: [ng18, ng19, ng20, ng21, ng22, ng22-zone]
needs: [build-angular, build-angular-server]
runs-on: ubuntu-latest
steps:
@@ -173,6 +180,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ - name: Install Stencil React Output Target
+ working-directory: ./packages/react
+ run: npm i @stencil/react-output-target@${{ inputs.npm_release_tag_react_output_target || 'latest' }}
+ shell: bash
- uses: ./.github/workflows/actions/build-react
build-react-router:
@@ -186,7 +197,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- apps: [reactrouter5]
+ apps: [reactrouter6-react18, reactrouter6-react19]
needs: [build-react, build-react-router]
runs-on: ubuntu-latest
steps:
@@ -208,7 +219,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- apps: [react17, react18, react19]
+ apps: [react18, react19]
needs: [build-react, build-react-router]
runs-on: ubuntu-latest
steps:
diff --git a/.gitignore b/.gitignore
index e610d8a11dd..d49be2c644e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -68,6 +68,7 @@ core/www/
# playwright
core/test-results/
core/playwright-report/
+packages/angular/test-results/
# ground truths generated outside of docker should not be committed to the repo
core/**/*-snapshots/*
diff --git a/BREAKING.md b/BREAKING.md
index a3cb3168f3d..8251366fe8c 100644
--- a/BREAKING.md
+++ b/BREAKING.md
@@ -14,15 +14,77 @@ This is a comprehensive list of the breaking changes introduced in the major ver
## Version 9.x
+- [Browser and Platform Support](#version-9x-browser-platform-support)
+- [Package Exports](#version-9x-package-exports)
- [Components](#version-9x-components)
- [Button](#version-9x-button)
- [Card](#version-9x-card)
- [Chip](#version-9x-chip)
- [Datetime](#version-9x-datetime)
- [Grid](#version-9x-grid)
+ - [Input](#version-9x-input)
- [Input Otp](#version-9x-input-otp)
+ - [Legacy Picker](#version-9x-legacy-picker)
+ - [Modal](#version-9x-modal)
+ - [Nav](#version-9x-nav)
- [Radio Group](#version-9x-radio-group)
+ - [Router Outlet](#version-9x-router-outlet)
+ - [Searchbar](#version-9x-searchbar)
+ - [Select](#version-9x-select)
- [Textarea](#version-9x-textarea)
+- [Framework Specific](#version-9x-framework-specific)
+ - [Angular](#version-9x-angular)
+ - [React](#version-9x-react)
+ - [Vue](#version-9x-vue)
+
+
Browser and Platform Support
+
+This section details the desktop browser, JavaScript framework, and mobile platform versions that are supported by Ionic 9.
+
+**Minimum Browser Versions**
+| Desktop Browser | Supported Versions |
+| --------------- | ------------------ |
+| Chrome | 89+ |
+| Safari | 16+ |
+| Edge | 89+ |
+| Firefox | 75+ |
+
+**Minimum JavaScript Framework Versions**
+| Framework | Supported Version |
+| --------- | --------------------- |
+| Angular | 18+ |
+| React | 18 or 19 |
+| Vue | 3.5+ |
+
+**Minimum Mobile Platform Versions**
+| Platform | Supported Version |
+| -------- | ---------------------- |
+| iOS | 16+ |
+| Android | 5.1+ with Chromium 89+ |
+
+**Minimum Native Runtime Versions**
+| Native Runtime | Supported Version |
+| -------------- | ----------------- |
+| Capacitor | 7+ |
+
+Ionic's native platform detection no longer checks the Capacitor 2 `isNative` flag. `isCapacitorNative` now relies solely on `Capacitor.isNativePlatform()`, which was added in Capacitor 3. Apps running Capacitor 2 will no longer be detected as a native/hybrid platform, so `isPlatform('capacitor')`, `isPlatform('hybrid')`, and `getPlatforms()` will report web instead of native. Upgrade to a supported Capacitor version (7 or later).
+
+
Package Exports
+
+`@ionic/core`'s `package.json` now declares an `exports` field. Subpaths like `@ionic/core/components` and `@ionic/core/loader` previously failed under Node ESM (Angular 21's default Vitest builder, raw Node, etc.) with `ERR_UNSUPPORTED_DIR_IMPORT`, because the strict ESM resolver doesn't read the nested `package.json` files this package relied on. The new `exports` map declares the documented subpaths explicitly.
+
+`exports` is an allowlist. Apps using Node ESM, webpack 5, or TypeScript `moduleResolution: "bundler"`/`"node16"`/`"nodenext"` that import from undocumented internal paths need to switch to one of the supported subpaths:
+
+| Subpath | Use |
+| ---------------------------------- | ----------------------------------------------------- |
+| `@ionic/core` | Root entry, controllers, animation builders |
+| `@ionic/core/components` | Custom-element constructors and shared utilities |
+| `@ionic/core/components/ion-*.js` | Single-component custom-element constructor |
+| `@ionic/core/loader` | `defineCustomElements` lazy loader |
+| `@ionic/core/hydrate` | SSR hydration entry |
+| `@ionic/core/css/*.css` | Global stylesheets and palettes |
+
+Apps on `moduleResolution: "node"` (classic) and webpack 4 keep resolving through the legacy fields and are unaffected.
Components
@@ -186,12 +248,145 @@ To reorder two columns where column 1 has `size="9" push="3"` and column 2 has `
```
+
Input
+
+**`autocorrect` Property Type Changed to Boolean**
+
+The `autocorrect` property on `ion-input` is now a `boolean` and defaults to `false`. It was previously typed as `'on' | 'off'` with a default of `'off'`. This resolves a type conflict introduced when TypeScript 5.9 added `autocorrect: boolean` to the DOM `HTMLElement` interface.
+
+The string form no longer behaves the same way. Because an HTML attribute coerces to `true` for any non-empty string, `autocorrect="off"` now evaluates to `true` (autocorrect enabled). Migrate to the boolean property:
+
+- Remove the attribute to keep autocorrect disabled (the default).
+- Use a property binding to enable it: `[autocorrect]="true"` (Angular), `autocorrect={true}` (React), or `:autocorrect="true"` (Vue).
+
+**Floating Label Behavior**
+
+Floating labels no longer automatically float when the input contains slotted content. Labels float only when the input is focused or has a value.
+
+**Internal DOM Structure Changes**
+
+The internal DOM structure has been reorganized to support floating labels with slotted content.
+
+Added:
+- `.input-start`
+- `.input-control`
+- `.input-end`
+
+Restructured:
+- `.label-text-wrapper` moved from `.input-wrapper` into `.input-control`
+- `.native-wrapper` moved from `.input-wrapper` into `.input-control`
+- Start slot moved from `.native-wrapper` into `.input-start`
+- Clear button icon moved from `.native-wrapper` into `.input-end`
+- End slot moved from `.native-wrapper` into `.input-end`
+- `.input-control` now contains the label text and native `input`, while start/end content is separated into dedicated wrappers
+
+Update your selectors to account for these structural changes:
+
+```diff
+-ion-input .input-wrapper .native-wrapper { }
++ion-input .input-control .native-wrapper { }
+
+-ion-input .input-wrapper .native-wrapper [slot="start"] { }
++ion-input .input-start [slot="start"] { }
+
+-ion-input .input-wrapper .native-wrapper .input-clear-icon { }
++ion-input .input-end .input-clear-icon { }
+
+-ion-input .input-wrapper .native-wrapper [slot="end"] { }
++ion-input .input-end [slot="end"] { }
+```
+
Input Otp
Converted `ion-input-otp` to use [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM).
If you were targeting the internals of `ion-input-otp` in your CSS, you will need to target the `group`, `container`, `native`, `separator` or `description` [Shadow Parts](https://ionicframework.com/docs/theming/css-shadow-parts) instead, or use the provided CSS Variables.
+
Legacy Picker
+
+- `ion-picker-legacy` and `ion-picker-legacy-column` have been removed. The legacy picker component has been replaced with an inline picker component.
+ - Usages such as `ion-picker-legacy` or `IonPickerLegacy` should be changed to `ion-picker` and `IonPicker`, respectively.
+- Remove any usages of `pickerController`. If using React, remove any usages of the `useIonPicker` hook. These controller-based APIs have been removed. Use the inline picker component instead.
+- Remove any usages of the `PickerOptions`, `PickerButton`, `PickerColumn`, and `PickerColumnOption` type exports. These types were associated with the legacy picker and have been removed.
+
+
Modal
+
+The `handleBehavior` property on `ion-modal` now defaults to `"cycle"` instead of `"none"`. For sheet modals that display a handle, this means the handle is now focusable and activating it (by click, keyboard, or screen reader) cycles the sheet through its available breakpoints. This matches the native iOS sheet behavior and keeps sheet modals operable for assistive technology users by default.
+
+Sheet modals that relied on the handle being inert should set `handleBehavior="none"` to restore the previous behavior:
+
+```html
+
+```
+
+
Nav
+
+`ion-nav` no longer integrates with `ion-router`. It is now a standalone imperative stack navigation component, driven only through its own API (`root`, `push`, `pop`, `setRoot`, etc.) and `ion-nav-link`.
+
+The following behaviors have been removed:
+
+- The router no longer discovers or drives an `ion-nav`. Placing an `ion-nav` inside an `ion-router` no longer turns it into a routed outlet.
+- Navigating an `ion-nav` (via `push`, `pop`, `ion-nav-link`, or the swipe-to-go-back gesture) no longer updates the URL, and the router's navigation guards no longer run for `ion-nav` transitions.
+- The internal `setRouteId()` and `getRouteId()` methods and the `updateURL` nav option have been removed.
+
+Apps that relied on `ion-nav` to update the URL (for example, pushing components and expecting the browser URL to change) should use `ion-router-outlet` for URL-based routing. Keep the `ion-route` definitions and swap the outlet element:
+
+```diff
+
+
+
+
+
+-
++
+```
+
+An `ion-nav` can still be used inside a routed page for local, URL-less stack navigation. It manages its own stack via `root` and `ion-nav-link`, and the URL never changes as you push and pop:
+
+```html
+
+
+
+
+```
+
Radio Group
Converted `ion-radio-group` to use [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM).
@@ -200,8 +395,503 @@ If you were targeting the internals of `ion-radio-group` in your CSS, you will n
Additionally, the `radio-group-wrapper` div element has been removed, causing slotted elements to be direct children of the `ion-radio-group`.
+
Router Outlet
+
+`ion-router-outlet` now exposes a `swipeGesture` property that controls the swipe-to-go-back gesture per outlet. This property defaults to `true` in `"ios"` mode and `false` in `"md"` mode.
+
+**`swipeBackEnabled` Config Behavior Change**
+
+In React and Vue, the `swipeBackEnabled` config option is now read once when the outlet mounts. Apps that dynamically toggle this config value at runtime should migrate to the `swipeGesture` property instead:
+
+**React:**
+
+```diff
+- setupIonicReact({ swipeBackEnabled: someCondition });
++
+```
+
+**Vue:**
+
+```diff
+- createApp(App).use(IonicVue, { swipeBackEnabled: someCondition })
++
+```
+
+**Disabling Swipe-to-Go-Back**
+
+To disable the gesture on a specific outlet, set `swipeGesture` to `false`:
+
+```tsx
+
+```
+
+The `swipeBackEnabled` config option is still respected as the initial default and does not need to change for apps that set it once at startup.
+
+
Searchbar
+
+The `autocorrect` property on `ion-searchbar` is now a `boolean` and defaults to `false`. It was previously typed as `'on' | 'off'` with a default of `'off'`. This resolves a type conflict introduced when TypeScript 5.9 added `autocorrect: boolean` to the DOM `HTMLElement` interface.
+
+The string form no longer behaves the same way. Because an HTML attribute coerces to `true` for any non-empty string, `autocorrect="off"` now evaluates to `true` (autocorrect enabled). Migrate to the boolean property:
+
+- Remove the attribute to keep autocorrect disabled (the default).
+- Use a property binding to enable it: `[autocorrect]="true"` (Angular), `autocorrect={true}` (React), or `:autocorrect="true"` (Vue).
+
+
Select
+
+**`ionChange` Only Fires When the Value Changes**
+
+The `ionChange` event on `ion-select` now only fires when the selected value actually changes. Previously, the `alert` and `action-sheet` interfaces emitted `ionChange` every time the overlay was confirmed, even when the user chose the option that was already selected. This aligns the `alert` and `action-sheet` interfaces with the existing behavior of the `popover` and `modal` interfaces, and with the documented contract of `ionChange`.
+
+Apps that relied on `ionChange` firing on every confirmation (for example, to detect overlay dismissal without a value change) should listen for `ionDismiss` instead, or use the `didDismiss` event on the underlying alert or action sheet.
+
+**Action Sheet Interface `selected` Role Removed**
+
+When using `interface="action-sheet"`, `ion-select` no longer assigns the `selected` role to the action sheet button for the currently selected option. This aligns the `action-sheet` interface with the `alert`, `popover`, and `modal` interfaces, none of which assign this role. This does not change the selected option's styling.
+
+Previously, the `selected` role was assigned only to the option matching the select's current value. Because the dismiss role mirrors the tapped button, this surfaced in just one case: re-selecting the already-selected option dismissed the action sheet with `role: "selected"` in `ionActionSheetDidDismiss`. Tapping any other option changed the value and dismissed with `role: ""`. Now that the role is no longer assigned, both cases dismiss with `role: undefined`. Apps that inspected this role to detect that a value was chosen, such as reading `role` from the underlying action sheet's `onDidDismiss` result, should listen for `ion-select`'s `ionChange` event instead, which emits the selected value when the selection changes.
+
+**Floating Label Behavior**
+
+Floating labels no longer automatically float when the select contains slotted content. Labels float only when the select is focused or has a value. Additionally, when using a floating label, the placeholder is only visible when the select is focused.
+
+**Internal DOM Structure Changes**
+
+The internal DOM structure has been reorganized to support floating labels with slotted content. This changes the structure and location of several exposed shadow parts.
+
+Added:
+- `.select-start` β `part="start"`
+- `.select-control` β `part="control"`
+- `.select-end` β `part="end"`
+
+Removed:
+- `.select-wrapper-inner` β `part="inner"`
+
+Restructured:
+- `.label-text-wrapper` remains `part="label"` but moved from `.select-wrapper` into `.select-control`
+- `.native-wrapper` remains `part="container"` but moved from `.select-wrapper-inner` into `.select-control`
+- Start slot moved from `.select-wrapper-inner` into `.select-start` (`part="start"`)
+- End slot moved from `.select-wrapper-inner` into `.select-end` (`part="end"`)
+- `.select-icon` remains `part="icon"` but its location depends on the label state:
+ - With a start/end label, the icon is inside `.native-wrapper`
+ - With a floating/stacked label, the icon is inside `.select-end`
+
+Update selectors that target the exposed shadow parts to account for the new structure:
+
+If you currently target `part="inner"`, that part has been removed. Update those styles to target the new parts as appropriate.
+
+If you target `part="label"`, `part="container"`, or `part="icon"`, the part names remain unchanged, but their position in the shadow DOM has changed. This may affect styles that depend on the relationship or layout of these parts.
+
+Use the new `part="start"`, `part="control"`, and `part="end"` parts to target the new structural wrappers.
+
Textarea
+**Floating Label Behavior**
+
+Floating labels no longer automatically float when the textarea contains slotted content. Labels float only when the textarea is focused or has a value.
+
+**Internal DOM Structure Changes**
+
+The internal DOM structure has been reorganized to support floating labels with slotted content.
+
+Removed: `.textarea-wrapper-inner`
+
+Added: `.textarea-control`
+
+Renamed:
+- `.start-slot-wrapper` β `.textarea-start`
+- `.end-slot-wrapper` β `.textarea-end`
+
+Restructured:
+- `.label-text-wrapper` moved from `.textarea-wrapper-inner` into `.textarea-control`
+- `.native-wrapper` moved from `.textarea-wrapper-inner` into `.textarea-control`
+- `.start-slot-wrapper` moved from `.textarea-wrapper-inner` to `.textarea-wrapper` and was renamed `.textarea-start`
+- `.end-slot-wrapper` moved from `.textarea-wrapper-inner` to `.textarea-wrapper` and was renamed `.textarea-end`
+
+Update your selectors to account for these structural changes:
+
+```diff
+-ion-textarea .textarea-wrapper-inner .native-wrapper { }
++ion-textarea .textarea-control .native-wrapper { }
+
+-ion-textarea .start-slot-wrapper [slot="start"] { }
++ion-textarea .textarea-start [slot="start"] { }
+
+-ion-textarea .end-slot-wrapper [slot="end"] { }
++ion-textarea .textarea-end [slot="end"] { }
+```
+
+**Minimum Height Change**
+
+The minimum height of textarea in Material Design (`md` mode) is now `72px`. At the default number of rows this makes textareas the same height regardless of the `fill` property or `labelPlacement`. Previously the minimum height was:
+
+| Fill | Label placement | Previous minimum height |
+| --- | --- | --- |
+| default | `start`, `end`, `fixed` | `44px` |
+| default | `floating`, `stacked` | `56px` |
+| `solid`, `outline` | any | `56px` |
+
+These were minimums, not the heights textareas actually rendered at. A textarea with content in the `start` or `end` slots was already taller than its minimum, so the change affects it differently. For example, a `fill="solid"` textarea with slotted icons and buttons previously rendered at `72px` with a `start` label and `81px` with a `floating` label. Both are now `72px`, so that floating label case is `9px` shorter than before rather than taller.
+
+Because `72px` is taller than two rows of text, `rows` values below `3` no longer change the height of the textarea in `md` mode: `rows="1"` and `rows="2"` both render at `72px`.
+
+If you were relying on the previous heights, or you need `rows` to control the height, override the minimum height back. The override has to be more specific than the component's own style, so a bare `ion-textarea` selector will not apply. Add a custom class to the textarea to increase specificity:
+
+```css
+/* Add a custom class to the textarea */
+ion-textarea.custom {
+ min-height: 44px;
+}
+```
+
Converted `ion-textarea` to use [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM).
If you were targeting the internals of `ion-textarea` in your CSS, you will need to target the `wrapper`, `container`, `label`, `native`, `supporting-text`, `helper-text`, `error-text`, `counter`, or `bottom` [Shadow Parts](https://ionicframework.com/docs/theming/css-shadow-parts) instead, or use the provided CSS Variables.
+
+
Framework Specific
+
+
Angular
+
+**Minimum Angular Version**
+
+Ionic 9 requires Angular 18 or later. Angular 16 and 17 are no longer supported.
+
+**Standalone Components Imported by Default**
+
+Following industry standards, Ionic 9 makes standalone components the default import path. Standalone component imports have changed from `@ionic/angular/standalone` to `@ionic/angular`. Lazy-loaded component imports have changed from `@ionic/angular` to `@ionic/angular/lazy`.
+
+**IonicModule Deprecation**
+
+`IonicModule` is deprecated in Ionic 9 and will be removed in a future major version. It remains fully functional in Ionic 9, so existing applications continue to work without changes.
+
+Applications should migrate to `provideIonicAngular()`, which works in both standalone and NgModule-based applications. For an NgModule-based app, replace `IonicModule.forRoot(config)` in the `imports` array with `provideIonicAngular(config)` in the `providers` array. Any config passed to `IonicModule.forRoot()` can be passed as an object to `provideIonicAngular()`. Refer to the [build options guide](https://ionicframework.com/docs/angular/build-options) for migration steps.
+
+**Zoneless Change Detection by Default**
+
+Ionic 9 defaults to zoneless change detection. Angular 21 bootstraps zoneless out of the box, so a new Ionic 9 app on Angular 21 runs without Zone.js and requires no change-detection provider. The `ng add @ionic/angular` schematic no longer registers `provideZoneChangeDetection()`.
+
+Because Zone.js no longer triggers change detection automatically, component state that you update from an asynchronous callback that Angular doesn't wrap (awaiting an overlay result such as `modal.onWillDismiss()`, `setTimeout`, RxJS subscriptions, `Platform` events) no longer re-renders on its own. Update a signal or call `ChangeDetectorRef.markForCheck()` in those callbacks. Template event bindings, `@HostListener`, reactive forms, and Ionic lifecycle hooks (`ionViewWillEnter`, etc.) that set state synchronously are unaffected. Refer to the [Zoneless Change Detection guide](https://ionicframework.com/docs/angular/zoneless) for the patterns.
+
+On Angular 18 through 20, Zone.js remains Angular's default, so those versions are unaffected and require no change. To adopt zoneless there, add `provideZonelessChangeDetection()` (named `provideExperimentalZonelessChangeDetection()` on Angular 18 and 19).
+
+**Keeping Zone.js on Angular 21 (optional)**
+
+To keep using Zone.js on Angular 21, opt back in with `provideZoneChangeDetection()` and keep `zone.js` in your polyfills.
+
+Standalone bootstrap:
+
+```diff
+ import { bootstrapApplication } from '@angular/platform-browser';
++ import { provideZoneChangeDetection } from '@angular/core';
+
+ bootstrapApplication(AppComponent, {
+ providers: [
++ provideZoneChangeDetection(),
+ // ...other providers
+ ],
+ });
+```
+
+NgModule bootstrap:
+
+```diff
+ import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
++ import { provideZoneChangeDetection } from '@angular/core';
+
+ platformBrowserDynamic()
+- .bootstrapModule(AppModule)
++ .bootstrapModule(AppModule, {
++ applicationProviders: [provideZoneChangeDetection()],
++ })
+ .catch((err) => console.error(err));
+```
+
+Angular forbids `provideZoneChangeDetection()` inside an NgModule's `providers` array, so for NgModule apps it must be passed as `applicationProviders` on the `bootstrapModule()` call. Both paths also require `zone.js` in your polyfills, which Angular 21's default scaffold omits:
+
+```ts
+// src/polyfills.ts
+import 'zone.js';
+```
+
+**OnPush by Default on Angular 22**
+
+Angular 22 changes the default change detection strategy to `OnPush` for components that don't declare one. Combined with the zoneless default above, any component state that you mutate as a plain field from an Ionic lifecycle hook (`ionViewWillEnter`, etc.) no longer re-renders on its own. Run `ng update`, which migrates existing components to eager change detection and preserves the previous behavior, or use a signal (or `ChangeDetectorRef.markForCheck()`) for state set in those hooks. Ionic's own Angular components already declare `OnPush` explicitly and are unaffected. Angular 18 through 21 keep the eager default, so they require no change.
+
+**TypeScript**
+
+Ionic 9 supports TypeScript 5.4 or later, matching the minimum for Angular 18. Angular 21 requires TypeScript 5.9 or later, and Angular 22 requires TypeScript 6.0 or later, per Angular's own requirements.
+
+**Node.js**
+
+Angular 22 raises the minimum Node.js version to `^22.22.3 || ^24.15.0 || ^26.0.0`. Angular 18 through 21 are unaffected.
+
+**Module Resolution**
+
+`@ionic/angular` is now published with `exports`-based subpath resolution. Apps using TypeScript `moduleResolution: "node"` (classic) can fail to resolve subpaths such as `@ionic/angular/lazy`. Set `moduleResolution` to `"bundler"` (the default for `ng new` on Angular 17 and later). Refer to [Package Exports](#version-9x-package-exports).
+
+**CSS Imports No Longer Use the `~` Prefix**
+
+Angular's current build pipeline no longer supports the webpack-loader `~` prefix in CSS `@import` statements:
+
+```diff
+- @import '~@ionic/angular/css/core.css';
++ @import '@ionic/angular/css/core.css';
+```
+
+
React
+
+The `@ionic/react` and `@ionic/react-router` packages now require React 18 or 19. React 17 is no longer supported.
+
+The `@ionic/react-router` package now requires React Router v6. React Router v5 is no longer supported.
+
+**Minimum Version Requirements**
+| Package | Supported Version |
+| ---------------- | ----------------- |
+| react | 18 or 19 |
+| react-dom | 18 or 19 |
+| react-router | 6.4.0+ |
+| react-router-dom | 6.4.0+ |
+
+**TypeScript**
+
+The `@ionic/react` package now requires TypeScript 5.4 or later. Its type definitions use `NoInfer`, which TypeScript added in 5.4. This matches the minimum that `@ionic/angular` already requires.
+
+**Typed Overlay Hook Props**
+
+The `useIonModal` and `useIonPopover` hooks type `componentProps` against the component they are given, instead of accepting `any`. Props that do not match the component are a compile error, and `componentProps` is required when the component declares required props. Applications passing incorrect props will see new type errors at build time rather than failing at runtime.
+
+```diff
+ const Modal: React.FC<{ title: string }> = ({ title }) => {title};
+
+- const [present, dismiss] = useIonModal(Modal, { subtitle: 'Wrong' });
++ const [present, dismiss] = useIonModal(Modal, { title: 'Hello' });
+```
+
+Props are read from the component rather than from `componentProps`, so a component declared inline needs its props annotated:
+
+```diff
+- const [present, dismiss] = useIonModal(({ name }) =>
, { name: 'Dave' });
+```
+
+Passing a JSX element rather than a component is unchanged, and `componentProps` is not type checked in that case.
+
+`npx @ionic/migrate` reports the calls this affects and names what is wrong with each, but does not rewrite them, since the right fix depends on what the call was meant to do. For the inline case above, `--experimental` can annotate the parameter from the `componentProps` object literal being passed.
+
+React Router v6 introduces several API changes that will require updates to your application's routing configuration:
+
+**Route Definition Changes**
+
+The `component` prop has been replaced with the `element` prop, which accepts JSX:
+
+```diff
+-
++ } />
+```
+
+**Redirect Changes**
+
+The `` component has been replaced with ``:
+
+```diff
+- import { Redirect } from 'react-router-dom';
++ import { Navigate } from 'react-router-dom';
+
+-
++
+```
+
+**Nested Route Paths**
+
+Routes that contain nested routes or child `IonRouterOutlet` components need a `/*` suffix to match sub-paths:
+
+```diff
+- } />
++ } />
+```
+
+**Accessing Route Parameters**
+
+Route parameters are now accessed via the `useParams` hook instead of props:
+
+```diff
+- import { RouteComponentProps } from 'react-router-dom';
++ import { useParams } from 'react-router-dom';
+
+- const MyComponent: React.FC> = ({ match }) => {
+- const id = match.params.id;
++ const MyComponent: React.FC = () => {
++ const { id } = useParams<{ id: string }>();
+```
+
+**RouteComponentProps Removed**
+
+The `RouteComponentProps` type and its `history`, `location`, and `match` props are no longer available in React Router v6. Use the equivalent hooks instead:
+
+- `history` -> `useNavigate` (see below) or `useIonRouter`
+- `match.params` -> `useParams` (covered above)
+- `location` -> `useLocation`
+
+```diff
+- import { RouteComponentProps } from 'react-router-dom';
++ import { useNavigate, useLocation } from 'react-router-dom';
++ import { useIonRouter } from '@ionic/react';
+
+- const MyComponent: React.FC = ({ history, location }) => {
+- history.push('/path');
+- history.replace('/path');
+- history.goBack();
+- console.log(location.pathname);
++ const MyComponent: React.FC = () => {
++ const navigate = useNavigate();
++ const router = useIonRouter();
++ const location = useLocation();
++ // In an event handler or useEffect:
++ navigate('/path');
++ navigate('/path', { replace: true });
++ router.goBack();
++ console.log(location.pathname);
+```
+
+**Exact Prop Removed**
+
+The `exact` prop is no longer needed. React Router v6 routes match exactly by default. To match sub-paths, use a `/*` suffix on the path:
+
+```diff
+-
++
+```
+
+**Render Prop Removed**
+
+The `render` prop has been replaced with the `element` prop:
+
+```diff
+- } />
++ } />
+```
+
+**Programmatic Navigation**
+
+The `useHistory` hook has been replaced with `useNavigate`:
+
+```diff
+- import { useHistory } from 'react-router-dom';
++ import { useNavigate } from 'react-router-dom';
++ import { useIonRouter } from '@ionic/react';
+
+- const history = useHistory();
++ const navigate = useNavigate();
++ const router = useIonRouter();
+
+- history.push('/path');
++ navigate('/path');
+
+- history.replace('/path');
++ navigate('/path', { replace: true });
+
+- history.goBack();
++ router.goBack();
+```
+
+**Custom History Prop Removed**
+
+The `history` prop has been removed from `IonReactRouter`, `IonReactHashRouter`, and `IonReactMemoryRouter`. React Router v6's `BrowserRouter`, `HashRouter`, and `MemoryRouter` no longer accept custom `history` objects.
+
+```diff
+- import { createBrowserHistory } from 'history';
+- const history = createBrowserHistory();
+-
++
+```
+
+For `IonReactMemoryRouter` (commonly used in tests), use `initialEntries` instead:
+
+```diff
+- import { createMemoryHistory } from 'history';
+- const history = createMemoryHistory({ initialEntries: ['/start'] });
+-
++
+```
+
+**IonRedirect Removed**
+
+The `IonRedirect` component has been removed. Use React Router's `` component instead:
+
+```diff
+- import { IonRedirect } from '@ionic/react';
+-
++ import { Navigate } from 'react-router-dom';
++ } />
+```
+
+**Path Regex Constraints Removed**
+
+React Router v6 no longer supports regex constraints in path parameters (e.g., `/:tab(sessions)`). Use literal paths instead:
+
+```diff
+-
+-
++ } />
++ } />
+```
+
+**IonRoute API Changes**
+
+The `IonRoute` component follows the same API changes as React Router's ``. The `render` prop has been replaced with `element`, and the `exact` prop has been removed:
+
+```diff
+- } />
++ } />
+```
+
+For more information on migrating from React Router v5 to v6, refer to the [React Router v6 Upgrade Guide](https://reactrouter.com/6.28.0/upgrading/v5).
+
+
- Phosphor Icon
+ Ionicons
- Phosphor Icon
+ Ionicons
diff --git a/core/src/components/img/img.tsx b/core/src/components/img/img.tsx
index 87c9668e58e..c37ac532dcc 100644
--- a/core/src/components/img/img.tsx
+++ b/core/src/components/img/img.tsx
@@ -2,12 +2,14 @@ import type { ComponentInterface, EventEmitter } from '@stencil/core';
import { Component, Element, Event, Host, Prop, State, Watch, h } from '@stencil/core';
import type { Attributes } from '@utils/helpers';
import { inheritAttributes } from '@utils/helpers';
+import { printIonWarning } from '@utils/logging';
import { getIonTheme } from '../../global/ionic-global';
/**
* @virtualProp {"ios" | "md"} mode - The mode determines the platform behaviors of the component.
* @virtualProp {"ios" | "md" | "ionic"} theme - The theme determines the visual appearance of the component.
+ * @deprecated
*
* @part image - The inner `img` element.
*/
@@ -57,6 +59,11 @@ export class Img implements ComponentInterface {
}
componentDidLoad() {
+ printIonWarning(
+ '[ion-img] - This component is deprecated and will be removed in Ionic v10. ' +
+ 'Use a native with the loading="lazy" attribute instead.',
+ this.el
+ );
this.addIO();
}
diff --git a/core/src/components/input-password-toggle/test/basic/input-password-toggle.e2e.ts-snapshots/input-password-toggle-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input-password-toggle/test/basic/input-password-toggle.e2e.ts-snapshots/input-password-toggle-ionic-md-ltr-light-Mobile-Chrome-linux.png
index e14c7092928..a961a46a79a 100644
Binary files a/core/src/components/input-password-toggle/test/basic/input-password-toggle.e2e.ts-snapshots/input-password-toggle-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input-password-toggle/test/basic/input-password-toggle.e2e.ts-snapshots/input-password-toggle-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input-password-toggle/test/basic/input-password-toggle.e2e.ts-snapshots/input-password-toggle-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input-password-toggle/test/basic/input-password-toggle.e2e.ts-snapshots/input-password-toggle-ionic-md-ltr-light-Mobile-Firefox-linux.png
index 88c66ddb1db..5c45a1a1dca 100644
Binary files a/core/src/components/input-password-toggle/test/basic/input-password-toggle.e2e.ts-snapshots/input-password-toggle-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input-password-toggle/test/basic/input-password-toggle.e2e.ts-snapshots/input-password-toggle-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input-password-toggle/test/basic/input-password-toggle.e2e.ts-snapshots/input-password-toggle-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/input-password-toggle/test/basic/input-password-toggle.e2e.ts-snapshots/input-password-toggle-ionic-md-ltr-light-Mobile-Safari-linux.png
index 444ecba0aec..9a49f14eb69 100644
Binary files a/core/src/components/input-password-toggle/test/basic/input-password-toggle.e2e.ts-snapshots/input-password-toggle-ionic-md-ltr-light-Mobile-Safari-linux.png and b/core/src/components/input-password-toggle/test/basic/input-password-toggle.e2e.ts-snapshots/input-password-toggle-ionic-md-ltr-light-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/input.common.scss b/core/src/components/input/input.common.scss
index 1cc609846a5..55f1801009b 100644
--- a/core/src/components/input/input.common.scss
+++ b/core/src/components/input/input.common.scss
@@ -162,7 +162,6 @@
// --------------------------------------------------
.input-clear-icon {
- @include margin(auto);
@include padding(0);
@include background-position(center);
@@ -216,6 +215,25 @@
line-height: normal;
}
+// Input Control (Label + Input)
+// ----------------------------------------------------------------
+
+.input-control {
+ display: flex;
+
+ flex-grow: 1;
+
+ width: 100%;
+
+ /**
+ * Allows the control to shrink below the label and input's intrinsic
+ * width, preventing the start and end slots from being pushed outside
+ * the wrapper. The label and input truncate independently, so it can
+ * use whatever space remains after accounting for the slots.
+ */
+ min-width: 0;
+}
+
// Input Native Wrapper
// ----------------------------------------------------------------
@@ -226,12 +244,24 @@
flex-grow: 1;
- // ensure start/end slot content is vertically centered
- align-items: center;
-
width: 100%;
}
+// Input Start/End Containers
+// ----------------------------------------------------------------
+
+.input-start,
+.input-end {
+ display: flex;
+
+ position: relative;
+
+ flex-shrink: 0;
+
+ // Ensure start/end content is vertically centered
+ align-items: center;
+}
+
// Input Highlight
// ----------------------------------------------------------------
@@ -361,6 +391,18 @@
pointer-events: none;
}
+/**
+ * When start/end slots are added or removed, we temporarily
+ * disable the label transition to prevent the floating label
+ * from animating as its position is adjusted.
+ *
+ * This class is applied by the start container controller, so
+ * renaming it here requires renaming it there too.
+ */
+:host(.skip-label-transition) .label-text-wrapper {
+ transition: none;
+}
+
/**
* We need to use two elements instead of
* one. The .label-text-wrapper is responsible
@@ -409,7 +451,7 @@
* Label is on the left of the input in LTR and
* on the right in RTL.
*/
-:host(.input-label-placement-start) .input-wrapper {
+:host(.input-label-placement-start) .input-control {
flex-direction: row;
}
@@ -420,7 +462,7 @@
* Label is on the right of the input in LTR and
* on the left in RTL.
*/
-:host(.input-label-placement-end) .input-wrapper {
+:host(.input-label-placement-end) .input-control {
flex-direction: row-reverse;
}
@@ -447,10 +489,9 @@
* Floating: Label sits over the input when the input has no
* value and is blurred. Label sits above the input and is scaled
* down when the input is focused or has a value.
- *
*/
-:host(.input-label-placement-stacked) .input-wrapper,
-:host(.input-label-placement-floating) .input-wrapper {
+:host(.input-label-placement-stacked) .input-control,
+:host(.input-label-placement-floating) .input-control {
flex-direction: column;
align-items: start;
}
@@ -474,15 +515,6 @@
z-index: 2;
}
-/**
- * Ensures the input does not
- * overlap the label.
- */
-:host(.input-label-placement-stacked) input,
-:host(.input-label-placement-floating) input {
- @include margin(1px, 0, 0, 0);
-}
-
/**
* This makes the label sit over the input
* when the input is blurred and has no value.
diff --git a/core/src/components/input/input.ionic.scss b/core/src/components/input/input.ionic.scss
index 4a7431dc4e6..e91a3e73961 100644
--- a/core/src/components/input/input.ionic.scss
+++ b/core/src/components/input/input.ionic.scss
@@ -33,6 +33,30 @@
border: var(--border-width) var(--border-style) var(--border-color);
}
+// Input Label Placement
+// ----------------------------------------------------------------
+
+:host(.input-label-placement-start) .input-wrapper {
+ flex-direction: row;
+}
+
+:host(.input-label-placement-end) .input-wrapper {
+ flex-direction: row-reverse;
+}
+
+:host(.input-label-placement-stacked) .input-wrapper,
+:host(.input-label-placement-floating) .input-wrapper {
+ flex-direction: column;
+
+ align-items: start;
+}
+
+// Keeps the input clear of the label.
+:host(.input-label-placement-stacked) input,
+:host(.input-label-placement-floating) input {
+ @include globals.margin(1px, 0, 0, 0);
+}
+
// Input Label Placement: Stacked
// ----------------------------------------------------------------
@@ -92,15 +116,24 @@
border-top: none;
}
-.native-wrapper {
+.input-wrapper-inner {
@include globals.border-radius(inherit);
@include globals.padding(var(--padding-top), var(--padding-end), var(--padding-bottom), var(--padding-start));
+ display: flex;
+
+ position: relative;
+
+ align-items: center;
+
+ width: 100%;
min-height: globals.$ion-scale-1000;
+ box-sizing: border-box;
+
/**
- * Apply the background to the native input
- * wrapper to only style the input.
+ * Apply the background to the inner wrapper so the label
+ * above it stays outside the field.
*/
background: var(--background);
}
@@ -123,15 +156,15 @@
--padding-end: #{globals.$ion-space-500};
}
-:host(.input-size-medium) .native-wrapper {
+:host(.input-size-medium) .input-wrapper-inner {
min-height: globals.$ion-scale-1000;
}
-:host(.input-size-large) .native-wrapper {
+:host(.input-size-large) .input-wrapper-inner {
min-height: globals.$ion-scale-1200;
}
-:host(.input-size-xlarge) .native-wrapper {
+:host(.input-size-xlarge) .input-wrapper-inner {
min-height: globals.$ion-scale-1400;
}
@@ -168,7 +201,7 @@
// Target area
// --------------------------------------------------
-.native-wrapper::after {
+.input-wrapper-inner::after {
@include globals.position(50%, 0, null, 0);
position: absolute;
@@ -199,11 +232,11 @@
// Start/End Slots
// ----------------------------------------------------------------
-::slotted([slot="start"]) {
+::slotted([slot="start"]:last-of-type) {
margin-inline-end: globals.$ion-space-200;
}
-::slotted([slot="end"]) {
+::slotted([slot="end"]:first-of-type) {
margin-inline-start: globals.$ion-space-200;
}
@@ -211,6 +244,8 @@
// ----------------------------------------------------------------
.input-clear-icon {
+ @include globals.margin(auto);
+
width: globals.$ion-scale-400;
height: globals.$ion-scale-400;
diff --git a/core/src/components/input/input.ionic.solid.scss b/core/src/components/input/input.ionic.solid.scss
index cad50c1fc30..11459ca1d40 100644
--- a/core/src/components/input/input.ionic.solid.scss
+++ b/core/src/components/input/input.ionic.solid.scss
@@ -11,8 +11,8 @@
* If the input has a validity state, the
* border should reflect that as a color.
*/
-:host(.input-fill-solid.has-focus.ion-valid) .native-wrapper,
-:host(.input-fill-solid.ion-touched.ion-invalid) .native-wrapper {
+:host(.input-fill-solid.has-focus.ion-valid) .input-wrapper-inner,
+:host(.input-fill-solid.ion-touched.ion-invalid) .input-wrapper-inner {
--border-color: var(--highlight-color);
}
diff --git a/core/src/components/input/input.md.outline.scss b/core/src/components/input/input.md.outline.scss
index c9577e16676..c4aa2d1c4ca 100644
--- a/core/src/components/input/input.md.outline.scss
+++ b/core/src/components/input/input.md.outline.scss
@@ -7,6 +7,15 @@
--padding-start: 16px;
--padding-end: 16px;
+ /**
+ * The measured width of the start container, as a negative offset
+ * in LTR and a positive one in RTL. Written to the host by the
+ * start container controller, so renaming it here requires renaming
+ * it there too. Declared with a default so the label is positioned
+ * correctly before the first measurement runs.
+ */
+ --internal-start-container-adjustment: 0px;
+
min-height: 56px;
}
@@ -62,6 +71,15 @@
border-bottom: none;
}
+/**
+ * The resting label is positioned relative to the control so it can size to
+ * the space between the start and end slots. When floating, the label needs
+ * to escape the control and position itself relative to the wrapper instead.
+ */
+:host(.input-fill-outline:not(.label-floating)) .input-control {
+ position: relative;
+}
+
:host(.input-fill-outline.input-label-placement-stacked) .label-text-wrapper,
:host(.input-fill-outline.input-label-placement-floating) .label-text-wrapper {
@include transform-origin(start, top);
@@ -69,10 +87,11 @@
position: absolute;
/**
- * Label text should not extend
- * beyond the bounds of the input.
+ * While resting this is the width of the text input, which already
+ * excludes the start and end slots. Once the label floats the
+ * containing block becomes the wrapper and the rule below takes over.
*/
- max-width: calc(100% - var(--padding-start) - var(--padding-end));
+ max-width: 100%;
}
/**
@@ -88,7 +107,10 @@
* This makes the label sit above the input.
*/
:host(.label-floating.input-fill-outline) .label-text-wrapper {
- @include transform(translateY(-32%), scale(#{$form-control-label-stacked-scale}));
+ @include transform(
+ translate(var(--internal-start-container-adjustment, 0px), -32%),
+ scale(#{$form-control-label-stacked-scale})
+ );
@include margin(0);
/**
@@ -100,16 +122,6 @@
);
}
-/**
- * This ensures that the input does not
- * overlap the floating label while still
- * remaining visually centered.
- */
-:host(.input-fill-outline.input-label-placement-stacked) input,
-:host(.input-fill-outline.input-label-placement-floating) input {
- @include margin(6px, 0, 6px, 0);
-}
-
// Input Fill: Outline Outline Container
// ----------------------------------------------------------------
diff --git a/core/src/components/input/input.native.scss b/core/src/components/input/input.native.scss
index 4ac5d333b8b..a81c16693eb 100644
--- a/core/src/components/input/input.native.scss
+++ b/core/src/components/input/input.native.scss
@@ -123,6 +123,19 @@
// Input Label Placement - Start
// ----------------------------------------------------------------
+/**
+ * When the label sits beside the input, the label should size to its content
+ * and the input should take the remaining space. A zero flex basis prevents
+ * the input from requesting its full width and forcing the label to shrink.
+ * Stacked and floating placements use a column layout, so their flex basis
+ * controls height instead and does not need to be overridden.
+ */
+:host(.input-label-placement-start) .native-wrapper,
+:host(.input-label-placement-end) .native-wrapper,
+:host(.input-label-placement-fixed) .native-wrapper {
+ flex: 1 1 0;
+}
+
:host(.input-label-placement-start) .label-text-wrapper {
/**
* The margin between the label and
@@ -172,6 +185,18 @@
max-width: calc(100% / #{$form-control-label-stacked-scale});
}
+// Label
+// ----------------------------------------------------------------
+
+.label-text-wrapper {
+ /**
+ * Allows the label to shrink below its intrinsic content width.
+ * Without this the label keeps its full width and can push the
+ * input and end slot outside the wrapper.
+ */
+ min-width: 0;
+}
+
// Start/End Slots
// ----------------------------------------------------------------
diff --git a/core/src/components/input/input.tsx b/core/src/components/input/input.tsx
index 672a2bf414a..1c35a445f60 100644
--- a/core/src/components/input/input.tsx
+++ b/core/src/components/input/input.tsx
@@ -14,8 +14,13 @@ import {
forceUpdate,
h,
} from '@stencil/core';
-import type { NotchController } from '@utils/forms';
-import { createClearButtonPressController, createNotchController, checkInvalidState } from '@utils/forms';
+import type { NotchController, StartContainerController } from '@utils/forms';
+import {
+ createClearButtonPressController,
+ createNotchController,
+ createStartContainerController,
+ checkInvalidState,
+} from '@utils/forms';
import type { Attributes } from '@utils/helpers';
import { inheritAriaAttributes, debounceEvent, inheritAttributes, componentOnReady } from '@utils/helpers';
import { printIonWarning } from '@utils/logging';
@@ -59,6 +64,8 @@ export class Input implements ComponentInterface {
private slotMutationController?: SlotMutationController;
private notchController?: NotchController;
private notchSpacerEl: HTMLElement | undefined;
+ private startContainerController?: StartContainerController;
+ private startContainerEl: HTMLElement | undefined;
private originalIonInput?: EventEmitter;
@@ -122,7 +129,7 @@ export class Input implements ComponentInterface {
/**
* Whether auto correction should be enabled when the user is entering/editing the text value.
*/
- @Prop() autocorrect: 'on' | 'off' = 'off';
+ @Prop() autocorrect: boolean = false;
/**
* Sets the [`autofocus` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autofocus) on the native input element.
@@ -437,6 +444,8 @@ export class Input implements ComponentInterface {
const { el } = this;
this.slotMutationController = createSlotMutationController(el, ['label', 'start', 'end'], () => {
+ this.startContainerController?.calculateStartContainerWidth();
+
this.setSlottedLabelId();
forceUpdate(this);
});
@@ -448,6 +457,16 @@ export class Input implements ComponentInterface {
() => this.labelSlot
);
+ this.startContainerController = createStartContainerController(
+ el,
+ () => this.startContainerEl,
+ () => {
+ return Build.isBrowser && getIonTheme(this) === 'md' && this.fill === 'outline';
+ }
+ );
+
+ this.startContainerController.calculateStartContainerWidth();
+
// Watch for class changes to update validation state
if (Build.isBrowser && typeof MutationObserver !== 'undefined') {
this.validationObserver = new MutationObserver(() => {
@@ -493,6 +512,7 @@ export class Input implements ComponentInterface {
componentDidRender() {
this.notchController?.calculateNotchWidth();
+ this.startContainerController?.calculateStartContainerWidth();
}
disconnectedCallback() {
@@ -516,6 +536,11 @@ export class Input implements ComponentInterface {
this.notchController = undefined;
}
+ if (this.startContainerController) {
+ this.startContainerController.destroy();
+ this.startContainerController = undefined;
+ }
+
// Clean up validation observer to prevent memory leaks
if (this.validationObserver) {
this.validationObserver.disconnect();
@@ -889,58 +914,168 @@ export class Input implements ComponentInterface {
}
/**
- * Stops propagation when the label is clicked,
- * otherwise, two clicks will be triggered.
+ * Stops propagation for clicks on the input's own content (label text,
+ * input field) to prevent double-click events. Allows clicks on slotted
+ * content to propagate so event delegation works for parent handlers.
+ *
+ * Only slots belonging directly to this input should be considered.
+ * The input itself may have a slot attribute when placed in an item
+ * or toolbar, which does not make its content slotted content.
*/
private onLabelClick = (ev: MouseEvent) => {
- // Only stop propagation if the click was directly on the label
- // and not on the input or other child elements
- if (ev.target === ev.currentTarget) {
+ const target = ev.target as HTMLElement;
+ const slotted = target.closest('[slot="start"], [slot="end"]');
+
+ if (slotted === null || slotted === this.el || !this.el.contains(slotted)) {
ev.stopPropagation();
}
};
/**
- * Renders the border container
- * when fill="outline".
+ * Renders the outline border with a notch for the label.
*/
- private renderLabelContainer() {
- const theme = getIonTheme(this);
- const hasOutlineFill = this.fill === 'outline';
-
- if (hasOutlineFill && theme === 'md') {
- /**
- * The outline fill has a special outline
- * that appears around the input and the label.
- * Certain stacked and floating label placements cause the
- * label to translate up and create a "cut out"
- * inside of that border by using the notch-spacer element.
- */
- return [
-
-
-
-
(this.notchSpacerEl = el)}>
- {this.label}
-
+ private renderOutlineContainer() {
+ return (
+
+
+
+
(this.notchSpacerEl = el)}>
+ {this.label}
-
-
,
- this.renderLabel(),
- ];
+
+
+
+ );
+ }
+
+ private renderNativeInput() {
+ const { disabled, readonly, inputId } = this;
+
+ return (
+ (this.nativeInput = input)}
+ id={inputId}
+ disabled={disabled}
+ autoCapitalize={this.autocapitalize}
+ autoComplete={this.autocomplete}
+ autoCorrect={this.autocorrect ? 'on' : 'off'}
+ autoFocus={this.autofocus}
+ enterKeyHint={this.enterkeyhint}
+ inputMode={this.inputmode}
+ min={this.min}
+ max={this.max}
+ minLength={this.minlength}
+ maxLength={this.maxlength}
+ multiple={this.multiple}
+ name={this.name}
+ pattern={this.pattern}
+ placeholder={this.placeholder || ''}
+ readOnly={readonly}
+ required={this.required}
+ spellcheck={this.spellcheck}
+ step={this.step}
+ type={this.type}
+ value={this.getValue()}
+ onInput={this.onInput}
+ onChange={this.onChange}
+ onBlur={this.onBlur}
+ onFocus={this.onFocus}
+ onKeyDown={this.onKeydown}
+ onCompositionstart={this.onCompositionStart}
+ onCompositionend={this.onCompositionEnd}
+ aria-describedby={this.getHintTextID()}
+ aria-invalid={this.isInvalid ? 'true' : undefined}
+ aria-labelledby={this.getLabelledById()}
+ {...this.inheritedAttributes}
+ />
+ );
+ }
+
+ private renderClearButton() {
+ const { clearInput, disabled, readonly } = this;
+
+ if (!clearInput || readonly || disabled) {
+ return undefined;
}
- /**
- * If not using the outline style, OR if using the
- * ionic theme, just render the label. For the ionic
- * theme, the outline will be rendered elsewhere.
- */
- return this.renderLabel();
+ return (
+
+ );
+ }
+
+ /**
+ * The ionic theme keeps the label above a field box that wraps the slots and
+ * the input, so the label can size independently of the slotted content.
+ */
+ private renderIonicField() {
+ return [
+ this.renderLabel(),
+
+
+ {this.renderStartContainer()}
+
+
+ {this.renderNativeInput()}
+
+
+ {this.renderEndContainer()}
+
,
+ ];
+ }
+
+ /**
+ * The ios and md themes nest the label alongside the input so a floating
+ * label can escape the control and clear the start and end slots.
+ */
+ private renderStartContainer() {
+ return (
+
,
+ this.renderEndContainer(),
+ ];
}
/**
@@ -973,9 +1108,8 @@ export class Input implements ComponentInterface {
}
render() {
- const { disabled, readonly, inputId, el, hasFocus, clearInput, inputClearIcon } = this;
+ const { disabled, readonly, inputId, hasFocus } = this;
const theme = getIonTheme(this);
- const value = this.getValue();
const fill = this.getFill();
const size = this.getSize();
const shape = this.getShape();
@@ -984,27 +1118,13 @@ export class Input implements ComponentInterface {
const labelPlacement = this.getLabelPlacement();
const hasValue = this.hasValue();
- const hasStartEndSlots = el.querySelector('[slot="start"], [slot="end"]') !== null;
/**
* If the label is stacked, it should always sit above the input.
* For floating labels, the label should move above the input if
- * the input has a value, is focused, or has anything in either
- * the start or end slot.
- *
- * If there is content in the start slot, the label would overlap
- * it if not forced to float. This is also applied to the end slot
- * because with the default or solid fills, the input is not
- * vertically centered in the container, but the label is. This
- * causes the slots and label to appear vertically offset from each
- * other when the label isn't floating above the input. This doesn't
- * apply to the outline fill, but this was not accounted for to keep
- * things consistent.
- *
- * TODO(FW-5592): Remove hasStartEndSlots condition
+ * the input has a value or is focused.
*/
- const labelShouldFloat =
- labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots));
+ const labelShouldFloat = labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus));
return (
- {this.renderLabelContainer()}
-
- {
- /**
- * For the ionic theme, we render the outline container here
- * instead of higher up, so it can be positioned relative to
- * the native wrapper instead of the
+ {theme === 'ionic' ? this.renderIonicField() : this.renderNativeField()}
{shouldRenderHighlight && }
{this.renderBottomContent()}
diff --git a/core/src/components/input/test/basic/input.e2e.ts b/core/src/components/input/test/basic/input.e2e.ts
index a44c8a7cf78..7ae4828ee91 100644
--- a/core/src/components/input/test/basic/input.e2e.ts
+++ b/core/src/components/input/test/basic/input.e2e.ts
@@ -200,7 +200,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, screenshot, c
// Verify the click was triggered exactly once
expect(clickEvent).toHaveReceivedEventTimes(1);
- // Verify that the event target is the checkbox and not the item
+ // Verify that the event target is the input and not the item
const event = clickEvent.events[0];
expect((event.target as HTMLElement).tagName.toLowerCase()).toBe('ion-input');
});
@@ -238,10 +238,149 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, screenshot, c
// Verify the click was triggered exactly once
expect(clickEvent).toHaveReceivedEventTimes(1);
- // Verify that the event target is the checkbox and not the item
+ // Verify that the event target is the input and not the item
const event = clickEvent.events[0];
expect((event.target as HTMLElement).tagName.toLowerCase()).toBe('ion-input');
});
+
+ test('should trigger onclick only once when the input is itself slotted', async ({ page }) => {
+ await page.setContent(
+ `
+
+
+
+ `,
+ config
+ );
+
+ const clickEvent = await page.spyOnEvent('click');
+
+ await page.locator('label.input-wrapper').click({
+ position: {
+ x: 5,
+ y: 5,
+ },
+ });
+
+ expect(clickEvent).toHaveReceivedEventTimes(1);
+ });
+
+ test('should propagate clicks from start slot button to parent', async ({ page }) => {
+ await page.setContent(
+ `
+
+ Parent Container
+
+ Icon
+
+
+ `,
+ config
+ );
+
+ const button = page.locator('ion-button[slot="start"]');
+ const parent = page.locator('#parent');
+
+ // Click the button in the start slot
+ await button.click();
+
+ // The button's own click handler should have fired
+ let buttonClicks = await page.evaluate(() => (window as any).buttonClicks);
+ expect(buttonClicks).toBe(1);
+
+ // The parent's click handler should also have fired
+ let parentClicks = await page.evaluate(() => (window as any).parentClicks);
+ expect(parentClicks).toBe(1);
+
+ // Click on the parent container (far right to avoid the start button)
+ await parent.click({ position: { x: 250, y: 50 } });
+
+ // Parent should have incremented
+ parentClicks = await page.evaluate(() => (window as any).parentClicks);
+ expect(parentClicks).toBe(2);
+
+ // Button should NOT have incremented
+ buttonClicks = await page.evaluate(() => (window as any).buttonClicks);
+ expect(buttonClicks).toBe(1);
+ });
+
+ test('should propagate clicks from end slot button to parent', async ({ page }) => {
+ await page.setContent(
+ `
+
+ Parent Container
+
+ Toggle
+
+
+ `,
+ config
+ );
+
+ const button = page.locator('ion-button[slot="end"]');
+ const parent = page.locator('#parent');
+
+ // Click the button in the end slot
+ await button.click();
+
+ // The button's own click handler should have fired
+ let buttonClicks = await page.evaluate(() => (window as any).buttonClicks);
+ expect(buttonClicks).toBe(1);
+
+ // The parent's click handler should also have fired
+ let parentClicks = await page.evaluate(() => (window as any).parentClicks);
+ expect(parentClicks).toBe(1);
+
+ // Click on the parent container (far left to avoid the end button)
+ await parent.click({ position: { x: 10, y: 50 } });
+
+ // Parent should have incremented
+ parentClicks = await page.evaluate(() => (window as any).parentClicks);
+ expect(parentClicks).toBe(2);
+
+ // Button should NOT have incremented
+ buttonClicks = await page.evaluate(() => (window as any).buttonClicks);
+ expect(buttonClicks).toBe(1);
+ });
+ });
+});
+
+/**
+ * The solid and outline fills are only supported by `md` mode. These
+ * are the only fills that get padding which can cause a double click.
+ */
+configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
+ test.describe(title('input: click'), () => {
+ ['solid', 'outline'].forEach((fill) => {
+ test(`should trigger onclick only once when clicking the ${fill} wrapper padding`, async ({ page }) => {
+ await page.setContent(
+ `
+
+ `,
+ config
+ );
+
+ const clickEvent = await page.spyOnEvent('click');
+ const wrapper = page.locator('label.input-wrapper');
+
+ await wrapper.click({
+ position: {
+ x: 5,
+ y: 5,
+ },
+ });
+
+ expect(clickEvent).toHaveReceivedEventTimes(1);
+
+ const event = clickEvent.events[0];
+ expect((event.target as HTMLElement).tagName.toLowerCase()).toBe('ion-input');
+ });
+ });
});
});
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-clear-button-focused-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-clear-button-focused-ionic-md-ltr-light-Mobile-Chrome-linux.png
index 0293b605187..50afa0a5ac5 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-clear-button-focused-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-clear-button-focused-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-clear-button-focused-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-clear-button-focused-ionic-md-ltr-light-Mobile-Firefox-linux.png
index 1a94f75809d..fec5a027f17 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-clear-button-focused-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-clear-button-focused-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-clear-button-focused-ionic-md-rtl-light-Mobile-Chrome-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-clear-button-focused-ionic-md-rtl-light-Mobile-Chrome-linux.png
index a8adcd44b9d..042fc54608c 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-clear-button-focused-ionic-md-rtl-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-clear-button-focused-ionic-md-rtl-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-clear-button-focused-ionic-md-rtl-light-Mobile-Firefox-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-clear-button-focused-ionic-md-rtl-light-Mobile-Firefox-linux.png
index ea8ff4412cf..a49fb7a6a33 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-clear-button-focused-ionic-md-rtl-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-clear-button-focused-ionic-md-rtl-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-ionic-md-ltr-light-Mobile-Firefox-linux.png
index bdf34196200..d123d20152b 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-ionic-md-rtl-light-Mobile-Firefox-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-ionic-md-rtl-light-Mobile-Firefox-linux.png
index 153d317ff9e..aa43156abb0 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-ionic-md-rtl-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-ionic-md-rtl-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-ios-ltr-Mobile-Chrome-linux.png
index 3d4c3ff1a22..b22eb76ca24 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-ios-ltr-Mobile-Chrome-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-ios-ltr-Mobile-Firefox-linux.png
index d230a8837dd..4f66ccb3a6d 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-ios-ltr-Mobile-Firefox-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-ios-ltr-Mobile-Safari-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-ios-ltr-Mobile-Safari-linux.png
index 06a87f6ff08..93fb8591820 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-ios-ltr-Mobile-Safari-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-ios-rtl-Mobile-Chrome-linux.png
index 89ad96687a2..83e977839aa 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-ios-rtl-Mobile-Chrome-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-ios-rtl-Mobile-Firefox-linux.png
index 2b23456247d..d42a8fc1a58 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-ios-rtl-Mobile-Firefox-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-ios-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-ios-rtl-Mobile-Safari-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-ios-rtl-Mobile-Safari-linux.png
index 999af592674..8f9d746ce6c 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-ios-rtl-Mobile-Safari-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-md-ltr-Mobile-Chrome-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-md-ltr-Mobile-Chrome-linux.png
index 7cf2077e13f..ed7c43da3ec 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-md-ltr-Mobile-Firefox-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-md-ltr-Mobile-Firefox-linux.png
index 1a67e211b54..3c905d00026 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-md-ltr-Mobile-Firefox-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-md-ltr-Mobile-Safari-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-md-ltr-Mobile-Safari-linux.png
index cb872930207..eb9e5bc181c 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-md-ltr-Mobile-Safari-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-md-rtl-Mobile-Chrome-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-md-rtl-Mobile-Chrome-linux.png
index ff0d89ee7cd..39d658598d4 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-md-rtl-Mobile-Chrome-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-md-rtl-Mobile-Firefox-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-md-rtl-Mobile-Firefox-linux.png
index 98bedf8d815..e7090e5dcfa 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-md-rtl-Mobile-Firefox-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-md-rtl-Mobile-Safari-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-md-rtl-Mobile-Safari-linux.png
index 841d24f9e1c..3f114f47e15 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-md-rtl-Mobile-Safari-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-dbclick-stacked-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-ionic-md-ltr-light-Mobile-Chrome-linux.png
index 3d4052b843c..2e4faaf2ce0 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-ionic-md-ltr-light-Mobile-Firefox-linux.png
index a3d08c4b1e8..5ff6967ad8c 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-ionic-md-rtl-light-Mobile-Chrome-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-ionic-md-rtl-light-Mobile-Chrome-linux.png
index 77e4d2c956f..e3070487746 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-ionic-md-rtl-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-ionic-md-rtl-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-ionic-md-rtl-light-Mobile-Firefox-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-ionic-md-rtl-light-Mobile-Firefox-linux.png
index 14adb7e8d0b..2fb2bdd9839 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-ionic-md-rtl-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-ionic-md-rtl-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-md-ltr-Mobile-Chrome-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-md-ltr-Mobile-Chrome-linux.png
index 6a884b66e77..1928e6fc404 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-md-ltr-Mobile-Firefox-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-md-ltr-Mobile-Firefox-linux.png
index 2d044ccb6ed..7f2c4fc70bc 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-md-ltr-Mobile-Firefox-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-md-rtl-Mobile-Chrome-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-md-rtl-Mobile-Chrome-linux.png
index 67b1faf09bb..d94cefb2a5d 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-md-rtl-Mobile-Chrome-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-md-rtl-Mobile-Firefox-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-md-rtl-Mobile-Firefox-linux.png
index 09dc4838fad..2af043a2df7 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-md-rtl-Mobile-Firefox-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-ios-ltr-Mobile-Chrome-linux.png
index 76faa45cfae..94129a3a28f 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-ios-ltr-Mobile-Chrome-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-ios-ltr-Mobile-Firefox-linux.png
index 55ade608a5d..c7d8a9e0ada 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-ios-ltr-Mobile-Firefox-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-ios-ltr-Mobile-Safari-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-ios-ltr-Mobile-Safari-linux.png
index 700f20ba311..218e216fd04 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-ios-ltr-Mobile-Safari-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-ios-rtl-Mobile-Chrome-linux.png
index 2fcdb0d8b11..af5a2ee619e 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-ios-rtl-Mobile-Chrome-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-ios-rtl-Mobile-Firefox-linux.png
index de9a5994e78..07c07866f89 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-ios-rtl-Mobile-Firefox-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-ios-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-ios-rtl-Mobile-Safari-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-ios-rtl-Mobile-Safari-linux.png
index 70a46841629..32d1f4b058e 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-ios-rtl-Mobile-Safari-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-md-ltr-Mobile-Chrome-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-md-ltr-Mobile-Chrome-linux.png
index 422929323d0..fd3a571dec1 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-md-ltr-Mobile-Firefox-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-md-ltr-Mobile-Firefox-linux.png
index 3ac1fb79fbf..1504c7cc9b7 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-md-ltr-Mobile-Firefox-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-md-ltr-Mobile-Safari-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-md-ltr-Mobile-Safari-linux.png
index 1f04b62a988..aa5ac5a834a 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-md-ltr-Mobile-Safari-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-md-rtl-Mobile-Chrome-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-md-rtl-Mobile-Chrome-linux.png
index 9f3f37fa1be..6a87981f337 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-md-rtl-Mobile-Chrome-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-md-rtl-Mobile-Firefox-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-md-rtl-Mobile-Firefox-linux.png
index 9d1ab23021b..68b1e3bd9b7 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-md-rtl-Mobile-Firefox-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-md-rtl-Mobile-Safari-linux.png b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-md-rtl-Mobile-Safari-linux.png
index 271795584c1..7e1ff070dbf 100644
Binary files a/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-md-rtl-Mobile-Safari-linux.png and b/core/src/components/input/test/basic/input.e2e.ts-snapshots/input-with-clear-button-stacked-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-error-text-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-error-text-ionic-md-ltr-light-Mobile-Chrome-linux.png
index b5231b20763..2a1fe70c137 100644
Binary files a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-error-text-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-error-text-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-error-text-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-error-text-ionic-md-ltr-light-Mobile-Firefox-linux.png
index aab81f4a116..f716c64efd4 100644
Binary files a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-error-text-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-error-text-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-error-text-stacked-label-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-error-text-stacked-label-ionic-md-ltr-light-Mobile-Chrome-linux.png
index b5231b20763..2a1fe70c137 100644
Binary files a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-error-text-stacked-label-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-error-text-stacked-label-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-error-text-stacked-label-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-error-text-stacked-label-ionic-md-ltr-light-Mobile-Firefox-linux.png
index aab81f4a116..f716c64efd4 100644
Binary files a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-error-text-stacked-label-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-error-text-stacked-label-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-full-bottom-no-fill-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-full-bottom-no-fill-ionic-md-ltr-light-Mobile-Chrome-linux.png
index 41f0345ff4d..49671af7033 100644
Binary files a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-full-bottom-no-fill-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-full-bottom-no-fill-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-full-bottom-no-fill-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-full-bottom-no-fill-ionic-md-ltr-light-Mobile-Firefox-linux.png
index cae5bcbe2d0..00a25c533c5 100644
Binary files a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-full-bottom-no-fill-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-full-bottom-no-fill-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-full-bottom-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-full-bottom-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png
index 41f0345ff4d..49671af7033 100644
Binary files a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-full-bottom-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-full-bottom-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-full-bottom-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-full-bottom-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png
index cae5bcbe2d0..00a25c533c5 100644
Binary files a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-full-bottom-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-full-bottom-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-helper-text-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-helper-text-ionic-md-ltr-light-Mobile-Chrome-linux.png
index 7a5f83074fa..213ebe149ee 100644
Binary files a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-helper-text-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-helper-text-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-helper-text-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-helper-text-ionic-md-ltr-light-Mobile-Firefox-linux.png
index f54f3514151..2ad438c5694 100644
Binary files a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-helper-text-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-helper-text-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-helper-text-stacked-label-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-helper-text-stacked-label-ionic-md-ltr-light-Mobile-Chrome-linux.png
index 7a5f83074fa..213ebe149ee 100644
Binary files a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-helper-text-stacked-label-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-helper-text-stacked-label-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-helper-text-stacked-label-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-helper-text-stacked-label-ionic-md-ltr-light-Mobile-Firefox-linux.png
index f54f3514151..2ad438c5694 100644
Binary files a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-helper-text-stacked-label-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-helper-text-stacked-label-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-helper-text-wrapping-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-helper-text-wrapping-ionic-md-ltr-light-Mobile-Chrome-linux.png
index 332539eee78..3183e05045b 100644
Binary files a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-helper-text-wrapping-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-helper-text-wrapping-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-helper-text-wrapping-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-helper-text-wrapping-ionic-md-ltr-light-Mobile-Firefox-linux.png
index 15d2bf388a1..2528d20671d 100644
Binary files a/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-helper-text-wrapping-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/bottom-content/input.e2e.ts-snapshots/input-helper-text-wrapping-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/color/input.e2e.ts-snapshots/input-no-fill-color-floating-md-ltr-Mobile-Chrome-linux.png b/core/src/components/input/test/color/input.e2e.ts-snapshots/input-no-fill-color-floating-md-ltr-Mobile-Chrome-linux.png
index 3c3db356ad0..e3f13fcfe5c 100644
Binary files a/core/src/components/input/test/color/input.e2e.ts-snapshots/input-no-fill-color-floating-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/input/test/color/input.e2e.ts-snapshots/input-no-fill-color-floating-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/color/input.e2e.ts-snapshots/input-no-fill-color-floating-md-ltr-Mobile-Firefox-linux.png b/core/src/components/input/test/color/input.e2e.ts-snapshots/input-no-fill-color-floating-md-ltr-Mobile-Firefox-linux.png
index 15c518a3a7e..f46ae9fa7f6 100644
Binary files a/core/src/components/input/test/color/input.e2e.ts-snapshots/input-no-fill-color-floating-md-ltr-Mobile-Firefox-linux.png and b/core/src/components/input/test/color/input.e2e.ts-snapshots/input-no-fill-color-floating-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/color/input.e2e.ts-snapshots/input-no-fill-color-floating-md-ltr-Mobile-Safari-linux.png b/core/src/components/input/test/color/input.e2e.ts-snapshots/input-no-fill-color-floating-md-ltr-Mobile-Safari-linux.png
index 7def53b2a2d..ea5a23d4acf 100644
Binary files a/core/src/components/input/test/color/input.e2e.ts-snapshots/input-no-fill-color-floating-md-ltr-Mobile-Safari-linux.png and b/core/src/components/input/test/color/input.e2e.ts-snapshots/input-no-fill-color-floating-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/color/input.e2e.ts-snapshots/input-no-fill-color-stacked-md-ltr-Mobile-Chrome-linux.png b/core/src/components/input/test/color/input.e2e.ts-snapshots/input-no-fill-color-stacked-md-ltr-Mobile-Chrome-linux.png
index 3c3db356ad0..e3f13fcfe5c 100644
Binary files a/core/src/components/input/test/color/input.e2e.ts-snapshots/input-no-fill-color-stacked-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/input/test/color/input.e2e.ts-snapshots/input-no-fill-color-stacked-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/color/input.e2e.ts-snapshots/input-no-fill-color-stacked-md-ltr-Mobile-Firefox-linux.png b/core/src/components/input/test/color/input.e2e.ts-snapshots/input-no-fill-color-stacked-md-ltr-Mobile-Firefox-linux.png
index 15c518a3a7e..f46ae9fa7f6 100644
Binary files a/core/src/components/input/test/color/input.e2e.ts-snapshots/input-no-fill-color-stacked-md-ltr-Mobile-Firefox-linux.png and b/core/src/components/input/test/color/input.e2e.ts-snapshots/input-no-fill-color-stacked-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/color/input.e2e.ts-snapshots/input-no-fill-color-stacked-md-ltr-Mobile-Safari-linux.png b/core/src/components/input/test/color/input.e2e.ts-snapshots/input-no-fill-color-stacked-md-ltr-Mobile-Safari-linux.png
index 7def53b2a2d..ea5a23d4acf 100644
Binary files a/core/src/components/input/test/color/input.e2e.ts-snapshots/input-no-fill-color-stacked-md-ltr-Mobile-Safari-linux.png and b/core/src/components/input/test/color/input.e2e.ts-snapshots/input-no-fill-color-stacked-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-ionic-md-ltr-light-Mobile-Chrome-linux.png
index de352dc4ddc..f0eef7628b0 100644
Binary files a/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-ionic-md-ltr-light-Mobile-Firefox-linux.png
index 373b533e6ca..c4cd8c8e951 100644
Binary files a/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-ionic-md-rtl-light-Mobile-Chrome-linux.png b/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-ionic-md-rtl-light-Mobile-Chrome-linux.png
index 1849e45a37c..81aa364e9a1 100644
Binary files a/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-ionic-md-rtl-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-ionic-md-rtl-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-ionic-md-rtl-light-Mobile-Firefox-linux.png b/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-ionic-md-rtl-light-Mobile-Firefox-linux.png
index aa852496b06..38c6c11afe7 100644
Binary files a/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-ionic-md-rtl-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-ionic-md-rtl-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-size-large-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-size-large-ionic-md-ltr-light-Mobile-Chrome-linux.png
index 9908ebbf002..8024aaecf03 100644
Binary files a/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-size-large-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-size-large-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-size-large-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-size-large-ionic-md-ltr-light-Mobile-Firefox-linux.png
index 9bcaa879c1f..c84c3b7aca9 100644
Binary files a/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-size-large-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-size-large-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-size-large-ionic-md-rtl-light-Mobile-Chrome-linux.png b/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-size-large-ionic-md-rtl-light-Mobile-Chrome-linux.png
index 71213f950c5..3561f1e1e33 100644
Binary files a/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-size-large-ionic-md-rtl-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-size-large-ionic-md-rtl-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-size-large-ionic-md-rtl-light-Mobile-Firefox-linux.png b/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-size-large-ionic-md-rtl-light-Mobile-Firefox-linux.png
index f4d47b14956..bb777513d12 100644
Binary files a/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-size-large-ionic-md-rtl-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/fill/input.e2e.ts-snapshots/input-fill-outline-label-stacked-size-large-ionic-md-rtl-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-no-fill-invalid-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-no-fill-invalid-ionic-md-ltr-light-Mobile-Chrome-linux.png
index 184760403c3..720176f621c 100644
Binary files a/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-no-fill-invalid-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-no-fill-invalid-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-no-fill-invalid-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-no-fill-invalid-ionic-md-ltr-light-Mobile-Firefox-linux.png
index 82789e75669..37c83ba2637 100644
Binary files a/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-no-fill-invalid-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-no-fill-invalid-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-no-fill-valid-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-no-fill-valid-ionic-md-ltr-light-Mobile-Chrome-linux.png
index 8d6255b156c..a1cbfed275c 100644
Binary files a/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-no-fill-valid-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-no-fill-valid-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-no-fill-valid-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-no-fill-valid-ionic-md-ltr-light-Mobile-Firefox-linux.png
index 420fa30805b..904e88e28d9 100644
Binary files a/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-no-fill-valid-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-no-fill-valid-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-outline-custom-highlight-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-outline-custom-highlight-ionic-md-ltr-light-Mobile-Chrome-linux.png
index 9b42ae50ce4..d23dd757d79 100644
Binary files a/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-outline-custom-highlight-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-outline-custom-highlight-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-outline-custom-highlight-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-outline-custom-highlight-ionic-md-ltr-light-Mobile-Firefox-linux.png
index c3534b0a286..19705dce0fe 100644
Binary files a/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-outline-custom-highlight-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-outline-custom-highlight-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-outline-invalid-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-outline-invalid-ionic-md-ltr-light-Mobile-Chrome-linux.png
index 184760403c3..720176f621c 100644
Binary files a/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-outline-invalid-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-outline-invalid-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-outline-invalid-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-outline-invalid-ionic-md-ltr-light-Mobile-Firefox-linux.png
index 82789e75669..37c83ba2637 100644
Binary files a/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-outline-invalid-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-outline-invalid-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-outline-valid-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-outline-valid-ionic-md-ltr-light-Mobile-Chrome-linux.png
index 8d6255b156c..a1cbfed275c 100644
Binary files a/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-outline-valid-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-outline-valid-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-outline-valid-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-outline-valid-ionic-md-ltr-light-Mobile-Firefox-linux.png
index 420fa30805b..904e88e28d9 100644
Binary files a/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-outline-valid-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/highlight/input.e2e.ts-snapshots/input-outline-valid-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts b/core/src/components/input/test/label-placement/input.e2e.ts
index 0e036e1136d..e29063efa8e 100644
--- a/core/src/components/input/test/label-placement/input.e2e.ts
+++ b/core/src/components/input/test/label-placement/input.e2e.ts
@@ -130,7 +130,7 @@ configs().forEach(({ title, screenshot, config }) => {
});
/**
- * This style only appears on MD
+ * The solid and outline fills are only supported by `md` mode.
*/
configs({ modes: ['md'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('input: label with fill'), () => {
@@ -144,6 +144,7 @@ configs({ modes: ['md'] }).forEach(({ title, screenshot, config }) => {
const input = page.locator('ion-input');
await expect(input).toHaveScreenshot(screenshot(`input-placement-floating-long-label-outline`));
});
+
test('long label should truncate with solid', async ({ page }) => {
await page.setContent(
`
@@ -154,6 +155,61 @@ configs({ modes: ['md'] }).forEach(({ title, screenshot, config }) => {
const input = page.locator('ion-input');
await expect(input).toHaveScreenshot(screenshot(`input-placement-floating-long-label-solid`));
});
+
+ /**
+ * The floating label must be positioned relative to `.input-wrapper` so its
+ * width is not constrained when the input width collapses. These tests cover
+ * both cases: a long label should retain the same available width despite
+ * wide start content, and a short label should not collapse when the start
+ * content takes up most of the input's width.
+ */
+ test('start slot content should not shrink the label', async ({ page }) => {
+ await page.setContent(
+ `
+
+
+
+
+
+
+ `,
+ config
+ );
+
+ const labelWidth = (id: string) =>
+ page.locator(`${id} .label-text`).evaluate((el: HTMLElement) => ({
+ available: el.clientWidth,
+ wanted: el.scrollWidth,
+ }));
+
+ const plain = await labelWidth('#plain');
+ const wideStart = await labelWidth('#wide-start');
+
+ // The label is long enough that it has to truncate in both cases
+ expect(plain.wanted).toBeGreaterThan(plain.available);
+
+ expect(wideStart.available).toBe(plain.available);
+ });
+
+ test('start slot content should not collapse a short label', async ({ page }) => {
+ await page.setContent(
+ `
+
+
+
+
+
+ `,
+ config
+ );
+
+ const label = await page.locator('.label-text').evaluate((el: HTMLElement) => ({
+ available: el.clientWidth,
+ wanted: el.scrollWidth,
+ }));
+
+ expect(label.available).toBe(label.wanted);
+ });
});
});
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-ios-ltr-Mobile-Chrome-linux.png
index 488d54c6e44..8e1b42adae7 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-ios-ltr-Mobile-Chrome-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-ios-ltr-Mobile-Firefox-linux.png
index 2f2c2c3b57b..6b1ee04e799 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-ios-ltr-Mobile-Firefox-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-ios-ltr-Mobile-Safari-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-ios-ltr-Mobile-Safari-linux.png
index 08dcbb4b3d7..369a2d70fb5 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-ios-ltr-Mobile-Safari-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-ios-rtl-Mobile-Chrome-linux.png
index 125fe750ed5..7ecca712d85 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-ios-rtl-Mobile-Chrome-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-ios-rtl-Mobile-Firefox-linux.png
index 7ee2d48582d..f8a353f8962 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-ios-rtl-Mobile-Firefox-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-ios-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-ios-rtl-Mobile-Safari-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-ios-rtl-Mobile-Safari-linux.png
index 5d2533038c6..87d91d04ef7 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-ios-rtl-Mobile-Safari-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-md-ltr-Mobile-Chrome-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-md-ltr-Mobile-Chrome-linux.png
index 09eb11dfcb1..6d05da8ae79 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-md-ltr-Mobile-Firefox-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-md-ltr-Mobile-Firefox-linux.png
index c94fbd5eaeb..046b25b79ec 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-md-ltr-Mobile-Firefox-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-md-ltr-Mobile-Safari-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-md-ltr-Mobile-Safari-linux.png
index 0d20736ae47..f7892dc2729 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-md-ltr-Mobile-Safari-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-md-rtl-Mobile-Chrome-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-md-rtl-Mobile-Chrome-linux.png
index 2d46c72b922..37f394a97f5 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-md-rtl-Mobile-Chrome-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-md-rtl-Mobile-Firefox-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-md-rtl-Mobile-Firefox-linux.png
index da335222652..5d2a9feed5c 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-md-rtl-Mobile-Firefox-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-md-rtl-Mobile-Safari-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-md-rtl-Mobile-Safari-linux.png
index 6af07703892..9d9693c6a8e 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-md-rtl-Mobile-Safari-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-focused-placement-floating-no-value-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-ios-ltr-Mobile-Chrome-linux.png
index 4f01f13cf06..160c2882e78 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-ios-ltr-Mobile-Chrome-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-ios-ltr-Mobile-Firefox-linux.png
index fc58277d876..7d5b4ebb831 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-ios-ltr-Mobile-Firefox-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-ios-ltr-Mobile-Safari-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-ios-ltr-Mobile-Safari-linux.png
index 9cc9bc00f6e..09f38ae2dea 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-ios-ltr-Mobile-Safari-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-ios-rtl-Mobile-Chrome-linux.png
index 3a2442d19f2..0a6ced79717 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-ios-rtl-Mobile-Chrome-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-ios-rtl-Mobile-Firefox-linux.png
index 41f3ab8efd5..8c3aea5347f 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-ios-rtl-Mobile-Firefox-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-ios-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-ios-rtl-Mobile-Safari-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-ios-rtl-Mobile-Safari-linux.png
index f8479cb6412..f870b7a3456 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-ios-rtl-Mobile-Safari-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-md-ltr-Mobile-Chrome-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-md-ltr-Mobile-Chrome-linux.png
index 1dd4e91cff3..de5e6e66b4e 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-md-ltr-Mobile-Firefox-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-md-ltr-Mobile-Firefox-linux.png
index d5fdfd5bbe2..88072961c4e 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-md-ltr-Mobile-Firefox-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-md-ltr-Mobile-Safari-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-md-ltr-Mobile-Safari-linux.png
index ae17350de60..f03823b0647 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-md-ltr-Mobile-Safari-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-md-rtl-Mobile-Chrome-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-md-rtl-Mobile-Chrome-linux.png
index 8acaf1c54bd..d06f676a0c6 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-md-rtl-Mobile-Chrome-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-md-rtl-Mobile-Firefox-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-md-rtl-Mobile-Firefox-linux.png
index f845477a535..c159c3a8498 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-md-rtl-Mobile-Firefox-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-md-rtl-Mobile-Safari-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-md-rtl-Mobile-Safari-linux.png
index 306dd13a590..ce56267a7b9 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-md-rtl-Mobile-Safari-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-outline-md-ltr-Mobile-Chrome-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-outline-md-ltr-Mobile-Chrome-linux.png
index 7ecf76baa48..75a0b9ccad7 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-outline-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-outline-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-outline-md-ltr-Mobile-Firefox-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-outline-md-ltr-Mobile-Firefox-linux.png
index fbec1a8fe23..1d954c8dd2c 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-outline-md-ltr-Mobile-Firefox-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-outline-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-outline-md-rtl-Mobile-Chrome-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-outline-md-rtl-Mobile-Chrome-linux.png
index d60e591d92f..1aac7b111ee 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-outline-md-rtl-Mobile-Chrome-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-outline-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-outline-md-rtl-Mobile-Firefox-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-outline-md-rtl-Mobile-Firefox-linux.png
index 187961bbac7..346c60da9c3 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-outline-md-rtl-Mobile-Firefox-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-long-label-outline-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-ios-ltr-Mobile-Chrome-linux.png
index 52cc53cd39e..90a2ee1f8b6 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-ios-ltr-Mobile-Chrome-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-ios-ltr-Mobile-Firefox-linux.png
index df4c7e25d78..3be719ad236 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-ios-ltr-Mobile-Firefox-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-ios-ltr-Mobile-Safari-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-ios-ltr-Mobile-Safari-linux.png
index 00b1fb9e9b5..339798091f8 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-ios-ltr-Mobile-Safari-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-ios-rtl-Mobile-Chrome-linux.png
index bd02ce08a05..6fb7830e097 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-ios-rtl-Mobile-Chrome-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-ios-rtl-Mobile-Firefox-linux.png
index cdce9bf3fc9..0caf2bc82e8 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-ios-rtl-Mobile-Firefox-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-ios-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-ios-rtl-Mobile-Safari-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-ios-rtl-Mobile-Safari-linux.png
index f26a7cf5e27..49a6e85e429 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-ios-rtl-Mobile-Safari-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-md-ltr-Mobile-Chrome-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-md-ltr-Mobile-Chrome-linux.png
index 1202d9dc19b..984b0d7d748 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-md-ltr-Mobile-Firefox-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-md-ltr-Mobile-Firefox-linux.png
index 4769a907477..9f07ceba139 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-md-ltr-Mobile-Firefox-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-md-ltr-Mobile-Safari-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-md-ltr-Mobile-Safari-linux.png
index 55d13227d5f..2080c557462 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-md-ltr-Mobile-Safari-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-md-rtl-Mobile-Chrome-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-md-rtl-Mobile-Chrome-linux.png
index 563684ad8ad..a0fb25dfb70 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-md-rtl-Mobile-Chrome-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-md-rtl-Mobile-Firefox-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-md-rtl-Mobile-Firefox-linux.png
index 10d7e472784..fe139e41a6f 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-md-rtl-Mobile-Firefox-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-md-rtl-Mobile-Safari-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-md-rtl-Mobile-Safari-linux.png
index 7248c24be30..a1aabb42b6a 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-md-rtl-Mobile-Safari-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-floating-value-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-ios-ltr-Mobile-Chrome-linux.png
index 4f01f13cf06..160c2882e78 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-ios-ltr-Mobile-Chrome-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-ios-ltr-Mobile-Firefox-linux.png
index fc58277d876..7d5b4ebb831 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-ios-ltr-Mobile-Firefox-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-ios-ltr-Mobile-Safari-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-ios-ltr-Mobile-Safari-linux.png
index 9cc9bc00f6e..09f38ae2dea 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-ios-ltr-Mobile-Safari-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-ios-rtl-Mobile-Chrome-linux.png
index 3a2442d19f2..0a6ced79717 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-ios-rtl-Mobile-Chrome-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-ios-rtl-Mobile-Firefox-linux.png
index 41f3ab8efd5..8c3aea5347f 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-ios-rtl-Mobile-Firefox-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-ios-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-ios-rtl-Mobile-Safari-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-ios-rtl-Mobile-Safari-linux.png
index f8479cb6412..f870b7a3456 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-ios-rtl-Mobile-Safari-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-md-ltr-Mobile-Chrome-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-md-ltr-Mobile-Chrome-linux.png
index 1dd4e91cff3..de5e6e66b4e 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-md-ltr-Mobile-Firefox-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-md-ltr-Mobile-Firefox-linux.png
index d5fdfd5bbe2..88072961c4e 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-md-ltr-Mobile-Firefox-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-md-ltr-Mobile-Safari-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-md-ltr-Mobile-Safari-linux.png
index ae17350de60..f03823b0647 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-md-ltr-Mobile-Safari-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-md-rtl-Mobile-Chrome-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-md-rtl-Mobile-Chrome-linux.png
index 8acaf1c54bd..d06f676a0c6 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-md-rtl-Mobile-Chrome-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-md-rtl-Mobile-Firefox-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-md-rtl-Mobile-Firefox-linux.png
index f845477a535..c159c3a8498 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-md-rtl-Mobile-Firefox-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-md-rtl-Mobile-Safari-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-md-rtl-Mobile-Safari-linux.png
index 306dd13a590..ce56267a7b9 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-md-rtl-Mobile-Safari-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-long-label-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-ios-ltr-Mobile-Chrome-linux.png
index 52cc53cd39e..90a2ee1f8b6 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-ios-ltr-Mobile-Chrome-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-ios-ltr-Mobile-Firefox-linux.png
index df4c7e25d78..3be719ad236 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-ios-ltr-Mobile-Firefox-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-ios-ltr-Mobile-Safari-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-ios-ltr-Mobile-Safari-linux.png
index 00b1fb9e9b5..339798091f8 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-ios-ltr-Mobile-Safari-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-ios-rtl-Mobile-Chrome-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-ios-rtl-Mobile-Chrome-linux.png
index bd02ce08a05..6fb7830e097 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-ios-rtl-Mobile-Chrome-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-ios-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-ios-rtl-Mobile-Firefox-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-ios-rtl-Mobile-Firefox-linux.png
index cdce9bf3fc9..0caf2bc82e8 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-ios-rtl-Mobile-Firefox-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-ios-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-ios-rtl-Mobile-Safari-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-ios-rtl-Mobile-Safari-linux.png
index f26a7cf5e27..49a6e85e429 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-ios-rtl-Mobile-Safari-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-ios-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-md-ltr-Mobile-Chrome-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-md-ltr-Mobile-Chrome-linux.png
index 1202d9dc19b..984b0d7d748 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-md-ltr-Mobile-Chrome-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-md-ltr-Mobile-Firefox-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-md-ltr-Mobile-Firefox-linux.png
index 4769a907477..9f07ceba139 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-md-ltr-Mobile-Firefox-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-md-ltr-Mobile-Safari-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-md-ltr-Mobile-Safari-linux.png
index 55d13227d5f..2080c557462 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-md-ltr-Mobile-Safari-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-md-rtl-Mobile-Chrome-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-md-rtl-Mobile-Chrome-linux.png
index 563684ad8ad..a0fb25dfb70 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-md-rtl-Mobile-Chrome-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-md-rtl-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-md-rtl-Mobile-Firefox-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-md-rtl-Mobile-Firefox-linux.png
index 10d7e472784..fe139e41a6f 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-md-rtl-Mobile-Firefox-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-md-rtl-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-md-rtl-Mobile-Safari-linux.png b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-md-rtl-Mobile-Safari-linux.png
index 7248c24be30..a1aabb42b6a 100644
Binary files a/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-md-rtl-Mobile-Safari-linux.png and b/core/src/components/input/test/label-placement/input.e2e.ts-snapshots/input-placement-stacked-value-md-rtl-Mobile-Safari-linux.png differ
diff --git a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-custom-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-custom-ionic-md-ltr-light-Mobile-Chrome-linux.png
index c4526613e5d..9e8a0ff4026 100644
Binary files a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-custom-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-custom-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-custom-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-custom-ionic-md-ltr-light-Mobile-Firefox-linux.png
index 21c0e18ed20..b36aef822f2 100644
Binary files a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-custom-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-custom-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-custom-ionic-md-rtl-light-Mobile-Chrome-linux.png b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-custom-ionic-md-rtl-light-Mobile-Chrome-linux.png
index 6a5b04e1b8e..403ca727491 100644
Binary files a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-custom-ionic-md-rtl-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-custom-ionic-md-rtl-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-custom-ionic-md-rtl-light-Mobile-Firefox-linux.png b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-custom-ionic-md-rtl-light-Mobile-Firefox-linux.png
index 4a22d40bf1b..90ee159cee2 100644
Binary files a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-custom-ionic-md-rtl-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-custom-ionic-md-rtl-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png
index d56d1d246ba..f362b35be70 100644
Binary files a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png
index 4bc1268397c..d856ae3d8c8 100644
Binary files a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-ionic-md-rtl-light-Mobile-Chrome-linux.png b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-ionic-md-rtl-light-Mobile-Chrome-linux.png
index 9c78f87bce0..f1389b84bc5 100644
Binary files a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-ionic-md-rtl-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-ionic-md-rtl-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-ionic-md-rtl-light-Mobile-Firefox-linux.png b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-ionic-md-rtl-light-Mobile-Firefox-linux.png
index ba6ae3280f0..99068d1bc9e 100644
Binary files a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-ionic-md-rtl-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-rectangular-fill-outline-ionic-md-rtl-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-custom-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-custom-ionic-md-ltr-light-Mobile-Chrome-linux.png
index c4526613e5d..9e8a0ff4026 100644
Binary files a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-custom-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-custom-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-custom-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-custom-ionic-md-ltr-light-Mobile-Firefox-linux.png
index 21c0e18ed20..b36aef822f2 100644
Binary files a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-custom-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-custom-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-custom-ionic-md-rtl-light-Mobile-Chrome-linux.png b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-custom-ionic-md-rtl-light-Mobile-Chrome-linux.png
index 6a5b04e1b8e..403ca727491 100644
Binary files a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-custom-ionic-md-rtl-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-custom-ionic-md-rtl-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-custom-ionic-md-rtl-light-Mobile-Firefox-linux.png b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-custom-ionic-md-rtl-light-Mobile-Firefox-linux.png
index 4a22d40bf1b..90ee159cee2 100644
Binary files a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-custom-ionic-md-rtl-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-custom-ionic-md-rtl-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png
index 9db3cb7c160..9de22bde883 100644
Binary files a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png
index 5e2095162dd..b2c74c526d4 100644
Binary files a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-ionic-md-rtl-light-Mobile-Chrome-linux.png b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-ionic-md-rtl-light-Mobile-Chrome-linux.png
index 127f0a655a7..2a65de63956 100644
Binary files a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-ionic-md-rtl-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-ionic-md-rtl-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-ionic-md-rtl-light-Mobile-Firefox-linux.png b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-ionic-md-rtl-light-Mobile-Firefox-linux.png
index 6d6ddeee453..ec2feb6d63b 100644
Binary files a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-ionic-md-rtl-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-round-fill-outline-ionic-md-rtl-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-soft-fill-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-soft-fill-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png
index 1fb3cd17783..3d71a94dd4d 100644
Binary files a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-soft-fill-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-soft-fill-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-soft-fill-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-soft-fill-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png
index 7abc928b3c4..552f81ab02b 100644
Binary files a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-soft-fill-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-soft-fill-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-soft-fill-outline-ionic-md-rtl-light-Mobile-Chrome-linux.png b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-soft-fill-outline-ionic-md-rtl-light-Mobile-Chrome-linux.png
index da6c9ab793f..0ecd470ef2d 100644
Binary files a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-soft-fill-outline-ionic-md-rtl-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-soft-fill-outline-ionic-md-rtl-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-soft-fill-outline-ionic-md-rtl-light-Mobile-Firefox-linux.png b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-soft-fill-outline-ionic-md-rtl-light-Mobile-Firefox-linux.png
index dccdb666ef6..5f7c4f92482 100644
Binary files a/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-soft-fill-outline-ionic-md-rtl-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/shape/input.e2e.ts-snapshots/input-shape-soft-fill-outline-ionic-md-rtl-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-ionic-md-ltr-light-Mobile-Chrome-linux.png
index dd94e9a8370..47ba774b4a1 100644
Binary files a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-ionic-md-ltr-light-Mobile-Firefox-linux.png
index a7563b2ca44..c653852c8bc 100644
Binary files a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-label-stacked-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-label-stacked-ionic-md-ltr-light-Mobile-Chrome-linux.png
index dd94e9a8370..47ba774b4a1 100644
Binary files a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-label-stacked-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-label-stacked-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-label-stacked-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-label-stacked-ionic-md-ltr-light-Mobile-Firefox-linux.png
index a7563b2ca44..c653852c8bc 100644
Binary files a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-label-stacked-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-label-stacked-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png
index dd94e9a8370..47ba774b4a1 100644
Binary files a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png
index a7563b2ca44..c653852c8bc 100644
Binary files a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-outline-round-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-outline-round-ionic-md-ltr-light-Mobile-Chrome-linux.png
index dd94e9a8370..47ba774b4a1 100644
Binary files a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-outline-round-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-outline-round-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-outline-round-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-outline-round-ionic-md-ltr-light-Mobile-Firefox-linux.png
index a7563b2ca44..c653852c8bc 100644
Binary files a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-outline-round-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-large-outline-round-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-ionic-md-ltr-light-Mobile-Chrome-linux.png
index 1c8c452638e..cc75fc7086c 100644
Binary files a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-ionic-md-ltr-light-Mobile-Firefox-linux.png
index 3b624b2e928..589a88cd550 100644
Binary files a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-label-stacked-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-label-stacked-ionic-md-ltr-light-Mobile-Chrome-linux.png
index 1c8c452638e..cc75fc7086c 100644
Binary files a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-label-stacked-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-label-stacked-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-label-stacked-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-label-stacked-ionic-md-ltr-light-Mobile-Firefox-linux.png
index 3b624b2e928..589a88cd550 100644
Binary files a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-label-stacked-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-label-stacked-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png
index 1c8c452638e..cc75fc7086c 100644
Binary files a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png
index 3b624b2e928..589a88cd550 100644
Binary files a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-outline-round-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-outline-round-ionic-md-ltr-light-Mobile-Chrome-linux.png
index 1c8c452638e..cc75fc7086c 100644
Binary files a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-outline-round-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-outline-round-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-outline-round-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-outline-round-ionic-md-ltr-light-Mobile-Firefox-linux.png
index 3b624b2e928..589a88cd550 100644
Binary files a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-outline-round-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-medium-outline-round-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-ionic-md-ltr-light-Mobile-Chrome-linux.png
index 85326e97e20..bde9a9597db 100644
Binary files a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-ionic-md-ltr-light-Mobile-Firefox-linux.png
index 1350a8ea343..5b02e1731ee 100644
Binary files a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-label-stacked-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-label-stacked-ionic-md-ltr-light-Mobile-Chrome-linux.png
index 85326e97e20..bde9a9597db 100644
Binary files a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-label-stacked-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-label-stacked-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-label-stacked-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-label-stacked-ionic-md-ltr-light-Mobile-Firefox-linux.png
index 1350a8ea343..5b02e1731ee 100644
Binary files a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-label-stacked-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-label-stacked-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png
index 85326e97e20..bde9a9597db 100644
Binary files a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-outline-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png
index 1350a8ea343..5b02e1731ee 100644
Binary files a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-outline-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-outline-round-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-outline-round-ionic-md-ltr-light-Mobile-Chrome-linux.png
index 85326e97e20..bde9a9597db 100644
Binary files a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-outline-round-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-outline-round-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-outline-round-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-outline-round-ionic-md-ltr-light-Mobile-Firefox-linux.png
index 1350a8ea343..5b02e1731ee 100644
Binary files a/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-outline-round-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/input/test/size/input.e2e.ts-snapshots/input-size-xlarge-outline-round-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/input/test/slot/index.html b/core/src/components/input/test/slot/index.html
index fd646c13333..044ee661131 100644
--- a/core/src/components/input/test/slot/index.html
+++ b/core/src/components/input/test/slot/index.html
@@ -37,6 +37,19 @@
.required {
color: red;
}
+
+ .hint {
+ font-size: 12px;
+ color: #6f7378;
+ max-width: 60ch;
+ }
+
+ .counts {
+ font-size: 12px;
+ color: #6f7378;
+
+ margin-top: 6px;
+ }
@@ -53,42 +66,63 @@
Label Slot
No Fill / Start Label
-
+
Email *
Solid / Start Label
-
+
Email *
Outline / Start Label
-
+
Email *
No Fill / Floating Label
-
+
Email *
Solid / Floating Label
-
+
Email *
Outline / Floating Label
-
+
+
Email *
+
+
+
+
+
No Fill / Stacked Label
+
+
Email *
+
+
+
+
+
Solid / Stacked Label
+
+
Email *
+
+
+
+
+
Outline / Stacked Label
+
Email *
@@ -98,7 +132,7 @@
Start/End Slots
No Fill / Start Label
-
+
@@ -108,7 +142,7 @@
No Fill / Start Label
Solid / Start Label
-
+
@@ -118,7 +152,7 @@
Solid / Start Label
Outline / Start Label
-
+
@@ -128,7 +162,7 @@
Outline / Start Label
No Fill / Floating Label
-
+
@@ -138,7 +172,7 @@
No Fill / Floating Label
Solid / Floating Label
-
+
@@ -148,7 +182,37 @@
Solid / Floating Label
Outline / Floating Label
-
+
+
+
+
+
+
+
+
+
+
No Fill / Stacked Label
+
+
+
+
+
+
+
+
+
+
Solid / Stacked Label
+
+
+
+
+
+
+
+
+
+
Outline / Stacked Label
+
@@ -187,11 +251,147 @@
Outline / Stacked Label
+
Overflowing Slots
+
+
+
No Fill / Start Label / No Slot
+
+
+
+
+
+
No Fill / Start Label / Start Slot
+
+
+
+
+
+
+
No Fill / Start Label / End Slot
+
+
+
+
+
+
+
Outline / Start Label / No Slot
+
+
+
+
+
+
Outline / Start Label / Start Slot
+
+
+
+
+
+
+
Outline / Start Label / End Slot
+
+
+
+
+
+
+
Outline / Floating Label / No Slot
+
+
+
+
+
+
Outline / Floating Label / Start Slot
+
+
+
+
+
+
+
Outline / Floating Label / End Slot
+
+
+
+
+
+
+
Click Propagation
+
+ Each click on the host is counted, and the target of each is logged to the console. One physical click should
+ count once. Click the padding strip (the gap between the border and the text), the label, the input text, and
+ the slotted button, and compare.
+
+
+
+
No Fill
+
+
+
+
+
+
+
host: 0
+
+
+
+
Solid (16px padding)
+
+
+
+
+
+
+
host: 0
+
+
+
+
Outline (16px padding)
+
+
+
+
+
+
+
host: 0
+
+
+
+ Reset Counts
+
Async Slot Content
Outline / Async Label
-
+
@@ -203,6 +403,7 @@
Outline / Async Decorations
Add Slotted ContentUpdate Slotted ContentRemove Slotted Content
+ Add Value to All
@@ -272,6 +473,29 @@