Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(searchbar): add sizes for ionic theme #30211

Open
wants to merge 14 commits into
base: next
Choose a base branch
from
Open
8 changes: 8 additions & 0 deletions core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3115,6 +3115,10 @@ export namespace Components {
* Sets the behavior for the clear button. Defaults to `"focus"`. Setting to `"focus"` shows the clear button on focus if the input is not empty. Setting to `"never"` hides the clear button. Setting to `"always"` shows the clear button regardless of focus state, but only if the input is not empty.
*/
"showClearButton": 'never' | 'focus' | 'always';
/**
* Set to `"large"` for a searchbar with an increase in height, or `"medium"` for a searchbar with a medium height. Defaults to `"medium"` for the ionic theme, and `undefined` for all other themes.
*/
"size"?: 'medium' | 'large';
/**
* If `true`, enable spellcheck on the input.
*/
Expand Down Expand Up @@ -8522,6 +8526,10 @@ declare namespace LocalJSX {
* Sets the behavior for the clear button. Defaults to `"focus"`. Setting to `"focus"` shows the clear button on focus if the input is not empty. Setting to `"never"` hides the clear button. Setting to `"always"` shows the clear button regardless of focus state, but only if the input is not empty.
*/
"showClearButton"?: 'never' | 'focus' | 'always';
/**
* Set to `"large"` for a searchbar with an increase in height, or `"medium"` for a searchbar with a medium height. Defaults to `"medium"` for the ionic theme, and `undefined` for all other themes.
*/
"size"?: 'medium' | 'large';
/**
* If `true`, enable spellcheck on the input.
*/
Expand Down
95 changes: 66 additions & 29 deletions core/src/components/searchbar/searchbar.ionic.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@
// -----------------------------------------

.searchbar-search-icon {
// Position is based on the size of the search icon.
@include globals.position(globals.$ion-scale-400, null, null, globals.$ion-scale-400);

width: globals.$ion-scale-400;
height: globals.$ion-scale-400;
}
Expand All @@ -50,14 +47,7 @@
* the size of the clear icon,
* and the gap between the icon and the input.
*/
@include globals.padding(
globals.$ion-space-300,
calc(globals.$ion-space-400 + globals.$ion-scale-400 + globals.$ion-space-200),
globals.$ion-space-300,
calc(globals.$ion-space-400 + globals.$ion-scale-400 + globals.$ion-space-200)
);

min-height: globals.$ion-scale-1200;
@include globals.padding(globals.$ion-space-300, null);

contain: strict;
}
Expand All @@ -66,9 +56,6 @@
// -----------------------------------------

.searchbar-clear-button {
// Position is based on the size of the clear icon.
@include globals.position(globals.$ion-scale-400, globals.$ion-scale-400, null, null);

width: globals.$ion-scale-400;
height: globals.$ion-scale-400;

Expand All @@ -83,14 +70,6 @@
// -----------------------------------------

.searchbar-cancel-button {
/**
* The left edge of the cancel button
* should align with the left edge
* of the back button if the searchbar
* is used in a toolbar.
*/
@include globals.position(0, null, null, 9px);

background-color: transparent;

font-size: globals.$ion-font-size-400;
Expand All @@ -102,7 +81,11 @@
.searchbar-search-icon,
.searchbar-clear-button,
.searchbar-cancel-button {
@include globals.position(50%, null);

position: absolute;

transform: translateY(-50%);
}

// Clear Icon & Cancel Icon
Expand All @@ -117,13 +100,6 @@
opacity: 1;
}

// Searchbar in Toolbar
// -----------------------------------------

:host-context(ion-toolbar) {
min-height: globals.$ion-scale-1200;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed because it doesn't seem to be used.

// Searchbar States
// --------------------------------------------------

Expand Down Expand Up @@ -157,3 +133,64 @@
cursor: default;
pointer-events: none;
}

// Searchbar Sizes
// --------------------------------------------------

/* Medium */
:host(.searchbar-size-medium) .searchbar-input {
/**
* Padding start is based on
* desired padding from design,
* the size of the search icon,
* and the gap between the icon and the input.
*
* Padding end is based on
* desired padding from design,
* the size of the clear icon,
* and the gap between the icon and the input.
*/
@include globals.padding-horizontal(calc(globals.$ion-space-400 + globals.$ion-scale-400 + globals.$ion-space-200));

min-height: globals.$ion-scale-1200;
}

:host(.searchbar-size-medium) .searchbar-search-icon,
:host(.searchbar-size-medium) .searchbar-cancel-button {
// Start is based on the desired padding start from design.
@include globals.position-horizontal(globals.$ion-space-400, null);
}

:host(.searchbar-size-medium) .searchbar-clear-button {
// End is based on the desired padding end from design.
@include globals.position-horizontal(null, globals.$ion-scale-400);
}

/* Large */
:host(.searchbar-size-large) .searchbar-input {
/**
* Padding start is based on
* desired padding from design,
* the size of the search icon,
* and the gap between the icon and the input.
*
* Padding end is based on
* desired padding from design,
* the size of the clear icon,
* and the gap between the icon and the input.
*/
@include globals.padding-horizontal(calc(globals.$ion-space-500 + globals.$ion-scale-400 + globals.$ion-space-200));

min-height: globals.$ion-scale-1400;
}

:host(.searchbar-size-large) .searchbar-search-icon,
:host(.searchbar-size-large) .searchbar-cancel-button {
// Start is based on the desired padding start from design.
@include globals.position-horizontal(globals.$ion-space-500, null);
}

:host(.searchbar-size-large) .searchbar-clear-button {
// End is based on the desired padding end from design.
@include globals.position-horizontal(null, globals.$ion-scale-500);
}
25 changes: 25 additions & 0 deletions core/src/components/searchbar/searchbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,13 @@ export class Searchbar implements ComponentInterface {
*/
@Prop({ mutable: true }) value?: string | null = '';

/**
* Set to `"large"` for a searchbar with an increase in height,
* or `"medium"` for a searchbar with a medium height.
* Defaults to `"medium"` for the ionic theme, and `undefined` for all other themes.
*/
@Prop() size?: 'medium' | 'large';

/**
* Emitted when the `value` of the `ion-searchbar` element has changed.
*/
Expand Down Expand Up @@ -612,6 +619,22 @@ export class Searchbar implements ComponentInterface {
return true;
}

private getSize(): string | undefined {
const theme = getIonTheme(this);
const { size } = this;

// TODO(ROU-11678): Remove theme check when sizes are defined for all themes.
if (theme !== 'ionic') {
return undefined;
}

if (size === undefined) {
return 'medium';
}

return size;
}

/**
* Get the icon to use for the clear icon.
* If an icon is set on the component, use that.
Expand Down Expand Up @@ -698,6 +721,7 @@ export class Searchbar implements ComponentInterface {
const animated = this.animated && config.getBoolean('animated', true);
const theme = getIonTheme(this);
const shouldShowCancelButton = this.shouldShowCancelButton();
const size = this.getSize();

const cancelButton = this.showCancelButton !== 'never' && (
<button
Expand Down Expand Up @@ -734,6 +758,7 @@ export class Searchbar implements ComponentInterface {
'searchbar-has-focus': this.focused,
'searchbar-should-show-clear': this.shouldShowClearButton(),
'searchbar-should-show-cancel': this.shouldShowCancelButton(),
[`searchbar-size-${size}`]: size !== undefined,
})}
>
<div class="searchbar-input-container">
Expand Down
31 changes: 31 additions & 0 deletions core/src/components/searchbar/test/size/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8" />
<title>Searchbar - Size</title>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"
/>
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
<script src="../../../../../scripts/testing/scripts.js"></script>
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
</head>

<body>
<ion-app>
<ion-content>
<h5 class="ion-padding-start ion-padding-top">Search - Default</h5>
<ion-searchbar show-clear-button="always" value="Filled text"></ion-searchbar>

<h5 class="ion-padding-start ion-padding-top">Search - Medium</h5>
<ion-searchbar size="medium" show-clear-button="always" value="Filled text"></ion-searchbar>

<h5 class="ion-padding-start ion-padding-top">Search - Large</h5>
<ion-searchbar size="large" show-clear-button="always" value="Filled text"></ion-searchbar>
</ion-content>
</ion-app>
</body>
</html>
25 changes: 25 additions & 0 deletions core/src/components/searchbar/test/size/searchbar.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';

/**
* This behavior only applies to the `ionic` theme.
* This behavior does not vary across directions.
*/
configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('searchbar: size'), () => {
['medium', 'large'].forEach((size) => {
test(`${size} - should not have visual regressions`, async ({ page }) => {
await page.setContent(
`
<ion-searchbar size="${size}" show-clear-button="always" value="Filled text"></ion-searchbar>
`,
config
);

const searchbar = page.locator('ion-searchbar');

await expect(searchbar).toHaveScreenshot(screenshot(`searchbar-size-${size}`));
});
});
});
});
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.
4 changes: 2 additions & 2 deletions packages/angular/src/directives/proxies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1900,15 +1900,15 @@ export declare interface IonRow extends Components.IonRow {}


