Compare commits

..

1 Commits

Author SHA1 Message Date
rug
0b34c174b0 Removing padding in columns for ionic theme 2025-12-01 12:39:54 +01:00
223 changed files with 2203 additions and 3321 deletions

View File

@@ -22,7 +22,7 @@ runs:
using: 'composite'
steps:
- name: 🟢 Configure Node for Publish
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: ${{ inputs.node-version }}
registry-url: 'https://registry.npmjs.org'

View File

@@ -3,7 +3,7 @@ description: 'Build Ionic Angular Server'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive

View File

@@ -8,8 +8,8 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 24.x

View File

@@ -8,8 +8,8 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 24.x
- name: 🕸️ Install Dependencies

View File

@@ -3,7 +3,7 @@ description: 'Build Ionic React Router'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive

View File

@@ -3,7 +3,7 @@ description: 'Build Ionic React'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive

View File

@@ -3,7 +3,7 @@ description: 'Builds Ionic Vue Router'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive

View File

@@ -3,7 +3,7 @@ description: 'Build Ionic Vue'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive

View File

@@ -10,7 +10,7 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v6
with:
name: ${{ inputs.name }}
path: ${{ inputs.path }}

View File

@@ -6,7 +6,7 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive

View File

@@ -3,7 +3,7 @@ description: 'Test Core Clean Build'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 24.x

View File

@@ -3,7 +3,7 @@ description: 'Test Core Lint'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 24.x
- name: 🕸️ Install Dependencies

View File

@@ -13,7 +13,7 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
@@ -62,7 +62,7 @@ runs:
working-directory: ./core
- name: 📦 Archive Updated Screenshots
if: inputs.update == 'true' && steps.test-and-update.outputs.hasUpdatedScreenshots == 'true'
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v5
with:
name: updated-screenshots-${{ inputs.shard }}-${{ inputs.totalShards }}
path: UpdatedScreenshots-${{ inputs.shard }}-${{ inputs.totalShards }}.zip

View File

@@ -6,7 +6,7 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 24.x
- name: 🕸️ Install Dependencies

View File

@@ -6,7 +6,7 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive

View File

@@ -6,7 +6,7 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive

View File

@@ -6,7 +6,7 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive

View File

@@ -7,10 +7,10 @@ on:
runs:
using: 'composite'
steps:
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 24.x
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v6
with:
path: ./artifacts
- name: 🔎 Extract Archives

View File

@@ -13,7 +13,7 @@ runs:
- name: 🗄️ Create Archive
run: zip -q -r ${{ inputs.output }} ${{ inputs.paths }}
shell: bash
- uses: actions/upload-artifact@v6
- uses: actions/upload-artifact@v5
with:
name: ${{ inputs.name }}
path: ${{ inputs.output }}

View File

@@ -22,7 +22,7 @@ jobs:
build-core:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/build-core
with:
ionicons-version: ${{ inputs.ionicons_npm_release_tag }}
@@ -31,21 +31,21 @@ jobs:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/test-core-clean-build
test-core-lint:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/test-core-lint
test-core-spec:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/test-core-spec
test-core-screenshot:
@@ -62,7 +62,7 @@ jobs:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/test-core-screenshot
with:
shard: ${{ matrix.shard }}
@@ -90,14 +90,14 @@ jobs:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/build-vue
build-vue-router:
needs: [build-vue]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/build-vue-router
test-vue-e2e:
@@ -108,7 +108,7 @@ jobs:
needs: [build-vue, build-vue-router]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/test-vue-e2e
with:
app: ${{ matrix.apps }}
@@ -126,14 +126,14 @@ jobs:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/build-angular
build-angular-server:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/build-angular-server
test-angular-e2e:
@@ -144,7 +144,7 @@ jobs:
needs: [build-angular, build-angular-server]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/test-angular-e2e
with:
app: ${{ matrix.apps }}
@@ -162,14 +162,14 @@ jobs:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/build-react
build-react-router:
needs: [build-react]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/build-react-router
test-react-router-e2e:
@@ -180,7 +180,7 @@ jobs:
needs: [build-react, build-react-router]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/test-react-router-e2e
with:
app: ${{ matrix.apps }}
@@ -202,7 +202,7 @@ jobs:
needs: [build-react, build-react-router]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/test-react-e2e
with:
app: ${{ matrix.apps }}

View File

@@ -14,7 +14,7 @@ jobs:
permissions:
security-events: write
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: github/codeql-action/init@v4
with:
languages: javascript

View File

@@ -13,7 +13,7 @@ jobs:
outputs:
dev-hash: ${{ steps.create-dev-hash.outputs.DEV_HASH }}
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
# A 1 is required before the timestamp
# as lerna will fail when there is a leading 0
# See https://github.com/lerna/lerna/issues/2840

View File

@@ -13,7 +13,7 @@ jobs:
outputs:
nightly-hash: ${{ steps.create-nightly-hash.outputs.NIGHTLY_HASH }}
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
# A 1 is required before the timestamp
# as lerna will fail when there is a leading 0
# See https://github.com/lerna/lerna/issues/2840

View File

