Skip to content

Commit

Permalink
fix(input, textarea): show error state after touch (#26940)
Browse files Browse the repository at this point in the history
resolves #26939, resolves #21643
  • Loading branch information
liamdebeasi authored Mar 10, 2023
1 parent 4810e6f commit ef33270
Show file tree
Hide file tree
Showing 104 changed files with 258 additions and 129 deletions.
2 changes: 1 addition & 1 deletion core/src/components/input/input.md.outline.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
* If the input has a validity state, the
* border should reflect that as a color.
*/
:host(.input-fill-outline.ion-touched.ion-valid),
:host(.has-focus.input-fill-outline.ion-valid),
:host(.input-fill-outline.ion-touched.ion-invalid) {
--border-color: var(--highlight-color);
}
Expand Down
6 changes: 3 additions & 3 deletions core/src/components/input/input.md.scss
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
* If the input has a validity state, the
* border and label should reflect that as a color.
*/
:host(.ion-touched.ion-valid),
:host(.has-focus.ion-valid),
:host(.ion-touched.ion-invalid) {
--border-color: var(--highlight-color);
}
Expand Down Expand Up @@ -76,9 +76,9 @@
color: var(--highlight-color);
}

:host(.input-label-placement-floating.ion-touched.ion-valid) .label-text-wrapper,
:host(.has-focus.input-label-placement-floating.ion-valid) .label-text-wrapper,
:host(.input-label-placement-floating.ion-touched.ion-invalid) .label-text-wrapper,
:host(.input-label-placement-stacked.ion-touched.ion-valid) .label-text-wrapper,
:host(.has-focus.input-label-placement-stacked.ion-valid) .label-text-wrapper,
:host(.input-label-placement-stacked.ion-touched.ion-invalid) .label-text-wrapper {
color: var(--highlight-color);
}
Expand Down
2 changes: 1 addition & 1 deletion core/src/components/input/input.md.solid.scss
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
* If the input has a validity state, the
* border should reflect that as a color.
*/
:host(.input-fill-solid.ion-touched.ion-valid),
:host(.has-focus.input-fill-solid.ion-valid),
:host(.input-fill-solid.ion-touched.ion-invalid) {
--border-color: var(--highlight-color);
}
Expand Down
35 changes: 20 additions & 15 deletions core/src/components/input/input.scss
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,17 @@
--highlight-color: var(--highlight-color-invalid);
}

:host(.ion-touched.ion-valid) {
/**
* The component highlight is only shown
* on focus, so we can safely set the valid
* color state when valid. If we
* set it when .has-focus is present then
* the highlight color would change
* from the valid color to the component's
* color during the transition after the
* component loses focus.
*/
:host(.ion-valid) {
--highlight-color: var(--highlight-color-valid);
}

Expand All @@ -346,8 +356,14 @@
/**
* If the input has a validity state, the
* border and label should reflect that as a color.
* The invalid state should show if the input is
* invalid and has already been touched.
* The valid state should show if the input
* is valid, has already been touched, and
* is currently focused. Do not show the valid
* highlight when the input is blurred.
*/
:host(.ion-touched.ion-valid),
:host(.has-focus.ion-valid),
:host(.ion-touched.ion-invalid) {
--border-color: var(--highlight-color);
}
Expand All @@ -372,11 +388,11 @@
color: #{$background-color-step-550};
}

