Compare commits

..

58 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
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
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
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
757 changed files with 9117 additions and 3737 deletions

View File

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

View File

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

View File

@@ -8,8 +8,8 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: 24.x
@@ -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,8 +8,8 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: 24.x
- name: 🕸️ Install Dependencies
@@ -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,7 +3,7 @@ description: 'Build Ionic React Router'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -13,7 +13,7 @@ runs:
- name: 🗄️ Create Archive
run: zip -q -r ${{ inputs.output }} ${{ inputs.paths }}
shell: bash
- uses: actions/upload-artifact@v5
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/workflows/actions/test-react-e2e
with:
app: ${{ matrix.apps }}

View File

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

View File

@@ -13,7 +13,7 @@ jobs:
outputs:
dev-hash: ${{ steps.create-dev-hash.outputs.DEV_HASH }}
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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

View File

@@ -13,7 +13,7 @@ jobs:
outputs:
nightly-hash: ${{ steps.create-nightly-hash.outputs.NIGHTLY_HASH }}
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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

View File

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

View File

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

View File

@@ -54,8 +54,11 @@ jobs:
finalize-release:
needs: [release-ionic]
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
token: ${{ secrets.IONITRON_TOKEN }}
fetch-depth: 0
@@ -82,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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/workflows/actions/test-react-e2e
with:
app: ${{ matrix.apps }}

View File

@@ -26,7 +26,7 @@ jobs:
build-core:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- 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,28 @@
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)

View File

@@ -3,6 +3,28 @@
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)

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

3457
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.11",
"version": "8.7.13",
"description": "Base components for Ionic",
"engines": {
"node": ">= 16"
},
"keywords": [
"ionic",
"framework",
@@ -38,10 +41,10 @@
},
"devDependencies": {
"@axe-core/playwright": "^4.11.0",
"@capacitor/core": "^7.0.0",
"@capacitor/haptics": "^7.0.0",
"@capacitor/keyboard": "^7.0.0",
"@capacitor/status-bar": "^7.0.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",
@@ -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",
@@ -67,6 +71,7 @@
"jest": "^29.7.0",
"jest-cli": "^29.7.0",
"outsystems-design-tokens": "^1.3.4",
"playwright-core": "^1.56.1",
"prettier": "^2.8.8",
"rollup": "^2.26.4",
"sass": "^1.33.0",
@@ -75,11 +80,12 @@
"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": "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",
@@ -93,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

@@ -14,14 +14,17 @@
* 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:mode`: Set to `ios` or `md` to load a specific mode.
* Defaults to `md`.
* - `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`.
*/
(function() {
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`.
@@ -49,37 +52,16 @@
}
/**
* 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.
* The `theme` param is used to load a specific theme.
* This can be `ionic`, `ios`, or `md`. Default to `md` for tests.
*/
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 paletteName = paletteQuery?.[1] || paletteHash?.[1] || darkClass || 'light';
if (paletteName !== 'light') {
const linkTag = document.createElement('link');
linkTag.setAttribute('rel', 'stylesheet');
linkTag.setAttribute('type', 'text/css');
linkTag.setAttribute('href', `/css/palettes/${paletteName}.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"]');
@@ -91,21 +73,136 @@
document.head.appendChild(linkTag);
}
const utilsBundleLinkTag = document.querySelector('link[href*="css/utils.bundle.css"]');
if (!utilsBundleLinkTag) {
const linkTag = document.createElement('link');
linkTag.setAttribute('rel', 'stylesheet');
linkTag.setAttribute('type', 'text/css');
linkTag.setAttribute('href', '/css/utils.bundle.css');
document.head.appendChild(linkTag);
}
const defaultThemeLinkTag = document.querySelector('link[href*="css/ionic.bundle.css"]');
if (defaultThemeLinkTag) {
defaultThemeLinkTag.remove();
}
}
/**
* 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

@@ -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

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: 11 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

@@ -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: 3.7 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: 3.9 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: 3.8 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: 15 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: 15 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: 7.8 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 316 B

After

Width:  |  Height:  |  Size: 324 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 356 B

After

Width:  |  Height:  |  Size: 357 B

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 316 B

After

Width:  |  Height:  |  Size: 324 B

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