@@ -23,7 +23,7 @@ jobs:
release-core:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/actions/publish-npm
with:
scope: '@ionic/core'
@@ -48,7 +48,7 @@ jobs:
needs: [release-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- name: Restore @ionic/docs built cache
uses: ./.github/workflows/actions/download-archive
with:
@@ -67,7 +67,7 @@ jobs:
needs: [release-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- name: Restore @ionic/core built cache
uses: ./.github/workflows/actions/download-archive
with:
@@ -93,7 +93,7 @@ jobs:
needs: [release-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- name: Restore @ionic/core built cache
uses: ./.github/workflows/actions/download-archive
with:
@@ -118,7 +118,7 @@ jobs:
needs: [release-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- name: Restore @ionic/core built cache
uses: ./.github/workflows/actions/download-archive
with:
@@ -143,7 +143,7 @@ jobs:
needs: [release-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- name: Restore @ionic/core built cache
uses: ./.github/workflows/actions/download-archive
with:
@@ -163,7 +163,7 @@ jobs:
needs: [release-react]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- name: Restore @ionic/core built cache
uses: ./.github/workflows/actions/download-archive
with:
@@ -188,7 +188,7 @@ jobs:
needs: [release-vue]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- name: Restore @ionic/core built cache
uses: ./.github/workflows/actions/download-archive
with:

View File

@@ -71,7 +71,7 @@ jobs:
run-production:
if: ${{ github.event_name == 'workflow_dispatch' && inputs.release-type == 'production' }}
permissions:
contents: write
contents: read
id-token: write
uses: ./.github/workflows/release.yml
secrets: inherit

View File

@@ -54,11 +54,8 @@ jobs:
finalize-release:
needs: [release-ionic]
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
token: ${{ secrets.IONITRON_TOKEN }}
fetch-depth: 0
@@ -85,11 +82,8 @@ jobs:
# possible for them to push at the same time.
needs: [finalize-release]
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
# Pull the latest version of the reference
# branch instead of the revision that triggered
# the workflow otherwise we won't get the commit

View File

@@ -26,7 +26,7 @@ jobs:
build-core-with-stencil-nightly:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/build-core-stencil-prerelease
with:
stencil-version: ${{ inputs.npm_release_tag || 'nightly' }}
@@ -35,21 +35,21 @@ jobs:
needs: [build-core-with-stencil-nightly]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/test-core-clean-build
test-core-lint:
needs: [build-core-with-stencil-nightly]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/test-core-lint
test-core-spec:
needs: [build-core-with-stencil-nightly]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/test-core-spec
with:
stencil-version: ${{ inputs.npm_release_tag || 'nightly' }}
@@ -72,7 +72,7 @@ jobs:
needs: [build-core-with-stencil-nightly]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/test-core-screenshot
with:
shard: ${{ matrix.shard }}
@@ -100,14 +100,14 @@ jobs:
needs: [build-core-with-stencil-nightly]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/build-vue
build-vue-router:
needs: [build-vue]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/build-vue-router
test-vue-e2e:
@@ -118,7 +118,7 @@ jobs:
needs: [build-vue, build-vue-router]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/test-vue-e2e
with:
app: ${{ matrix.apps }}
@@ -136,14 +136,14 @@ jobs:
needs: [build-core-with-stencil-nightly]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/build-angular
build-angular-server:
needs: [build-core-with-stencil-nightly]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/build-angular-server
test-angular-e2e:
@@ -154,7 +154,7 @@ jobs:
needs: [build-angular, build-angular-server]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/test-angular-e2e
with:
app: ${{ matrix.apps }}
@@ -172,14 +172,14 @@ jobs:
needs: [build-core-with-stencil-nightly]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/build-react
build-react-router:
needs: [build-react]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/build-react-router
test-react-router-e2e:
@@ -190,7 +190,7 @@ jobs:
needs: [build-react, build-react-router]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/test-react-router-e2e
with:
app: ${{ matrix.apps }}
@@ -212,7 +212,7 @@ jobs:
needs: [build-react, build-react-router]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/test-react-e2e
with:
app: ${{ matrix.apps }}

View File

@@ -26,7 +26,7 @@ jobs:
build-core:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/build-core
test-core-screenshot:
@@ -47,7 +47,7 @@ jobs:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ./.github/workflows/actions/test-core-screenshot
with:
shard: ${{ matrix.shard }}
@@ -59,7 +59,7 @@ jobs:
runs-on: ubuntu-latest
needs: [test-core-screenshot]
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
# Normally, we could just push with the
# default GITHUB_TOKEN, but that will
# not cause the build workflow

View File

@@ -38,12 +38,6 @@ This is a comprehensive list of the breaking changes introduced in the major ver
- The properties `pull` and `push` have been deprecated and no longer work. A similar look can be achieved with the newly added property `order`.
<h4 id="version-9x-radio-group">Radio Group</h4>
- Converted `ion-radio-group` to use [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM).<br/>
If you were targeting the internals of `ion-radio-group` in your CSS, you will need to target the `supporting-text`, `helper-text` or `error-text` [Shadow Parts](https://ionicframework.com/docs/theming/css-shadow-parts) instead, or use the provided CSS Variables.<br/>
Additionally, the `radio-group-wrapper` div element has been removed, causing slotted elements to be direct children of the `ion-radio-group`.
<h5>Example 1: Swap two columns</h5>
**Version up to 8.x**

View File

@@ -3,53 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [8.7.15](https://github.com/ionic-team/ionic-framework/compare/v8.7.14...v8.7.15) (2025-12-23)
### Bug Fixes
* **core:** use Capacitor safe-area CSS variables on older WebViews ([#30865](https://github.com/ionic-team/ionic-framework/issues/30865)) ([8573bf8](https://github.com/ionic-team/ionic-framework/commit/8573bf8083f75eda13c954a56731a6aac8ca5724))
* **header:** show iOS condense header when app is in MD mode ([#30690](https://github.com/ionic-team/ionic-framework/issues/30690)) ([f83b000](https://github.com/ionic-team/ionic-framework/commit/f83b0005309400d674e43c497bdffbcb9d2c4d94)), closes [#29929](https://github.com/ionic-team/ionic-framework/issues/29929)
* **input-password-toggle:** improve screen reader announcements ([#30885](https://github.com/ionic-team/ionic-framework/issues/30885)) ([12ede4b](https://github.com/ionic-team/ionic-framework/commit/12ede4b79c8d5cffc2b014c7c8a0d2ef1d3bf90d))
* **modal:** dismiss top-most overlay when multiple IDs match ([#30883](https://github.com/ionic-team/ionic-framework/issues/30883)) ([3b60a1d](https://github.com/ionic-team/ionic-framework/commit/3b60a1d68a1df1606ffee0bde7db7a206bac404a)), closes [#30030](https://github.com/ionic-team/ionic-framework/issues/30030)
## [8.7.14](https://github.com/ionic-team/ionic-framework/compare/v8.7.13...v8.7.14) (2025-12-17)
### Bug Fixes
* **tabs:** select correct tab when routes have similar prefixes ([#30863](https://github.com/ionic-team/ionic-framework/issues/30863)) ([03fb422](https://github.com/ionic-team/ionic-framework/commit/03fb422bfa775e3e9dd695ea1857fa88d4245ecd)), closes [#30448](https://github.com/ionic-team/ionic-framework/issues/30448)
## [8.7.13](https://github.com/ionic-team/ionic-framework/compare/v8.7.12...v8.7.13) (2025-12-13)
**Note:** Version bump only for package ionic-framework
## [8.7.12](https://github.com/ionic-team/ionic-framework/compare/v8.7.11...v8.7.12) (2025-12-10)
### Bug Fixes
* **modal:** allow interaction with parent content through sheet modals in child routes ([#30839](https://github.com/ionic-team/ionic-framework/issues/30839)) ([b9e3cf0](https://github.com/ionic-team/ionic-framework/commit/b9e3cf0f5aae79a1f27a07b102c77e51f24825f4)), closes [#30700](https://github.com/ionic-team/ionic-framework/issues/30700)
* **modal:** prevent browser hang when using ModalController in Angular ([#30845](https://github.com/ionic-team/ionic-framework/issues/30845)) ([b164516](https://github.com/ionic-team/ionic-framework/commit/b1645168a7fb9378dc39a081c207b2de0e180089))
* **popover:** recalculate the content dimensions after the header has fully loaded ([#30853](https://github.com/ionic-team/ionic-framework/issues/30853)) ([99dcf38](https://github.com/ionic-team/ionic-framework/commit/99dcf3810a0c32416996d1e992ddf63359965cfc))
* **select, action-sheet:** use radio role for options ([#30769](https://github.com/ionic-team/ionic-framework/issues/30769)) ([1c89cf0](https://github.com/ionic-team/ionic-framework/commit/1c89cf06ac959f9c9a35a66f811227c244d3198b))
## [8.7.11](https://github.com/ionic-team/ionic-framework/compare/v8.7.10...v8.7.11) (2025-11-26)

View File

@@ -3,50 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [8.7.15](https://github.com/ionic-team/ionic-framework/compare/v8.7.14...v8.7.15) (2025-12-23)
### Bug Fixes
* **core:** use Capacitor safe-area CSS variables on older WebViews ([#30865](https://github.com/ionic-team/ionic-framework/issues/30865)) ([8573bf8](https://github.com/ionic-team/ionic-framework/commit/8573bf8083f75eda13c954a56731a6aac8ca5724))
* **header:** show iOS condense header when app is in MD mode ([#30690](https://github.com/ionic-team/ionic-framework/issues/30690)) ([f83b000](https://github.com/ionic-team/ionic-framework/commit/f83b0005309400d674e43c497bdffbcb9d2c4d94)), closes [#29929](https://github.com/ionic-team/ionic-framework/issues/29929)
* **input-password-toggle:** improve screen reader announcements ([#30885](https://github.com/ionic-team/ionic-framework/issues/30885)) ([12ede4b](https://github.com/ionic-team/ionic-framework/commit/12ede4b79c8d5cffc2b014c7c8a0d2ef1d3bf90d))
* **modal:** dismiss top-most overlay when multiple IDs match ([#30883](https://github.com/ionic-team/ionic-framework/issues/30883)) ([3b60a1d](https://github.com/ionic-team/ionic-framework/commit/3b60a1d68a1df1606ffee0bde7db7a206bac404a)), closes [#30030](https://github.com/ionic-team/ionic-framework/issues/30030)
## [8.7.14](https://github.com/ionic-team/ionic-framework/compare/v8.7.13...v8.7.14) (2025-12-17)
**Note:** Version bump only for package @ionic/core
## [8.7.13](https://github.com/ionic-team/ionic-framework/compare/v8.7.12...v8.7.13) (2025-12-13)
**Note:** Version bump only for package @ionic/core
## [8.7.12](https://github.com/ionic-team/ionic-framework/compare/v8.7.11...v8.7.12) (2025-12-10)
### Bug Fixes
* **modal:** allow interaction with parent content through sheet modals in child routes ([#30839](https://github.com/ionic-team/ionic-framework/issues/30839)) ([b9e3cf0](https://github.com/ionic-team/ionic-framework/commit/b9e3cf0f5aae79a1f27a07b102c77e51f24825f4)), closes [#30700](https://github.com/ionic-team/ionic-framework/issues/30700)
* **modal:** prevent browser hang when using ModalController in Angular ([#30845](https://github.com/ionic-team/ionic-framework/issues/30845)) ([b164516](https://github.com/ionic-team/ionic-framework/commit/b1645168a7fb9378dc39a081c207b2de0e180089))
* **popover:** recalculate the content dimensions after the header has fully loaded ([#30853](https://github.com/ionic-team/ionic-framework/issues/30853)) ([99dcf38](https://github.com/ionic-team/ionic-framework/commit/99dcf3810a0c32416996d1e992ddf63359965cfc))
* **select, action-sheet:** use radio role for options ([#30769](https://github.com/ionic-team/ionic-framework/issues/30769)) ([1c89cf0](https://github.com/ionic-team/ionic-framework/commit/1c89cf06ac959f9c9a35a66f811227c244d3198b))
## [8.7.11](https://github.com/ionic-team/ionic-framework/compare/v8.7.10...v8.7.11) (2025-11-26)

View File

@@ -1845,7 +1845,7 @@ ion-radio,part,container
ion-radio,part,label
ion-radio,part,mark
ion-radio-group,shadow
ion-radio-group,none
ion-radio-group,prop,allowEmptySelection,boolean,false,false,false
ion-radio-group,prop,compareWith,((currentValue: any, compareValue: any) => boolean) | null | string | undefined,undefined,false,false
ion-radio-group,prop,errorText,string | undefined,undefined,false,false
@@ -1855,9 +1855,6 @@ ion-radio-group,prop,name,string,this.inputId,false,false
ion-radio-group,prop,theme,"ios" | "md" | "ionic",undefined,false,false
ion-radio-group,prop,value,any,undefined,false,false
ion-radio-group,event,ionChange,RadioGroupChangeEventDetail<any>,true
ion-radio-group,part,error-text
ion-radio-group,part,helper-text
ion-radio-group,part,supporting-text
ion-range,shadow
ion-range,prop,activeBarStart,number | undefined,undefined,false,false

2972
core/package-lock.json generated
View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,7 @@
{
"name": "@ionic/core",
"version": "8.7.15",
"version": "8.7.11",
"description": "Base components for Ionic",
"engines": {
"node": ">= 16"
},
"keywords": [
"ionic",
"framework",
@@ -41,10 +38,10 @@
},
"devDependencies": {
"@axe-core/playwright": "^4.11.0",
"@capacitor/core": "^8.0.0",
"@capacitor/haptics": "^8.0.0",
"@capacitor/keyboard": "^8.0.0",
"@capacitor/status-bar": "^8.0.0",
"@capacitor/core": "^7.0.0",
"@capacitor/haptics": "^7.0.0",
"@capacitor/keyboard": "^7.0.0",
"@capacitor/status-bar": "^7.0.0",
"@clack/prompts": "^0.11.0",
"@ionic/eslint-config": "^0.3.0",
"@ionic/prettier-config": "^2.0.0",
@@ -70,7 +67,6 @@
"jest": "^29.7.0",
"jest-cli": "^29.7.0",
"outsystems-design-tokens": "^1.3.4",
"playwright-core": "^1.56.1",
"prettier": "^2.8.8",
"rollup": "^2.26.4",
"sass": "^1.33.0",

View File

@@ -14,7 +14,7 @@
* The following URL parameters are supported:
* - `rtl`: Set to `true` to enable right-to-left directionality.
* - `ionic:_testing`: Set to `true` to identify testing environments.
* - `ionic:theme`: Set to `ios` or `md` to load a specific theme.
* - `ionic:mode`: Set to `ios` or `md` to load a specific mode.
* Defaults to `md`.
* - `palette`: Set to `light`, `dark`, `high-contrast`, or
* `high-contrast-dark` to load a specific palette. Defaults to `light`.
@@ -57,19 +57,11 @@
* Values can be `light`, `dark`, `high-contrast`,
* or `high-contrast-dark`. Default to `light` for tests.
*/
const validPalettes = ['light', 'dark', 'high-contrast', 'high-contrast-dark'];
const paletteQuery = window.location.search.match(/palette=([a-z-]+)/);
const paletteHash = window.location.hash.match(/palette=([a-z-]+)/);
const paletteQuery = window.location.search.match(/palette=([a-z]+)/);
const paletteHash = window.location.hash.match(/palette=([a-z]+)/);
const darkClass = document.body?.classList.contains('ion-palette-dark') ? 'dark' : null;
const highContrastClass = document.body?.classList.contains('ion-palette-high-contrast') ? 'high-contrast' : null;
const highContrastDarkClass = darkClass && highContrastClass ? 'high-contrast-dark' : null;
let paletteName = paletteQuery?.[1] || paletteHash?.[1] || highContrastDarkClass || darkClass || highContrastClass || 'light';
if (!validPalettes.includes(paletteName)) {
console.warn(`Invalid palette name: '${paletteName}'. Falling back to 'light' palette.`);
paletteName = 'light';
}
const paletteName = paletteQuery?.[1] || paletteHash?.[1] || darkClass || 'light';
if (paletteName !== 'light') {
const linkTag = document.createElement('link');

View File

@@ -1071,10 +1071,6 @@ export namespace Components {
* The mode determines the platform behaviors of the component.
*/
"mode"?: "ios" | "md";
/**
* Recalculate content dimensions. Called by overlays (e.g., popover) when sibling elements like headers or footers have finished rendering and their heights are available, ensuring accurate offset-top calculations.
*/
"recalculateDimensions": () => Promise<void>;
/**
* Scroll by a specified X/Y distance in the component.
* @param x The amount to scroll by on the horizontal axis.

View File

@@ -1,5 +1,5 @@
import type { ComponentInterface, EventEmitter } from '@stencil/core';
import { Watch, Component, Element, Event, Host, Listen, Method, Prop, State, h, readTask } from '@stencil/core';
import { Watch, Component, Element, Event, Host, Method, Prop, h, readTask } from '@stencil/core';
import type { Gesture } from '@utils/gesture';
import { createButtonActiveGesture } from '@utils/gesture/button-active';
import { raf } from '@utils/helpers';
@@ -48,18 +48,11 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
private wrapperEl?: HTMLElement;
private groupEl?: HTMLElement;
private gesture?: Gesture;
private hasRadioButtons = false;
presented = false;
lastFocus?: HTMLElement;
animation?: any;
/**
* The ID of the currently active/selected radio button.
* Used for keyboard navigation and ARIA attributes.
*/
@State() activeRadioId?: string;
@Element() el!: HTMLIonActionSheetElement;
/** @internal */
@@ -90,22 +83,6 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
* An array of buttons for the action sheet.
*/
@Prop() buttons: (ActionSheetButton | string)[] = [];
@Watch('buttons')
buttonsChanged() {
const radioButtons = this.getRadioButtons();
this.hasRadioButtons = radioButtons.length > 0;
// Initialize activeRadioId when buttons change
if (this.hasRadioButtons) {
const checkedButton = radioButtons.find((b) => b.htmlAttributes?.['aria-checked'] === 'true');
if (checkedButton) {
const allButtons = this.getButtons();
const checkedIndex = allButtons.indexOf(checkedButton);
this.activeRadioId = this.getButtonId(checkedButton, checkedIndex);
}
}
}
/**
* Additional classes to apply for custom CSS. If multiple classes are
@@ -302,53 +279,12 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
return true;
}
/**
* Get all buttons regardless of role.
*/
private getButtons(): ActionSheetButton[] {
return this.buttons.map((b) => {
return typeof b === 'string' ? { text: b } : b;
});
}
/**
* Get all radio buttons (buttons with role="radio").
*/
private getRadioButtons(): ActionSheetButton[] {
return this.getButtons().filter((b) => {
const role = b.htmlAttributes?.role;
return role === 'radio' && !isCancel(role);
});
}
/**
* Handle radio button selection and update aria-checked state.
*
* @param button The radio button that was selected.
*/
private selectRadioButton(button: ActionSheetButton) {
const buttonId = this.getButtonId(button);
// Set the active radio ID (this will trigger a re-render and update aria-checked)
this.activeRadioId = buttonId;
}
/**
* Get or generate an ID for a button.
*
* @param button The button for which to get the ID.
* @param index Optional index of the button in the buttons array.
* @returns The ID of the button.
*/
private getButtonId(button: ActionSheetButton, index?: number): string {
if (button.id) {
return button.id;
}
const allButtons = this.getButtons();
const buttonIndex = index !== undefined ? index : allButtons.indexOf(button);
return `action-sheet-button-${this.overlayIndex}-${buttonIndex}`;
}
private onBackdropTap = () => {
this.dismiss(undefined, BACKDROP);
};
@@ -361,96 +297,6 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
}
};
/**
* When the action sheet has radio buttons, we want to follow the
* keyboard navigation pattern for radio groups:
* - Arrow Down/Right: Move to the next radio button (wrap to first if at end)
* - Arrow Up/Left: Move to the previous radio button (wrap to last if at start)
* - Space/Enter: Select the focused radio button and trigger its handler
*/
@Listen('keydown')
onKeydown(ev: KeyboardEvent) {
// Only handle keyboard navigation if we have radio buttons
if (!this.hasRadioButtons || !this.presented) {
return;
}
const target = ev.target as HTMLElement;
// Ignore if the target element is not within the action sheet or not a radio button
if (
!this.el.contains(target) ||
!target.classList.contains('action-sheet-button') ||
target.getAttribute('role') !== 'radio'
) {
return;
}
// Get all radio button elements and filter out disabled ones
const radios = Array.from(this.el.querySelectorAll('.action-sheet-button[role="radio"]')).filter(
(el) => !(el as HTMLButtonElement).disabled
) as HTMLButtonElement[];
const currentIndex = radios.findIndex((radio) => radio.id === target.id);
if (currentIndex === -1) {
return;
}
const allButtons = this.getButtons();
const radioButtons = this.getRadioButtons();
/**
* Build a map of button element IDs to their ActionSheetButton
* config objects.
* This allows us to quickly look up which button config corresponds
* to a DOM element when handling keyboard navigation
* (e.g., whenuser presses Space/Enter or arrow keys).
* The key is the ID that was set on the DOM element during render,
* and the value is the ActionSheetButton config that contains the
* handler and other properties.
*/
const buttonIdMap = new Map<string, ActionSheetButton>();
radioButtons.forEach((b) => {
const allIndex = allButtons.indexOf(b);
const buttonId = this.getButtonId(b, allIndex);
buttonIdMap.set(buttonId, b);
});
let nextEl: HTMLButtonElement | undefined;
if (['ArrowDown', 'ArrowRight'].includes(ev.key)) {
ev.preventDefault();
ev.stopPropagation();
nextEl = currentIndex === radios.length - 1 ? radios[0] : radios[currentIndex + 1];
} else if (['ArrowUp', 'ArrowLeft'].includes(ev.key)) {
ev.preventDefault();
ev.stopPropagation();
nextEl = currentIndex === 0 ? radios[radios.length - 1] : radios[currentIndex - 1];
} else if (ev.key === ' ' || ev.key === 'Enter') {
ev.preventDefault();
ev.stopPropagation();
const button = buttonIdMap.get(target.id);
if (button) {
this.selectRadioButton(button);
this.buttonClick(button);
}
return;
}
// Focus the next radio button
if (nextEl) {
const button = buttonIdMap.get(nextEl.id);
if (button) {
this.selectRadioButton(button);
nextEl.focus();
}
}
}
connectedCallback() {
prepareOverlay(this.el);
this.triggerChanged();
@@ -468,8 +314,6 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
if (!this.htmlAttributes?.id) {
setOverlayId(this.el);
}
// Initialize activeRadioId for radio buttons
this.buttonsChanged();
}
componentDidLoad() {
@@ -514,82 +358,8 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
this.triggerChanged();
}
private renderActionSheetButtons(filteredButtons: ActionSheetButton[]) {
const theme = getIonTheme(this);
const { activeRadioId } = this;
return filteredButtons.map((b, index) => {
const isRadio = b.htmlAttributes?.role === 'radio';
const buttonId = this.getButtonId(b, index);
const radioButtons = this.getRadioButtons();
const isActiveRadio = isRadio && buttonId === activeRadioId;
const isFirstRadio = isRadio && b === radioButtons[0];
// For radio buttons, set tabindex: 0 for the active one, -1 for others
// For non-radio buttons, use default tabindex (undefined, which means 0)
/**
* For radio buttons, set tabindex based on activeRadioId
* - If the button is the active radio, tabindex is 0
* - If no radio is active, the first radio button should have tabindex 0
* - All other radio buttons have tabindex -1
* For non-radio buttons, use default tabindex (undefined, which means 0)
*/
let tabIndex: number | undefined;
if (isRadio) {
// Focus on the active radio button
if (isActiveRadio) {
tabIndex = 0;
} else if (!activeRadioId && isFirstRadio) {
// No active radio, first radio gets focus
tabIndex = 0;
} else {
// All other radios are not focusable
tabIndex = -1;
}
} else {
tabIndex = undefined;
}
// For radio buttons, set aria-checked based on activeRadioId
// Otherwise, use the value from htmlAttributes if provided
const htmlAttrs = { ...b.htmlAttributes };
if (isRadio) {
htmlAttrs['aria-checked'] = isActiveRadio ? 'true' : 'false';
}
return (
<button
{...htmlAttrs}
role={isRadio ? 'radio' : undefined}
type="button"
id={buttonId}
class={{
...buttonClass(b),
'action-sheet-selected': isActiveRadio,
}}
onClick={() => {
if (isRadio) {
this.selectRadioButton(b);
}
this.buttonClick(b);
}}
disabled={b.disabled}
tabIndex={tabIndex}
>
<span class="action-sheet-button-inner">
{b.icon && <ion-icon icon={b.icon} aria-hidden="true" lazy={false} class="action-sheet-icon" />}
{b.text}
</span>
{theme === 'md' && <ion-ripple-effect></ion-ripple-effect>}
</button>
);
});
}
render() {
const { header, htmlAttributes, overlayIndex, hasRadioButtons } = this;
const { header, htmlAttributes, overlayIndex } = this;
const theme = getIonTheme(this);
const allButtons = this.getButtons();
const cancelButton = allButtons.find((b) => b.role === 'cancel');
@@ -621,11 +391,7 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
<div class="action-sheet-wrapper ion-overlay-wrapper" ref={(el) => (this.wrapperEl = el)}>
<div class="action-sheet-container">
<div
class="action-sheet-group"
ref={(el) => (this.groupEl = el)}
role={hasRadioButtons ? 'radiogroup' : undefined}
>
<div class="action-sheet-group" ref={(el) => (this.groupEl = el)}>
{header !== undefined && (
<div
id={headerID}
@@ -638,7 +404,22 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
{this.subHeader && <div class="action-sheet-sub-title">{this.subHeader}</div>}
</div>
)}
{this.renderActionSheetButtons(buttons)}
{buttons.map((b) => (
<button
{...b.htmlAttributes}
type="button"
id={b.id}
class={buttonClass(b)}
onClick={() => this.buttonClick(b)}
disabled={b.disabled}
>
<span class="action-sheet-button-inner">
{b.icon && <ion-icon icon={b.icon} aria-hidden="true" lazy={false} class="action-sheet-icon" />}
{b.text}
</span>
{theme === 'md' && <ion-ripple-effect></ion-ripple-effect>}
</button>
))}
</div>
{cancelButton && (

View File

@@ -134,58 +134,3 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
});
});
});
/**
* This behavior does not vary across modes/directions.
*/
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
test.describe(title('action-sheet: radio buttons'), () => {
test('should render action sheet with radio buttons correctly', async ({ page }) => {
await page.goto(`/src/components/action-sheet/test/a11y`, config);
const ionActionSheetDidPresent = await page.spyOnEvent('ionActionSheetDidPresent');
const button = page.locator('#radioButtons');
await button.click();
await ionActionSheetDidPresent.next();
const actionSheet = page.locator('ion-action-sheet');
const radioButtons = actionSheet.locator('.action-sheet-button[role="radio"]');
await expect(radioButtons).toHaveCount(2);
});
test('should navigate radio buttons with keyboard', async ({ page, pageUtils }) => {
await page.goto(`/src/components/action-sheet/test/a11y`, config);
const ionActionSheetDidPresent = await page.spyOnEvent('ionActionSheetDidPresent');
const button = page.locator('#radioButtons');
await button.click();
await ionActionSheetDidPresent.next();
// Focus on the radios
await pageUtils.pressKeys('Tab');
// Verify the first focusable radio button is focused
let focusedElement = await page.evaluate(() => document.activeElement?.textContent?.trim());
expect(focusedElement).toBe('Option 2');
// Navigate to the next radio button
await page.keyboard.press('ArrowDown');
// Verify the first radio button is focused again (wrap around)
focusedElement = await page.evaluate(() => document.activeElement?.textContent?.trim());
expect(focusedElement).toBe('Option 1');
// Navigate to the next radio button
await page.keyboard.press('ArrowDown');
// Navigate to the cancel button
await pageUtils.pressKeys('Tab');
focusedElement = await page.evaluate(() => document.activeElement?.textContent?.trim());
expect(focusedElement).toBe('Cancel');
});
});
});

View File

@@ -27,7 +27,6 @@
<button class="expand" id="ariaLabelCancelButton" onclick="presentAriaLabelCancelButton()">
Aria Label Cancel Button
</button>
<button class="expand" id="radioButtons" onclick="presentRadioButtons()">Radio Buttons</button>
</main>
<script>
@@ -101,32 +100,6 @@
],
});
}
function presentRadioButtons() {
openActionSheet({
header: 'Select an option',
buttons: [
{
text: 'Option 1',
htmlAttributes: {
role: 'radio',
'aria-checked': 'false',
},
},
{
text: 'Option 2',
htmlAttributes: {
role: 'radio',
'aria-checked': 'true',
},
},
{
text: 'Cancel',
role: 'cancel',
},
],
});
}
</script>
</body>
</html>

View File

@@ -5,7 +5,7 @@ import type { E2EPage } from '@utils/test/playwright';
/**
* Safe area tests only check top and bottom edges. RTL checks are not required here.
*/
configs({ directions: ['ltr'], modes: ['ios', 'md', 'ionic-md'] }).forEach(({ config, title, screenshot }) => {
configs({ directions: ['ltr'] }).forEach(({ config, title, screenshot }) => {
test.describe(title('app: safe-area'), () => {
const testOverlay = async (page: E2EPage, trigger: string, event: string, screenshotModifier: string) => {
const presentEvent = await page.spyOnEvent(event);
@@ -18,66 +18,20 @@ configs({ directions: ['ltr'], modes: ['ios', 'md', 'ionic-md'] }).forEach(({ co
await expect(page).toHaveScreenshot(screenshot(`app-${screenshotModifier}-diff`));
};
test.beforeEach(async ({ page }) => {
await page.goto(`/src/components/app/test/safe-area`, config);
});
test.describe(title('Ionic safe area variables'), () => {
test.beforeEach(async ({ page }) => {
const htmlTag = page.locator('html');
const hasSafeAreaClass = await htmlTag.evaluate((el) => el.classList.contains('safe-area'));
expect(hasSafeAreaClass).toBe(true);
});
test('should not have visual regressions with action sheet', async ({ page }) => {
await testOverlay(page, '#show-action-sheet', 'ionActionSheetDidPresent', 'action-sheet');
});
test('should not have visual regressions with menu', async ({ page }) => {
await testOverlay(page, '#show-menu', 'ionDidOpen', 'menu');
});
test('should not have visual regressions with picker', async ({ page }) => {
await testOverlay(page, '#show-picker', 'ionPickerDidPresent', 'picker');
});
test('should not have visual regressions with toast', async ({ page }) => {
await testOverlay(page, '#show-toast', 'ionToastDidPresent', 'toast');
});
test('should not have visual regressions with action sheet', async ({ page }) => {
await testOverlay(page, '#show-action-sheet', 'ionActionSheetDidPresent', 'action-sheet');
});
test.describe(title('Capacitor safe area variables'), () => {
test('should use safe-area-inset vars when safe-area class is not defined', async ({ page }) => {
await page.evaluate(() => {
const html = document.documentElement;
// Remove the safe area class
html.classList.remove('safe-area');
// Set the safe area inset variables
html.style.setProperty('--safe-area-inset-top', '10px');
html.style.setProperty('--safe-area-inset-bottom', '20px');
html.style.setProperty('--safe-area-inset-left', '30px');
html.style.setProperty('--safe-area-inset-right', '40px');
});
const top = await page.evaluate(() =>
getComputedStyle(document.documentElement).getPropertyValue('--ion-safe-area-top').trim()
);
const bottom = await page.evaluate(() =>
getComputedStyle(document.documentElement).getPropertyValue('--ion-safe-area-bottom').trim()
);
const left = await page.evaluate(() =>
getComputedStyle(document.documentElement).getPropertyValue('--ion-safe-area-left').trim()
);
const right = await page.evaluate(() =>
getComputedStyle(document.documentElement).getPropertyValue('--ion-safe-area-right').trim()
);
expect(top).toBe('10px');
expect(bottom).toBe('20px');
expect(left).toBe('30px');
expect(right).toBe('40px');
});
test('should not have visual regressions with menu', async ({ page }) => {
await testOverlay(page, '#show-menu', 'ionDidOpen', 'menu');
});
test('should not have visual regressions with picker', async ({ page }) => {
await testOverlay(page, '#show-picker', 'ionPickerDidPresent', 'picker');
});
test('should not have visual regressions with toast', async ({ page }) => {
await testOverlay(page, '#show-toast', 'ionToastDidPresent', 'toast');
});
});
});

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

View File

@@ -244,7 +244,7 @@
// Avatar Disabled
// --------------------------------------------------
:host(.avatar-disabled)::after {
:host(.avatar-disabled)::before {
@include globals.border-radius(var(--border-radius));
@include globals.disabled-state();
}

View File

@@ -12,9 +12,6 @@ configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screens
`
<div id="container">
<ion-avatar disabled> AV </ion-avatar>
<ion-avatar disabled>
<ion-icon name="person-outline"></ion-icon>
</ion-avatar>
<ion-avatar disabled>
<img src="/src/components/avatar/test/avatar.svg" />
</ion-avatar>

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -25,9 +25,6 @@
<ion-content>
<h3>Disabled</h3>
<ion-avatar disabled>AV</ion-avatar>
<ion-avatar disabled>
<ion-icon name="person-outline"></ion-icon>
</ion-avatar>
<ion-avatar disabled>
<img src="/src/components/avatar/test/avatar.svg" />
</ion-avatar>

View File

@@ -174,7 +174,6 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
*/
@Watch('aria-checked')
@Watch('aria-label')
@Watch('aria-pressed')
onAriaChanged(newValue: string, _oldValue: string, propName: string) {
this.inheritedAttributes = {
...this.inheritedAttributes,

View File

@@ -113,11 +113,11 @@ input {
// ----------------------------------------------------------------
.checkbox-bottom {
@include globals.typography(globals.$ion-body-sm-medium);
@include globals.typography(globals.$ion-body-md-regular);
}
.checkbox-bottom .error-text {
color: globals.$ion-text-danger;
color: globals.$ion-semantics-danger-800;
}
.checkbox-bottom .helper-text {
@@ -198,7 +198,7 @@ input {
// Ionic Design Checkbox Invalid
// --------------------------------------------------
:host(.ion-invalid) {
--focus-ring-color: #{globals.$ion-border-danger-default};
--focus-ring-color: #{globals.$ion-border-focus-error};
}
:host(.ion-invalid:not(.checkbox-checked)),

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -19,8 +19,6 @@
gap: globals.$ion-space-100;
line-height: globals.$ion-font-line-height-full;
cursor: auto;
}
// Outline Chip

View File

@@ -0,0 +1,9 @@
@import "./col.scss";
// Column
// --------------------------------------------------
:host {
// Override default padding for Ionic mode
--ion-grid-column-padding: 0;
}

View File

@@ -14,7 +14,11 @@ const BREAKPOINTS = ['', 'xs', 'sm', 'md', 'lg', 'xl'];
*/
@Component({
tag: 'ion-col',
styleUrl: 'col.scss',
styleUrls: {
ios: 'col.scss',
md: 'col.scss',
ionic: 'col.ionic.scss',
},
shadow: true,
})
export class Col implements ComponentInterface {

View File

@@ -257,17 +257,6 @@ export class Content implements ComponentInterface {
}
}
/**
* Recalculate content dimensions. Called by overlays (e.g., popover) when
* sibling elements like headers or footers have finished rendering and their
* heights are available, ensuring accurate offset-top calculations.
* @internal
*/
@Method()
async recalculateDimensions(): Promise<void> {
readTask(() => this.readDimensions());
}
private readDimensions() {
const page = getPageElement(this.el);
const top = Math.max(this.el.offsetTop, 0);

View File

@@ -25,13 +25,24 @@
width: 100%;
}
:host .calendar-body,
:host .datetime-year {
opacity: 0;
}
:host(:not(.datetime-ready)) .datetime-year {
position: absolute;
pointer-events: none;
}
:host(.datetime-ready) .calendar-body {
opacity: 1;
}
:host(.datetime-ready) .datetime-year {
display: none;
opacity: 1;
}
/**

View File

@@ -12,30 +12,6 @@
--background: #{globals.$ion-bg-surface-default};
--focus-ring-color: #{globals.$ion-border-focus-default};
--focus-ring-width: #{globals.$ion-border-radius-025};
/**
* TODO(FW-6931): Remove these variables upon solving the root cause
*/
--body-opacity: 0;
--year-opacity: 0;
}
/**
* TODO(FW-6931): Remove all this css related to opacity upon solving the root cause
*/
:host .calendar-body {
opacity: var(--body-opacity);
}
:host .datetime-year {
opacity: var(--year-opacity);
}
:host(.datetime-ready) .calendar-body {
--body-opacity: 1;
}
:host(.datetime-ready) .datetime-year {
--year-opacity: 1;
}
// Header

View File

@@ -23,22 +23,6 @@
max-width: 350px;
}
/**
* TODO(FW-6931): Move this back to common file upon solving the root cause
*/
:host .calendar-body,
:host .datetime-year {
opacity: 0;
}
/**
* TODO(FW-6931): Move this back to common file upon solving the root cause
*/
:host(.datetime-ready) .calendar-body,
:host(.datetime-ready) .datetime-year {
opacity: 1;
}
/**
* This ensures that the picker is appropriately
* sized and never truncates the text.

View File

@@ -8,7 +8,7 @@ ion-header {
z-index: 10; // TODO(ROU-10853): replace this value with a layer token.
&.header-divider {
border-bottom: globals.$ion-border-size-025 globals.$ion-border-style-solid globals.$ion-border-default;
border-bottom: globals.$ion-border-size-025 globals.$ion-border-style-solid globals.$ion-primitives-neutral-300;
}
}

View File

@@ -8,7 +8,7 @@
box-shadow: $header-md-box-shadow;
}
.header-md.header-collapse-condense {
.header-collapse-condense {
display: none;
}

View File

@@ -1,71 +0,0 @@
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';
/**
* This test verifies that collapsible headers with mode="ios" work correctly
* when both iOS and MD stylesheets are loaded. The bug occurred because
* `.header-collapse-condense { display: none }` in the MD stylesheet was not
* scoped to `.header-md`, causing it to hide iOS condense headers when both
* stylesheets were present.
*/
configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
test.describe(title('header: condense with iOS mode override'), () => {
test('should show iOS condense header when both MD and iOS styles are loaded', async ({ page }) => {
test.info().annotations.push({
type: 'issue',
description: 'https://github.com/ionic-team/ionic-framework/issues/29929',
});
// Include both an MD header and an iOS modal to force both stylesheets to load
await page.setContent(
`
<!-- MD header to force MD stylesheet to load -->
<ion-header mode="md" id="mdHeader">
<ion-toolbar>
<ion-title>MD Header</ion-title>
</ion-toolbar>
</ion-header>
<!-- Modal with iOS condense header -->
<ion-modal>
<ion-header mode="ios" id="smallTitleHeader">
<ion-toolbar>
<ion-title>Header</ion-title>
</ion-toolbar>
</ion-header>
<ion-content fullscreen="true">
<ion-header collapse="condense" mode="ios" id="largeTitleHeader">
<ion-toolbar>
<ion-title size="large">Large Header</ion-title>
</ion-toolbar>
</ion-header>
<p>Content</p>
</ion-content>
</ion-modal>
`,
config
);
const modal = page.locator('ion-modal');
const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent');
await modal.evaluate((el: HTMLIonModalElement) => el.present());
await ionModalDidPresent.next();
const largeTitleHeader = modal.locator('#largeTitleHeader');
// The large title header should be visible, not hidden by MD styles
await expect(largeTitleHeader).toBeVisible();
// Verify it has the iOS mode class
await expect(largeTitleHeader).toHaveClass(/header-ios/);
// Verify it does NOT have display: none applied
// This would fail if the MD stylesheet's unscoped .header-collapse-condense rule applies
const display = await largeTitleHeader.evaluate((el) => {
return window.getComputedStyle(el).display;
});
expect(display).not.toBe('none');
});
});
});

Some files were not shown because too many files have changed in this diff Show More