:host(.ion-invalid) .input-bottom .error-text {
:host(.ion-touched.ion-invalid) .input-bottom .error-text {
display: block;
}

:host(.ion-invalid) .input-bottom .helper-text {
:host(.ion-touched.ion-invalid) .input-bottom .helper-text {
display: none;
}

Expand All @@ -398,17 +414,6 @@
padding-inline-start: 16px;
}

// Input Highlight
// ----------------------------------------------------------------

:host(.ion-touched.ion-invalid) {
--highlight-color: var(--highlight-color-invalid);
}

:host(.ion-touched.ion-valid) {
--highlight-color: var(--highlight-color-valid);
}

// Input Native
// ----------------------------------------------------------------

Expand Down
10 changes: 7 additions & 3 deletions core/src/components/input/test/bottom-content/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,17 @@ <h2>Helper Hint</h2>

<div class="grid-item">
<h2>Error Hint</h2>
<ion-input class="ion-invalid" label="Email" error-text="Please enter a valid email"></ion-input>
<ion-input
class="ion-touched ion-invalid"
label="Email"
error-text="Please enter a valid email"
></ion-input>
</div>

<div class="grid-item">
<h2>Custom Error Color</h2>
<ion-input
class="ion-invalid custom-error-color"
class="ion-touched ion-invalid custom-error-color"
label="Email"
error-text="Please enter a valid email"
></ion-input>
Expand All @@ -92,7 +96,7 @@ <h2>Counter with Helper</h2>
<div class="grid-item">
<h2>Counter with Error</h2>
<ion-input
class="ion-invalid"
class="ion-touched ion-invalid"
label="Email"
counter="true"
maxlength="100"
Expand Down
8 changes: 5 additions & 3 deletions core/src/components/input/test/bottom-content/input.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ test.describe('input: hint text', () => {
});
test('error text should be visible when input is invalid', async ({ page }) => {
await page.setContent(
`<ion-input class="ion-invalid" helper-text="my helper" error-text="my error" label="my input"></ion-input>`
`<ion-input class="ion-invalid ion-touched" helper-text="my helper" error-text="my error" label="my input"></ion-input>`
);

const helperText = page.locator('ion-input .helper-text');
Expand All @@ -68,7 +68,7 @@ test.describe('input: hint text', () => {
--highlight-color-invalid: purple;
}
</style>
<ion-input class="ion-invalid custom-input" label="my label" error-text="my error"></ion-input>
<ion-input class="ion-invalid ion-touched custom-input" label="my label" error-text="my error"></ion-input>
`);

const errorText = page.locator('ion-input .error-text');
Expand All @@ -88,7 +88,9 @@ test.describe('input: hint text', () => {
);
});
test('should not have visual regressions when rendering error text', async ({ page }) => {
await page.setContent(`<ion-input class="ion-invalid" error-text="my helper" label="my input"></ion-input>`);
await page.setContent(
`<ion-input class="ion-invalid ion-touched" error-text="my helper" label="my input"></ion-input>`
);

const bottomEl = page.locator('ion-input .input-bottom');
expect(await bottomEl.screenshot()).toMatchSnapshot(
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 18 additions & 18 deletions core/src/components/input/test/highlight/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ <h2>Focus</h2>
</div>

<div class="grid-item">
<h2>Valid</h2>
<h2>Valid, Focus</h2>
<ion-input
label-placement="start"
class="ion-touched ion-valid"
class="ion-valid has-focus"
label="Email"
error-text="Please enter a valid email"
helper-text="Enter an email"
Expand Down Expand Up @@ -105,10 +105,10 @@ <h2>Focus</h2>
</div>

<div class="grid-item">
<h2>Valid</h2>
<h2>Valid, Focus</h2>
<ion-input
label-placement="floating"
class="ion-touched ion-valid"
class="ion-valid has-focus"
label="Email"
error-text="Please enter a valid email"
helper-text="Enter an email"
Expand Down Expand Up @@ -148,10 +148,10 @@ <h2>Focus</h2>
</div>

<div class="grid-item">
<h2>Valid</h2>
<h2>Valid, Focus</h2>
<ion-input
label-placement="stacked"
class="ion-touched ion-valid"
class="ion-valid has-focus"
label="Email"
error-text="Please enter a valid email"
helper-text="Enter an email"
Expand Down Expand Up @@ -192,11 +192,11 @@ <h2>Focus</h2>
</div>

<div class="grid-item">
<h2>Valid</h2>
<h2>Valid, Focus</h2>
<ion-input
fill="solid"
label-placement="start"
class="ion-touched ion-valid"
class="ion-valid has-focus"
label="Email"
error-text="Please enter a valid email"
helper-text="Enter an email"
Expand Down Expand Up @@ -238,11 +238,11 @@ <h2>Focus</h2>
</div>

<div class="grid-item">
<h2>Valid</h2>
<h2>Valid, Focus</h2>
<ion-input
fill="solid"
label-placement="floating"
class="ion-touched ion-valid"
class="ion-valid has-focus"
label="Email"
error-text="Please enter a valid email"
helper-text="Enter an email"
Expand Down Expand Up @@ -284,11 +284,11 @@ <h2>Focus</h2>
</div>

<div class="grid-item">
<h2>Valid</h2>
<h2>Valid, Focus</h2>
<ion-input
fill="solid"
label-placement="stacked"
class="ion-touched ion-valid"
class="ion-valid has-focus"
label="Email"
error-text="Please enter a valid email"
helper-text="Enter an email"
Expand Down Expand Up @@ -330,11 +330,11 @@ <h2>Focus</h2>
</div>

<div class="grid-item">
<h2>Valid</h2>
<h2>Valid, Focus</h2>
<ion-input
fill="outline"
label-placement="start"
class="ion-touched ion-valid"
class="ion-valid has-focus"
label="Email"
error-text="Please enter a valid email"
helper-text="Enter an email"
Expand Down Expand Up @@ -376,11 +376,11 @@ <h2>Focus</h2>
</div>

<div class="grid-item">
<h2>Valid</h2>
<h2>Valid, Focus</h2>
<ion-input
fill="outline"
label-placement="floating"
class="ion-touched ion-valid"
class="ion-valid has-focus"
label="Email"
error-text="Please enter a valid email"
helper-text="Enter an email"
Expand Down Expand Up @@ -422,11 +422,11 @@ <h2>Focus</h2>
</div>

<div class="grid-item">
<h2>Valid</h2>
<h2>Valid, Focus</h2>
<ion-input
fill="outline"
label-placement="stacked"
class="ion-touched ion-valid"
class="ion-valid has-focus"
label="Email"
error-text="Please enter a valid email"
helper-text="Enter an email"
Expand Down
6 changes: 3 additions & 3 deletions core/src/components/input/test/highlight/input.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ test.describe('input: highlights', () => {
await page.setContent(`
<ion-input
value="[email protected]"
class="ion-touched ion-valid"
class="ion-valid has-focus"
label="Email"
error-text="Please enter a valid email"
helper-text="Enter an email"
Expand Down Expand Up @@ -61,7 +61,7 @@ test.describe('input: highlights', () => {
<ion-input
fill="solid"
value="[email protected]"
class="ion-touched ion-valid"
class="ion-valid has-focus"
label="Email"
error-text="Please enter a valid email"
helper-text="Enter an email"
Expand Down Expand Up @@ -114,7 +114,7 @@ test.describe('input: highlights', () => {
<ion-input
fill="outline"
value="[email protected]"
class="ion-touched ion-valid"
class="ion-valid has-focus"
label="Email"
error-text="Please enter a valid email"
helper-text="Enter an email"
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion core/src/components/select/select.md.outline.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
* If the select has a validity state, the
* border should reflect that as a color.
*/
:host(.select-fill-outline.ion-touched.ion-valid),
:host(.has-focus.select-fill-outline.ion-valid),
:host(.select-fill-outline.ion-touched.ion-invalid) {
--border-color: var(--highlight-color);
}
Expand Down
6 changes: 3 additions & 3 deletions core/src/components/select/select.md.scss
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@
color: var(--highlight-color);
}

:host(.select-label-placement-floating.ion-touched.ion-valid) .label-text-wrapper,
:host(.has-focus.select-label-placement-floating.ion-valid) .label-text-wrapper,
:host(.select-label-placement-floating.ion-touched.ion-invalid) .label-text-wrapper,
:host(.select-label-placement-stacked.ion-touched.ion-valid) .label-text-wrapper,
:host(.has-focus.select-label-placement-stacked.ion-valid) .label-text-wrapper,
:host(.select-label-placement-stacked.ion-touched.ion-invalid) .label-text-wrapper {
color: var(--highlight-color);
}
Expand Down Expand Up @@ -103,7 +103,7 @@
* color if there is a validation state.
*/
:host(.select-expanded) .select-wrapper .select-icon,
:host(.ion-touched.ion-valid) .select-wrapper .select-icon,
:host(.has-focus.ion-valid) .select-wrapper .select-icon,
:host(.ion-touched.ion-invalid) .select-wrapper .select-icon,
:host(.ion-focused) .select-wrapper .select-icon {
color: var(--highlight-color);
Expand Down
2 changes: 1 addition & 1 deletion core/src/components/select/select.md.solid.scss
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
* If the select has a validity state, the
* border should reflect that as a color.
*/
:host(.select-fill-solid.ion-touched.ion-valid),
:host(.has-focus.select-fill-solid.ion-valid),
:host(.select-fill-solid.ion-touched.ion-invalid) {
--border-color: var(--highlight-color);
}
Expand Down
12 changes: 11 additions & 1 deletion core/src/components/select/select.scss
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,17 @@ button {
--highlight-color: var(--highlight-color-invalid);
}

:host(.ion-touched.ion-valid) {
/**
* The component highlight is only shown
* on focus, so we can safely set the valid
* color state when touched/valid. If we
* set it when .has-focus is present then
* the highlight color would change
* from the valid color to the component's
* color during the transition after the
* component loses focus.
*/
:host(.ion-valid) {
--highlight-color: var(--highlight-color-valid);
}

Expand Down
Loading

0 comments on commit ef33270

Please sign in to comment.