@ProxyCmp({
inputs: ['animated', 'autocapitalize', 'autocomplete', 'autocorrect', 'cancelButtonIcon', 'cancelButtonText', 'clearIcon', 'color', 'debounce', 'disabled', 'enterkeyhint', 'inputmode', 'maxlength', 'minlength', 'mode', 'name', 'placeholder', 'searchIcon', 'showCancelButton', 'showClearButton', 'spellcheck', 'theme', 'type', 'value'],
inputs: ['animated', 'autocapitalize', 'autocomplete', 'autocorrect', 'cancelButtonIcon', 'cancelButtonText', 'clearIcon', 'color', 'debounce', 'disabled', 'enterkeyhint', 'inputmode', 'maxlength', 'minlength', 'mode', 'name', 'placeholder', 'searchIcon', 'showCancelButton', 'showClearButton', 'size', 'spellcheck', 'theme', 'type', 'value'],
methods: ['setFocus', 'getInputElement']
})
@Component({
selector: 'ion-searchbar',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['animated', 'autocapitalize', 'autocomplete', 'autocorrect', 'cancelButtonIcon', 'cancelButtonText', 'clearIcon', 'color', 'debounce', 'disabled', 'enterkeyhint', 'inputmode', 'maxlength', 'minlength', 'mode', 'name', 'placeholder', 'searchIcon', 'showCancelButton', 'showClearButton', 'spellcheck', 'theme', 'type', 'value'],
inputs: ['animated', 'autocapitalize', 'autocomplete', 'autocorrect', 'cancelButtonIcon', 'cancelButtonText', 'clearIcon', 'color', 'debounce', 'disabled', 'enterkeyhint', 'inputmode', 'maxlength', 'minlength', 'mode', 'name', 'placeholder', 'searchIcon', 'showCancelButton', 'showClearButton', 'size', 'spellcheck', 'theme', 'type', 'value'],
})
export class IonSearchbar {
protected el: HTMLElement;
Expand Down
1 change: 1 addition & 0 deletions packages/vue/src/proxies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,7 @@ export const IonSearchbar = /*@__PURE__*/ defineContainer<JSX.IonSearchbar, JSX.
'spellcheck',
'type',
'value',
'size',
'ionInput',
'ionChange',
'ionCancel',
Expand Down
Loading