Compare commits

...

135 Commits

Author SHA1 Message Date
Maria Hutt
55cac74c95 feat(chip): add recipe and variables (#30873)
Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
Co-authored-by: Shane <shane@shanessite.net>
2026-02-19 13:18:26 -08:00
Maria Hutt
52779dd46c feat(themes): enable all palettes (#30874)
Issue number: internal

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

The new theming structure does not allow high contrast and high contrast
dark to render properly. This can be seen when running a test that uses
`set-content`.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- High contrast and high contrast dark have been enabled to the testing
environments
- The theme files for high contrast and high contrast dark have been
added under `themes`.

## Does this introduce a breaking change?

- [x] Yes
- [ ] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

[Colors
preview](https://ionic-framework-git-set-content-ionic1.vercel.app/src/themes/test/color/)

How to test:
1. Verify that tests related to palettes are passing especially those
that use `setContent`
2. Verify that the preview page renders the right colors for each
possible variation of palettes and themes

---------

Co-authored-by: ionitron <hi@ionicframework.com>
Co-authored-by: Brandy Smith <brandyscarney@users.noreply.github.com>
2026-01-16 13:20:08 -08:00
Maria Hutt
a61ab385dc chore(git): sync next (#30876)
Syncing with `next`
2025-12-15 17:27:20 -08:00
Maria Hutt
2de307de4f Merge remote-tracking branch 'origin/next' into chore-sync-ionic-modular-with-next 2025-12-15 17:09:10 -08:00
Maria Hutt
29f3f72e75 chore(git): sync main (#30875)
Syncing with `main`
2025-12-15 17:06:33 -08:00
Maria Hutt
bc9f7ef10e Merge remote-tracking branch 'origin/main' into chore-sync-next-with-main 2025-12-15 16:48:27 -08:00
renovate[bot]
82de33b96e chore(deps): update download + upload artifacts (major) (#30872)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[actions/download-artifact](https://redirect.github.com/actions/download-artifact)
| action | major | `v6` -> `v7` |
|
[actions/upload-artifact](https://redirect.github.com/actions/upload-artifact)
| action | major | `v5` -> `v6` |

---

### Release Notes

<details>
<summary>actions/download-artifact (actions/download-artifact)</summary>

###
[`v7`](https://redirect.github.com/actions/download-artifact/compare/v6...v7)

[Compare
Source](https://redirect.github.com/actions/download-artifact/compare/v6...v7)

</details>

<details>
<summary>actions/upload-artifact (actions/upload-artifact)</summary>

###
[`v6`](https://redirect.github.com/actions/upload-artifact/compare/v5...v6)

[Compare
Source](https://redirect.github.com/actions/upload-artifact/compare/v5...v6)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi40Mi4yIiwidXBkYXRlZEluVmVyIjoiNDIuNDIuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-15 21:31:47 +00:00
Shane
76b715874a release-8.7.13 (#30870)
v8.7.13

---------

Co-authored-by: ionitron <hi@ionicframework.com>
2025-12-13 08:16:52 -08:00
ionitron
6205338620 chore(): update package lock files 2025-12-13 15:52:33 +00:00
ionitron
f775815a13 v8.7.13 2025-12-13 15:51:51 +00:00
Shane
cf3caa287e chore(core): aligning core engine requirement with main ionic-framework requirement (#30869)
Issue number: resolves #30868

---------

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

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

## What is the current behavior?

Currently, users are unable to use ionic-framework with node < 24. This
was an accidental change, not something we actually require.

## What is the new behavior?

This change aligns the core file with the [top level
package.json](https://github.com/ionic-team/ionic-framework/blob/main/package.json#L9)
requirement. We may want to look into upping this at some point in the
future, but right now this should be fine.

## Does this introduce a breaking change?

- [ ] Yes
- [X] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2025-12-13 15:00:20 +00:00
renovate[bot]
2ee52d77c8 chore(deps): update capacitor to v8 (major) (#30847)
This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [@capacitor/core](https://capacitorjs.com)
([source](https://redirect.github.com/ionic-team/capacitor)) | [`^7.0.0`
->
`^8.0.0`](https://renovatebot.com/diffs/npm/@capacitor%2fcore/7.4.4/8.0.0)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@capacitor%2fcore/8.0.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@capacitor%2fcore/7.4.4/8.0.0?slim=true)
|
|
[@capacitor/haptics](https://redirect.github.com/ionic-team/capacitor-haptics)
| [`^7.0.0` ->
`^8.0.0`](https://renovatebot.com/diffs/npm/@capacitor%2fhaptics/7.0.3/8.0.0)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@capacitor%2fhaptics/8.0.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@capacitor%2fhaptics/7.0.3/8.0.0?slim=true)
|
|
[@capacitor/keyboard](https://redirect.github.com/ionic-team/capacitor-keyboard)
| [`^7.0.0` ->
`^8.0.0`](https://renovatebot.com/diffs/npm/@capacitor%2fkeyboard/7.0.4/8.0.0)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@capacitor%2fkeyboard/8.0.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@capacitor%2fkeyboard/7.0.4/8.0.0?slim=true)
|
|
[@capacitor/status-bar](https://redirect.github.com/ionic-team/capacitor-plugins)
| [`^7.0.0` ->
`^8.0.0`](https://renovatebot.com/diffs/npm/@capacitor%2fstatus-bar/7.0.4/8.0.0)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@capacitor%2fstatus-bar/8.0.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@capacitor%2fstatus-bar/7.0.4/8.0.0?slim=true)
|

---

### Release Notes

<details>
<summary>ionic-team/capacitor (@&#8203;capacitor/core)</summary>

###
[`v8.0.0`](https://redirect.github.com/ionic-team/capacitor/blob/HEAD/CHANGELOG.md#800-2025-12-08)

[Compare
Source](https://redirect.github.com/ionic-team/capacitor/compare/7.4.4...8.0.0)

##### Bug Fixes

- **cli:** Android apk name multi flavor dimensions parsing
([#&#8203;7598](https://redirect.github.com/ionic-team/capacitor/issues/7598))
([2dc20ee](2dc20ee894))
- **cli:** make migrate update to 8.0.0
([#&#8203;8250](https://redirect.github.com/ionic-team/capacitor/issues/8250))
([ee8ba7b](ee8ba7bbee))
- **ios:** move PrivacyInfo.xcprivacy to resource\_bundles to fix build…
([#&#8203;8264](https://redirect.github.com/ionic-team/capacitor/issues/8264))
([e6f50b8](e6f50b8c0c))

##### Features

- **android:** Improving SystemBars inset handling
([#&#8203;8268](https://redirect.github.com/ionic-team/capacitor/issues/8268))
([81ae30a](81ae30a503))

</details>

<details>
<summary>ionic-team/capacitor-haptics
(@&#8203;capacitor/haptics)</summary>

###
[`v8.0.0`](https://redirect.github.com/ionic-team/capacitor-haptics/blob/HEAD/CHANGELOG.md#800-2025-12-08)

[Compare
Source](e492876ac8...v8.0.0)

##### Bug Fixes

- **android:** use 'propName = value' assignment syntax in build.gradle
files
([e0d3987](e0d3987eea))

##### feature

- Capacitor 8 support
([7d840c7](7d840c7825))

##### BREAKING CHANGES

- Capacitor 8 requires major update

</details>

<details>
<summary>ionic-team/capacitor-keyboard
(@&#8203;capacitor/keyboard)</summary>

###
[`v8.0.0`](https://redirect.github.com/ionic-team/capacitor-keyboard/blob/HEAD/CHANGELOG.md#800-2025-12-08)

[Compare
Source](e492876ac8...v8.0.0)

##### Bug Fixes

- **android:** Adjust WebView sizing during keyboard size changes
([ae75247](ae752478ff))
- **android:** use 'propName = value' assignment syntax in build.gradle
files
([37b39b0](37b39b0c64))

##### feature

- Capacitor 8 support
([f8c21ef](f8c21ef521))

##### BREAKING CHANGES

- Capacitor 8 requires major update

</details>

<details>
<summary>ionic-team/capacitor-plugins
(@&#8203;capacitor/status-bar)</summary>

###
[`v8.0.0`](https://redirect.github.com/ionic-team/capacitor-plugins/releases/tag/%40capacitor/app%408.0.0)

[Compare
Source](https://redirect.github.com/ionic-team/capacitor-plugins/compare/@capacitor/status-bar@7.0.4...@capacitor/status-bar@8.0.0)

**Note:** Version bump only for package
[@&#8203;capacitor/app](https://redirect.github.com/capacitor/app)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these
updates again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi4zMi4yIiwidXBkYXRlZEluVmVyIjoiNDIuNDIuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-11 19:26:50 +00:00
renovate[bot]
0e110de5e3 chore(deps): update capacitor to v7.0.3 (#30846)
This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
|
[@capacitor/haptics](https://redirect.github.com/ionic-team/capacitor-haptics)
| [`7.0.2` ->
`7.0.3`](https://renovatebot.com/diffs/npm/@capacitor%2fhaptics/7.0.2/7.0.3)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@capacitor%2fhaptics/7.0.3?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@capacitor%2fhaptics/7.0.2/7.0.3?slim=true)
|
|
[@capacitor/keyboard](https://redirect.github.com/ionic-team/capacitor-keyboard)
| [`7.0.3` ->
`7.0.4`](https://renovatebot.com/diffs/npm/@capacitor%2fkeyboard/7.0.3/7.0.4)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@capacitor%2fkeyboard/7.0.4?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@capacitor%2fkeyboard/7.0.3/7.0.4?slim=true)
|
|
[@capacitor/status-bar](https://redirect.github.com/ionic-team/capacitor-plugins)
| [`7.0.3` ->
`7.0.4`](https://renovatebot.com/diffs/npm/@capacitor%2fstatus-bar/7.0.3/7.0.4)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@capacitor%2fstatus-bar/7.0.4?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@capacitor%2fstatus-bar/7.0.3/7.0.4?slim=true)
|

---

### Release Notes

<details>
<summary>ionic-team/capacitor-haptics
(@&#8203;capacitor/haptics)</summary>

###
[`v7.0.3`](https://redirect.github.com/ionic-team/capacitor-haptics/compare/v7.0.2...e492876ac85661078e39664652b01ac9e0ab08c7)

[Compare
Source](https://redirect.github.com/ionic-team/capacitor-haptics/compare/v7.0.2...e492876ac85661078e39664652b01ac9e0ab08c7)

</details>

<details>
<summary>ionic-team/capacitor-keyboard
(@&#8203;capacitor/keyboard)</summary>

###
[`v7.0.4`](https://redirect.github.com/ionic-team/capacitor-keyboard/compare/v7.0.3...e492876ac85661078e39664652b01ac9e0ab08c7)

[Compare
Source](https://redirect.github.com/ionic-team/capacitor-keyboard/compare/v7.0.3...e492876ac85661078e39664652b01ac9e0ab08c7)

</details>

<details>
<summary>ionic-team/capacitor-plugins
(@&#8203;capacitor/status-bar)</summary>

###
[`v7.0.4`](https://redirect.github.com/ionic-team/capacitor-plugins/releases/tag/%40capacitor/splash-screen%407.0.4)

[Compare
Source](https://redirect.github.com/ionic-team/capacitor-plugins/compare/@capacitor/status-bar@7.0.3...@capacitor/status-bar@7.0.4)

**Note:** Version bump only for package
[@&#8203;capacitor/splash-screen](https://redirect.github.com/capacitor/splash-screen)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these
updates again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi4zMi4yIiwidXBkYXRlZEluVmVyIjoiNDIuNDIuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-11 18:57:45 +00:00
Shane
ae05a809be chore(git): sync main (#30859)
Syncing main v8.7.12
2025-12-10 19:56:07 -08:00
ShaneK
ab3ffceb88 chore(git): resolving merge conflict 2025-12-10 19:42:14 -08:00
Shane
f50994a6ef merge release-8.7.12 (#30856)
v8.7.12

---------

Co-authored-by: ionitron <hi@ionicframework.com>
2025-12-10 13:52:10 -08:00
ionitron
5bf6f6e825 chore(): update package lock files 2025-12-10 21:34:28 +00:00
ionitron
afa15d23d2 v8.7.12 2025-12-10 21:33:15 +00:00
Shane
b1645168a7 fix(modal): prevent browser hang when using ModalController in Angular (#30845)
Issue number: resolves internal

---------

## What is the current behavior?

When using ModalController to present a modal in Angular applications,
the browser becomes non-responsive and hangs in some circumstances. This
regression was introduced in #30544 with the addition of a
MutationObserver that watches document.body with subtree: true to detect
when a modal's parent element is removed from the DOM. For
controller-based modals, this observer fires on every DOM mutation in
the document, causing severe performance issues during Angular's change
detection cycles.

## What is the new behavior?

The MutationObserver for parent removal detection is now skipped for
controller-based modals and when the cached parent is the app root
(document.body or ion-app). These parents are never removed from the
DOM, so observing them is unnecessary. This prevents the performance
issues while still maintaining the parent removal detection behavior for
inline modals with meaningful parent elements.

## Does this introduce a breaking change?

- [ ] Yes
- [X] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

Current dev build:
```
8.7.12-dev.11765231260.1def96ab
```

---------

Co-authored-by: Maria Hutt <thetaPC@users.noreply.github.com>
2025-12-10 21:11:49 +00:00
Shane
b9e3cf0f5a fix(modal): allow interaction with parent content through sheet modals in child routes (#30839)
Issue number: resolves #30700

---------

## What is the current behavior?

When a sheet modal with showBackdrop=false is rendered in a child route
(nested ion-router-outlet), the parent content becomes non-interactive.
Clicks on buttons or other interactive elements in the parent component
are blocked, even though showBackdrop=false should allow background
interaction.

Two separate issues contributed to this bug:
1. **Root locking with `backdropBreakpoint`**: The `shouldLockRoot`
logic in `overlays.ts` didn't account for `backdropBreakpoint`. Modals
with `backdropBreakpoint > 0` were still locking the root with
`aria-hidden`, even though developers expect background interaction when
the modal is below the backdrop breakpoint.
2. **Child route wrapper blocking**: When a modal is in a child route,
the child route's page wrapper (`ion-page`) and its parent
`ion-router-outlet` remain in the DOM with `position: absolute` covering
the viewport. Even after the modal is moved to `ion-app` and has
`pointer-events: none`, these wrapper elements block clicks to the
parent page's content.

This issue stems from
[#30563](https://github.com/ionic-team/ionic-framework/pull/30563),
which added root-locking behavior that didn't account for modals that
allow background interaction. A partial fix in
[#30689](https://github.com/ionic-team/ionic-framework/pull/30689)
partially addressed `showBackdrop=false` and `focusTrap=false`, but
missed `backdropBreakpoint`.

## What is the new behavior?

Sheet modals with showBackdrop=false or focusTrap=false now correctly
allow interaction with parent content when the modal is in a child
route.
Improvements:
- Recalculates isSheetModal in present() to handle Angular binding
timing
- Sets pointer-events: none on the modal element and its original parent
elements when background interaction should be allowed
- Cleans up pointer-events on dismiss
- Adds regression tests

## Does this introduce a breaking change?

- [ ] Yes
- [X] No


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

Dev build:
```
8.7.12-dev.11765060985.14ad27fb
```
2025-12-10 21:08:48 +00:00
Brandy Smith
99dcf3810a fix(popover): recalculate the content dimensions after the header has fully loaded (#30853)
Issue number: internal

---------

## What is the current behavior?
A translucent header in a popover does not consistently render as
translucent upon presenting due to the `offset-top` of the content being
set to `0`.

## What is the new behavior?
Watch the header for height changes using `ResizeObserver` and
recalculate the content dimensions when the header height is greater
than `0`.

## Does this introduce a breaking change?
- [ ] Yes
- [x] No

---------

Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-12-10 20:56:59 +00:00
Brandy Smith
6643f6a115 chore(angular): add @types/node dep to ng17 test app (#30855)
Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-12-10 20:34:08 +00:00
Maria Hutt
1c89cf06ac fix(select, action-sheet): use radio role for options (#30769)
Issue number: internal

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

The screen reader does not announce when an option is selected within
the action sheet interface. This is because the action sheet uses
standard buttons, which do not support a detectable selected state via
native properties or ARIA attributes like `aria-checked` or
`aria-selected`, creating an inconsistent user experience across
different interface types.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Updated the action sheet buttons to accept `role="radio"`
- Added keyboard navigation to follow the pattern for radio group
- Added test

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->


[Basic](https://ionic-framework-git-fw-6818-ionic1.vercel.app/src/components/select/test/basic/)

---------

Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
Co-authored-by: Shane <shane@shanessite.net>
Co-authored-by: Brandy Smith <brandyscarney@users.noreply.github.com>
2025-12-08 20:50:46 +00:00
Maria Hutt
3129565e4e test(scripts): update palette query (#30842)
Issue number: N/A

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

`high-contrast` and `high-contrast-dark` palettes were not working when
requested through a URL query or hash for a test page. This was due to
the `match` not accepting hyphens so it would only save `high` which is
not a valid palette.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Updated `match` to accept hyphens
- Added an error if an invalid palette is provided
- Added a palette fallback if an invalid palette is provided
- Added a class check for high contrast and high contrast dark

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

How to test:
1. Verify that `?palette=high-contrast`, `?palette=high-contrast-dark`,
`#palette=high-contrast`, and `#palette=high-contrast-dark` render
correctly (I recommend using [button basic
page](https://ionic-framework-git-scripts-ionic1.vercel.app/src/components/button/test/basic/))

---------

Co-authored-by: Brandy Smith <brandyscarney@users.noreply.github.com>
2025-12-08 20:23:53 +00:00
Brandy Smith
39a0be848c docs(testing): add a note on flaky tests to usage instructions (#30843)
Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-12-08 18:56:29 +00:00
Maria Hutt
57687623aa chore(renovate): configure node version consistency (#30816)
Issue number: N/A

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Core does not indicate what node version we should be running, which can
lead to inconsistent versions between local and workflows. These
inconsistencies can lead to workflow failures.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Provides the node version within package
- Updates the node version of workflows and package at the same time

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2025-12-08 17:16:10 +00:00
Bernardo Cardoso
5a91dbd6f9 fix(datetime): add temporary workaround for datetime-ready logic issue on Ionic theme. (#30841)
Issue number: internal

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Although the work done on
[FW-6931](https://outsystemsrd.atlassian.net/browse/FW-6931), there was
still a scenario on MobileUI, inside the ion-modal, where the datetime
would disappear. This seems to only happen on iOS 26+, as we were not
able to replicate it on version 18.*

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

As there's already task to better fix this issue across all themes, this
PR introduces a small css backdoor, to be able to override the opacity
value when necessary. This was done on ionic theme only and the css was
split, to have no impact on md and iOS.

* In `datetime.ionic.scss`, opacity is now controlled via CSS variables
(`--body-opacity`, `--year-opacity`) for `.calendar-body` and
`.datetime-year`.
* In `datetime.native.scss`, explicit opacity rules for `.calendar-body`
and `.datetime-year` are added, with visibility toggled based on the
`.datetime-ready` class.
* In `datetime.common.scss`, redundant and hard-coded opacity rules for
`.calendar-body` and `.datetime-year` are removed, deferring control to
theme-specific stylesheets.

A small fix was also done on IonHeader token used for the border-color,
to correctly reflect the value from Figma.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->




[FW-6931]:
https://outsystemsrd.atlassian.net/browse/FW-6931?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
2025-12-05 18:34:13 +00:00
Pedro Lourenço
9555a2a09a feat(radio-group): remove radio-group-wrapper and convert to shadow DOM (#30835)
Issue number: internal

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->
The radio-group's wrapper div is responsible for several issues that
have been reported, specially due to making it so that radio elements
are not direct children of radio-groups. Now it is also causing problems
on the OutSystems side.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->
The solution involved:
- Removing the radio-group-wrapper div, which was first added as a
workaround to a Stencil issue where radio children would incorrectly
fire blur events on focus;
- Converting the radio-group into a shadow component as another
workaround to the Stencil issue;
- Adjusting the radio-group's styling to the new changes. 

## Does this introduce a breaking change?

- [x] Yes
- [ ] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

---------

Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
Co-authored-by: Brandy Smith <brandyscarney@users.noreply.github.com>
2025-12-05 11:25:55 +00:00
José Rio
e8d52aec7c fix(checkbox, input, select, textarea): uniform invalid border color for ionic theme (#30838)
Issue number: resolves #

---------

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

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

This pull request updates the error text color handling for several form
components to use a consistent variable, improving maintainability and
visual consistency. The changes also update the focus ring color for
invalid checkboxes to align with the new variable naming.

**Error text color standardization:**

* Updated `.error-text` color in `checkbox.ionic.scss` to use
`globals.$ion-text-danger` instead of
`globals.$ion-semantics-danger-800`.
* Added `.error-text` color rule using `globals.$ion-text-danger` to
`input.ionic.scss`, `select.ionic.scss`, and `textarea.ionic.scss`.
[[1]](diffhunk://#diff-4d89e41650632cecdd15dbe6b2ef5ad30d100788ecd786dd97a990aaf1ab08d9R274-R277)
[[2]](diffhunk://#diff-030647f0cfb9ca6f042e9d7114611c7076a7c01af73076d1db05cc881b40ddf7R39-R42)
[[3]](diffhunk://#diff-45914a3d091d2c33732c1bdfbd74ce4375d12c6b23811c211a038d829e110886R149-R152)

**Focus ring color update:**

* Changed the invalid checkbox focus ring color variable from
`globals.$ion-border-focus-error` to
`globals.$ion-border-danger-default` in `checkbox.ionic.scss`.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->

---------

Co-authored-by: ionitron <hi@ionicframework.com>
2025-12-04 16:54:15 +00:00
José Rio
b9ced5522a fix(checkbox, radio-button): fixed error message font-size for Ionic theme (#30836)
Issue number: resolves #

---------

## What is the current behavior?
- Checkbox and RadioGroup font-size was medium regular (14px)

## What is the new behavior?
- Checkbox and RadioGroup are now with font-size small regular (12px)

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->

---------

Co-authored-by: ionitron <hi@ionicframework.com>
2025-12-04 10:22:27 +00:00
renovate[bot]
3709bba41e chore(deps): update actions/checkout action to v6.0.1 (#30832)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [actions/checkout](https://redirect.github.com/actions/checkout) |
action | patch | `v6.0.0` -> `v6.0.1` |

---

### Release Notes

<details>
<summary>actions/checkout (actions/checkout)</summary>

###
[`v6.0.1`](https://redirect.github.com/actions/checkout/compare/v6.0.0...v6.0.1)

[Compare
Source](https://redirect.github.com/actions/checkout/compare/v6.0.0...v6.0.1)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi4xOS45IiwidXBkYXRlZEluVmVyIjoiNDIuMzIuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-03 20:50:17 +00:00
renovate[bot]
76e4901189 chore(deps): update actions/setup-node action to v6.1.0 (#30834)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [actions/setup-node](https://redirect.github.com/actions/setup-node) |
action | minor | `v6.0.0` -> `v6.1.0` |

---

### Release Notes

<details>
<summary>actions/setup-node (actions/setup-node)</summary>

###
[`v6.1.0`](https://redirect.github.com/actions/setup-node/releases/tag/v6.1.0)

[Compare
Source](https://redirect.github.com/actions/setup-node/compare/v6.0.0...v6.1.0)

#### What's Changed

##### Enhancement:

- Remove always-auth configuration handling by
[@&#8203;priyagupta108](https://redirect.github.com/priyagupta108) in
[#&#8203;1436](https://redirect.github.com/actions/setup-node/pull/1436)

##### Dependency updates:

- Upgrade
[@&#8203;actions/cache](https://redirect.github.com/actions/cache) from
4.0.3 to 4.1.0 by
[@&#8203;dependabot](https://redirect.github.com/dependabot)\[bot] in
[#&#8203;1384](https://redirect.github.com/actions/setup-node/pull/1384)
- Upgrade actions/checkout from 5 to 6 by
[@&#8203;dependabot](https://redirect.github.com/dependabot)\[bot] in
[#&#8203;1439](https://redirect.github.com/actions/setup-node/pull/1439)
- Upgrade js-yaml from 3.14.1 to 3.14.2 by
[@&#8203;dependabot](https://redirect.github.com/dependabot)\[bot] in
[#&#8203;1435](https://redirect.github.com/actions/setup-node/pull/1435)

##### Documentation update:

- Add example for restore-only cache in documentation by
[@&#8203;aparnajyothi-y](https://redirect.github.com/aparnajyothi-y) in
[#&#8203;1419](https://redirect.github.com/actions/setup-node/pull/1419)

**Full Changelog**:
<https://github.com/actions/setup-node/compare/v6...v6.1.0>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi4xOS45IiwidXBkYXRlZEluVmVyIjoiNDIuMTkuOSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-03 14:43:34 +00:00
João Ferreira
10f4197e31 fix(avatar): fix avatar disabled for icon content (#30820)
Issue number: internal

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->
- When Avatar has an icon as content and is disabled, the icon is above
the disabled layer.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->
- add avatar with icon on disabled state page;
- add avatar with icon on snapshots tests;
- change disable state to be the :after pseudo element avatar content;


## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

[state](https://ionic-framework-git-rou-12319-ionic1.vercel.app/src/components/avatar/test/states?ionic:theme=ionic)

---------

Co-authored-by: ionitron <hi@ionicframework.com>
2025-12-03 14:20:00 +00:00
João Ferreira
16cbe63164 fix(chip): update cursor from chip of ionic theme (#30829)
Issue number: internal

---------

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

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

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->
- change cursor to auto instead of pointer;

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

[basic](https://ionic-framework-git-rou-12366v2-ionic1.vercel.app/src/components/chip/test/basic?ionic:theme=ionic)
2025-12-02 12:06:57 +00:00
Maria Hutt
6ae701e80c chore(git): sync ionic-modular with next (#30826)
Syncing with next
2025-12-01 17:28:16 -08:00
Maria Hutt
ba04e4d14b Merge branch 'chore-sync-ionic-modular-with-next' of github.com:ionic-team/ionic-framework into chore-sync-ionic-modular-with-next 2025-12-01 17:12:16 -08:00
Maria Hutt
4732ba6761 chore(package): use caret 2025-12-01 17:11:51 -08:00
Brandy Smith
22288319ed chore(deps): add playwright-core as a dev dependency (#30827)
This updates the `package-lock` file to match the structure `next` uses
so we won't have a mismatch with errors on each branch. It installs
`playwright-core` as a dev dependency to align with `next`.

How to test this:

1. Switch to this branch `chore/deps-playwright`
1. Remove `node_modules`: `rm -rf node_modules`
1. Run `npx lerna@5 bootstrap --include-dependencies --scope @ionic/core
--ignore-scripts -- --legacy-peer-deps && npm run build`
1.  Verify: build is successful
1. Run `git revert 76cf4bda6a`
1. Run `npx lerna@5 bootstrap --include-dependencies --scope @ionic/core
--ignore-scripts -- --legacy-peer-deps && npm run build`
1. 🛑 Verify: the following error occurs:
    ```bash
[ ERROR ] TypeScript:
node_modules/@axe-core/playwright/dist/index.d.ts:2:22
              Cannot find module 'playwright-core' or its corresponding
              type declarations.

L1: import { SerialFrameSelector, RunOptions, AxeResults } from
'axe-core';
          L2:  import { Page } from 'playwright-core';

    [00:58.9]  build failed in 6.36 s
    ```

⚠️ Please do not push the reverted commit, it is just to show that the
new dev dependency is required.

This shows that without `playwright-core` installed the lerna command in
the release process will fail.

---------

Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-12-01 22:21:22 +00:00
Brandy Smith
6db73011a3 chore: update next from main and add playwright-core as a dev dependency (#30824)
Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-12-01 17:20:38 -05:00
Brandy Smith
f19160497f chore(deps): add playwright-core as a dev dependency 2025-12-01 17:05:11 -05:00
Brandy Smith
bbf2c4fd39 Merge branch 'main' into chore/update-next-from-main 2025-12-01 17:04:15 -05:00
ionitron
e31511090e chore(): add updated snapshots 2025-12-01 22:01:30 +00:00
ionitron
7bf0c7a117 chore(): add updated snapshots 2025-12-01 21:32:32 +00:00
ionitron
99087b2a85 chore(): add updated snapshots 2025-12-01 21:17:43 +00:00
ionitron
1928650ce6 chore(): add updated snapshots 2025-12-01 20:58:04 +00:00
ionitron
9b71483b28 chore(): add updated snapshots 2025-12-01 19:09:25 +00:00
Maria Hutt
f44d6ccf8b refactor(ionic): add missing new line 2025-12-01 10:37:09 -08:00
Maria Hutt
e50c4f9d74 Merge remote-tracking branch 'origin/next' into chore-sync-ionic-modular-with-next 2025-12-01 10:33:39 -08:00
Maria Hutt
3da2384b52 test(set-content): use the proper theme keyterm (#30817) 2025-12-01 10:00:02 -08:00
Brandy Smith
c65b76e727 chore(workflows): fix release workflow permissions (#30823)
The workflow permissions update did not work due to it being nested in a
workflow that only had `read` permissions.

You can see a failing run here (scroll down to annotations):
[19828029833](https://github.com/ionic-team/ionic-framework/actions/runs/19828029833)

```
Invalid workflow file: .github/workflows/release-orchestrator.yml#L71
The workflow is not valid. .github/workflows/release-orchestrator.yml (Line: 71, Col: 3): Error calling workflow 'ionic-team/ionic-framework/.github/workflows/release.yml@b4e540decc484bd22eb84484a8eb94f19b1790c1'. The nested job 'finalize-release' is requesting 'contents: write', but is only allowed 'contents: read'. .github/workflows/release-orchestrator.yml (Line: 71, Col: 3): Error calling workflow 'ionic-team/ionic-framework/.github/workflows/release.yml@b4e540decc484bd22eb84484a8eb94f19b1790c1'. The nested job 'update-package-lock' is requesting 'contents: write', but is only allowed 'contents: read'.
```

This updates the parent workflow to have `write` permissions. You can
see a passing run here:
[19828895682](https://github.com/ionic-team/ionic-framework/actions/runs/19828895682)

Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-12-01 16:25:26 +00:00
Brandy Smith
b4e540decc chore(workflows): update release workflow permissions for finalizing (#30814)
Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-12-01 15:10:00 +00:00
João Ferreira
707f02d7c8 fix(chip): remove hover state from chip of ionic theme; (#30819)
Issue number: internal

---------

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

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

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- remove hover state from ionic theme chip;


## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

[basic](https://ionic-framework-git-rou-12366-ionic1.vercel.app/src/components/chip/test/basic?ionic:theme=ionic)
2025-11-28 17:38:28 +00:00
João Ferreira
c0a1b4355b fix(header): remove Shadow from Ionic Header (#30818)
Issue number: internal

---------

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

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

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->
- The header should not have a shadow.
- Following the design experience, this shadow shouldn't exist. If
needed, the dev should use the divider prop

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

---------

Co-authored-by: ionitron <hi@ionicframework.com>
2025-11-28 12:14:51 +00:00
Maria Hutt
4a568a6179 chore(git): update next from main (#30815)
Syncing with `main`
2025-11-26 15:21:22 -08:00
Maria Hutt
cb3d025756 chore(package-lock): use correct playwright version 2025-11-26 14:39:58 -08:00
Maria Hutt
306608d844 chore(playwright): use correct version 2025-11-26 14:23:01 -08:00
Maria Hutt
e2a3d4f45f chore(core): run install with correct node version 2025-11-26 13:56:30 -08:00
Maria Hutt
b6df59a02c Merge remote-tracking branch 'origin/main' into chore-sync-next-with-main 2025-11-26 13:51:27 -08:00
Maria Hutt
87e50ad9da merge release-8.7.11 (#30812)
v8.7.11

---------

Co-authored-by: ionitron <hi@ionicframework.com>
2025-11-26 12:03:03 -08:00
Maria Hutt
595643fd14 chore(many): update lock files 2025-11-26 11:33:54 -08:00
ionitron
3249e1dce8 v8.7.11 2025-11-26 18:47:18 +00:00
Maria Hutt
e9bd3f819d test(scripts): update to handle hash params (#30807)
Issue number: N/A

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Playwright's `setContent` cannot handle query params which causes the
`scripts.js` to not run effectively.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Update `scripts.js` to accept hash params as well
- Update `scripts.js` to accept the dark class to set dark mode if dark
query or hash was not passed

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

How to test:
1. Verify that tests are passing

---------

Co-authored-by: Brandy Smith <brandyscarney@users.noreply.github.com>
2025-11-26 18:19:31 +00:00
João Ferreira
0985187a5c fix(toggle): remove full width rule from ionic theme (#30809)
Issue number: internal

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->
- even when the justify was undefined, the toggle was full-width:

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- It's possible to have an inline input;
- If a full width is needed, use the justify prop;

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

[basic](https://ionic-framework-git-rou-12327-ionic1.vercel.app/src/components/toggle/test/basic/?ionic:theme=ionic)

[item](https://ionic-framework-git-rou-12327-ionic1.vercel.app/src/components/toggle/test/item?ionic:theme=ionic)

[label](https://ionic-framework-git-rou-12327-ionic1.vercel.app/src/components/toggle/test/label?ionic:theme=ionic)

---------

Co-authored-by: ionitron <hi@ionicframework.com>
2025-11-25 17:34:23 +00:00
renovate[bot]
bf0f1e36e4 chore(deps): update actions/checkout action to v6 (#30802)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [actions/checkout](https://redirect.github.com/actions/checkout) |
action | major | `v5.0.1` -> `v6.0.0` |

---

### Release Notes

<details>
<summary>actions/checkout (actions/checkout)</summary>

###
[`v6.0.0`](https://redirect.github.com/actions/checkout/compare/v5.0.1...v6.0.0)

[Compare
Source](https://redirect.github.com/actions/checkout/compare/v5.0.1...v6.0.0)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi4xNi4xIiwidXBkYXRlZEluVmVyIjoiNDIuMTYuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-25 17:23:59 +00:00
José Rio
dd0c849512 fix(item, tab-button): activation behaviour for Ionic theme (#30806)
Issue number: resolves #

---------

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

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

## What is the current behavior?
Currently, in the`ion-item` and `tab-button` components under the Ionic
theme, activation behaviors (such as ripple effects and clickability)
are applied to both `md` and `ios`, but they should only be applied
to`md`.

## What is the new behavior?
Activation behavior is now conditional on both theme and mode. The main
goal is to ensure that activation only occurs specifically for `md` mode
when using the `ionic` theme.


## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->
2025-11-25 09:49:03 +00:00
Maria Hutt
682e25dace chore(git): update next from main (#30800)
Syncing with `main`
2025-11-20 13:20:41 -08:00
ionitron
3f87a2c279 chore(): add updated snapshots 2025-11-20 20:42:47 +00:00
Shane
9d781db662 fix(datetime): ensure datetime is shown when intersection observer fails to report visibility (#30793)
Issue number: resolves #30706

---------

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

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

## What is the current behavior?

Due to some recent unknown changes, the intersection observer for date
time no longer reliably fires, especially in mobile views.

## What is the new behavior?

In this PR, we're adding a visibility check after everything has had a
chance to render to make sure we're setting up properly even if the
intersection observer has failed to trigger for some reason.

## Does this introduce a breaking change?

- [ ] Yes
- [X] No

## Other information

Since the intersection observer is being set up after a `raf`, it's
possible something got introduced to make the initial setup slower for
some reason, causing timing issues. I think we should do a more thorough
investigation into the cause of this problem when we have more time.

This PR also adds tests to verify the new fallback works properly.

Current dev build:
```
8.7.10-dev.11763478209.1d9c4cd8
```

---------

Co-authored-by: Brandy Smith <brandyscarney@users.noreply.github.com>
2025-11-20 20:16:09 +00:00
Maria Hutt
f349aac6bb Merge branch 'next' of github.com:ionic-team/ionic-framework into chore-sync-next-with-main 2025-11-20 11:33:49 -08:00
Maria Hutt
9d3576e5ee chore(core): update lockfile to fix npm ci errors 2025-11-20 11:20:29 -08:00
Maria Hutt
3254075557 chore(core): update package-lock 2025-11-20 10:59:15 -08:00
Bernardo Cardoso
f9a936b875 fix(tokens): remove style dictionary scripts and reuse os tokens logic (#30786)
Issue number: internal

---------

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

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

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

This pull request updates the design token build system and its
dependencies, simplifying the process and removing custom scripts in
favor of using the latest features of the `outsystems-design-tokens`
package. The changes modernize how design tokens are generated and
maintained, reducing custom code and leveraging upstream improvements.

Key changes include:

**Build Process Simplification:**
- The custom design token generation scripts
(`core/scripts/tokens/index.mjs` and `core/scripts/tokens/utils.mjs`)
have been removed. Token generation is now handled directly via the
`outsystems-design-tokens` package using an `npx` command in the
`build.tokens` script. This reduces maintenance overhead and keeps the
build process aligned with upstream best practices.
[[1]](diffhunk://#diff-0b9870c62ff80af860467e2541bba0b9ba5e7280b12bea6eeb124b1d174efbcfL1-L188)
[[2]](diffhunk://#diff-8b5c339d9dd13300954577213f84a443321a0d6477acd7553787fbcc00ce8cabL1-L320)
[[3]](diffhunk://#diff-7f67769260741e2563407af949f7e54fbf0431d1c607933f6e8a8094e3219e26L83-R82)

**Dependency Updates:**
- Updated `outsystems-design-tokens` to version `1.3.3` and
`style-dictionary` to version `5.1.1` in both `package.json` and
`package-lock.json`. This ensures compatibility with the latest features
and bug fixes and removes the need to specify `style-dictionary`
directly as a dependency.
[[1]](diffhunk://#diff-4ff996db8bece1eded512c3b97a6bde33622f94bb387634ef32496d832d57744L47-L52)
[[2]](diffhunk://#diff-4ff996db8bece1eded512c3b97a6bde33622f94bb387634ef32496d832d57744L9592-R9598)
[[3]](diffhunk://#diff-4ff996db8bece1eded512c3b97a6bde33622f94bb387634ef32496d832d57744L11137-R11138)
[[4]](diffhunk://#diff-7f67769260741e2563407af949f7e54fbf0431d1c607933f6e8a8094e3219e26L69-L74)

**SCSS Utility Import:**
- The `@forward "../../foundations/ionic.utility";` statement was
removed from `core/src/css/ionic/utils.bundle.ionic.scss`, likely
because the utility SCSS is now generated and managed by the new token
build process.

Removed CSS tests for Ionic theme, as they relied heavily on testing the
effect of the utility-classes, that are no longer created on the ionic
scope.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->

---------

Co-authored-by: ionitron <hi@ionicframework.com>
2025-11-20 13:02:37 -05:00
Maria Hutt
f4cff58dde refactor(header): add collapsible role check 2025-11-19 15:35:22 -08:00
Maria Hutt
608ce9a97c Merge remote-tracking branch 'origin/main' into chore-sync-next-with-main 2025-11-19 15:07:38 -08:00
Maria Hutt
9ae41efddb merge release-8.7.10 (#30797)
v8.7.10

---------

Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
Co-authored-by: Maria Hutt <maria.hutt@outsystems.com>
2025-11-19 11:11:45 -08:00
Maria Hutt
7379d34f38 chore(angular): add missing new line to package-lock 2025-11-19 10:36:45 -08:00
Maria Hutt
53f3bea244 chore(angular): correct package-lock 2025-11-19 10:35:57 -08:00
Maria Hutt
5c86b87fe3 chore(angular): add package-lock back 2025-11-19 10:28:23 -08:00
Brandy Smith
d8e6756ac3 chore(): update package lock files 2025-11-19 13:07:46 -05:00
Brandy Smith
627416b9d7 v8.7.10 2025-11-19 12:59:00 -05:00
OS-jacobbell
eeb15c3c5c chore(ci): change condition for success messages (#30796)
For Stencil Nightly alert messages, instead of checking if anything
succeeded, check if nothing failed.

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->
Both a success and failure message was sent when some jobs passed and
some failed.
## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Success message should only be sent if nothing failed.

## Does this introduce a breaking change?

- [ ] Yes
- [X] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2025-11-19 15:24:41 +00:00
renovate[bot]
2bebbd7a3e chore(deps): update actions/checkout action to v5.0.1 (#30790)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [actions/checkout](https://redirect.github.com/actions/checkout) |
action | patch | `v5.0.0` -> `v5.0.1` |

---

### Release Notes

<details>
<summary>actions/checkout (actions/checkout)</summary>

###
[`v5.0.1`](https://redirect.github.com/actions/checkout/compare/v5.0.0...v5.0.1)

[Compare
Source](https://redirect.github.com/actions/checkout/compare/v5.0.0...v5.0.1)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNzMuMSIsInVwZGF0ZWRJblZlciI6IjQxLjE3My4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-18 16:59:49 +00:00
Gonçalo M.
b3826febe0 chore(github-actions): fine tune workflow orchestrator defaults (#30794)
Issue number: resolves #

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

- "nightly" was the default choice and was available for manual trigger
when running `release-orchestrator`

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Set "dev" as the default choice (changed from "nightly")
- Removed "nightly" from manual workflow_dispatch options (only "dev"
and "production" remain)
- Simplified the `run-nightly` condition to only run on schedule
(`github.event_name == 'schedule'`)


## Does this introduce a breaking change?

- [ ] Yes
- [-] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

- Manual triggers (workflow_dispatch): Only "dev" (default) and
"production" are available
- Scheduled triggers: The nightly build continues to run automatically
every Monday–Friday at 6:00 UTC via the schedule trigger
- Trusted Publishers compliance: Maintained — all releases still go
through the single orchestrator workflow, ensuring the OIDC token is
issued from the whitelisted workflow
2025-11-18 16:20:27 +00:00
Gonçalo M.
1ff26b796b chore(github-actions): fine tune workflow permissions (#30791)
Issue number: resolves #

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

- Permissions not set as expected

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Permissions are properly set throughout the hierarchy

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2025-11-18 14:08:47 +00:00
João Ferreira
2b0a42393f fix(radio-button): update radio tokens (#30788)
Issue number: internal
---------

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

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

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- update radio tokens

## Does this introduce a breaking change?
- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

[supporting-text](https://ionic-framework-git-rou-12145-ionic1.vercel.app/src/components/radio-group/test/supporting-text?ionic:theme=ionic)
2025-11-18 10:17:37 +00:00
Gonçalo M.
99bfdee4cd chore(github-actions): Review workflow structure and fine tune permissions (#30789)
Issue number: resolves #

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

- Permissions not set as expected

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Permissions are properly set throughout the hierarchy
- Workflow structure prevents unintended standalone executions

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2025-11-17 19:19:32 +00:00
OS-jacobbell
d03e88179b chore(deps): update @types/node (#30783)
Update node types for compatibility with typescript 5.8 now used in
Stencil.

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->
- Ionic fails to build with Stencil Nightly due to typed array changes
in typescript 5.7.
- Angular package fails to build with Stencil Nightly due to type errors
with Mixins.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->
- Ionic can build with Stencil Nightly.
- Angular package can build with Stencil Nightly.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2025-11-17 18:23:36 +00:00
Gonçalo M.
ecc291138e chore(npm): attempt to fix issue with Trusted Publishers when using reusable workflows (#30787)
Issue number: resolves #

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->
- Publishing to npm is failing due to the changes to move to Trusted
Publishers, since it seems that they still don't support reusable
workflows, as mentioned
[here](https://github.com/orgs/community/discussions/174507)
- The action to which we grant permissions on npm needs to follow a
strict path location `.github/workflows/` in your repository.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Fixed permissions mismatch by applying the orchestrator method for npm
publish:
release-orchestrator.yml (contents: read, id-token: write)

  ├─→ nightly.yml (contents: read, id-token: write)
  │   └─→ release-ionic.yml (contents: read, id-token: write)
  │       └─→ publish-npm.yml (contents: read, id-token: write) 

  ├─→ dev-build.yml (contents: read, id-token: write)
  │   └─→ release-ionic.yml (contents: read, id-token: write)
  │       └─→ publish-npm.yml (contents: read, id-token: write) 

  └─→ release.yml (contents: read, id-token: write)
      └─→ release-ionic.yml (contents: read, id-token: write)
          └─→ publish-npm.yml (contents: read, id-token: write) 

- `release-orchestrator.yml` calls three workflows: `nightly.yml`,
`dev-build.yml`, and `release.yml`.
- All three call `release-ionic.yml`, which handles publishing multiple
packages.
- `release-ionic.yml` calls `publish-npm.yml` multiple times (once per
package).
- All workflows have `contents: read` and `id-token: write` permissions.
- `publish-npm.yml` is in `.github/workflows/`, which satisfies npm
Trusted Publishers requirements.
- This shows that `publish-npm.yml` is reachable through all three
release paths, and moving it to `.github/workflows/` ensures npm Trusted
Publishers can authenticate it correctly.




## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->

- Run pipelines after merge


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
- The workflow `release-orchestrator.yml` needs to be the one set up in
the npm package settings for the Trusted Publishers
2025-11-17 18:09:29 +00:00
Maria Hutt
92db36489c fix(checkbox, toggle, radio-group): improve screen reader announcement timing for validation errors (#30714)
Issue number: internal

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Currently, when an error text is shown, it may not announce itself to
voice assistants. This is because the way error text currently works is
by always existing in the DOM, but being hidden when there is no error.
When the error state changes, the error text is shown, but as far as the
voice assistant can tell it's always been there and nothing has changed.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Updated aria attributes
- Added observer with an observer

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

[Checkbox
preview](https://ionic-framework-git-fw-6757-ionic1.vercel.app/src/components/checkbox/test/validation/)
[Toggle
preview](https://ionic-framework-git-fw-6757-ionic1.vercel.app/src/components/toggle/test/validation/)
[Radio Group
preview](https://ionic-framework-git-fw-6757-ionic1.vercel.app/src/components/radio-group/test/validation/)

⚠️ Flakiness ⚠️ 

The flakiness on checkbox and toggle is because when a native input is
present on the page, the browser will have the screen reader to be
really fast when it comes to checking information. This speed ends up
being too fast for `ion-checkbox` to be able to add the error text. This
leads to the error text not being announce consistently. There's no
issue when it comes to ion-input or ion-textarea because Ionic uses the
native inputs so their arias are read. There's also no issue
with ion-select because we don't have a native input. It's only an issue
with checkbox and the others is because it has a [native input that is
being
hidden](8e884bd2cb/core/src/components/checkbox/checkbox.tsx (L368-L369)).
So the browser sees that and speeds up the screen reader.

The flakiness on radio group is because when you tab out of the last
radio button, the ionBlur event is emitted by the child <ion-radio>.
This event bubbles up, but the timing is still too early for the group.
2025-11-13 18:11:32 +00:00
Gonçalo M.
c37e2a5d9e chore(npm): Update release npm action to stop using tokens (#30778)
Issue number: internal

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

- Release workflows still inject a long-lived `NPM_TOKEN` via `.npmrc`,
so publishes do not use npm’s trusted OIDC flow.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- The shared `actions/publish-npm` composite action now configures
`setup-node` with the npm registry, upgrades npm in place, and publishes
with `--provenance` without writing `.npmrc`.
- `release-dev.yml`, `release-nightly.yml`, and `release-production.yml`
call into that trusted flow by removing the token input and (for
production) inlining the same OIDC setup before `npm run release.ci`.
- Allows npm to authenticate through trusted publishing requirements
[docs.npmjs.com/trusted-publishers](https://docs.npmjs.com/trusted-publishers).
- Step names were refreshed with emojis, but there are no other
behavioral changes.


## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

- These changes align the Ionic release automation with npm’s
trusted-publisher enforcement while keeping the existing Lerna
build/publish process intact.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-11 19:35:11 +00:00
rug
68e634c5fe fix(tab-bar): ui tweaks for ionic theme (#30775)
Issue number: internal

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->
The current UI of the tab-bar and tab-button in the ionic theme is not
matching the expected, in edge use cases:
- tab-button:
- Long label: causes the size of the tab-button to increase and
eventually making other tab-buttons, not visible.
- size: in different scenarios the size of each tab-button could become
different.
- tab-bar:
   - Many tab-buttons: would case some of them to become inaccessible.
   - Floating: distance from the bottom, was incorrect.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->
The changes made allow to fix the issues described above, specifically
for ionic theme, containing this way, potential impacts:
- tab-button:
   - min-width: has been defined for the tab-button.
   - property was set to force each tab-button to have the same size.
- tab-bar:
- allow the ability for the content to overflow on the x axis - a scroll
will appear if needed.
- increased the distance from the bottom, to comply with latest design
trends.

## Does this introduce a breaking change?
- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

---------

Co-authored-by: Brandy Smith <brandyscarney@users.noreply.github.com>
2025-11-11 12:20:39 +01:00
José Rio
cac12b31fb feat(select-modal): add select default modal styling for ionic theme (#30771)
Issue number: resolves #

---------

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

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

## What is the current behavior?
Once IonSelect was using a modal-default (with no breakpoints) the
styling of the modal do not fit with the expected ones for ionic theme.
<img width="433" height="933" alt="Screenshot 2025-11-06 at 11 01 00"
src="https://github.com/user-attachments/assets/c9e23203-0f42-4ee3-af23-9d8f43936fd3"
/>



## What is the new behavior?
Under the same context new styling has been added.
<img width="429" height="930" alt="Screenshot 2025-11-06 at 11 01 22"
src="https://github.com/user-attachments/assets/e6fdfea0-2b09-424e-bb83-4af3c66d67a4"
/>



## Does this introduce a breaking change?

- [ ] Yes
- [X] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->
2025-11-10 16:43:51 +00:00
João Ferreira
7828a7a501 fix(button): update tokens (#30776)
Issue number: internal

---------

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

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->
## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->
- update tokens;

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->
2025-11-07 17:19:05 +00:00
João Ferreira
745c13489c fix(ionic): update light base color (#30773)
Issue number: internal

---------

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

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

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->
- guarantee that light base is #ffffff;

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->

---------

Co-authored-by: ionitron <hi@ionicframework.com>
2025-11-06 22:21:51 +00:00
João Ferreira
fe18f9984f fix(button): update colors for ionic theme (#30764)
Issue number: internal

---------
## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- fix outline and clear colors and ripple-effect;

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

[clear](https://ionic-framework-git-rou-12076-ionic1.vercel.app/src/components/button/test/clear?ionic:theme=ionic)

[outline](https://ionic-framework-git-rou-12076-ionic1.vercel.app/src/components/button/test/outline?ionic:theme=ionic)
[test
theme](https://ionic-framework-git-rou-12076-ionic1.vercel.app/src/components/button/test/theme-ionic?ionic:theme=ionic)

---------

Co-authored-by: ionitron <hi@ionicframework.com>
Co-authored-by: Maria Hutt <thetaPC@users.noreply.github.com>
Co-authored-by: Maria Hutt <maria.hutt@outsystems.com>
2025-11-06 09:37:47 +00:00
Shane
0a02e0f8cf merge release-8.7.9 (#30767)
v8.7.9

---------

Co-authored-by: ionitron <hi@ionicframework.com>
2025-11-05 09:22:32 -08:00
ionitron
e1293ff9f6 chore(): update package lock files 2025-11-05 17:05:03 +00:00
ionitron
32df083e87 v8.7.9 2025-11-05 17:04:11 +00:00
Pedro Lourenço
0361bf0376 refactor(input-otp): update according to design (#30765)
Issue number: internal

---------

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

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

## What is the current behavior?
The input-otp component does not currently match our UX designs for the
ionic theme.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->
- Changed shape design tokens;
- Changed background to use correct design token.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
2025-11-04 09:46:43 +00:00
Shane
58d563805f fix(accordion-group): skip initial animation (#30729)
Issue number: resolves #30613

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->
Currently, when you load an accordion group, the initially selected
accordion animates open. This is an unexpected change caused by
upgrading Stencil to >= 4.21.0, which changed the way component
lifecycles got triggered.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

With this change, we're waiting for the accordion in the accordion group
to render and telling it if the update it's going through is the initial
update or not. This allows it to decide to animate properly.

## Does this introduce a breaking change?

- [ ] Yes
- [X] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

Current dev build:
```
8.7.8-dev.11761840817.1bede576
```
2025-11-03 22:03:10 +00:00
José Rio
d685d09193 fix(select): add missing filled type styles (#30763)
Issue number: resolves #

---------

This is based on
https://github.com/ionic-team/ionic-framework/pull/30755 PR to try to
clean up things.

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

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

## What is the current behavior?
- Select text color was not according design
- Fill solid type was missing the background color

## What is the new behavior?
- Added the expected color to the select text
- Added missing background color variable to the fill solid type

## Does this introduce a breaking change?

- [ ] Yes
- [X] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->

---------

Co-authored-by: ionitron <hi@ionicframework.com>
2025-10-30 19:48:31 +00:00
José Rio
28caeff459 fix(select): remove item focus style when there are no selected items only at ionic mode (#30750)
Issue number: resolves #

---------

This PR introduces improvements to the visual focus styling of Ionic
items when inside a select modal.

## What is the current behavior?
- The CSS variables `--background-focused` and
`--background-focused-opacity` were missing from `item.ionic.scss`,
which resulted in the native default outline focus style being applied
to focused items.
- When no item is selected, the focus style is currently applied to the
first list item by default, which we intend to change.

## What is the new behavior?
- Added missing focus css variables
- Hide the default focus style when there is no item selected

## NOTE
- This change will require an additional interaction to observe the
focus behavior when navigating through keyboard, since tap-based
navigation does not rely on focus styling.

## Does this introduce a breaking change?

- [ ] Yes
- [X] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

---------

Co-authored-by: ionitron <hi@ionicframework.com>
Co-authored-by: Maria Hutt <thetaPC@users.noreply.github.com>
2025-10-30 15:14:43 +00:00
renovate[bot]
cfd8c42f07 chore(deps): update download + upload artifacts (major) (#30754)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[actions/download-artifact](https://redirect.github.com/actions/download-artifact)
| action | major | `v5` -> `v6` |
|
[actions/upload-artifact](https://redirect.github.com/actions/upload-artifact)
| action | major | `v4` -> `v5` |

---

### Release Notes

<details>
<summary>actions/download-artifact (actions/download-artifact)</summary>

###
[`v6`](https://redirect.github.com/actions/download-artifact/compare/v5...v6)

[Compare
Source](https://redirect.github.com/actions/download-artifact/compare/v5...v6)

</details>

<details>
<summary>actions/upload-artifact (actions/upload-artifact)</summary>

###
[`v5`](https://redirect.github.com/actions/upload-artifact/compare/v4...v5)

[Compare
Source](https://redirect.github.com/actions/upload-artifact/compare/v4...v5)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNTYuMSIsInVwZGF0ZWRJblZlciI6IjQxLjE1OS40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-30 15:00:04 +00:00
renovate[bot]
0b2e766609 chore(deps): update dependency node to v24 (#30756)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [node](https://redirect.github.com/actions/node-versions) | uses-with
| major | `22.x` -> `24.x` |

---

### Release Notes

<details>
<summary>actions/node-versions (node)</summary>

###
[`v24.10.0`](https://redirect.github.com/actions/node-versions/releases/tag/24.10.0-18453495281):
24.10.0

[Compare
Source](https://redirect.github.com/actions/node-versions/compare/24.9.0-18024003193...24.10.0-18453495281)

Node.js 24.10.0

###
[`v24.9.0`](https://redirect.github.com/actions/node-versions/releases/tag/24.9.0-18024003193):
24.9.0

[Compare
Source](https://redirect.github.com/actions/node-versions/compare/24.8.0-17630522236...24.9.0-18024003193)

Node.js 24.9.0

###
[`v24.8.0`](https://redirect.github.com/actions/node-versions/releases/tag/24.8.0-17630522236):
24.8.0

[Compare
Source](https://redirect.github.com/actions/node-versions/compare/24.7.0-17283839804...24.8.0-17630522236)

Node.js 24.8.0

###
[`v24.7.0`](https://redirect.github.com/actions/node-versions/releases/tag/24.7.0-17283839804):
24.7.0

[Compare
Source](https://redirect.github.com/actions/node-versions/compare/24.6.0-16980723897...24.7.0-17283839804)

Node.js 24.7.0

###
[`v24.6.0`](https://redirect.github.com/actions/node-versions/releases/tag/24.6.0-16980723897):
24.6.0

[Compare
Source](https://redirect.github.com/actions/node-versions/compare/24.5.0-16666195981...24.6.0-16980723897)

Node.js 24.6.0

###
[`v24.5.0`](https://redirect.github.com/actions/node-versions/releases/tag/24.5.0-16666195981):
24.5.0

[Compare
Source](https://redirect.github.com/actions/node-versions/compare/24.4.1-16309768053...24.5.0-16666195981)

Node.js 24.5.0

###
[`v24.4.1`](https://redirect.github.com/actions/node-versions/releases/tag/24.4.1-16309768053):
24.4.1

[Compare
Source](https://redirect.github.com/actions/node-versions/compare/24.4.0-16210503505...24.4.1-16309768053)

Node.js 24.4.1

###
[`v24.4.0`](https://redirect.github.com/actions/node-versions/releases/tag/24.4.0-16210503505):
24.4.0

[Compare
Source](https://redirect.github.com/actions/node-versions/compare/24.3.0-15866716565...24.4.0-16210503505)

Node.js 24.4.0

###
[`v24.3.0`](https://redirect.github.com/actions/node-versions/releases/tag/24.3.0-15866716565):
24.3.0

[Compare
Source](https://redirect.github.com/actions/node-versions/compare/24.2.0-15549907769...24.3.0-15866716565)

Node.js 24.3.0

###
[`v24.2.0`](https://redirect.github.com/actions/node-versions/releases/tag/24.2.0-15549907769):
24.2.0

[Compare
Source](https://redirect.github.com/actions/node-versions/compare/24.1.0-15177436545...24.2.0-15549907769)

Node.js 24.2.0

###
[`v24.1.0`](https://redirect.github.com/actions/node-versions/releases/tag/24.1.0-15177436545):
24.1.0

[Compare
Source](https://redirect.github.com/actions/node-versions/compare/24.0.2-15035852679...24.1.0-15177436545)

Node.js 24.1.0

###
[`v24.0.2`](https://redirect.github.com/actions/node-versions/releases/tag/24.0.2-15035852679):
24.0.2

[Compare
Source](https://redirect.github.com/actions/node-versions/compare/24.0.1-14928016774...24.0.2-15035852679)

Node.js 24.0.2

###
[`v24.0.1`](https://redirect.github.com/actions/node-versions/releases/tag/24.0.1-14928016774):
24.0.1

[Compare
Source](https://redirect.github.com/actions/node-versions/compare/24.0.0-14863421234...24.0.1-14928016774)

Node.js 24.0.1

###
[`v24.0.0`](https://redirect.github.com/actions/node-versions/releases/tag/24.0.0-14863421234):
24.0.0

[Compare
Source](https://redirect.github.com/actions/node-versions/compare/22.21.0-18671149699...24.0.0-14863421234)

Node.js 24.0.0

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNTkuNCIsInVwZGF0ZWRJblZlciI6IjQxLjE1OS40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-30 14:13:19 +00:00
Brandy Smith
10f895b8b6 merge release-8.7.8 (#30761)
v8.7.8
2025-10-29 14:09:19 -04:00
ionitron
66abc05c46 chore(): update package lock files 2025-10-29 17:41:33 +00:00
ionitron
8a8eec4247 v8.7.8 2025-10-29 17:40:53 +00:00
OS-jacobbell
abd3eacadf chore(ci): send alert message when stencil-nightly workflow finishes (#30743)
Send alert to a Discord channel using a webhook.

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- If a step in the workflow fails, an alert message will be sent to a
Discord channel using a webhook.

## Does this introduce a breaking change?

- [ ] Yes
- [X] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

---------

Co-authored-by: Brandy Smith <brandyscarney@users.noreply.github.com>
2025-10-27 16:47:56 +00:00
Maria Hutt
54a1c86d6a fix(checkbox, toggle): fire ionFocus and ionBlur (#30733)
Issue number: internal

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

`ionFocus` and `ionBlur` are not being emitted for checkbox and toggle. 

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Moved the `onFocus` and `onBlur` to `Host`
- Added tests for `onFocus`, `onBlur`, and `onChange`.
- Added a workaround on Playwright in order to trigger `ionBlur` since
Playwright browsers aren't acting like native browsers when it comes to
tabbing.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

Dev build: `8.7.7-dev.11761071592.1d1b804d`

---------

Co-authored-by: ionitron <hi@ionicframework.com>
Co-authored-by: Shane <shane@shanessite.net>
2025-10-23 17:09:05 +00:00
renovate[bot]
ba73988750 chore(deps): update dependency @axe-core/playwright to ^4.11.0 (#30747)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
|
[@axe-core/playwright](https://redirect.github.com/dequelabs/axe-core-npm)
| [`^4.10.2` ->
`^4.11.0`](https://renovatebot.com/diffs/npm/@axe-core%2fplaywright/4.10.2/4.11.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@axe-core%2fplaywright/4.11.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@axe-core%2fplaywright/4.10.2/4.11.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>dequelabs/axe-core-npm (@&#8203;axe-core/playwright)</summary>

###
[`v4.11.0`](https://redirect.github.com/dequelabs/axe-core-npm/blob/HEAD/CHANGELOG.md#4110-2025-10-14)

[Compare
Source](https://redirect.github.com/dequelabs/axe-core-npm/compare/v4.10.2...a7af9e96a24105a56def373bf0339cf57cda0403)

##### Bug Fixes

- Optimize AxeBuilder memory usage.
([#&#8203;1154](https://redirect.github.com/dequelabs/axe-core-npm/issues/1154))
([e53cd36](e53cd36d07)),
closes
[/github.com/bensenescu/axe-core-npm/blob/develop/packages/puppeteer/src/axePuppeteer.ts#L59](https://redirect.github.com//github.com/bensenescu/axe-core-npm/blob/develop/packages/puppeteer/src/axePuppeteer.ts/issues/L59)
[/github.com/bensenescu/axe-core-npm/blob/develop/packages/puppeteer/src/utils.ts#L34](https://redirect.github.com//github.com/bensenescu/axe-core-npm/blob/develop/packages/puppeteer/src/utils.ts/issues/L34)
- Update axe-core to v4.10.3
([#&#8203;1155](https://redirect.github.com/dequelabs/axe-core-npm/issues/1155))
([f8e3a14](f8e3a14043))
- **wdio:** resolve blank navigation issue in WDIO v9
([#&#8203;1169](https://redirect.github.com/dequelabs/axe-core-npm/issues/1169))
([6505560](6505560d64))

##### Features

- Update axe-core to v4.11.0
([#&#8203;1233](https://redirect.github.com/dequelabs/axe-core-npm/issues/1233))
([2758476](2758476481))

####
[4.10.2](https://redirect.github.com/dequelabs/axe-core-npm/compare/v4.10.1...v4.10.2)
(2025-05-12)

##### Bug Fixes

- Optimize AxeBuilder memory usage.
([#&#8203;1154](https://redirect.github.com/dequelabs/axe-core-npm/issues/1154))
([e53cd36](e53cd36d07)),
closes
[/github.com/bensenescu/axe-core-npm/blob/develop/packages/puppeteer/src/axePuppeteer.ts#L59](https://redirect.github.com//github.com/bensenescu/axe-core-npm/blob/develop/packages/puppeteer/src/axePuppeteer.ts/issues/L59)
[/github.com/bensenescu/axe-core-npm/blob/develop/packages/puppeteer/src/utils.ts#L34](https://redirect.github.com//github.com/bensenescu/axe-core-npm/blob/develop/packages/puppeteer/src/utils.ts/issues/L34)
- Update axe-core to v4.10.3
([#&#8203;1155](https://redirect.github.com/dequelabs/axe-core-npm/issues/1155))
([f8e3a14](f8e3a14043))
- **wdio:** resolve blank navigation issue in WDIO v9
([#&#8203;1169](https://redirect.github.com/dequelabs/axe-core-npm/issues/1169))
([6505560](6505560d64))

####
[4.10.1](https://redirect.github.com/dequelabs/axe-core-npm/compare/v4.10.0...v4.10.1)
(2024-10-29)

##### Bug Fixes

- Update axe-core to v4.10.1
([#&#8203;1124](https://redirect.github.com/dequelabs/axe-core-npm/issues/1124))
([099818b](099818bcef))
- Update axe-core to v4.10.2
([#&#8203;1128](https://redirect.github.com/dequelabs/axe-core-npm/issues/1128))
([aaaa34e](aaaa34e7c3))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNTYuMSIsInVwZGF0ZWRJblZlciI6IjQxLjE1Ni4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-23 13:58:36 +00:00
renovate[bot]
bdc80d8e82 chore(deps): update dependency @capacitor/core to v7.4.4 (#30746)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [@capacitor/core](https://capacitorjs.com)
([source](https://redirect.github.com/ionic-team/capacitor)) | [`7.4.3`
->
`7.4.4`](https://renovatebot.com/diffs/npm/@capacitor%2fcore/7.4.3/7.4.4)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@capacitor%2fcore/7.4.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@capacitor%2fcore/7.4.3/7.4.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>ionic-team/capacitor (@&#8203;capacitor/core)</summary>

###
[`v7.4.4`](https://redirect.github.com/ionic-team/capacitor/compare/7.4.3...20fa5015b7940a19a61e005e4212af967ae8f108)

[Compare
Source](https://redirect.github.com/ionic-team/capacitor/compare/7.4.3...7.4.4)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNTYuMSIsInVwZGF0ZWRJblZlciI6IjQxLjE1Ni4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-23 13:58:13 +00:00
Brandy Smith
81024ab68e feat(themes): add ios theme tokens (#30736)
Adds and defines the `ios` theme tokens. Removes the duplicated `--ion-font-family` assignment.

Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-10-21 16:33:26 -04:00
Brandy Smith
a7699eabbe feat(themes): add md theme tokens and update ionic theme to include semantic tokens (#30734)
- Updates the theme tokens interface to add more numeric tokens & semantic tokens
- Moves the `config` values into a separate `config` option which uses the `IonicConfig` interface
  - Adds a config option for `formHighlight` to `IonicConfig`
- Defines default & dark tokens for the `md` theme
- Removes the numeric tokens from the `ionic` theme and adds semantic tokens
- Remove the numerous `--ion-font-family` overrides in favor of the tokens

---------

Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-10-21 15:56:18 -04:00
renovate[bot]
9f013b7a51 chore(deps): update playwright (#30732)
This PR contains the following updates:

| Package | Change | Age | Confidence | Type | Update |
|---|---|---|---|---|---|
| [@playwright/test](https://playwright.dev)
([source](https://redirect.github.com/microsoft/playwright)) |
[`^1.56.0` ->
`^1.56.1`](https://renovatebot.com/diffs/npm/@playwright%2ftest/1.56.0/1.56.1)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@playwright%2ftest/1.56.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@playwright%2ftest/1.56.0/1.56.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
| devDependencies | patch |
| mcr.microsoft.com/playwright | `v1.56.0` -> `v1.56.1` |
[![age](https://developer.mend.io/api/mc/badges/age/docker/mcr.microsoft.com%2fplaywright/v1.56.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/docker/mcr.microsoft.com%2fplaywright/v1.56.0/v1.56.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
| final | patch |

---

### Release Notes

<details>
<summary>microsoft/playwright (@&#8203;playwright/test)</summary>

###
[`v1.56.1`](https://redirect.github.com/microsoft/playwright/releases/tag/v1.56.1)

[Compare
Source](https://redirect.github.com/microsoft/playwright/compare/v1.56.0...v1.56.1)

#### Highlights


[#&#8203;37871](https://redirect.github.com/microsoft/playwright/issues/37871)
chore: allow local-network-access permission in chromium

[#&#8203;37891](https://redirect.github.com/microsoft/playwright/issues/37891)
fix(agents): remove workspaceFolder ref from vscode mcp

[#&#8203;37759](https://redirect.github.com/microsoft/playwright/issues/37759)
chore: rename agents to test agents

[#&#8203;37757](https://redirect.github.com/microsoft/playwright/issues/37757)
chore(mcp): fallback to cwd when resolving test config

#### Browser Versions

- Chromium 141.0.7390.37
- Mozilla Firefox 142.0.1
- WebKit 26.0

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNDMuMSIsInVwZGF0ZWRJblZlciI6IjQxLjE0My4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-17 17:25:46 +00:00
Brandy Smith
3fd1d5cab1 feat(themes): add ionic theme tokens (#30708)
- Updates the token interface to accept a numeric scale.
- Updates the base tokens to use the new interface.
- Adds tokens for the `ionic` theme based on the existing design tokens.
- Excludes certain keys (`enabled`, `rippleEffect`, `formHighlight`) from the generated CSS variables.
- Removes the `--background` and `--ion-background-color` from the global `ionic` theme overrides, allowing it to use the dark palette.
- Removes the different Ionic colors from the `ionic` theme, ensuring all of the themes use the same named (primary, secondary, etc.) colors.
- Updates the testing script to pull in the tokens based on the theme & palette passed to the URL.
- Adds a new npm script, `build.themes`, to generate the theme files.

---------

Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-10-16 10:07:57 -04:00
Brandy Smith
e4fc33f331 merge release-8.7.7 (#30727)
v8.7.7
2025-10-15 15:27:43 -04:00
ionitron
4a49e52b6d chore(): update package lock files 2025-10-15 19:01:26 +00:00
ionitron
7a293d768c v8.7.7 2025-10-15 19:00:38 +00:00
renovate[bot]
72c2b3e916 chore(deps): update playwright (#30709)
> [!NOTE]
> Mend has cancelled [the proposed
renaming](https://redirect.github.com/renovatebot/renovate/discussions/37842)
of the Renovate GitHub app being renamed to `mend[bot]`.
> 
> This notice will be removed on 2025-10-07.

<hr>

This PR contains the following updates:

| Package | Change | Age | Confidence | Type | Update |
|---|---|---|---|---|---|
| [@playwright/test](https://playwright.dev)
([source](https://redirect.github.com/microsoft/playwright)) |
[`^1.55.1` ->
`^1.56.0`](https://renovatebot.com/diffs/npm/@playwright%2ftest/1.55.1/1.56.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@playwright%2ftest/1.56.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@playwright%2ftest/1.55.1/1.56.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
| devDependencies | minor |
| mcr.microsoft.com/playwright | `v1.55.1` -> `v1.56.0` |
[![age](https://developer.mend.io/api/mc/badges/age/docker/mcr.microsoft.com%2fplaywright/v1.56.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/docker/mcr.microsoft.com%2fplaywright/v1.55.1/v1.56.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
| final | minor |

---

### Release Notes

<details>
<summary>microsoft/playwright (@&#8203;playwright/test)</summary>

###
[`v1.56.0`](https://redirect.github.com/microsoft/playwright/compare/v1.55.1...v1.56.0)

[Compare
Source](https://redirect.github.com/microsoft/playwright/compare/v1.55.1...v1.56.0)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xMzEuOSIsInVwZGF0ZWRJblZlciI6IjQxLjEzMS45IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-15 18:09:32 +00:00
Maria Hutt
12084af163 fix(header): ensure one banner role in condensed header (#30718)
Issue number: internal

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

As per accessibility guidelines, there should only be one banner
landmark per page. A condensed header creates two banner landmarks since
2 `ion-header` components are required on the page. `ion-header` renders
with a `role="banner"` by default (when not in `ion-menu`).

The visual effect of the condensed header is achieved by rendering two
distinct header components. Because both components exist in the code at
the same time and both have `role="banner"`, they create a duplicate
landmark announcement for screen readers. This leads to a violation with
the accessibility guidelines.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- The role is updated to either `none` or `banner` based off the
header's active state.
- Added test.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->


[Preview](https://ionic-framework-git-fw-6767-ionic1.vercel.app/src/components/header/test/condense/?ionic%3Amode=ios)
2025-10-15 17:50:44 +00:00
Brandy Smith
add33c5995 refactor(button): only check for undefined fill (#30722)
Issue number: internal

---------

## What is the current behavior?
Button checks for undefined and null fill as a result of Stencil bug
https://github.com/ionic-team/stencil/issues/3586

## What is the new behavior?
- Removes check for `null` with the release of Stencil v4.38.0
- No test needed as one exists already:
https://github.com/ionic-team/ionic-framework/pull/26339/files

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-10-15 17:50:12 +00:00
Maria Hutt
03303d73f0 fix(select): improve screen reader announcement timing for validation errors (#30723)
Issue number: internal

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Currently, when an error text is shown, it may not announce itself to
voice assistants. This is because the way error text currently works is
by always existing in the DOM, but being hidden when there is no error.
When the error state changes, the error text is shown, but as far as the
voice assistant can tell it's always been there and nothing has changed.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Updated aria attributes
- Added observer with an observer

We had to do this with a mutation observer and state because it's
important in some frameworks, like Angular, that state changes to cause
a re-render. This, combined with some minor aria changes, makes it so
that when a field is declared invalid, it immediately announces the
invalid state instead of waiting for the user to go back to the invalid
field.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->


[Preview](https://ionic-framework-git-fw-6797-ionic1.vercel.app/src/components/select/test/validation/)
2025-10-15 17:50:07 +00:00
renovate[bot]
18e1d3e1b8 chore(deps): update github/codeql-action action to v4 (#30717)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[github/codeql-action](https://redirect.github.com/github/codeql-action)
| action | major | `v3` -> `v4` |

---

### Release Notes

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

###
[`v4`](https://redirect.github.com/github/codeql-action/compare/v3...v4)

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

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xMzEuOSIsInVwZGF0ZWRJblZlciI6IjQxLjEzMS45IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-15 17:36:50 +00:00
Maria Hutt
820fa28543 fix(header): prevent flickering during iOS page transitions (#30705)
Issue number: resolves #25326

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

The header flickers upon page transition when on iOS mode and using a
condensed header:

**Entering Page Two (P1 → P2):**
When navigating to Page Two, which has a collapsing header (intended to
be hidden until scroll), the header briefly flashes into view. This
happens because the header is initially rendered with full `opacity: 1`
before the component's logic can apply `opacity: 0` to hide it, causing
a visible flicker.

**Navigating Back (P2 → P1):**
When navigating back, Page One's header briefly bleeds through the top
of Page Two. Although Page Two is on top (`z−index: 100`), its
collapsing header is set to `opacity: 0`. This transparency allows Page
One header (`z−index: 99`) to become visible underneath, as the
transparent area cannot block the content below it.

The header flickers upon page transition when on iOS mode and using a
fade header:

**Entering Page Two (P1 → P2):**
When navigating to Page Two, which has a fade header (should not have a
background on load), the header background briefly flashes into view.
This happens because the header is initially rendered with full
`opacity: 1` before the component's logic can apply `opacity: 0` to hide
it, causing a visible flicker.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Added a transition-specific class that is applied to the condensed
ion-header element to override its default transparency.

This guarantees the header to act as an opaque block during the page
transition, eliminating visual flickering caused by early `opacity: 0`
or the header underneath bleeding through.

- Added a transition-specific class that is applied to the fade
ion-header element to override its default opaque background.

This guarantees the header to act as a transparent block during the page
transition, eliminating visual flickering caused by default `opacity:
1`.


## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

Dev build: `8.7.6-dev.11759524961.1cff6814`
2025-10-14 17:48:35 +00:00
renovate[bot]
f44585657c chore(deps): update actions/setup-node action to v6 (#30726)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [actions/setup-node](https://redirect.github.com/actions/setup-node) |
action | major | `v5` -> `v6` |

---

### Release Notes

<details>
<summary>actions/setup-node (actions/setup-node)</summary>

###
[`v6`](https://redirect.github.com/actions/setup-node/compare/v5...v6)

[Compare
Source](https://redirect.github.com/actions/setup-node/compare/v5...v6)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNDMuMSIsInVwZGF0ZWRJblZlciI6IjQxLjE0My4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-14 10:59:55 +00:00
Brandy Smith
2586284dce merge release-8.7.6 (#30719)
v8.7.6
2025-10-08 14:50:14 -04:00
ionitron
ce048a507a chore(): update package lock files 2025-10-08 18:36:26 +00:00
ionitron
2156f99c2a v8.7.6 2025-10-08 18:35:35 +00:00
renovate[bot]
daf311f63a chore(deps): update dependency @stencil/core to v4.38.0 (#30615)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [@stencil/core](https://stenciljs.com/)
([source](https://redirect.github.com/stenciljs/core)) | [`4.36.2` ->
`4.38.0`](https://renovatebot.com/diffs/npm/@stencil%2fcore/4.36.2/4.38.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@stencil%2fcore/4.38.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@stencil%2fcore/4.36.2/4.38.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>stenciljs/core (@&#8203;stencil/core)</summary>

###
[`v4.38.0`](https://redirect.github.com/stenciljs/core/blob/HEAD/CHANGELOG.md#-4380-2025-10-02)

[Compare
Source](https://redirect.github.com/stenciljs/core/compare/v4.37.1...v4.38.0)

##### Bug Fixes

- local (same-file) class inheritance search
([#&#8203;6403](https://redirect.github.com/stenciljs/core/issues/6403))
([695b1ac](695b1acabd))
- **runtime:** stop immediate re-renders for reflected props when null
!== undefined
([#&#8203;6404](https://redirect.github.com/stenciljs/core/issues/6404))
([680b12e](680b12ec73))
- **test:** stop duplicate super calls in Jest
([#&#8203;6401](https://redirect.github.com/stenciljs/core/issues/6401))
([32160ad](32160ad13b))
- **test:** trigger [@&#8203;Watch](https://redirect.github.com/Watch)
decorators on inherited classes in jest env
([#&#8203;6402](https://redirect.github.com/stenciljs/core/issues/6402))
([f277068](f2770687f5))

##### Features

- **config:** allow suppressing reserved public name warning
([#&#8203;6389](https://redirect.github.com/stenciljs/core/issues/6389))
([341fec4](341fec4ed0))
- new core decorators `@PropSerialize` & `@AttrDeserialize`
([#&#8203;6387](https://redirect.github.com/stenciljs/core/issues/6387))
([967c234](967c2346e9))

#### 🏰
[4.37.1](https://redirect.github.com/stenciljs/core/compare/v4.37.0...v4.37.1)
(2025-09-19)

##### Bug Fixes

- **dist-custom-elements:** revert
[#&#8203;6381](https://redirect.github.com/stenciljs/core/issues/6381)
([77cfdb3](77cfdb3b70))
- **Mixin:** export `MixinFactory` type for ease of use
([#&#8203;6390](https://redirect.github.com/stenciljs/core/issues/6390))
([a26114e](a26114ee8a))
- **runtime:** stop eager json parsing for unknown and any type bindings
([#&#8203;6384](https://redirect.github.com/stenciljs/core/issues/6384))
([ccae0d7](ccae0d743c))

###
[`v4.37.1`](https://redirect.github.com/stenciljs/core/blob/HEAD/CHANGELOG.md#-4371-2025-09-19)

[Compare
Source](https://redirect.github.com/stenciljs/core/compare/v4.37.0...v4.37.1)

##### Bug Fixes

- **dist-custom-elements:** revert
[#&#8203;6381](https://redirect.github.com/stenciljs/core/issues/6381)
([77cfdb3](77cfdb3b70))
- **Mixin:** export `MixinFactory` type for ease of use
([#&#8203;6390](https://redirect.github.com/stenciljs/core/issues/6390))
([a26114e](a26114ee8a))
- **runtime:** stop eager json parsing for unknown and any type bindings
([#&#8203;6384](https://redirect.github.com/stenciljs/core/issues/6384))
([ccae0d7](ccae0d743c))

###
[`v4.37.0`](https://redirect.github.com/stenciljs/core/blob/HEAD/CHANGELOG.md#-4370-2025-09-13)

[Compare
Source](https://redirect.github.com/stenciljs/core/compare/v4.36.3...v4.37.0)

##### Bug Fixes

- **dist-custom-elements:** apply `initializeNextTick` config
([dbcdeff](dbcdeff26a))
- **dist-custom-elements:** apply `initializeNextTick` config setting
([#&#8203;6382](https://redirect.github.com/stenciljs/core/issues/6382))
([7bdf9fb](7bdf9fbba0))
- **runtime:** make sure watchers can fire immediately if the custom
element is already defined
([#&#8203;6381](https://redirect.github.com/stenciljs/core/issues/6381))
([4fb9140](4fb914024b))

##### Features

- new core api - Mixin
([#&#8203;6375](https://redirect.github.com/stenciljs/core/issues/6375))
([08f6583](08f6583878))
- **runtime:** allow class extending
([#&#8203;6362](https://redirect.github.com/stenciljs/core/issues/6362))
([0456db1](0456db1484))

##### BREAKING CHANGES

- **runtime:** Watchers will fire earlier than before, but this is the
expected behavior

#### 🐈
[4.36.3](https://redirect.github.com/stenciljs/core/compare/v4.36.2...v4.36.3)
(2025-08-20)

##### Bug Fixes

- **rollup:** proper `warn` handling
([#&#8203;6357](https://redirect.github.com/stenciljs/core/issues/6357))
([0831d2c](0831d2c35b))
- **runtime:** fixed parsing of complex attributes that contains JSON
strings
([#&#8203;6359](https://redirect.github.com/stenciljs/core/issues/6359))
([7047196](7047196b87))

#### 💚
[4.36.2](https://redirect.github.com/stenciljs/core/compare/v4.36.1...v4.36.2)
(2025-07-28)

##### Bug Fixes

- **bundle:** remove post order of node-resolve
([#&#8203;6353](https://redirect.github.com/stenciljs/core/issues/6353))
([19b56d1](19b56d1977)),
closes
[#&#8203;6335](https://redirect.github.com/stenciljs/core/issues/6335)

#### 🍺
[4.36.1](https://redirect.github.com/stenciljs/core/compare/v4.36.0...v4.36.1)
(2025-07-18)

##### Bug Fixes

- **runtime:** only patch non-shadow components with <slot>s
([#&#8203;6348](https://redirect.github.com/stenciljs/core/issues/6348))
([827b7f0](827b7f0d55))
- **runtime:** stop applying patches to non-shadow / non-render()
components
([#&#8203;6349](https://redirect.github.com/stenciljs/core/issues/6349))
([3a18a37](3a18a37785))

###
[`v4.36.3`](https://redirect.github.com/stenciljs/core/blob/HEAD/CHANGELOG.md#-4363-2025-08-20)

[Compare
Source](https://redirect.github.com/stenciljs/core/compare/v4.36.2...v4.36.3)

##### Bug Fixes

- **rollup:** proper `warn` handling
([#&#8203;6357](https://redirect.github.com/stenciljs/core/issues/6357))
([0831d2c](0831d2c35b))
- **runtime:** fixed parsing of complex attributes that contains JSON
strings
([#&#8203;6359](https://redirect.github.com/stenciljs/core/issues/6359))
([7047196](7047196b87))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every weekday before 11am" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Never, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/ionic-team/ionic-framework).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS41MS4xIiwidXBkYXRlZEluVmVyIjoiNDEuMTMxLjkiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbXX0=-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-07 18:01:23 +00:00
Brandy Smith
003de2d85e chore(deps): do not group stencil with output targets (#30711)
Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-10-07 15:47:53 +00:00
Shane
7bb9535f60 fix(tabs): respect stencil lifecycle order for tab selection (#30702)
Issue number: resolves #30611

---------

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

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

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Currently, the way tabs are set in the tab bar abuses a bug that existed
in older versions of Stencil where children would be rendered out of the
correct order. This worked in the tab and tab bar's favor previously,
but after the fix it broke our implementation so tabs would no longer
correctly indicate the selected tab on direct navigation.


## What is the new behavior?

We had a temporary fix before we knew what actually caused this issue
before, which was basically just a timeout. That blindly worked because
it triggered after the child was fully rendered. This change embraces
the new, and correct, way these components render and triggers tab
updates correctly.

## Does this introduce a breaking change?

- [ ] Yes
- [X] No

<!--
  If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
  2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
Current dev build:
```
8.7.6-dev.11759345401.165fca78
```

---------

Co-authored-by: ionitron <hi@ionicframework.com>
2025-10-06 14:54:41 +00:00
Brandy Smith
41953b0b3b feat(themes): add base tokens and update colors to use new token system (#30692)
## What is the current behavior?
The colors are generated using the Sass functions and a `$colors` map
and the design tokens are undefined.

## What is the new behavior?
- Moves the helper & theme `spec` tests into the `test` directory with
the other ones
- Defines base tokens for the default, light & dark tokens
- Defines the interfaces for the different theme objects
- Adds new theme utility functions to mix colors together (used for
shade & tint) and convert hex to rgb
- Updates the functions that generate the design token variables to:
- Automatically generate the rgb variables without needing to set them
manually
- Create the color classes (`.ion-color-primary`,
`.ion-color-secondary`, etc.) which are used by the components to change
their color via the `color` property
- Adds 3 e2e tests to verify visually that the design tokens are
generating properly: Basic, Color & Typography
- Removes the old Sass mixins/functions & updates the ones we still need
to pull from the design tokens instead of the `$colors` map

## Does this introduce a breaking change?

- [x] Yes
- [ ] No

This adds `foreground` as a required variant to the colors now.
Currently foreground is only used by clear buttons but it should be used
by all text-only components. This will break for any apps overriding
`--ion-color-primary` without `--ion-color-primary-foreground`. We will
have to look into improving the migration path on this later.

## Other information

- [Themes /
Basic](https://ionic-framework-git-fw-6748-ionic1.vercel.app/src/themes/test/basic)
- [Themes /
Color](https://ionic-framework-git-fw-6748-ionic1.vercel.app/src/themes/test/color)
- [Themes /
Typography](https://ionic-framework-git-fw-6748-ionic1.vercel.app/src/themes/test/typography)

---------

Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
Co-authored-by: ionitron <hi@ionicframework.com>
2025-10-01 12:13:41 -04:00
Brandy Smith
93d75502a3 feat(themes): allow mode specific custom theme overrides with modular themes (#30657)
Issue number: internal

---------

## What is the current behavior?
A `customTheme` object can not change based on the mode.

## What is the new behavior?
Adds top level `ios` and `md` property checks to flatten with the
`customTheme` object based on the mode.

## Does this introduce a breaking change?
- [ ] Yes
- [x] No

## Other information
Requires additional changes in order to test.

---------

Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-09-25 15:39:40 -04:00
Brandy Smith
1aa7c35da1 feat(themes): add support for modular themes and custom themes (#30651)
Issue number: internal

---------

## What is the new behavior?
- Moves `openURL` out of the `theme` utils because it makes more sense
in `helpers`
- Adds support for the default `default.tokens.ts` design tokens file
- Adds support for custom theme set globally and on a component 

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

## Other information

Requires additional changes in order to test.

---------

Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-09-25 15:39:40 -04:00
Brandy Smith
fea1e64920 refactor(themes): add modular themes directory structure and docs (#30640)
Issue number: internal

---------

## What is the new behavior?
Separates the themes directory for each new modular theme. Documents the
new structure.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
2025-09-25 15:39:40 -04:00
1173 changed files with 13534 additions and 9183 deletions

View File

@@ -8,48 +8,53 @@ inputs:
tag:
description: 'The tag to publish to on NPM.'
preid:
description: 'The prerelease identifier used when doing a prerelease.'
description: "Prerelease identifier such as 'alpha', 'beta', 'rc', or 'next'. Leave blank to skip prerelease tagging."
working-directory:
description: 'The directory of the package.'
folder:
default: './'
description: 'A folder containing a package.json file.'
token:
description: 'The NPM authentication token required to publish.'
node-version:
description: 'Node.js version to use when publishing.'
required: false
default: '24.x'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v5
- name: 🟢 Configure Node for Publish
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: 22.x
node-version: ${{ inputs.node-version }}
registry-url: 'https://registry.npmjs.org'
scope: '@ionic'
# Provenance requires npm 9.5.0+
- name: Install latest npm
- name: 📦 Install latest npm
run: npm install -g npm@latest
shell: bash
# This ensures the local version of Lerna is installed
# and that we do not use the global Lerna version
- name: Install root dependencies
- name: 🕸️ Install root dependencies
run: npm ci
shell: bash
- name: Install Dependencies
- name: 📦 Install Dependencies
run: npx lerna@5 bootstrap --include-dependencies --scope ${{ inputs.scope }} --ignore-scripts -- --legacy-peer-deps
shell: bash
working-directory: ${{ inputs.working-directory }}
- name: Update Version
run: npx lerna@5 version ${{ inputs.version }} --yes --exact --no-changelog --no-push --no-git-tag-version --preid=${{ inputs.preid }}
- name: 🏷️ Set Version
run: |
if [ -z "${{ inputs.preid }}" ]; then
npx lerna@5 version ${{ inputs.version }} --yes --exact --no-changelog --no-push --no-git-tag-version
else
npx lerna@5 version ${{ inputs.version }} --yes --exact --no-changelog --no-push --no-git-tag-version --preid=${{ inputs.preid }}
fi
shell: bash
working-directory: ${{ inputs.working-directory }}
- name: Run Build
- name: 🏗️ Run Build
run: npm run build
shell: bash
working-directory: ${{ inputs.working-directory }}
- name: Prepare NPM Token
run: echo //registry.npmjs.org/:_authToken=${NPM_TOKEN} > .npmrc
working-directory: ${{ inputs.working-directory }}
shell: bash
env:
NPM_TOKEN: ${{ inputs.token }}
- name: Publish to NPM
- name: 🚀 Publish to NPM
run: npm publish ${{ inputs.folder }} --tag ${{ inputs.tag }} --provenance
shell: bash
working-directory: ${{ inputs.working-directory }}

View File

@@ -3,23 +3,23 @@ description: 'Build Ionic Angular Server'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v5
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: 22.x
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- name: Install Angular Server Dependencies
- name: 🕸️ Install Angular Server Dependencies
run: npm ci
shell: bash
working-directory: ./packages/angular-server
- name: Sync
- name: 🔄 Sync
run: npm run sync
shell: bash
working-directory: ./packages/angular-server
- name: Build
- name: 🏗️ Build
run: npm run build.prod
shell: bash
working-directory: ./packages/angular-server

View File

@@ -3,31 +3,31 @@ description: 'Build Ionic Angular'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v5
- uses: actions/setup-node@v6
with:
node-version: 22.x
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- name: Install Angular Dependencies
- name: 🕸️ Install Angular Dependencies
run: npm ci
shell: bash
working-directory: ./packages/angular
- name: Sync
- name: 🔄 Sync
run: npm run sync
shell: bash
working-directory: ./packages/angular
- name: Lint
- name: 🖌️ Lint
run: npm run lint
shell: bash
working-directory: ./packages/angular
- name: Build
- name: 🏗️ Build
run: npm run build
shell: bash
working-directory: ./packages/angular
- name: Check Diff
- name: 🔍 Check Diff
run: git diff --exit-code
shell: bash
working-directory: ./packages/angular

View File

@@ -8,20 +8,20 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: 22.x
node-version: 24.x
- name: Install Dependencies
- name: 🕸️ Install Dependencies
run: npm ci
working-directory: ./core
shell: bash
- name: Install Stencil ${{ inputs.stencil-version }}
- name: 📦 Install Stencil ${{ inputs.stencil-version }}
working-directory: ./core
run: npm i @stencil/core@${{ inputs.stencil-version }}
shell: bash
- name: Build Core
- name: 🏗️ Build Core
run: npm run build -- --ci --debug --verbose
working-directory: ./core
shell: bash
@@ -29,4 +29,4 @@ runs:
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
paths: core/dist core/components core/src/foundations core/css core/themes core/hydrate core/loader core/src/components.d.ts

View File

@@ -8,22 +8,22 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: 22.x
- name: Install Dependencies
node-version: 24.x
- name: 🕸️ Install Dependencies
run: npm install
working-directory: ./core
shell: bash
# If an Ionicons version was specified install that.
# Otherwise just use the version defined in the package.json.
- name: Install Ionicons Version
- name: 📦 Install Ionicons Version
if: inputs.ionicons-version != ''
run: npm install ionicons@${{ inputs.ionicons-version }}
working-directory: ./core
shell: bash
- name: Build Core
- name: 🏗️ Build Core
run: npm run build -- --ci
working-directory: ./core
shell: bash
@@ -33,4 +33,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/themes 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

View File

@@ -3,9 +3,9 @@ description: 'Build Ionic React Router'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v5
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: 22.x
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
@@ -16,19 +16,19 @@ runs:
name: ionic-react
path: ./packages/react
filename: ReactBuild.zip
- name: Install Dependencies
- name: 🕸️ Install Dependencies
run: npm ci
shell: bash
working-directory: ./packages/react-router
- name: Sync
- name: 🔄 Sync
run: npm run sync
shell: bash
working-directory: ./packages/react-router
- name: Lint
- name: 🖌️ Lint
run: npm run lint
shell: bash
working-directory: ./packages/react-router
- name: Build
- name: 🏗️ Build
run: npm run build
shell: bash
working-directory: ./packages/react-router

View File

@@ -3,35 +3,35 @@ description: 'Build Ionic React'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v5
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: 22.x
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- name: Install React Dependencies
- name: 🕸️ Install React Dependencies
run: npm ci
shell: bash
working-directory: ./packages/react
- name: Sync
- name: 🔄 Sync
run: npm run sync
shell: bash
working-directory: ./packages/react
- name: Lint
- name: 🖌️ Lint
run: npm run lint
shell: bash
working-directory: ./packages/react
- name: Build
- name: 🏗️ Build
run: npm run build
shell: bash
working-directory: ./packages/react
- name: Test Spec
- name: 🧪 Test Spec
run: npm run test.spec
shell: bash
working-directory: ./packages/react
- name: Check Diff
- name: 🔍 Check Diff
run: git diff --exit-code
shell: bash
working-directory: ./packages/react

View File

@@ -3,9 +3,9 @@ description: 'Builds Ionic Vue Router'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v5
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: 22.x
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
@@ -16,23 +16,23 @@ runs:
name: ionic-vue
path: ./packages/vue
filename: VueBuild.zip
- name: Install Vue Router Dependencies
- name: 🕸️ Install Vue Router Dependencies
run: npm ci
shell: bash
working-directory: ./packages/vue-router
- name: Sync
- name: 🔄 Sync
run: npm run sync
shell: bash
working-directory: ./packages/vue-router
- name: Lint
- name: 🖌️ Lint
run: npm run lint
shell: bash
working-directory: ./packages/vue-router
- name: Build
- name: 🏗️ Build
run: npm run build
shell: bash
working-directory: ./packages/vue-router
- name: Test Spec
- name: 🧪 Test Spec
run: npm run test.spec
shell: bash
working-directory: ./packages/vue-router

View File

@@ -3,31 +3,31 @@ description: 'Build Ionic Vue'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v5
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: 22.x
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- name: Install Vue Dependencies
- name: 🕸️ Install Vue Dependencies
run: npm ci
shell: bash
working-directory: ./packages/vue
- name: Sync
- name: 🔄 Sync
run: npm run sync
shell: bash
working-directory: ./packages/vue
- name: Lint
- name: 🖌️ Lint
run: npm run lint
shell: bash
working-directory: ./packages/vue
- name: Build
- name: 🏗️ Build
run: npm run build
shell: bash
working-directory: ./packages/vue
- name: Check Diff
- name: 🔍 Check Diff
run: git diff --exit-code
shell: bash
working-directory: ./packages/vue

View File

@@ -10,10 +10,10 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/download-artifact@v5
- uses: actions/download-artifact@v7
with:
name: ${{ inputs.name }}
path: ${{ inputs.path }}
- name: Extract Archive
- name: 🔎 Extract Archive
run: unzip -q -o ${{ inputs.path }}/${{ inputs.filename }}
shell: bash

View File

@@ -6,9 +6,9 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v5
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: 22.x
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
@@ -24,23 +24,23 @@ runs:
name: ionic-angular-server
path: ./packages/angular-server
filename: AngularServerBuild.zip
- name: Create Test App
- name: 🧪 Create Test App
run: ./build.sh ${{ inputs.app }}
shell: bash
working-directory: ./packages/angular/test
- name: Install Dependencies
- name: 🕸️ Install Dependencies
run: npm install
shell: bash
working-directory: ./packages/angular/test/build/${{ inputs.app }}
- name: Install Playwright Browsers
- name: 📦 Install Playwright Browsers
run: npx playwright install
shell: bash
working-directory: ./packages/angular/test/build/${{ inputs.app }}
- name: Sync Built Changes
- name: 🔄 Sync Built Changes
run: npm run sync
shell: bash
working-directory: ./packages/angular/test/build/${{ inputs.app }}
- name: Run Tests
- name: 🧪 Run Tests
run: npm run test
shell: bash
working-directory: ./packages/angular/test/build/${{ inputs.app }}

View File

@@ -3,16 +3,16 @@ description: 'Test Core Clean Build'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v5
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: 22.x
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- name: Check Diff
- name: 🔍 Check Diff
run: |
git diff --exit-code || {
echo -e "\033[1;31m⚠ Error: Differences Detected ⚠️\033[0m"

View File

@@ -3,21 +3,21 @@ description: 'Test Core Lint'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v5
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: 22.x
- name: Install Dependencies
node-version: 24.x
- name: 🕸️ Install Dependencies
run: npm ci
working-directory: ./core
shell: bash
- name: Lint
- name: 🖌️ Lint
run: npm run lint
shell: bash
working-directory: ./core
# Lint changes should be pushed
# to the branch before the branch
# is merge eligible.
- name: Check Lint Results
- name: 🔎 Check Lint Results
run: git diff --exit-code
shell: bash
working-directory: ./core

View File

@@ -13,19 +13,19 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v5
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: 22.x
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- name: Install Dependencies
- name: 🕸️ Install Dependencies
run: npm install
shell: bash
working-directory: ./core
- name: Test
- name: 🧪 Test
if: inputs.update != 'true'
run: npm run test.e2e.docker.ci ${{ inputs.component }} -- --shard=${{ inputs.shard }}/${{ inputs.totalShards }}
shell: bash
@@ -60,13 +60,13 @@ runs:
fi
shell: bash
working-directory: ./core
- name: Archive Updated Screenshots
- name: 📦 Archive Updated Screenshots
if: inputs.update == 'true' && steps.test-and-update.outputs.hasUpdatedScreenshots == 'true'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: updated-screenshots-${{ inputs.shard }}-${{ inputs.totalShards }}
path: UpdatedScreenshots-${{ inputs.shard }}-${{ inputs.totalShards }}.zip
- name: Archive Test Results
- name: 📦 Archive Test Results
# The always() ensures that this step
# runs even if the previous step fails.
# We want the test results to be archived

View File

@@ -6,14 +6,14 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v5
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: 22.x
- name: Install Dependencies
node-version: 24.x
- name: 🕸️ Install Dependencies
run: npm ci
working-directory: ./core
shell: bash
- name: Install Stencil ${{ inputs.stencil-version }}
- name: 📦 Install Stencil ${{ inputs.stencil-version }}
run: npm install @stencil/core@${{ inputs.stencil-version }}
shell: bash
working-directory: ./core
@@ -23,7 +23,7 @@ runs:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- name: Test
- name: 🧪 Test
run: npm run test.spec -- --ci
shell: bash
working-directory: ./core

View File

@@ -6,9 +6,9 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v5
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: 22.x
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
@@ -24,23 +24,23 @@ runs:
name: ionic-react-router
path: ./packages/react-router
filename: ReactRouterBuild.zip
- name: Create Test App
- name: 🧪 Create Test App
run: ./build.sh ${{ inputs.app }}
shell: bash
working-directory: ./packages/react/test
- name: Install Dependencies
- name: 🕸️ Install Dependencies
run: npm install
shell: bash
working-directory: ./packages/react/test/build/${{ inputs.app }}
- name: Sync Built Changes
- name: 🔄 Sync Built Changes
run: npm run sync
shell: bash
working-directory: ./packages/react/test/build/${{ inputs.app }}
- name: Build
- name: 🏗️ Build
run: npm run build
shell: bash
working-directory: ./packages/react/test/build/${{ inputs.app }}
- name: Run Tests
- name: 🧪 Run Tests
run: npm run e2e
shell: bash
working-directory: ./packages/react/test/build/${{ inputs.app }}

View File

@@ -6,9 +6,9 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v5
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: 22.x
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
@@ -24,23 +24,23 @@ runs:
name: ionic-react-router
path: ./packages/react-router
filename: ReactRouterBuild.zip
- name: Create Test App
- name: 🧪 Create Test App
run: ./build.sh ${{ inputs.app }}
shell: bash
working-directory: ./packages/react-router/test
- name: Install Dependencies
- name: 🕸️ Install Dependencies
run: npm install
shell: bash
working-directory: ./packages/react-router/test/build/${{ inputs.app }}
- name: Sync Built Changes
- name: 🔄 Sync Built Changes
run: npm run sync
shell: bash
working-directory: ./packages/react-router/test/build/${{ inputs.app }}
- name: Build
- name: 🏗️ Build
run: npm run build
shell: bash
working-directory: ./packages/react-router/test/build/${{ inputs.app }}
- name: Run Tests
- name: 🧪 Run Tests
run: npm run e2e
shell: bash
working-directory: ./packages/react-router/test/build/${{ inputs.app }}

View File

@@ -6,9 +6,9 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v5
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: 22.x
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
@@ -24,23 +24,23 @@ runs:
name: ionic-vue-router
path: ./packages/vue-router
filename: VueRouterBuild.zip
- name: Create Test App
- name: 🧪 Create Test App
run: ./build.sh ${{ inputs.app }}
shell: bash
working-directory: ./packages/vue/test
- name: Install Dependencies
- name: 📦 Install Dependencies
run: npm install
shell: bash
working-directory: ./packages/vue/test/build/${{ inputs.app }}
- name: Sync
- name: 🔄 Sync
run: npm run sync
shell: bash
working-directory: ./packages/vue/test/build/${{ inputs.app }}
- name: Run Spec Tests
- name: 🧪 Run Spec Tests
run: npm run test:unit
shell: bash
working-directory: ./packages/vue/test/build/${{ inputs.app }}
- name: Run E2E Tests
- name: 🧪 Run E2E Tests
run: npm run test:e2e
shell: bash
working-directory: ./packages/vue/test/build/${{ inputs.app }}

View File

@@ -7,13 +7,13 @@ on:
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v5
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: 22.x
- uses: actions/download-artifact@v5
node-version: 24.x
- uses: actions/download-artifact@v7
with:
path: ./artifacts
- name: Extract Archives
- name: 🔎 Extract Archives
# This finds all .zip files in the ./artifacts
# directory, including nested directories.
# It then unzips every .zip to the root directory
@@ -21,7 +21,7 @@ runs:
find . -type f -name 'UpdatedScreenshots-*.zip' -exec unzip -q -o -d ../ {} \;
shell: bash
working-directory: ./artifacts
- name: Push Screenshots
- name: 📸 Push Screenshots
# Configure user as Ionitron
# and push only the changed .png snapshots
# to the remote branch.

View File

@@ -10,10 +10,10 @@ inputs:
runs:
using: 'composite'
steps:
- name: Create Archive
- name: 🗄️ Create Archive
run: zip -q -r ${{ inputs.output }} ${{ inputs.paths }}
shell: bash
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v6
with:
name: ${{ inputs.name }}
path: ${{ inputs.output }}

View File

@@ -22,7 +22,7 @@ jobs:
build-core:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- 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@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/workflows/actions/test-core-clean-build
test-core-lint:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/workflows/actions/test-core-lint
test-core-spec:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- 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@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- 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@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/workflows/actions/build-vue
build-vue-router:
needs: [build-vue]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- 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@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- 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@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/workflows/actions/build-angular
build-angular-server:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- 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@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- 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@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/workflows/actions/build-react
build-react-router:
needs: [build-react]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- 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@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- 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@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/workflows/actions/test-react-e2e
with:
app: ${{ matrix.apps }}

View File

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

View File

@@ -1,7 +1,11 @@
name: 'Ionic Dev Build'
on:
workflow_dispatch:
workflow_call:
permissions:
contents: read
id-token: write
jobs:
create-dev-hash:
@@ -9,7 +13,7 @@ jobs:
outputs:
dev-hash: ${{ steps.create-dev-hash.outputs.DEV_HASH }}
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
# 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
@@ -25,13 +29,12 @@ jobs:
release-ionic:
needs: [create-dev-hash]
permissions:
contents: read
id-token: write
uses: ./.github/workflows/release-ionic.yml
with:
tag: dev
version: ${{ needs.create-dev-hash.outputs.dev-hash }}
secrets:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
get-build:
name: Get your dev build!

View File

@@ -1,10 +1,11 @@
name: 'Ionic Nightly Build'
on:
schedule:
# Run every Monday-Friday
# at 6:00 UTC (6:00 am UTC)
- cron: '00 06 * * 1-5'
workflow_call:
permissions:
contents: read
id-token: write
jobs:
create-nightly-hash:
@@ -12,7 +13,7 @@ jobs:
outputs:
nightly-hash: ${{ steps.create-nightly-hash.outputs.NIGHTLY_HASH }}
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
# 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
@@ -30,10 +31,10 @@ jobs:
release-ionic:
needs: [create-nightly-hash]
permissions:
contents: read
id-token: write
uses: ./.github/workflows/release-ionic.yml
secrets: inherit
with:
tag: nightly
version: ${{ needs.create-nightly-hash.outputs.nightly-hash }}
secrets:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

View File

@@ -14,23 +14,23 @@ on:
preid:
description: 'The prerelease identifier used when doing a prerelease.'
type: string
secrets:
NPM_TOKEN:
required: true
permissions:
contents: read
id-token: write
jobs:
release-core:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: ./.github/workflows/actions/publish-npm
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/actions/publish-npm
with:
scope: '@ionic/core'
tag: ${{ inputs.tag }}
version: ${{ inputs.version }}
preid: ${{ inputs.preid }}
working-directory: 'core'
token: ${{ secrets.NPM_TOKEN }}
- name: Cache Built @ionic/core
uses: ./.github/workflows/actions/upload-archive
with:
@@ -48,34 +48,33 @@ jobs:
needs: [release-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Restore @ionic/docs built cache
uses: ./.github/workflows/actions/download-archive
with:
name: ionic-docs
path: ./packages/docs
filename: DocsBuild.zip
- uses: ./.github/workflows/actions/publish-npm
- uses: ./.github/actions/publish-npm
with:
scope: '@ionic/docs'
tag: ${{ inputs.tag }}
version: ${{ inputs.version }}
preid: ${{ inputs.preid }}
working-directory: 'packages/docs'
token: ${{ secrets.NPM_TOKEN }}
release-angular:
needs: [release-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Restore @ionic/core built cache
uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- uses: ./.github/workflows/actions/publish-npm
- uses: ./.github/actions/publish-npm
with:
scope: '@ionic/angular'
tag: ${{ inputs.tag }}
@@ -83,7 +82,6 @@ jobs:
preid: ${{ inputs.preid }}
working-directory: 'packages/angular'
folder: './dist'
token: ${{ secrets.NPM_TOKEN }}
- name: Cache Built @ionic/angular
uses: ./.github/workflows/actions/upload-archive
with:
@@ -95,21 +93,20 @@ jobs:
needs: [release-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Restore @ionic/core built cache
uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- uses: ./.github/workflows/actions/publish-npm
- uses: ./.github/actions/publish-npm
with:
scope: '@ionic/react'
tag: ${{ inputs.tag }}
version: ${{ inputs.version }}
preid: ${{ inputs.preid }}
working-directory: 'packages/react'
token: ${{ secrets.NPM_TOKEN }}
- name: Cache Built @ionic/react
uses: ./.github/workflows/actions/upload-archive
with:
@@ -121,21 +118,20 @@ jobs:
needs: [release-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Restore @ionic/core built cache
uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- uses: ./.github/workflows/actions/publish-npm
- uses: ./.github/actions/publish-npm
with:
scope: '@ionic/vue'
tag: ${{ inputs.tag }}
version: ${{ inputs.version }}
preid: ${{ inputs.preid }}
working-directory: 'packages/vue'
token: ${{ secrets.NPM_TOKEN }}
- name: Cache Built @ionic/vue
uses: ./.github/workflows/actions/upload-archive
with:
@@ -147,14 +143,14 @@ jobs:
needs: [release-core]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Restore @ionic/core built cache
uses: ./.github/workflows/actions/download-archive
with:
name: ionic-core
path: ./core
filename: CoreBuild.zip
- uses: ./.github/workflows/actions/publish-npm
- uses: ./.github/actions/publish-npm
with:
scope: '@ionic/angular-server'
tag: ${{ inputs.tag }}
@@ -162,13 +158,12 @@ jobs:
preid: ${{ inputs.preid }}
working-directory: 'packages/angular-server'
folder: './dist'
token: ${{ secrets.NPM_TOKEN }}
release-react-router:
needs: [release-react]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Restore @ionic/core built cache
uses: ./.github/workflows/actions/download-archive
with:
@@ -181,20 +176,19 @@ jobs:
name: ionic-react
path: ./packages/react
filename: ReactBuild.zip
- uses: ./.github/workflows/actions/publish-npm
- uses: ./.github/actions/publish-npm
with:
scope: '@ionic/react-router'
tag: ${{ inputs.tag }}
version: ${{ inputs.version }}
preid: ${{ inputs.preid }}
working-directory: 'packages/react-router'
token: ${{ secrets.NPM_TOKEN }}
release-vue-router:
needs: [release-vue]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Restore @ionic/core built cache
uses: ./.github/workflows/actions/download-archive
with:
@@ -207,11 +201,10 @@ jobs:
name: ionic-vue
path: ./packages/vue
filename: VueBuild.zip
- uses: ./.github/workflows/actions/publish-npm
- uses: ./.github/actions/publish-npm
with:
scope: '@ionic/vue-router'
tag: ${{ inputs.tag }}
version: ${{ inputs.version }}
preid: ${{ inputs.preid }}
working-directory: 'packages/vue-router'
token: ${{ secrets.NPM_TOKEN }}

View File

@@ -0,0 +1,81 @@
name: 'Release - Ionic Framework'
on:
schedule:
# Run every Monday-Friday
# at 6:00 UTC (6:00 am UTC)
- cron: '00 06 * * 1-5'
workflow_dispatch:
inputs:
release-type:
description: 'Which Ionic release workflow should run?'
required: true
type: choice
default: dev
options:
- dev
- production
version:
description: 'Which version should be published? (Only for production releases)'
required: false
type: choice
options:
- patch
- minor
- major
- prepatch
- preminor
- premajor
- prerelease
tag:
description: 'Which npm tag should this be published to? (Only for production releases)'
required: false
type: choice
default: latest
options:
- latest
- next
preid:
description: 'Which prerelease identifier should be used? (Only for production releases)'
required: false
type: choice
default: ''
options:
- ''
- alpha
- beta
- rc
- next
permissions:
contents: read
id-token: write
jobs:
run-nightly:
if: ${{ github.event_name == 'schedule' }}
permissions:
contents: read
id-token: write
uses: ./.github/workflows/nightly.yml
secrets: inherit
run-dev:
if: ${{ github.event_name == 'workflow_dispatch' && inputs.release-type == 'dev' }}
permissions:
contents: read
id-token: write
uses: ./.github/workflows/dev-build.yml
secrets: inherit
run-production:
if: ${{ github.event_name == 'workflow_dispatch' && inputs.release-type == 'production' }}
permissions:
contents: write
id-token: write
uses: ./.github/workflows/release.yml
secrets: inherit
with:
version: ${{ inputs.version }}
tag: ${{ inputs.tag }}
preid: ${{ inputs.preid }}

View File

@@ -1,54 +1,64 @@
name: 'Ionic Production Release'
on:
workflow_dispatch:
workflow_call:
inputs:
version:
description: 'Which version should be published?'
required: true
type: choice
description: Which version should be published?
options:
- patch
- minor
- major
- prepatch
- preminor
- premajor
- prerelease
type: string
tag:
description: 'Which npm tag should this be published to?'
required: true
type: choice
description: Which npm tag should this be published to?
options:
- latest
- next
type: string
preid:
type: choice
description: Which prerelease identifier should be used? This is only needed when version is "prepatch", "preminor", "premajor", or "prerelease".
options:
- ''
- alpha
- beta
- rc
- next
description: 'Which prerelease identifier should be used? This is only needed when version is "prepatch", "preminor", "premajor", or "prerelease".'
required: false
type: string
permissions:
contents: read
id-token: write
jobs:
validate_version:
name: ✅ Validate Version Input
runs-on: ubuntu-latest
steps:
- name: 🔎 Ensure version is allowed
env:
VERSION: ${{ inputs.version }}
run: |
case "$VERSION" in
patch|minor|major|prepatch|preminor|premajor|prerelease)
exit 0
;;
*)
echo "::error::Invalid version input: '$VERSION'. Allowed values: patch, minor, major, prepatch, preminor, premajor, prerelease."
exit 1
;;
esac
shell: bash
release-ionic:
needs: [validate_version]
permissions:
contents: read
id-token: write
uses: ./.github/workflows/release-ionic.yml
with:
tag: ${{ inputs.tag }}
version: ${{ inputs.version }}
preid: ${{ inputs.preid }}
secrets:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
finalize-release:
needs: [release-ionic]
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
token: ${{ secrets.IONITRON_TOKEN }}
fetch-depth: 0
@@ -75,8 +85,11 @@ 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@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
# 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@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- 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@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- 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@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/workflows/actions/test-core-lint
test-core-spec:
needs: [build-core-with-stencil-nightly]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- 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@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- 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@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/workflows/actions/build-vue
build-vue-router:
needs: [build-vue]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- 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@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- 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@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/workflows/actions/build-angular
build-angular-server:
needs: [build-core-with-stencil-nightly]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- 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@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- 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@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/workflows/actions/build-react
build-react-router:
needs: [build-react]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- 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@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- 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@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/workflows/actions/test-react-e2e
with:
app: ${{ matrix.apps }}
@@ -225,3 +225,35 @@ jobs:
- name: Check build matrix status
if: ${{ needs.test-react-e2e.result != 'success' }}
run: exit 1
send-success-messages:
needs: [test-core-clean-build, test-core-lint, test-core-spec, verify-screenshots, verify-test-vue-e2e, verify-test-angular-e2e, verify-test-react-router-e2e, verify-test-react-e2e]
runs-on: ubuntu-latest
if: ${{ !cancelled() && !contains(needs.*.result, 'failure') }}
steps:
- name: Notify success on Discord
run: |
curl -H "Content-Type:application/json" \
-d '{"embeds": [{"title": "✅ Workflow ${{github.workflow}} #${{github.run_number}} finished successfully", "color": 65280, "url": "${{github.server_url}}/${{github.repository}}/actions/runs/${{github.run_id}}"}]}' \
${{secrets.DISCORD_NOTIFY_WEBHOOK}}
- name: Notify success on Slack
run: |
curl -H "Content-Type:application/json" \
-d '{"title": "✅ Workflow ${{github.workflow}} #${{github.run_number}} finished successfully", "url": "${{github.server_url}}/${{github.repository}}/actions/runs/${{github.run_id}}"}' \
${{secrets.SLACK_NOTIFY_SUCCESS_WEBHOOK}}
send-failure-messages:
needs: [test-core-clean-build, test-core-lint, test-core-spec, verify-screenshots, verify-test-vue-e2e, verify-test-angular-e2e, verify-test-react-router-e2e, verify-test-react-e2e]
runs-on: ubuntu-latest
if: ${{ !cancelled() && contains(needs.*.result, 'failure') }}
steps:
- name: Notify failure on Discord
run: |
curl -H "Content-Type:application/json" \
-d '{"content": "Alerting <@&1347593178580254761>!", "embeds": [{"title": "❌ Workflow ${{github.workflow}} #${{github.run_number}} failed", "color": 16711680, "url": "${{github.server_url}}/${{github.repository}}/actions/runs/${{github.run_id}}"}]}' \
${{secrets.DISCORD_NOTIFY_WEBHOOK}}
- name: Notify failure on Slack
run: |
curl -H "Content-Type:application/json" \
-d '{"title": "❌ Workflow ${{github.workflow}} #${{github.run_number}} failed", "url": "${{github.server_url}}/${{github.repository}}/actions/runs/${{github.run_id}}"}' \
${{secrets.SLACK_NOTIFY_FAILURE_WEBHOOK}}

View File

@@ -26,7 +26,7 @@ jobs:
build-core:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- 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@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- 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@v5
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
# Normally, we could just push with the
# default GITHUB_TOKEN, but that will
# not cause the build workflow

1
.gitignore vendored
View File

@@ -23,6 +23,7 @@ temp/
core/theme-builder/
core/test-components/
core/css/
core/themes/
$RECYCLE.BIN/
.DS_Store

View File

@@ -38,6 +38,12 @@ 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,6 +3,96 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [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)
### Bug Fixes
* **datetime:** ensure datetime is shown when intersection observer fails to report visibility ([#30793](https://github.com/ionic-team/ionic-framework/issues/30793)) ([9d781db](https://github.com/ionic-team/ionic-framework/commit/9d781db662d213090d0b7198d0cdc5abb16fed1b)), closes [#30706](https://github.com/ionic-team/ionic-framework/issues/30706)
## [8.7.10](https://github.com/ionic-team/ionic-framework/compare/v8.7.9...v8.7.10) (2025-11-19)
### Bug Fixes
* **checkbox, toggle, radio-group:** improve screen reader announcement timing for validation errors ([#30714](https://github.com/ionic-team/ionic-framework/issues/30714)) ([92db364](https://github.com/ionic-team/ionic-framework/commit/92db36489cca944caf1593dbd518a1f025a171a2))
## [8.7.9](https://github.com/ionic-team/ionic-framework/compare/v8.7.8...v8.7.9) (2025-11-05)
### Bug Fixes
* **accordion-group:** skip initial animation ([#30729](https://github.com/ionic-team/ionic-framework/issues/30729)) ([58d5638](https://github.com/ionic-team/ionic-framework/commit/58d563805fca1db88caeeb40a8f710ac30416d93)), closes [#30613](https://github.com/ionic-team/ionic-framework/issues/30613)
## [8.7.8](https://github.com/ionic-team/ionic-framework/compare/v8.7.7...v8.7.8) (2025-10-29)
### Bug Fixes
* **checkbox, toggle:** fire ionFocus and ionBlur ([#30733](https://github.com/ionic-team/ionic-framework/issues/30733)) ([54a1c86](https://github.com/ionic-team/ionic-framework/commit/54a1c86d6a5d533b0c8c2d18edc62454a7c17bab))
## [8.7.7](https://github.com/ionic-team/ionic-framework/compare/v8.7.6...v8.7.7) (2025-10-15)
### Bug Fixes
* **header:** ensure one banner role in condensed header ([#30718](https://github.com/ionic-team/ionic-framework/issues/30718)) ([12084af](https://github.com/ionic-team/ionic-framework/commit/12084af163ed811b9c6bda3c7850fc0c53c60c7b))
* **header:** prevent flickering during iOS page transitions ([#30705](https://github.com/ionic-team/ionic-framework/issues/30705)) ([820fa28](https://github.com/ionic-team/ionic-framework/commit/820fa2854331722d22efd0e38a1936117477967a)), closes [#25326](https://github.com/ionic-team/ionic-framework/issues/25326)
* **select:** improve screen reader announcement timing for validation errors ([#30723](https://github.com/ionic-team/ionic-framework/issues/30723)) ([03303d7](https://github.com/ionic-team/ionic-framework/commit/03303d73f0bfe2380ced7931525fc52fd8576367))
## [8.7.6](https://github.com/ionic-team/ionic-framework/compare/v8.7.5...v8.7.6) (2025-10-08)
### Bug Fixes
* **tabs:** respect stencil lifecycle order for tab selection ([#30702](https://github.com/ionic-team/ionic-framework/issues/30702)) ([7bb9535](https://github.com/ionic-team/ionic-framework/commit/7bb9535f601d2469ce60687a9c03f8b1cfe4aba4)), closes [#30611](https://github.com/ionic-team/ionic-framework/issues/30611)
## [8.7.5](https://github.com/ionic-team/ionic-framework/compare/v8.7.4...v8.7.5) (2025-09-24)

View File

@@ -3,6 +3,96 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [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)
### Bug Fixes
* **datetime:** ensure datetime is shown when intersection observer fails to report visibility ([#30793](https://github.com/ionic-team/ionic-framework/issues/30793)) ([9d781db](https://github.com/ionic-team/ionic-framework/commit/9d781db662d213090d0b7198d0cdc5abb16fed1b)), closes [#30706](https://github.com/ionic-team/ionic-framework/issues/30706)
## [8.7.10](https://github.com/ionic-team/ionic-framework/compare/v8.7.9...v8.7.10) (2025-11-19)
### Bug Fixes
* **checkbox, toggle, radio-group:** improve screen reader announcement timing for validation errors ([#30714](https://github.com/ionic-team/ionic-framework/issues/30714)) ([92db364](https://github.com/ionic-team/ionic-framework/commit/92db36489cca944caf1593dbd518a1f025a171a2))
## [8.7.9](https://github.com/ionic-team/ionic-framework/compare/v8.7.8...v8.7.9) (2025-11-05)
### Bug Fixes
* **accordion-group:** skip initial animation ([#30729](https://github.com/ionic-team/ionic-framework/issues/30729)) ([58d5638](https://github.com/ionic-team/ionic-framework/commit/58d563805fca1db88caeeb40a8f710ac30416d93)), closes [#30613](https://github.com/ionic-team/ionic-framework/issues/30613)
## [8.7.8](https://github.com/ionic-team/ionic-framework/compare/v8.7.7...v8.7.8) (2025-10-29)
### Bug Fixes
* **checkbox, toggle:** fire ionFocus and ionBlur ([#30733](https://github.com/ionic-team/ionic-framework/issues/30733)) ([54a1c86](https://github.com/ionic-team/ionic-framework/commit/54a1c86d6a5d533b0c8c2d18edc62454a7c17bab))
## [8.7.7](https://github.com/ionic-team/ionic-framework/compare/v8.7.6...v8.7.7) (2025-10-15)
### Bug Fixes
* **header:** ensure one banner role in condensed header ([#30718](https://github.com/ionic-team/ionic-framework/issues/30718)) ([12084af](https://github.com/ionic-team/ionic-framework/commit/12084af163ed811b9c6bda3c7850fc0c53c60c7b))
* **header:** prevent flickering during iOS page transitions ([#30705](https://github.com/ionic-team/ionic-framework/issues/30705)) ([820fa28](https://github.com/ionic-team/ionic-framework/commit/820fa2854331722d22efd0e38a1936117477967a)), closes [#25326](https://github.com/ionic-team/ionic-framework/issues/25326)
* **select:** improve screen reader announcement timing for validation errors ([#30723](https://github.com/ionic-team/ionic-framework/issues/30723)) ([03303d7](https://github.com/ionic-team/ionic-framework/commit/03303d73f0bfe2380ced7931525fc52fd8576367))
## [8.7.6](https://github.com/ionic-team/ionic-framework/compare/v8.7.5...v8.7.6) (2025-10-08)
### Bug Fixes
* **tabs:** respect stencil lifecycle order for tab selection ([#30702](https://github.com/ionic-team/ionic-framework/issues/30702)) ([7bb9535](https://github.com/ionic-team/ionic-framework/commit/7bb9535f601d2469ce60687a9c03f8b1cfe4aba4)), closes [#30611](https://github.com/ionic-team/ionic-framework/issues/30611)
## [8.7.5](https://github.com/ionic-team/ionic-framework/compare/v8.7.4...v8.7.5) (2025-09-24)

View File

@@ -1,5 +1,5 @@
# Get Playwright
FROM mcr.microsoft.com/playwright:v1.55.1
FROM mcr.microsoft.com/playwright:v1.56.1
# Set the working directory
WORKDIR /ionic

View File

@@ -596,23 +596,17 @@ ion-checkbox,part,supporting-text
ion-chip,shadow
ion-chip,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
ion-chip,prop,disabled,boolean,false,false,false
ion-chip,prop,hue,"bold" | "subtle" | undefined,'subtle',false,false
ion-chip,prop,fill,"outline" | "solid" | undefined,undefined,false,false
ion-chip,prop,hue,"bold" | "subtle" | undefined,undefined,false,false
ion-chip,prop,mode,"ios" | "md",undefined,false,false
ion-chip,prop,outline,boolean,false,false,false
ion-chip,prop,shape,"rectangular" | "round" | "soft" | undefined,undefined,false,false
ion-chip,prop,size,"large" | "small" | undefined,undefined,false,false
ion-chip,prop,theme,"ios" | "md" | "ionic",undefined,false,false
ion-chip,css-prop,--background,ionic
ion-chip,css-prop,--background,ios
ion-chip,css-prop,--background,md
ion-chip,css-prop,--border-radius,ionic
ion-chip,css-prop,--border-radius,ios
ion-chip,css-prop,--border-radius,md
ion-chip,css-prop,--color,ionic
ion-chip,css-prop,--color,ios
ion-chip,css-prop,--color,md
ion-chip,css-prop,--focus-ring-color,ionic
ion-chip,css-prop,--focus-ring-width,ionic
ion-chip,css-prop,--border-radius
ion-chip,css-prop,--color
ion-chip,css-prop,--focus-ring-color
ion-chip,css-prop,--focus-ring-style
ion-chip,css-prop,--focus-ring-width
ion-col,shadow
ion-col,prop,mode,"ios" | "md",undefined,false,false
@@ -1845,7 +1839,7 @@ ion-radio,part,container
ion-radio,part,label
ion-radio,part,mark
ion-radio-group,none
ion-radio-group,shadow
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,6 +1849,9 @@ 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

3598
core/package-lock.json generated
View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,10 @@
{
"name": "@ionic/core",
"version": "8.7.5",
"version": "8.7.13",
"description": "Base components for Ionic",
"engines": {
"node": ">= 16"
},
"keywords": [
"ionic",
"framework",
@@ -37,15 +40,15 @@
"tslib": "^2.1.0"
},
"devDependencies": {
"@axe-core/playwright": "^4.10.2",
"@capacitor/core": "^7.0.0",
"@capacitor/haptics": "^7.0.0",
"@capacitor/keyboard": "^7.0.0",
"@capacitor/status-bar": "^7.0.0",
"@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",
"@clack/prompts": "^0.11.0",
"@ionic/eslint-config": "^0.3.0",
"@ionic/prettier-config": "^2.0.0",
"@playwright/test": "^1.55.1",
"@playwright/test": "^1.56.1",
"@rollup/plugin-node-resolve": "^8.4.0",
"@rollup/plugin-virtual": "^2.0.3",
"@stencil/angular-output-target": "^0.10.0",
@@ -59,6 +62,7 @@
"chalk": "^5.3.0",
"clean-css-cli": "^5.6.1",
"domino": "^2.1.6",
"esbuild": "^0.27.0",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-custom-rules": "file:custom-rules",
@@ -66,21 +70,22 @@
"fs-extra": "^9.0.1",
"jest": "^29.7.0",
"jest-cli": "^29.7.0",
"outsystems-design-tokens": "^1.3.2",
"outsystems-design-tokens": "^1.3.4",
"playwright-core": "^1.56.1",
"prettier": "^2.8.8",
"rollup": "^2.26.4",
"sass": "^1.33.0",
"serve": "^14.0.1",
"style-dictionary": "^5.0.0",
"stylelint": "^13.13.1",
"stylelint-order": "^4.1.0"
},
"scripts": {
"build": "npm run clean && npm run build.css && stencil build --es5 --docs-json dist/docs.json",
"build": "npm run clean && npm run build.css && npm run build.themes && stencil build --es5 --docs-json dist/docs.json",
"build.css": "npm run css.sass && npm run css.minify",
"build.debug": "npm run clean && stencil build --debug",
"build.docs.json": "stencil build --docs-json dist/docs.json",
"build.tokens": "node ./node_modules/outsystems-design-tokens/scripts/index.js --config ./scripts/tokens/index.mjs && npm run prettier.tokens",
"build.tokens": "npx build.tokens --dest src/foundations/ --root=false --scss=true --scss-file=ionic.vars.scss --scss-prefix=ion --utilities=false && npm run prettier.tokens",
"build.themes": "esbuild src/themes/*/*.tokens.ts --bundle --format=esm --platform=browser --target=es2017 --outdir=themes --outbase=src/themes && esbuild src/utils/theme.ts --bundle --format=esm --platform=browser --target=es2017 --outfile=themes/utils/theme.js",
"clean": "node scripts/clean.js",
"css.minify": "cleancss -O2 -o ./css/ionic.bundle.css ./css/ionic.bundle.css",
"css.sass": "sass --embed-sources --style compressed src/css:./css",
@@ -94,7 +99,7 @@
"prerender.e2e": "node scripts/testing/prerender.js",
"prettier": "prettier \"./src/**/*.{html,ts,tsx,js,jsx,scss}\"",
"prettier.tokens": "prettier \"./src/foundations/*.{scss, html}\" --write --cache",
"start": "npm run build.css && stencil build --dev --watch --serve",
"start": "npm run build.css && npm run build.themes && stencil build --dev --watch --serve",
"test": "npm run test.spec && npm run test.e2e",
"test.spec": "stencil test --spec --max-workers=2",
"test.e2e": "npx playwright test",

View File

@@ -4,7 +4,8 @@ const path = require('path');
const cleanDirs = [
'dist',
'css'
'css',
'themes'
];
cleanDirs.forEach(dir => {

View File

@@ -1,42 +1,67 @@
/**
* This script is loaded in testing environments to set up the
* document based on URL parameters.
*
* Test pages (e.g., `chip/test/basic/index.html`) are set to use
* URL query parameters.
*
* Playwright test environments (e.g., `chip/test/basic/chip.e2e.ts`)
* are set based on whether `setContent` or `goto` has been used:
* - `setContent` uses URL hash parameters. Tests will break if
* query parameters are used.
* - `goto` uses URL query parameters.
*
* 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 `ionic`, `ios`, or `md` to load a specific
* theme. Defaults to `md`.
* - `palette`: Set to `light`, `dark`, `high-contrast`, or
* `high-contrast-dark` to load a specific palette. Defaults to `light`.
*/
const DEFAULT_THEME = 'md';
const DEFAULT_PALETTE = 'light';
(function() {
/**
* The `rtl` param is used to set the directionality of the
* document. This can be `true` or `false`.
*/
const isRTL = window.location.search.indexOf('rtl=true') > -1 || window.location.hash.indexOf('rtl=true') > -1;
if (window.location.search.indexOf('rtl=true') > -1) {
if (isRTL) {
document.documentElement.setAttribute('dir', 'rtl');
}
if (window.location.search.indexOf('ionic:_testing=true') > -1) {
/**
* The `ionic:_testing` param is used to identify testing
* environments.
*/
const isTestEnv = window.location.search.indexOf('ionic:_testing=true') > -1 || window.location.hash.indexOf('ionic:_testing=true') > -1;
if (isTestEnv) {
const style = document.createElement('style');
style.innerHTML = `
* {
caret-color: transparent !important;
}`;
* {
caret-color: transparent !important;
}
`;
document.head.appendChild(style);
}
/**
* The term `palette` is used to as a param to match the
* Ionic docs, plus here is already a `ionic:theme` query being
* used for `md`, `ios`, and `ionic` themes.
* The `theme` param is used to load a specific theme.
* This can be `ionic`, `ios`, or `md`. Default to `md` for tests.
*/
const palette = window.location.search.match(/palette=([a-z]+)/);
if (palette && palette[1] !== 'light') {
const linkTag = document.createElement('link');
linkTag.setAttribute('rel', 'stylesheet');
linkTag.setAttribute('type', 'text/css');
linkTag.setAttribute('href', `/css/palettes/${palette[1]}.always.css`);
document.head.appendChild(linkTag);
}
/**
* The `ionic` theme uses a different stylesheet than the `iOS` and `md` themes.
* This is to ensure that the `ionic` theme is loaded when the `ionic:theme=ionic`
* or when the HTML tag has the `theme="ionic"` attribute. This is useful for
* the snapshot tests, where the `ionic` theme is not loaded by default.
*/
const themeQuery = window.location.search.match(/ionic:theme=([a-z]+)/);
const themeQuery = window.location.search.match(/ionic:theme=([a-z0-9]+)/i);
const themeHash = window.location.hash.match(/ionic:theme=([a-z0-9]+)/i);
const themeAttr = document.documentElement.getAttribute('theme');
const themeName = themeQuery?.[1] || themeHash?.[1] || themeAttr || DEFAULT_THEME;
// TODO(): Remove this when the tokens are working for all components
// and the themes all use the same bundle
if ((themeQuery && themeQuery[1] === 'ionic') || themeAttr === 'ionic') {
const ionicThemeLinkTag = document.querySelector('link[href*="css/ionic/bundle.ionic.css"]');
@@ -54,6 +79,130 @@
}
}
/**
* The `palette` param is used to load a specific palette
* for the theme.
* The dark class will load the dark palette automatically
* if no palette is specified through the URL.
*
* 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 configDarkMode = window.Ionic?.config?.customTheme?.palette?.dark?.enabled === 'always' ? 'dark' : null;
const configHighContrastMode = window.Ionic?.config?.customTheme?.palette?.highContrast?.enabled === 'always' ? 'high-contrast' : null;
const configHighContrastDarkMode = window.Ionic?.config?.customTheme?.palette?.highContrastDark?.enabled === 'always' ? 'high-contrast-dark' : null;
/**
* Ensure window.Ionic.config is defined before importing 'testing/scripts'
* in the test HTML to properly initialize the palette configuration below.
*
* Example:
* <script>
* window.Ionic = { config: { customTheme: { palette: { ... } } } };
* </script>
* <script src="testing/scripts.js"></script>
*/
const configPalette = configDarkMode || configHighContrastMode || configHighContrastDarkMode;
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;
const paletteClass = highContrastDarkClass || highContrastClass || darkClass;
let paletteName = configPalette || paletteQuery?.[1] || paletteHash?.[1] || paletteClass || DEFAULT_PALETTE;
if (!validPalettes.includes(paletteName)) {
console.warn(`Invalid palette name: '${paletteName}'. Falling back to 'light' palette.`);
paletteName = DEFAULT_PALETTE;
}
// Load theme tokens if the theme is valid
const validThemes = ['ionic', 'ios', 'md'];
if (themeName && validThemes.includes(themeName)) {
loadThemeTokens(themeName, paletteName);
} else if(themeName) {
console.warn(
`Unsupported theme "${themeName}". Supported themes are: ${validThemes.join(', ')}. Defaulting to ${DEFAULT_THEME}.`
);
}
async function loadThemeTokens(themeName, paletteName) {
try {
// Store existing theme set from the app initialization
const customTheme = window.Ionic?.config?.customTheme;
// Load the default tokens for the theme
const defaultTokens = await import(`/themes/${themeName}/default.tokens.js`);
let theme = defaultTokens.defaultTheme;
// Merge with existing theme to preserve any customizations
if (customTheme) {
theme = {
...theme,
...customTheme,
palette: {
...theme.palette,
...customTheme.palette,
},
};
}
// If a specific palette is requested, modify the palette structure
// to set the enabled property to 'always'
// TODO(FW-4004): Implement dark palette
if (paletteName === 'dark' && theme.palette?.dark) {
theme.palette.dark.enabled = 'always';
// TODO(FW-4005): Implement high contrast palette
} else if (paletteName === 'high-contrast' && theme.palette?.highContrast) {
theme.palette.highContrast.enabled = 'always';
// TODO(FW-4005): Implement high contrast dark palette
} else if (paletteName === 'high-contrast-dark' && theme.palette?.highContrastDark) {
theme.palette.highContrastDark.enabled = 'always';
}
if (window.Ionic?.config?.set) {
/**
* New Page Load after Initial App Load or Playwright Test:
*
* If the Config instance exists, we must use the
* `set()` method. This ensures the internal private Map inside
* the `Config` class is updated with the loaded theme tokens.
* Without this, components would read 'undefined' or 'base'
* values from the stale Map when trying to access them through
* methods like `config.get()`.
*/
window.Ionic.config.set('customTheme', theme);
} else {
/**
* App Initialization or Browser Refresh:
*
* If the Config instance doesn't exist yet,
* we attach the theme to the global Ionic object. The `initialize()`
* method in `ionic-global.ts` will later merge this into the new
* `Config` instance via `config.reset()`.
*/
window.Ionic = window.Ionic || {};
window.Ionic.config = window.Ionic.config || {};
window.Ionic.config.customTheme = theme;
}
/**
* Re-applying the global theme is critical for Playwright tests.
* Even if the config is set, the CSS variables for the specific theme
* (e.g., md or ios) must be force-injected into the document head to
* ensure visual assertions pass correctly.
*/
if (window.Ionic?.config?.get && window.Ionic?.config?.set) {
const themeModule = await import('/themes/utils/theme.js');
themeModule.applyGlobalTheme(theme);
themeModule.applyComponentsTheme(theme);
}
} catch (error) {
console.error(`Failed to load theme tokens for ${themeName}:`, error);
}
}
window.Ionic = window.Ionic || {};
window.Ionic.config = window.Ionic.config || {};

View File

File diff suppressed because one or more lines are too long

View File

@@ -1,188 +0,0 @@
/* eslint-disable @typescript-eslint/no-var-requires */
// For generating Design Tokens, we use Style Dictionary for several reasons:
// - It's prepared to easily generate tokens for multiple types of outputs (CSS, SCSS, iOS, Android, documentation, etc.).
// - It also works very well out of the box with any kind of Design Tokens formats, like Figma Tokens, as well as APIs to adjust to more custom ones.
// - It is probably the most well-known and widely used Design Tokens tool. It has also been regularly maintained for a long time.
// - It can easily scale to different necessities we might have in the future.
import StyleDictionary from 'style-dictionary';
import * as utils from './utils.mjs';
const {
generateShadowValue,
generateFontSizeValue,
generateFontFamilyValue,
generateTypographyOutput,
generateValue,
generateColorUtilityClasses,
generateDefaultSpaceUtilityClasses,
generateSpaceUtilityClasses,
removeConsecutiveRepeatedWords,
setVariablePrefixValue,
setClassesAndScssPrefixValue: setClassesPrefixValue,
generateRadiusUtilityClasses,
generateBorderUtilityClasses,
generateFontUtilityClasses,
generateShadowUtilityClasses,
generateUtilityClasses
} = utils;
const customHeader = `// Do not edit directly, this file was auto-generated.`;
// Set the prefix for classes
setClassesPrefixValue('ion');
// Set the prefix for variables
setVariablePrefixValue('token');
// SCSS variables format
StyleDictionary.registerFormat({
name: 'scssVariablesFormat',
format: function ({ dictionary }) { // Use 'format' for Style Dictionary v3
console.log('Generating SCSS variables...');
const primitiveProperties = dictionary.allTokens.filter((prop) => prop.path[0] === 'primitives');
const scaleProperties = dictionary.allTokens.filter((prop) => prop.path[0] === 'scale');
const borderProperties = dictionary.allTokens.filter((prop) => prop.path[0] === 'border');
const semanticsProperties = dictionary.allTokens.filter((prop) => prop.path[0] === 'semantics');
const nonPrimitiveScaleBorderSemanticsProperties = dictionary.allTokens.filter(
(prop) => !['primitives', 'scale', 'border', 'semantics'].includes(prop.path[0])
);
const typographyProperties = nonPrimitiveScaleBorderSemanticsProperties.filter((prop) => prop.$type === 'typography');
const otherProperties = nonPrimitiveScaleBorderSemanticsProperties.filter((prop) => prop.$type !== 'typography');
// Order: primitives → semantics → scale → border → other → typography
const sortedProperties = [
...primitiveProperties,
...semanticsProperties,
...scaleProperties,
...borderProperties,
...otherProperties,
...typographyProperties
];
const prefixedVariables = sortedProperties.map((prop) => {
// Remove consecutive repeated words from the token name, like border-border-color
const propName = removeConsecutiveRepeatedWords(prop.name);
switch (prop.$type) {
case 'boxShadow':
return generateShadowValue(prop, propName);
case 'fontFamilies':
return generateFontFamilyValue(prop, propName, 'scss');
case 'fontSizes':
return generateFontSizeValue(prop, propName, 'scss');
case 'typography':
return generateTypographyOutput(prop, propName, true);
default:
return generateValue(prop, propName);
}
});
// In v3, the header is added automatically by Style Dictionary.
// The format function should only return the file content.
return [
customHeader + '\n\n',
'@use "../themes/functions.sizes" as font;\n',
prefixedVariables.join('\n') + '\n',
].join('');
},
});
// Create utility-classes
StyleDictionary.registerFormat({
name: 'cssUtilityClassesFormat',
format: function ({ dictionary }) { // Use 'format' for Style Dictionary v3
console.log('Generating Utility-Classes...');
// Arrays to store specific utility classes
const typographyUtilityClasses = [];
const otherUtilityClasses = [];
// Generate utility classes for each token
dictionary.allTokens.map((prop) => {
const tokenCategory = prop.attributes.category;
if (prop.$type === 'fontFamilies' || tokenCategory === 'scale' || tokenCategory === 'backdrop') {
// Not creating for the tokens below, as they make no sense to exist as utility-classes.
return;
}
// Remove consecutive repeated words from the token name, like border-border-color
const propName = removeConsecutiveRepeatedWords(prop.name);
if (prop.$type === 'typography') {
// Typography tokens are handled differently, as each might have a different tokenType
return typographyUtilityClasses.push(generateTypographyOutput(prop, propName, false));
} else if (tokenCategory.startsWith('round') || tokenCategory.startsWith('rectangular') || tokenCategory.startsWith('soft')) {
// Generate utility classes for border-radius shape tokens, as they have their own token json file, based on primitive tokens
return otherUtilityClasses.push(generateRadiusUtilityClasses(propName));
}
let utilityClass = '';
switch (tokenCategory) {
case 'color':
case 'primitives':
case 'semantics':
case 'text':
case 'bg':
case 'icon':
case 'state':
utilityClass = generateColorUtilityClasses(prop, propName);
break;
case 'border':
utilityClass = generateBorderUtilityClasses(prop, propName);
break;
case 'font':
utilityClass = generateFontUtilityClasses(prop, propName);
break;
case 'space':
utilityClass = generateSpaceUtilityClasses(prop, propName);
break;
case 'shadow':
case 'elevation':
utilityClass = generateShadowUtilityClasses(propName);
break;
default:
utilityClass = generateUtilityClasses(tokenCategory, propName);
}
return otherUtilityClasses.push(utilityClass);
});
const defaultSpaceUtilityClasses = generateDefaultSpaceUtilityClasses();
otherUtilityClasses.push(defaultSpaceUtilityClasses);
// Concatenate typography utility classes at the beginning
const finalOutput = typographyUtilityClasses.concat(otherUtilityClasses).join('\n');
// In v3, the header is added automatically by Style Dictionary.
// The format function should only return the file content.
return [
customHeader + '\n\n',
'@import "./ionic.vars";\n@import "../themes/mixins";\n',
finalOutput,
].join('');
},
});
// APPLY THE CONFIGURATION
const config = {
source: ["node_modules/outsystems-design-tokens/tokens/**/*.json"],
platforms: {
scss: {
transformGroup: "scss",
buildPath: './src/foundations/',
files: [
{
destination: "ionic.vars.scss",
format: "scssVariablesFormat",
},
{
destination: "ionic.utility.scss",
format: "cssUtilityClassesFormat",
}
]
}
}
};
export default config;

View File

@@ -1,320 +0,0 @@
let variablesPrefix; // Variable that holds the prefix used on all css variables generated
let classAndScssPrefix; // Variable that holds the prefix used on all css utility-classes and scss variables generated
// Set the variable prefix value
export function setVariablePrefixValue(prefix) {
variablesPrefix = prefix;
return variablesPrefix;
}
export function setClassesAndScssPrefixValue(prefix) {
classAndScssPrefix = prefix;
return classAndScssPrefix;
}
// Generates a valid rgba() color
export function getRgbaValue(propValue) {
// Check if its rgba color
const isRgba = hexToRgba(propValue);
// If it is, then compose rgba() color, otherwise use the normal color
if (isRgba !== null) {
return (propValue = `rgba(${isRgba.r}, ${isRgba.g}, ${isRgba.b},${isRgba.a})`);
} else {
return propValue;
}
}
// Translates an hex color value to rgb
export function hexToRgb(hex) {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result
? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16),
}
: null;
}
// Translates an hex color value to rgba
function hexToRgba(hex) {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result
? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16),
a: Math.round((parseInt(result[4], 16) * 100) / 255) / 100,
}
: null;
}
// Utility function to remove consecutive repeated words
export function removeConsecutiveRepeatedWords(str) {
return str.replace(/(\b\w+\b)(-\1)+/g, '$1');
}
// Generates a reference variable for an alias token type
// (e.g., $ion-border-default: var(--ion-border-default, #d5d5d5) → $ion-border-default: var(--ion-border-default, $ion-primitives-neutral-400))
export function getAliasReferenceVariable(prop) {
if (typeof prop.$value === 'string' && prop.$value.startsWith('{') && prop.$value.endsWith('}')) {
// Remove curly braces and replace dots with dashes
let ref = prop.$value.slice(1, -1).replace(/\./g, '-');
// Remove consecutive repeated words (e.g., border-border-radius-0 → border-radius-0)
ref = removeConsecutiveRepeatedWords(ref);
return `$${classAndScssPrefix}-${ref}`;
}
return null;
}
// Generates a valid box-shadow value from a shadow Design Token structure
export function generateShadowValue(prop, propName) {
const cssShadow = prop.$value.map(shadow => {
// Assuming shadow is an object with properties like offsetX, offsetY, blurRadius, spreadRadius, color
const color = getRgbaValue(shadow.color);
return `${shadow.x}px ${shadow.y}px ${shadow.blur}px ${shadow.spread}px ${color}`;
}).join(', ');
return `$${classAndScssPrefix}-${propName}: var(--${variablesPrefix}-${propName}, ${cssShadow});`;
}
// Generates a valid font-size value from a font-size Design Token structure, while transforming the pixels to rem
export function generateFontSizeValue(prop, propName, variableType = 'css') {
return variableType === 'scss'
? `$${classAndScssPrefix}-${propName}: var(--${variablesPrefix}-${propName}, font.px-to-rem(${parseInt(
prop.$value
)}));`
: `--${propName}: #{font.px-to-rem(${parseInt(prop.$value)})};`;
}
// Generates a valid font-family value from a font-family Design Token structure
export function generateFontFamilyValue(prop, propName, variableType = 'css') {
// Remove the last word from the token, as it contains the name of the font, which we don't want to be included on the generated variables
const _propName = propName.split('-').slice(0, -1).join('-');
return variableType === 'scss'
? `$${classAndScssPrefix}-${_propName}: var(--${variablesPrefix}-${_propName}, ${prop.$value});`
: `--${variablesPrefix}-${_propName}: ${prop.$value};`;
}
// Generates a final value, based if the Design Token is of type color or not
export function generateValue(prop, propName) {
// Use the original value to detect aliases
const aliasVar = getAliasReferenceVariable({ $value: prop.original.$value });
// Always generate the main variable
let mainValue;
if (aliasVar) {
mainValue = `$${classAndScssPrefix}-${propName}: var(--${variablesPrefix}-${propName}, ${aliasVar});`;
} else {
mainValue = `$${classAndScssPrefix}-${propName}: var(--${variablesPrefix}-${propName}, ${prop.$value});`;
}
// Always generate the -rgb variable if it's a color
const rgb = hexToRgb(prop.$value);
let rgbDeclaration = '';
if (rgb) {
rgbDeclaration = `\n$${classAndScssPrefix}-${propName}-rgb: var(--${variablesPrefix}-${propName}-rgb, ${rgb.r}, ${rgb.g}, ${rgb.b});`;
}
return `${mainValue}${rgbDeclaration}`;
}
// Generates a typography based css utility-class or scss variable from a typography token structure
export function generateTypographyOutput(prop, propName, isVariable) {
const typography = prop.original.$value;
// Extract the part after the last dot and trim any extraneous characters
const extractLastPart = (str) => str.split('.').pop().replace(/[^\w-]/g, '');
const _initialWrapper = isVariable ? ': (' : ` {`;
const _endWrapper = isVariable ? ')' : `}`;
const _prefix = isVariable ? '$' : `.`;
const _endChar = isVariable ? ',' : ';';
// This exact format is needed so that it compiles the tokens with the expected lint rules
return `
${_prefix}${classAndScssPrefix}-${propName}${_initialWrapper}
font-size: $${classAndScssPrefix}-font-size-${extractLastPart(typography.fontSize)}${_endChar}
font-style: ${prop.attributes.item?.toLowerCase() === 'italic' ? 'italic' : 'normal'}${_endChar}
font-weight: $${classAndScssPrefix}-font-weight-${extractLastPart(typography.fontWeight)}${_endChar}
letter-spacing: $${classAndScssPrefix}-font-letter-spacing-${extractLastPart(typography.letterSpacing) || 0}${_endChar}
line-height: $${classAndScssPrefix}-font-line-height-${extractLastPart(typography.lineHeight)}${_endChar}
text-transform: ${typography.textCase}${_endChar}
text-decoration: ${typography.textDecoration}${_endChar}
${_endWrapper};
`;
}
// Generates a color based css utility-class from a color Design Token structure
export function generateColorUtilityClasses(prop, className) {
const isBg = className.includes('bg');
const cssProp = isBg ? 'background-color' : 'color';
return `.${classAndScssPrefix}-${className} {
--${cssProp}: #{$${classAndScssPrefix}-${prop.name}};
${cssProp}: $${classAndScssPrefix}-${prop.name};
}`;
}
// Generates margin and padding utility classes to match the token-agnostic
// utilities provided by the Ionic Framework
export function generateDefaultSpaceUtilityClasses() {
const zeroMarginPaddingToken = 'space-0';
const defaultMarginPaddingToken = 'space-400';
const marginPaddingTemplate = (type) => `
.${classAndScssPrefix}-no-${type} {
--${type}-top: #{$${classAndScssPrefix}-${zeroMarginPaddingToken}};
--${type}-end: #{$${classAndScssPrefix}-${zeroMarginPaddingToken}};
--${type}-bottom: #{$${classAndScssPrefix}-${zeroMarginPaddingToken}};
--${type}-start: #{$${classAndScssPrefix}-${zeroMarginPaddingToken}};
@include ${type}($${classAndScssPrefix}-${zeroMarginPaddingToken});
};
.${classAndScssPrefix}-${type} {
--${type}-top: #{$${classAndScssPrefix}-${defaultMarginPaddingToken}};
--${type}-end: #{$${classAndScssPrefix}-${defaultMarginPaddingToken}};
--${type}-bottom: #{$${classAndScssPrefix}-${defaultMarginPaddingToken}};
--${type}-start: #{$${classAndScssPrefix}-${defaultMarginPaddingToken}};
@include ${type}($${classAndScssPrefix}-${defaultMarginPaddingToken});
};
.${classAndScssPrefix}-${type}-top {
--${type}-top: #{$${classAndScssPrefix}-${defaultMarginPaddingToken}};
@include ${type}($${classAndScssPrefix}-${defaultMarginPaddingToken}, null, null, null);
};
.${classAndScssPrefix}-${type}-end {
--${type}-end: #{$${classAndScssPrefix}-${defaultMarginPaddingToken}};
@include ${type}(null, $${classAndScssPrefix}-${defaultMarginPaddingToken}, null, null);
};
.${classAndScssPrefix}-${type}-bottom {
--${type}-bottom: #{$${classAndScssPrefix}-${defaultMarginPaddingToken}};
@include ${type}(null, null, $${classAndScssPrefix}-${defaultMarginPaddingToken}, null);
};
.${classAndScssPrefix}-${type}-start {
--${type}-start: #{$${classAndScssPrefix}-${defaultMarginPaddingToken}};
@include ${type}(null, null, null, $${classAndScssPrefix}-${defaultMarginPaddingToken});
};
.${classAndScssPrefix}-${type}-vertical {
--${type}-top: #{$${classAndScssPrefix}-${defaultMarginPaddingToken}};
--${type}-bottom: #{$${classAndScssPrefix}-${defaultMarginPaddingToken}};
@include ${type}($${classAndScssPrefix}-${defaultMarginPaddingToken}, null, $${classAndScssPrefix}-${defaultMarginPaddingToken}, null);
};
.${classAndScssPrefix}-${type}-horizontal {
--${type}-start: #{$${classAndScssPrefix}-${defaultMarginPaddingToken}};
--${type}-end: #{$${classAndScssPrefix}-${defaultMarginPaddingToken}};
@include ${type}(null, $${classAndScssPrefix}-${defaultMarginPaddingToken}, null, $${classAndScssPrefix}-${defaultMarginPaddingToken});
};
`;
return `${marginPaddingTemplate('margin')}\n${marginPaddingTemplate('padding')}`;
}
// Generates a margin or padding based css utility-class from a space Design Token structure
export function generateSpaceUtilityClasses(prop, className) {
// This exact format is needed so that it compiles the tokens with the expected lint rules
// It will generate classes for margin and padding, for equal sizing on all side and each direction
const marginPaddingTemplate = (type) => `
.${classAndScssPrefix}-${type}-${className} {
--${type}-top: #{$${classAndScssPrefix}-${prop.name}};
--${type}-end: #{$${classAndScssPrefix}-${prop.name}};
--${type}-bottom: #{$${classAndScssPrefix}-${prop.name}};
--${type}-start: #{$${classAndScssPrefix}-${prop.name}};
@include ${type}($${classAndScssPrefix}-${prop.name});
};
.${classAndScssPrefix}-${type}-top-${className} {
--${type}-top: #{$${classAndScssPrefix}-${prop.name}};
@include ${type}($${classAndScssPrefix}-${prop.name}, null, null, null);
};
.${classAndScssPrefix}-${type}-end-${className} {
--${type}-end: #{$${classAndScssPrefix}-${prop.name}};
@include ${type}(null, $${classAndScssPrefix}-${prop.name}, null, null);
};
.${classAndScssPrefix}-${type}-bottom-${className} {
--${type}-bottom: #{$${classAndScssPrefix}-${prop.name}};
@include ${type}(null, null, $${classAndScssPrefix}-${prop.name}, null);
};
.${classAndScssPrefix}-${type}-start-${className} {
--${type}-start: #{$${classAndScssPrefix}-${prop.name}};
@include ${type}(null, null, null, $${classAndScssPrefix}-${prop.name});
};
`;
// Add gap utility classes for gap tokens
const generateGapUtilityClasses = () =>`
.${classAndScssPrefix}-gap-${prop.name} {
gap: #{$${classAndScssPrefix}-${prop.name}};
};
`;
return `${generateGapUtilityClasses()}\n${marginPaddingTemplate('margin')}\n${marginPaddingTemplate('padding')}`;
}
// Generates a valid box-shadow value from a shadow Design Token structure
export function generateRadiusUtilityClasses(propName) {
return `.${classAndScssPrefix}-${propName} {
--border-radius: #{$${classAndScssPrefix}-${propName}};
border-radius: $${classAndScssPrefix}-${propName};
}`;
}
// Generates a border based css utility-class from a font Design Token structure
export function generateBorderUtilityClasses(prop, propName) {
let attribute;
switch (prop.attributes.type) {
case 'border-radius':
case 'border-style':
attribute = prop.attributes.type;
break;
case 'border-size':
attribute = 'border-width';
break;
default:
attribute = 'border-color';
}
return `.${classAndScssPrefix}-${propName} {
--${attribute}: #{$${classAndScssPrefix}-${propName}};
${attribute}: $${classAndScssPrefix}-${propName};
}`;
}
// Generates a font based css utility-class from a font Design Token structure
export function generateFontUtilityClasses(prop, propName) {
return `.${classAndScssPrefix}-${propName} {\n ${prop.attributes.type}: $${classAndScssPrefix}-${propName};\n}`;
}
// Generates a valid box-shadow value from a shadow Design Token structure
export function generateShadowUtilityClasses(propName) {
return `.${classAndScssPrefix}-${propName} {
--box-shadow: #{$${classAndScssPrefix}-${propName}};
box-shadow: $${classAndScssPrefix}-${propName};
}`;
}
// Generates a utility class for a given token category and name
export function generateUtilityClasses(tokenCategory, propName){
return `.${classAndScssPrefix}-${propName} {\n ${tokenCategory}: $${classAndScssPrefix}-${propName};\n}`;
}

View File

@@ -872,8 +872,11 @@ export namespace Components {
*/
"disabled": boolean;
/**
* Set to `"bold"` for a chip with vibrant, bold colors or to `"subtle"` for a chip with muted, subtle colors. Only applies to the `ionic` theme.
* @default 'subtle'
* The fill for the chip. Set to `"outline"` for a chip with a border and background. Set to `"solid"` for a chip with a background. Defaults to `"solid"`.
*/
"fill"?: 'outline' | 'solid';
/**
* Set to `"bold"` for a chip with vibrant, bold colors or to `"subtle"` for a chip with muted, subtle colors. Defaults to `"subtle"`.
*/
"hue"?: 'bold' | 'subtle';
/**
@@ -882,21 +885,18 @@ export namespace Components {
"mode"?: "ios" | "md";
/**
* Display an outline style button.
* @deprecated - Use fill="outline" instead
* @default false
*/
"outline": boolean;
/**
* Set to `"soft"` for a chip with slightly rounded corners, `"round"` for a chip with fully rounded corners, or `"rectangular"` for a chip without rounded corners. Defaults to `"round"` for the `"ionic"` theme and `"soft"` for all other themes.
* Set to `"soft"` for a chip with slightly rounded corners, `"round"` for a chip with fully rounded corners, or `"rectangular"` for a chip without rounded corners. Defaults to `"round"`.
*/
"shape"?: 'soft' | 'round' | 'rectangular';
/**
* Set to `"small"` for a chip with less height and padding. Defaults to `"large"` for the ionic theme, and undefined for all other themes.
* Set to `"small"` for a chip with less height and padding. Defaults to `"large"`.
*/
"size"?: 'small' | 'large';
/**
* The theme determines the visual appearance of the component.
*/
"theme"?: "ios" | "md" | "ionic";
}
interface IonCol {
/**
@@ -1071,6 +1071,10 @@ 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.
@@ -6842,8 +6846,11 @@ declare namespace LocalJSX {
*/
"disabled"?: boolean;
/**
* Set to `"bold"` for a chip with vibrant, bold colors or to `"subtle"` for a chip with muted, subtle colors. Only applies to the `ionic` theme.
* @default 'subtle'
* The fill for the chip. Set to `"outline"` for a chip with a border and background. Set to `"solid"` for a chip with a background. Defaults to `"solid"`.
*/
"fill"?: 'outline' | 'solid';
/**
* Set to `"bold"` for a chip with vibrant, bold colors or to `"subtle"` for a chip with muted, subtle colors. Defaults to `"subtle"`.
*/
"hue"?: 'bold' | 'subtle';
/**
@@ -6852,21 +6859,18 @@ declare namespace LocalJSX {
"mode"?: "ios" | "md";
/**
* Display an outline style button.
* @deprecated - Use fill="outline" instead
* @default false
*/
"outline"?: boolean;
/**
* Set to `"soft"` for a chip with slightly rounded corners, `"round"` for a chip with fully rounded corners, or `"rectangular"` for a chip without rounded corners. Defaults to `"round"` for the `"ionic"` theme and `"soft"` for all other themes.
* Set to `"soft"` for a chip with slightly rounded corners, `"round"` for a chip with fully rounded corners, or `"rectangular"` for a chip without rounded corners. Defaults to `"round"`.
*/
"shape"?: 'soft' | 'round' | 'rectangular';
/**
* Set to `"small"` for a chip with less height and padding. Defaults to `"large"` for the ionic theme, and undefined for all other themes.
* Set to `"small"` for a chip with less height and padding. Defaults to `"large"`.
*/
"size"?: 'small' | 'large';
/**
* The theme determines the visual appearance of the component.
*/
"theme"?: "ios" | "md" | "ionic";
}
interface IonCol {
/**

View File

@@ -9,8 +9,8 @@ configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screens
`
<style>
/* Background styles to show the border radius */
:root {
--background: #ccc7c7;
.ionic {
--ion-background-color: #ccc7c7;
}
</style>
<ion-accordion-group>
@@ -47,8 +47,8 @@ configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screens
`
<style>
/* Background styles to show the border radius */
:root {
--background: #ccc7c7;
.ionic {
--ion-background-color: #ccc7c7;
}
</style>
<ion-accordion-group value="first">
@@ -87,8 +87,8 @@ configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screens
`
<style>
/* Background styles to show the border radius */
:root {
--background: #ccc7c7;
.ionic {
--ion-background-color: #ccc7c7;
}
</style>
<ion-accordion-group expand="inset">
@@ -125,8 +125,8 @@ configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screens
`
<style>
/* Background styles to show the border radius */
:root {
--background: #ccc7c7;
.ionic {
--ion-background-color: #ccc7c7;
}
</style>
<ion-accordion-group value="first" expand="inset">

View File

@@ -9,8 +9,8 @@ configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screens
`
<style>
/* Background styles to show the border radius */
:root {
--background: #222;
.ionic {
--ion-background-color: #222;
}
</style>

View File

@@ -42,7 +42,40 @@ const enum AccordionState {
})
export class Accordion implements ComponentInterface {
private accordionGroupEl?: HTMLIonAccordionGroupElement | null;
private updateListener = () => this.updateState(false);
private accordionGroupUpdateHandler = () => {
/**
* Determine if this update will cause an actual state change.
* We only want to mark as "interacted" if the state is changing.
*/
const accordionGroup = this.accordionGroupEl;
if (accordionGroup) {
const value = accordionGroup.value;
const accordionValue = this.value;
const shouldExpand = Array.isArray(value) ? value.includes(accordionValue) : value === accordionValue;
const isExpanded = this.state === AccordionState.Expanded || this.state === AccordionState.Expanding;
const stateWillChange = shouldExpand !== isExpanded;
/**
* Only mark as interacted if:
* 1. This is not the first update we've received with a defined value
* 2. The state is actually changing (prevents redundant updates from enabling animations)
*/
if (this.hasReceivedFirstUpdate && stateWillChange) {
this.hasInteracted = true;
}
/**
* Only count this as the first update if the group value is defined.
* This prevents the initial undefined value from the group's componentDidLoad
* from being treated as the first real update.
*/
if (value !== undefined) {
this.hasReceivedFirstUpdate = true;
}
}
this.updateState();
};
private contentEl: HTMLDivElement | undefined;
private contentElWrapper: HTMLDivElement | undefined;
private headerEl: HTMLDivElement | undefined;
@@ -54,6 +87,25 @@ export class Accordion implements ComponentInterface {
@State() state: AccordionState = AccordionState.Collapsed;
@State() isNext = false;
@State() isPrevious = false;
/**
* Tracks whether a user-initiated interaction has occurred.
* Animations are disabled until the first interaction happens.
* This prevents the accordion from animating when it's programmatically
* set to an expanded or collapsed state on initial load.
*/
@State() hasInteracted = false;
/**
* Tracks if this accordion has ever been expanded.
* Used to prevent the first expansion from animating.
*/
private hasEverBeenExpanded = false;
/**
* Tracks if this accordion has received its first update from the group.
* Used to distinguish initial programmatic sets from user interactions.
*/
private hasReceivedFirstUpdate = false;
/**
* The value of the accordion. Defaults to an autogenerated
@@ -92,15 +144,15 @@ export class Accordion implements ComponentInterface {
connectedCallback() {
const accordionGroupEl = (this.accordionGroupEl = this.el?.closest('ion-accordion-group'));
if (accordionGroupEl) {
this.updateState(true);
addEventListener(accordionGroupEl, 'ionValueChange', this.updateListener);
this.updateState();
addEventListener(accordionGroupEl, 'ionValueChange', this.accordionGroupUpdateHandler);
}
}
disconnectedCallback() {
const accordionGroupEl = this.accordionGroupEl;
if (accordionGroupEl) {
removeEventListener(accordionGroupEl, 'ionValueChange', this.updateListener);
removeEventListener(accordionGroupEl, 'ionValueChange', this.accordionGroupUpdateHandler);
}
}
@@ -237,10 +289,16 @@ export class Accordion implements ComponentInterface {
ionItem.appendChild(iconEl);
};
private expandAccordion = (initialUpdate = false) => {
private expandAccordion = () => {
const { contentEl, contentElWrapper } = this;
if (initialUpdate || contentEl === undefined || contentElWrapper === undefined) {
/**
* If the content elements aren't available yet, just set the state.
* This happens on initial render before the DOM is ready.
*/
if (contentEl === undefined || contentElWrapper === undefined) {
this.state = AccordionState.Expanded;
this.hasEverBeenExpanded = true;
return;
}
@@ -252,6 +310,12 @@ export class Accordion implements ComponentInterface {
cancelAnimationFrame(this.currentRaf);
}
/**
* Mark that this accordion has been expanded at least once.
* This allows subsequent expansions to animate.
*/
this.hasEverBeenExpanded = true;
if (this.shouldAnimate()) {
raf(() => {
this.state = AccordionState.Expanding;
@@ -272,9 +336,14 @@ export class Accordion implements ComponentInterface {
}
};
private collapseAccordion = (initialUpdate = false) => {
private collapseAccordion = () => {
const { contentEl } = this;
if (initialUpdate || contentEl === undefined) {
/**
* If the content element isn't available yet, just set the state.
* This happens on initial render before the DOM is ready.
*/
if (contentEl === undefined) {
this.state = AccordionState.Collapsed;
return;
}
@@ -316,6 +385,19 @@ export class Accordion implements ComponentInterface {
* of what is set in the config.
*/
private shouldAnimate = () => {
/**
* Don't animate until after the first user interaction.
* This prevents animations on initial load when accordions
* start in an expanded or collapsed state programmatically.
*
* Additionally, don't animate the very first expansion even if
* hasInteracted is true. This handles edge cases like React StrictMode
* where effects run twice and might incorrectly mark as interacted.
*/
if (!this.hasInteracted || !this.hasEverBeenExpanded) {
return false;
}
if (typeof (window as any) === 'undefined') {
return false;
}
@@ -337,7 +419,7 @@ export class Accordion implements ComponentInterface {
return true;
};
private updateState = async (initialUpdate = false) => {
private updateState = async () => {
const accordionGroup = this.accordionGroupEl;
const accordionValue = this.value;
@@ -350,10 +432,10 @@ export class Accordion implements ComponentInterface {
const shouldExpand = Array.isArray(value) ? value.includes(accordionValue) : value === accordionValue;
if (shouldExpand) {
this.expandAccordion(initialUpdate);
this.expandAccordion();
this.isNext = this.isPrevious = false;
} else {
this.collapseAccordion(initialUpdate);
this.collapseAccordion();
/**
* When using popout or inset,
@@ -403,6 +485,12 @@ export class Accordion implements ComponentInterface {
if (disabled || readonly) return;
/**
* Mark that the user has interacted with the accordion.
* This enables animations for all future state changes.
*/
this.hasInteracted = true;
if (accordionGroupEl) {
/**
* Because the accordion group may or may

View File

@@ -200,6 +200,87 @@ it('should set default values if not provided', async () => {
expect(accordion.classList.contains('accordion-collapsed')).toEqual(false);
});
it('should not animate when initial value is set before load', async () => {
const page = await newSpecPage({
components: [Item, Accordion, AccordionGroup],
});
const accordionGroup = page.doc.createElement('ion-accordion-group');
accordionGroup.innerHTML = `
<ion-accordion value="first">
<ion-item slot="header">Label</ion-item>
<div slot="content">Content</div>
</ion-accordion>
<ion-accordion value="second">
<ion-item slot="header">Label</ion-item>
<div slot="content">Content</div>
</ion-accordion>
`;
accordionGroup.value = 'first';
page.body.appendChild(accordionGroup);
await page.waitForChanges();
const firstAccordion = accordionGroup.querySelector('ion-accordion[value="first"]')!;
expect(firstAccordion.classList.contains('accordion-expanded')).toEqual(true);
expect(firstAccordion.classList.contains('accordion-expanding')).toEqual(false);
});
it('should not animate when initial value is set after load', async () => {
const page = await newSpecPage({
components: [Item, Accordion, AccordionGroup],
});
const accordionGroup = page.doc.createElement('ion-accordion-group');
accordionGroup.innerHTML = `
<ion-accordion value="first">
<ion-item slot="header">Label</ion-item>
<div slot="content">Content</div>
</ion-accordion>
<ion-accordion value="second">
<ion-item slot="header">Label</ion-item>
<div slot="content">Content</div>
</ion-accordion>
`;
page.body.appendChild(accordionGroup);
await page.waitForChanges();
accordionGroup.value = 'first';
await page.waitForChanges();
const firstAccordion = accordionGroup.querySelector('ion-accordion[value="first"]')!;
expect(firstAccordion.classList.contains('accordion-expanded')).toEqual(true);
expect(firstAccordion.classList.contains('accordion-expanding')).toEqual(false);
});
it('should not have animated class on first expansion', async () => {
const page = await newSpecPage({
components: [Item, Accordion, AccordionGroup],
html: `
<ion-accordion-group>
<ion-accordion value="first">
<ion-item slot="header">Label</ion-item>
<div slot="content">Content</div>
</ion-accordion>
</ion-accordion-group>
`,
});
const accordionGroup = page.body.querySelector('ion-accordion-group')!;
const firstAccordion = page.body.querySelector('ion-accordion[value="first"]')!;
// First expansion should not have the animated class
accordionGroup.value = 'first';
await page.waitForChanges();
expect(firstAccordion.classList.contains('accordion-animated')).toEqual(false);
expect(firstAccordion.classList.contains('accordion-expanded')).toEqual(true);
});
// Verifies fix for https://github.com/ionic-team/ionic-framework/issues/27047
it('should not have animated class when animated="false"', async () => {
const page = await newSpecPage({

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -9,8 +9,8 @@ configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screens
`
<style>
/* Background styles to show the border radius */
:root {
--background: #222;
.ionic {
--ion-background-color: #222;
}
</style>

View File

@@ -1,5 +1,5 @@
import type { ComponentInterface, EventEmitter } from '@stencil/core';
import { Watch, Component, Element, Event, Host, Method, Prop, h, readTask } from '@stencil/core';
import { Watch, Component, Element, Event, Host, Listen, Method, Prop, State, h, readTask } from '@stencil/core';
import type { Gesture } from '@utils/gesture';
import { createButtonActiveGesture } from '@utils/gesture/button-active';
import { raf } from '@utils/helpers';
@@ -48,11 +48,18 @@ 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 */
@@ -83,6 +90,22 @@ 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
@@ -279,12 +302,53 @@ 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);
};
@@ -297,6 +361,96 @@ 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();
@@ -314,6 +468,8 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
if (!this.htmlAttributes?.id) {
setOverlayId(this.el);
}
// Initialize activeRadioId for radio buttons
this.buttonsChanged();
}
componentDidLoad() {
@@ -358,8 +514,82 @@ 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 } = this;
const { header, htmlAttributes, overlayIndex, hasRadioButtons } = this;
const theme = getIonTheme(this);
const allButtons = this.getButtons();
const cancelButton = allButtons.find((b) => b.role === 'cancel');
@@ -391,7 +621,11 @@ 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)}>
<div
class="action-sheet-group"
ref={(el) => (this.groupEl = el)}
role={hasRadioButtons ? 'radiogroup' : undefined}
>
{header !== undefined && (
<div
id={headerID}
@@ -404,22 +638,7 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
{this.subHeader && <div class="action-sheet-sub-title">{this.subHeader}</div>}
</div>
)}
{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>
))}
{this.renderActionSheetButtons(buttons)}
</div>
{cancelButton && (

View File

@@ -134,3 +134,58 @@ 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,6 +27,7 @@
<button class="expand" id="ariaLabelCancelButton" onclick="presentAriaLabelCancelButton()">
Aria Label Cancel Button
</button>
<button class="expand" id="radioButtons" onclick="presentRadioButtons()">Radio Buttons</button>
</main>
<script>
@@ -100,6 +101,32 @@
],
});
}
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

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

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.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: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 392 B

After

Width:  |  Height:  |  Size: 474 B

View File

@@ -12,6 +12,9 @@ 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: 2.0 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -25,6 +25,9 @@
<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

@@ -3,8 +3,8 @@ import type { ComponentInterface } from '@stencil/core';
import { Component, Element, Host, Prop, h } from '@stencil/core';
import type { ButtonInterface } from '@utils/element-interface';
import type { Attributes } from '@utils/helpers';
import { inheritAriaAttributes } from '@utils/helpers';
import { createColorClasses, hostContext, openURL } from '@utils/theme';
import { inheritAriaAttributes, openURL } from '@utils/helpers';
import { createColorClasses, hostContext } from '@utils/theme';
import { arrowBackSharp, chevronBack } from 'ionicons/icons';
import { config } from '../../global/config';

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 62 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 87 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 63 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 87 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 84 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

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