feat(input,textarea,select): add --highlight-height variable (#29090)
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. --> In v7, using the legacy syntax, the height of the highlight on an item could be adjusted using the `--highlight-height` variable. This variable was not added to input and therefore would not work using the modern syntax. ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> Adds the `--highlight-height` variable to `ion-input`, `ion-textarea` and `ion-select` so that developers can customize this height in `md` mode. Since the highlight element is not added for `ios` mode, this variable won't do anything for `ios`. Note that this diverges from the v7 behavior, where setting `--highlight-height` enabled the highlight for `ios`. A design document outlining this has been proposed here: https://github.com/ionic-team/ionic-framework-design-documents/pull/252 ## 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/.github/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 Carney <brandyscarney@users.noreply.github.com>
@ -4,6 +4,7 @@
|
||||
:host {
|
||||
--border-width: #{$hairlines-width};
|
||||
--border-color: #{$item-ios-border-color};
|
||||
--highlight-height: 0px;
|
||||
|
||||
font-size: $input-ios-font-size;
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@
|
||||
* the input is focused.
|
||||
*/
|
||||
:host(.input-fill-outline.has-focus) {
|
||||
--border-width: 2px;
|
||||
--border-width: var(--highlight-height);
|
||||
--border-color: var(--highlight-color);
|
||||
}
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
:host {
|
||||
--border-width: 1px;
|
||||
--border-color: #{$item-md-border-color};
|
||||
--highlight-height: 2px;
|
||||
|
||||
font-size: $input-md-font-size;
|
||||
}
|
||||
@ -73,7 +74,7 @@
|
||||
position: absolute;
|
||||
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
height: var(--highlight-height);
|
||||
|
||||
transform: scale(0);
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
* @prop --placeholder-font-weight: Font weight of the input placeholder text
|
||||
* @prop --placeholder-opacity: Opacity of the input placeholder text
|
||||
*
|
||||
* @prop --highlight-height: The height of the highlight on the input. Only applies to md mode.
|
||||
* @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
|
||||
|
||||
@ -33,6 +33,13 @@
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.custom {
|
||||
--highlight-color-focused: purple;
|
||||
--highlight-color-invalid: purple;
|
||||
--highlight-color-valid: purple;
|
||||
--highlight-height: 6px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
@ -174,6 +181,49 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1>No Fill, Custom</h1>
|
||||
<div class="grid">
|
||||
<div class="grid-item">
|
||||
<h2>Focus</h2>
|
||||
<ion-input
|
||||
label-placement="start"
|
||||
value="hi@ionic.io"
|
||||
class="has-focus custom"
|
||||
label="Email"
|
||||
error-text="Please enter a valid email"
|
||||
helper-text="Enter an email"
|
||||
counter="true"
|
||||
maxlength="20"
|
||||
></ion-input>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<h2>Valid, Focus</h2>
|
||||
<ion-input
|
||||
label-placement="start"
|
||||
class="ion-valid has-focus custom"
|
||||
label="Email"
|
||||
error-text="Please enter a valid email"
|
||||
helper-text="Enter an email"
|
||||
counter="true"
|
||||
maxlength="20"
|
||||
></ion-input>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<h2>Invalid</h2>
|
||||
<ion-input
|
||||
label-placement="start"
|
||||
class="ion-touched ion-invalid custom"
|
||||
label="Email"
|
||||
error-text="Please enter a valid email"
|
||||
helper-text="Enter an email"
|
||||
counter="true"
|
||||
maxlength="20"
|
||||
></ion-input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1>Solid, Default</h1>
|
||||
<div class="grid">
|
||||
<div class="grid-item">
|
||||
@ -312,6 +362,52 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1>Solid, Custom</h1>
|
||||
<div class="grid">
|
||||
<div class="grid-item">
|
||||
<h2>Focus</h2>
|
||||
<ion-input
|
||||
fill="solid"
|
||||
label-placement="start"
|
||||
value="hi@ionic.io"
|
||||
class="has-focus custom"
|
||||
label="Email"
|
||||
error-text="Please enter a valid email"
|
||||
helper-text="Enter an email"
|
||||
counter="true"
|
||||
maxlength="20"
|
||||
></ion-input>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<h2>Valid, Focus</h2>
|
||||
<ion-input
|
||||
fill="solid"
|
||||
label-placement="start"
|
||||
class="ion-valid has-focus custom"
|
||||
label="Email"
|
||||
error-text="Please enter a valid email"
|
||||
helper-text="Enter an email"
|
||||
counter="true"
|
||||
maxlength="20"
|
||||
></ion-input>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<h2>Invalid</h2>
|
||||
<ion-input
|
||||
fill="solid"
|
||||
label-placement="start"
|
||||
class="ion-touched ion-invalid custom"
|
||||
label="Email"
|
||||
error-text="Please enter a valid email"
|
||||
helper-text="Enter an email"
|
||||
counter="true"
|
||||
maxlength="20"
|
||||
></ion-input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1>Outline, Default</h1>
|
||||
<div class="grid">
|
||||
<div class="grid-item">
|
||||
@ -449,6 +545,52 @@
|
||||
></ion-input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1>Outline, Custom</h1>
|
||||
<div class="grid">
|
||||
<div class="grid-item">
|
||||
<h2>Focus</h2>
|
||||
<ion-input
|
||||
fill="outline"
|
||||
label-placement="start"
|
||||
value="hi@ionic.io"
|
||||
class="has-focus custom"
|
||||
label="Email"
|
||||
error-text="Please enter a valid email"
|
||||
helper-text="Enter an email"
|
||||
counter="true"
|
||||
maxlength="20"
|
||||
></ion-input>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<h2>Valid, Focus</h2>
|
||||
<ion-input
|
||||
fill="outline"
|
||||
label-placement="start"
|
||||
class="ion-valid has-focus custom"
|
||||
label="Email"
|
||||
error-text="Please enter a valid email"
|
||||
helper-text="Enter an email"
|
||||
counter="true"
|
||||
maxlength="20"
|
||||
></ion-input>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<h2>Invalid</h2>
|
||||
<ion-input
|
||||
fill="outline"
|
||||
label-placement="start"
|
||||
class="ion-touched ion-invalid custom"
|
||||
label="Email"
|
||||
error-text="Please enter a valid email"
|
||||
helper-text="Enter an email"
|
||||
counter="true"
|
||||
maxlength="20"
|
||||
></ion-input>
|
||||
</div>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-app>
|
||||
</body>
|
||||
|
||||
@ -61,6 +61,56 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
const input = page.locator('ion-input');
|
||||
await expect(input).toHaveScreenshot(screenshot(`input-no-fill-focus`));
|
||||
});
|
||||
test('should render custom highlight correctly', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<style>
|
||||
ion-input.custom {
|
||||
--highlight-color-focused: red;
|
||||
--highlight-color-invalid: blue;
|
||||
--highlight-color-valid: purple;
|
||||
--highlight-height: 6px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container">
|
||||
<ion-input
|
||||
value="hi@ionic.io"
|
||||
class="custom has-focus"
|
||||
label="Email"
|
||||
error-text="Please enter a valid email"
|
||||
helper-text="Enter an email"
|
||||
counter="true"
|
||||
maxlength="20"
|
||||
></ion-input>
|
||||
|
||||
<ion-input
|
||||
value="hi@ionic.io"
|
||||
class="custom has-focus ion-valid"
|
||||
label="Email"
|
||||
error-text="Please enter a valid email"
|
||||
helper-text="Enter an email"
|
||||
counter="true"
|
||||
maxlength="20"
|
||||
></ion-input>
|
||||
|
||||
<ion-input
|
||||
value="hi@ionic.io"
|
||||
class="custom has-focus ion-invalid ion-touched"
|
||||
label="Email"
|
||||
error-text="Please enter a valid email"
|
||||
helper-text="Enter an email"
|
||||
counter="true"
|
||||
maxlength="20"
|
||||
></ion-input>
|
||||
</div>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const container = page.locator('.container');
|
||||
await expect(container).toHaveScreenshot(screenshot(`input-no-fill-custom-highlight`));
|
||||
});
|
||||
});
|
||||
test.describe('input: solid', () => {
|
||||
test('should render valid state correctly', async ({ page }) => {
|
||||
@ -123,6 +173,59 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
const input = page.locator('ion-input');
|
||||
await expect(input).toHaveScreenshot(screenshot(`input-solid-focus`));
|
||||
});
|
||||
test('should render custom highlight correctly', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<style>
|
||||
ion-input.custom {
|
||||
--highlight-color-focused: red;
|
||||
--highlight-color-invalid: blue;
|
||||
--highlight-color-valid: purple;
|
||||
--highlight-height: 6px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container">
|
||||
<ion-input
|
||||
fill="solid"
|
||||
value="hi@ionic.io"
|
||||
class="custom has-focus"
|
||||
label="Email"
|
||||
error-text="Please enter a valid email"
|
||||
helper-text="Enter an email"
|
||||
counter="true"
|
||||
maxlength="20"
|
||||
></ion-input>
|
||||
|
||||
<ion-input
|
||||
fill="solid"
|
||||
value="hi@ionic.io"
|
||||
class="custom has-focus ion-valid"
|
||||
label="Email"
|
||||
error-text="Please enter a valid email"
|
||||
helper-text="Enter an email"
|
||||
counter="true"
|
||||
maxlength="20"
|
||||
></ion-input>
|
||||
|
||||
<ion-input
|
||||
fill="solid"
|
||||
value="hi@ionic.io"
|
||||
class="custom has-focus ion-invalid ion-touched"
|
||||
label="Email"
|
||||
error-text="Please enter a valid email"
|
||||
helper-text="Enter an email"
|
||||
counter="true"
|
||||
maxlength="20"
|
||||
></ion-input>
|
||||
</div>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const container = page.locator('.container');
|
||||
await expect(container).toHaveScreenshot(screenshot(`input-solid-custom-highlight`));
|
||||
});
|
||||
});
|
||||
test.describe('input: outline', () => {
|
||||
test('should render valid state correctly', async ({ page }) => {
|
||||
@ -185,6 +288,59 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
const input = page.locator('ion-input');
|
||||
await expect(input).toHaveScreenshot(screenshot(`input-outline-focus`));
|
||||
});
|
||||
test('should render custom highlight correctly', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<style>
|
||||
ion-input.custom {
|
||||
--highlight-color-focused: red;
|
||||
--highlight-color-invalid: blue;
|
||||
--highlight-color-valid: purple;
|
||||
--highlight-height: 6px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container">
|
||||
<ion-input
|
||||
fill="outline"
|
||||
value="hi@ionic.io"
|
||||
class="custom has-focus"
|
||||
label="Email"
|
||||
error-text="Please enter a valid email"
|
||||
helper-text="Enter an email"
|
||||
counter="true"
|
||||
maxlength="20"
|
||||
></ion-input>
|
||||
|
||||
<ion-input
|
||||
fill="outline"
|
||||
value="hi@ionic.io"
|
||||
class="custom has-focus ion-valid"
|
||||
label="Email"
|
||||
error-text="Please enter a valid email"
|
||||
helper-text="Enter an email"
|
||||
counter="true"
|
||||
maxlength="20"
|
||||
></ion-input>
|
||||
|
||||
<ion-input
|
||||
fill="outline"
|
||||
value="hi@ionic.io"
|
||||
class="custom has-focus ion-invalid ion-touched"
|
||||
label="Email"
|
||||
error-text="Please enter a valid email"
|
||||
helper-text="Enter an email"
|
||||
counter="true"
|
||||
maxlength="20"
|
||||
></ion-input>
|
||||
</div>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const container = page.locator('.container');
|
||||
await expect(container).toHaveScreenshot(screenshot(`input-outline-custom-highlight`));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 9.8 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 9.7 KiB |