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>
@ -27,7 +27,8 @@
|
|||||||
|
|
||||||
// Size
|
// Size
|
||||||
--size: #{globals.$ion-scale-600};
|
--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};
|
--border-color-checked: #{globals.$ion-semantics-primary-base};
|
||||||
--checkmark-color: #{globals.$ion-primitives-base-white};
|
--checkmark-color: #{globals.$ion-primitives-base-white};
|
||||||
--transition: none;
|
--transition: none;
|
||||||
@ -120,7 +121,7 @@ input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.checkbox-bottom .helper-text {
|
.checkbox-bottom .helper-text {
|
||||||
color: globals.$ion-primitives-neutral-800;
|
color: globals.$ion-text-subtlest;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Label Placement - Start
|
// Label Placement - Start
|
||||||
@ -187,7 +188,6 @@ input {
|
|||||||
|
|
||||||
// Checked / Indeterminate Checkbox
|
// Checked / Indeterminate Checkbox
|
||||||
// ---------------------------------------------
|
// ---------------------------------------------
|
||||||
|
|
||||||
:host(.checkbox-checked) .native-wrapper,
|
:host(.checkbox-checked) .native-wrapper,
|
||||||
:host(.checkbox-indeterminate) .native-wrapper {
|
:host(.checkbox-indeterminate) .native-wrapper {
|
||||||
border-color: var(--border-color-checked);
|
border-color: var(--border-color-checked);
|
||||||
@ -199,9 +199,12 @@ input {
|
|||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
:host(.ion-invalid) {
|
:host(.ion-invalid) {
|
||||||
--focus-ring-color: #{globals.$ion-border-focus-error};
|
--focus-ring-color: #{globals.$ion-border-focus-error};
|
||||||
|
}
|
||||||
|
|
||||||
|
:host(.ion-invalid:not(.checkbox-checked)),
|
||||||
|
:host(.ion-invalid:not(.checkbox-checked).checkbox-disabled) {
|
||||||
.native-wrapper {
|
.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 {
|
:host(.checkbox-disabled.checkbox-checked) .native-wrapper {
|
||||||
border-width: globals.$ion-border-size-0;
|
border-width: globals.$ion-border-size-0;
|
||||||
|
|
||||||
background-color: globals.$ion-semantics-primary-base;
|
background-color: globals.$ion-bg-primary-base-default;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checkbox Hover
|
// Checkbox Hover
|
||||||
@ -233,7 +236,9 @@ input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
:host(:hover.checkbox-checked) .native-wrapper,
|
: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;
|
background-color: globals.$ion-semantics-primary-800;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -248,12 +253,22 @@ input {
|
|||||||
// Checkbox: Active
|
// Checkbox: Active
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
:host(.ion-activated) .native-wrapper {
|
: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-checked) .native-wrapper,
|
||||||
:host(.ion-activated.checkbox-indeterminate) .native-wrapper {
|
:host(.ion-activated.checkbox-checked) .checkbox-icon,
|
||||||
background-color: globals.$ion-semantics-primary-900;
|
: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
|
// Ionic Design Checkbox Shapes
|
||||||
|
|||||||
@ -15,6 +15,18 @@ configs({ modes: ['ios', 'md', 'ionic-md'], directions: ['ltr'] }).forEach(({ ti
|
|||||||
await expect(checkbox).toHaveScreenshot(screenshot(`checkbox-disabled`));
|
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 }) => {
|
test('should render disabled checked checkbox correctly', async ({ page }) => {
|
||||||
await page.setContent(
|
await page.setContent(
|
||||||
`
|
`
|
||||||
@ -57,6 +69,7 @@ configs({ modes: ['ios', 'md', 'ionic-md'], directions: ['ltr'] }).forEach(({ ti
|
|||||||
<div id="checkboxes" style="padding: 8px">
|
<div id="checkboxes" style="padding: 8px">
|
||||||
<ion-checkbox class="ion-focused">Label</ion-checkbox>
|
<ion-checkbox class="ion-focused">Label</ion-checkbox>
|
||||||
<ion-checkbox class="ion-focused" checked>Label</ion-checkbox>
|
<ion-checkbox class="ion-focused" checked>Label</ion-checkbox>
|
||||||
|
<ion-checkbox class="ion-invalid ion-focused">Label</ion-checkbox>
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
config
|
config
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 895 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1015 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 800 B |
|
After Width: | Height: | Size: 878 B |
|
After Width: | Height: | Size: 977 B |
@ -81,6 +81,18 @@
|
|||||||
<h2>Focused, Checked</h2>
|
<h2>Focused, Checked</h2>
|
||||||
<ion-checkbox checked class="ion-focused">Enable Notifications</ion-checkbox>
|
<ion-checkbox checked class="ion-focused">Enable Notifications</ion-checkbox>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
</ion-app>
|
</ion-app>
|
||||||
|
|||||||