fix(input) match invalid state to ionic design (#29291)
Co-authored-by: Sean Perkins <13732623+sean-perkins@users.noreply.github.com>
@ -656,6 +656,7 @@ ion-input,css-prop,--placeholder-color
|
||||
ion-input,css-prop,--placeholder-font-style
|
||||
ion-input,css-prop,--placeholder-font-weight
|
||||
ion-input,css-prop,--placeholder-opacity
|
||||
ion-input,css-prop,--text-color-invalid
|
||||
|
||||
ion-input-password-toggle,shadow
|
||||
ion-input-password-toggle,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
|
||||
|
||||
@ -8,9 +8,8 @@
|
||||
:host {
|
||||
--border-width: #{$ionic-border-size-small};
|
||||
--border-color: #{$ionic-color-neutral-300};
|
||||
|
||||
// TODO(FW-6113): Verify the ionic design token is correct once it's available and remove the hardcoded value.
|
||||
--highlight-color-invalid: var(--ionic-color-error-600, #970606);
|
||||
--highlight-color-invalid: #{$ionic-color-error-400};
|
||||
--text-color-invalid: #{$ionic-color-error-600};
|
||||
}
|
||||
|
||||
// Ionic Input Sizes
|
||||
@ -28,6 +27,6 @@
|
||||
color: var(--ionic-color-neutral-600, #535353);
|
||||
}
|
||||
|
||||
.input-bottom .error-text {
|
||||
color: var(--highlight-color-invalid);
|
||||
:host(.ion-touched.ion-invalid) .error-text {
|
||||
color: var(--text-color-invalid);
|
||||
}
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
* @prop --highlight-color-focused: The color of the highlight on the input when focused
|
||||
* @prop --highlight-color-valid: The color of the highlight on the input when valid
|
||||
* @prop --highlight-color-invalid: The color of the highlight on the input when invalid
|
||||
* @prop --text-color-invalid: The color of the error text on the input when invalid. Only applies to ionic theme.
|
||||
*
|
||||
* @prop --border-color: Color of the border below the input when using helper text, error text, or counter
|
||||
* @prop --border-radius: Radius of the input. A large radius may display unevenly when using fill="outline"; if needed, use shape="round" instead or increase --padding-start.
|
||||
|
||||
@ -105,12 +105,13 @@ configs({ modes: ['md', 'ionic-md'], directions: ['ltr'] }).forEach(({ title, sc
|
||||
await expect(errorText).toBeVisible();
|
||||
await expect(errorText).toHaveText('my error');
|
||||
});
|
||||
test('error text should change when variable is customized', async ({ page }) => {
|
||||
test('error text and highlight should change when variable is customized', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<style>
|
||||
ion-input.custom-input {
|
||||
--highlight-color-invalid: purple;
|
||||
--text-color-invalid: purple; /* ionic only */
|
||||
}
|
||||
</style>
|
||||
<ion-input class="ion-invalid ion-touched custom-input" label="my label" error-text="my error"></ion-input>
|
||||
@ -118,8 +119,8 @@ configs({ modes: ['md', 'ionic-md'], directions: ['ltr'] }).forEach(({ title, sc
|
||||
config
|
||||
);
|
||||
|
||||
const errorText = page.locator('ion-input .error-text');
|
||||
await expect(errorText).toHaveScreenshot(screenshot(`input-error-custom-color`));
|
||||
const bottomEl = page.locator('ion-input .input-bottom');
|
||||
await expect(bottomEl).toHaveScreenshot(screenshot(`input-error-custom-color`));
|
||||
});
|
||||
});
|
||||
test.describe('input: hint text rendering', () => {
|
||||
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 923 B After Width: | Height: | Size: 922 B |
|
Before Width: | Height: | Size: 873 B After Width: | Height: | Size: 990 B |
|
Before Width: | Height: | Size: 822 B After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 751 B After Width: | Height: | Size: 868 B |
|
Before Width: | Height: | Size: 873 B After Width: | Height: | Size: 990 B |
|
Before Width: | Height: | Size: 822 B After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 751 B After Width: | Height: | Size: 868 B |
@ -344,3 +344,51 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ title, screenshot, config }) => {
|
||||
test.describe(title('input: highlights'), () => {
|
||||
test.describe('input: no fill', () => {
|
||||
test('should render invalid state correctly', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-input
|
||||
value="hi@ionic.io"
|
||||
class="ion-touched ion-invalid"
|
||||
label="Email"
|
||||
error-text="Please enter a valid email"
|
||||
helper-text="Enter an email"
|
||||
counter="true"
|
||||
maxlength="20"
|
||||
></ion-input>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const input = page.locator('ion-input');
|
||||
await expect(input).toHaveScreenshot(screenshot(`input-no-fill-invalid`));
|
||||
});
|
||||
});
|
||||
test.describe('input: outline', () => {
|
||||
test('should render invalid state correctly', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-input
|
||||
fill="outline"
|
||||
value="hi@ionic.io"
|
||||
class="ion-touched ion-invalid"
|
||||
label="Email"
|
||||
error-text="Please enter a valid email"
|
||||
helper-text="Enter an email"
|
||||
counter="true"
|
||||
maxlength="20"
|
||||
></ion-input>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const input = page.locator('ion-input');
|
||||
await expect(input).toHaveScreenshot(screenshot(`input-outline-invalid`));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 3.7 KiB |