fix(checkbox): improve states and colors (#30559)

Issue number: internal

---------

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

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

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

- update scss to use vars;
- add more examples to states page;
- now the invalid state is only possible for unchecked checkboxes;

## 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-12073-ionic1.vercel.app/src/components/checkbox/test/basic?ionic:theme=ionic)

[indeterminate](https://ionic-framework-git-rou-12073-ionic1.vercel.app/src/components/checkbox/test/indeterminate?ionic:theme=ionic)
[Bottom
Content](https://ionic-framework-git-rou-12073-ionic1.vercel.app/src/components/checkbox/test/bottom-content?ionic:theme=ionic)

[States](https://ionic-framework-git-rou-12073-ionic1.vercel.app/src/components/checkbox/test/states?ionic:theme=ionic)

---------

Co-authored-by: ionitron <hi@ionicframework.com>
This commit is contained in:
João Ferreira
2025-07-22 09:42:41 +01:00
committed by GitHub
parent 79a12ceca3
commit 7f904d0d6d
21 changed files with 49 additions and 9 deletions

View File

@ -27,7 +27,8 @@
// Size
--size: #{globals.$ion-scale-600};
--checkbox-background-checked: #{globals.$ion-semantics-primary-base};
--checkbox-background: #{globals.$ion-bg-input-default};
--checkbox-background-checked: #{globals.$ion-bg-primary-base-default};
--border-color-checked: #{globals.$ion-semantics-primary-base};
--checkmark-color: #{globals.$ion-primitives-base-white};
--transition: none;
@ -120,7 +121,7 @@ input {
}
.checkbox-bottom .helper-text {
color: globals.$ion-primitives-neutral-800;
color: globals.$ion-text-subtlest;
}
// Label Placement - Start
@ -187,7 +188,6 @@ input {
// Checked / Indeterminate Checkbox
// ---------------------------------------------
:host(.checkbox-checked) .native-wrapper,
:host(.checkbox-indeterminate) .native-wrapper {
border-color: var(--border-color-checked);
@ -199,9 +199,12 @@ input {
// --------------------------------------------------
:host(.ion-invalid) {
--focus-ring-color: #{globals.$ion-border-focus-error};
}
:host(.ion-invalid:not(.checkbox-checked)),
:host(.ion-invalid:not(.checkbox-checked).checkbox-disabled) {
.native-wrapper {
border-color: globals.$ion-semantics-danger-800;
border-color: globals.$ion-border-danger-default;
}
}
@ -222,7 +225,7 @@ input {
:host(.checkbox-disabled.checkbox-checked) .native-wrapper {
border-width: globals.$ion-border-size-0;
background-color: globals.$ion-semantics-primary-base;
background-color: globals.$ion-bg-primary-base-default;
}
// Checkbox Hover
@ -233,7 +236,9 @@ input {
}
:host(:hover.checkbox-checked) .native-wrapper,
:host(:hover.checkbox-indeterminate) .native-wrapper {
:host(:hover.checkbox-checked) .checkbox-icon,
:host(:hover.checkbox-indeterminate) .native-wrapper,
:host(:hover.checkbox-indeterminate) .checkbox-icon {
background-color: globals.$ion-semantics-primary-800;
}
}
@ -248,12 +253,22 @@ input {
// Checkbox: Active
// --------------------------------------------------------
:host(.ion-activated) .native-wrapper {
background-color: globals.$ion-primitives-neutral-200;
background-color: globals.$ion-bg-input-press;
}
:host(.ion-activated.checkbox-checked) .native-wrapper,
:host(.ion-activated.checkbox-indeterminate) .native-wrapper {
background-color: globals.$ion-semantics-primary-900;
:host(.ion-activated.checkbox-checked) .checkbox-icon,
:host(.ion-activated.checkbox-indeterminate) .native-wrapper,
:host(.ion-activated.checkbox-indeterminate) .checkbox-icon {
background-color: globals.$ion-bg-primary-base-press;
}
:host(.ion-activated.ion-invalid:not(.checkbox-checked)) {
background-color: globals.$ion-bg-input-press;
.native-wrapper {
border-color: globals.$ion-border-danger-press;
}
}
// Ionic Design Checkbox Shapes

View File

@ -15,6 +15,18 @@ configs({ modes: ['ios', 'md', 'ionic-md'], directions: ['ltr'] }).forEach(({ ti
await expect(checkbox).toHaveScreenshot(screenshot(`checkbox-disabled`));
});
test('should render disabled invalid checkbox correctly', async ({ page }) => {
await page.setContent(
`
<ion-checkbox disabled="true" error-text="Error text" class="ion-invalid">Label</ion-checkbox>
`,
config
);
const checkbox = page.locator('ion-checkbox');
await expect(checkbox).toHaveScreenshot(screenshot(`invalid-checkbox-disabled`));
});
test('should render disabled checked checkbox correctly', async ({ page }) => {
await page.setContent(
`
@ -57,6 +69,7 @@ configs({ modes: ['ios', 'md', 'ionic-md'], directions: ['ltr'] }).forEach(({ ti
<div id="checkboxes" style="padding: 8px">
<ion-checkbox class="ion-focused">Label</ion-checkbox>
<ion-checkbox class="ion-focused" checked>Label</ion-checkbox>
<ion-checkbox class="ion-invalid ion-focused">Label</ion-checkbox>
</div>
`,
config

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -81,6 +81,18 @@
<h2>Focused, Checked</h2>
<ion-checkbox checked class="ion-focused">Enable Notifications</ion-checkbox>
</div>
<div class="grid-item">
<h2>Focused, Invalid</h2>
<ion-checkbox error-text="Error text" class="ion-invalid ion-focused">Enable Notifications</ion-checkbox>
</div>
<div class="grid-item">
<h2>Disabled, Invalid</h2>
<ion-checkbox disabled="true" error-text="Error text" class="ion-invalid"
>Enable Notifications
</ion-checkbox>
</div>
</div>
</ion-content>
</ion-app>