feat(searchbar): add shapes for ionic theme (#30210)
@@ -1886,6 +1886,7 @@ ion-searchbar,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-searchbar,prop,name,string,this.inputId,false,false
|
||||
ion-searchbar,prop,placeholder,string,'Search',false,false
|
||||
ion-searchbar,prop,searchIcon,string | undefined,undefined,false,false
|
||||
ion-searchbar,prop,shape,"rectangular" | "round" | "soft" | undefined,undefined,false,false
|
||||
ion-searchbar,prop,showCancelButton,"always" | "focus" | "never",'never',false,false
|
||||
ion-searchbar,prop,showClearButton,"always" | "focus" | "never",'always',false,false
|
||||
ion-searchbar,prop,spellcheck,boolean,false,false,false
|
||||
|
||||
8
core/src/components.d.ts
vendored
@@ -3107,6 +3107,10 @@ export namespace Components {
|
||||
* Sets focus on the native `input` in `ion-searchbar`. Use this method instead of the global `input.focus()`. Developers who wish to focus an input when a page enters should call `setFocus()` in the `ionViewDidEnter()` lifecycle method. Developers who wish to focus an input when an overlay is presented should call `setFocus` after `didPresent` has resolved. See [managing focus](/docs/developing/managing-focus) for more information.
|
||||
*/
|
||||
"setFocus": () => Promise<void>;
|
||||
/**
|
||||
* Set to `"soft"` for a searchbar with slightly rounded corners, `"round"` for a searchbar with fully rounded corners, or `"rectangular"` for a searchbar without rounded corners. Defaults to `"round"` for the ionic theme, and `undefined` for all other themes.
|
||||
*/
|
||||
"shape"?: 'soft' | 'round' | 'rectangular';
|
||||
/**
|
||||
* Sets the behavior for the cancel button. Defaults to `"never"`. Setting to `"focus"` shows the cancel button on focus. Setting to `"never"` hides the cancel button. Setting to `"always"` shows the cancel button regardless of focus state.
|
||||
*/
|
||||
@@ -8514,6 +8518,10 @@ declare namespace LocalJSX {
|
||||
* The icon to use as the search icon. Defaults to `"search-outline"` in the `"ios"` theme and `"search-sharp"` in the `"md"` and `"ionic"` themes.
|
||||
*/
|
||||
"searchIcon"?: string;
|
||||
/**
|
||||
* Set to `"soft"` for a searchbar with slightly rounded corners, `"round"` for a searchbar with fully rounded corners, or `"rectangular"` for a searchbar without rounded corners. Defaults to `"round"` for the ionic theme, and `undefined` for all other themes.
|
||||
*/
|
||||
"shape"?: 'soft' | 'round' | 'rectangular';
|
||||
/**
|
||||
* Sets the behavior for the cancel button. Defaults to `"never"`. Setting to `"focus"` shows the cancel button on focus. Setting to `"never"` hides the cancel button. Setting to `"always"` shows the cancel button regardless of focus state.
|
||||
*/
|
||||
|
||||
@@ -157,3 +157,18 @@
|
||||
cursor: default;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
// Searchbar Shapes
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.searchbar-shape-soft) {
|
||||
--border-radius: #{globals.$ion-border-radius-200};
|
||||
}
|
||||
|
||||
:host(.searchbar-shape-round) {
|
||||
--border-radius: #{globals.$ion-border-radius-400};
|
||||
}
|
||||
|
||||
:host(.searchbar-shape-rectangular) {
|
||||
--border-radius: #{globals.$ion-border-radius-0};
|
||||
}
|
||||
|
||||
@@ -216,6 +216,14 @@ export class Searchbar implements ComponentInterface {
|
||||
*/
|
||||
@Prop({ mutable: true }) value?: string | null = '';
|
||||
|
||||
/**
|
||||
* Set to `"soft"` for a searchbar with slightly rounded corners,
|
||||
* `"round"` for a searchbar with fully rounded corners,
|
||||
* or `"rectangular"` for a searchbar without rounded corners.
|
||||
* Defaults to `"round"` for the ionic theme, and `undefined` for all other themes.
|
||||
*/
|
||||
@Prop() shape?: 'soft' | 'round' | 'rectangular';
|
||||
|
||||
/**
|
||||
* Emitted when the `value` of the `ion-searchbar` element has changed.
|
||||
*/
|
||||
@@ -612,6 +620,22 @@ export class Searchbar implements ComponentInterface {
|
||||
return true;
|
||||
}
|
||||
|
||||
private getShape() {
|
||||
const theme = getIonTheme(this);
|
||||
const { shape } = this;
|
||||
|
||||
// TODO(ROU-11677): Remove theme check when shapes are defined for all themes.
|
||||
if (theme !== 'ionic') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (shape === undefined) {
|
||||
return 'round';
|
||||
}
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the icon to use for the clear icon.
|
||||
* If an icon is set on the component, use that.
|
||||
@@ -698,6 +722,7 @@ export class Searchbar implements ComponentInterface {
|
||||
const animated = this.animated && config.getBoolean('animated', true);
|
||||
const theme = getIonTheme(this);
|
||||
const shouldShowCancelButton = this.shouldShowCancelButton();
|
||||
const shape = this.getShape();
|
||||
|
||||
const cancelButton = this.showCancelButton !== 'never' && (
|
||||
<button
|
||||
@@ -734,6 +759,7 @@ export class Searchbar implements ComponentInterface {
|
||||
'searchbar-has-focus': this.focused,
|
||||
'searchbar-should-show-clear': this.shouldShowClearButton(),
|
||||
'searchbar-should-show-cancel': this.shouldShowCancelButton(),
|
||||
[`searchbar-shape-${shape}`]: shape !== undefined,
|
||||
})}
|
||||
>
|
||||
<div class="searchbar-input-container">
|
||||
|
||||
34
core/src/components/searchbar/test/shape/index.html
Normal file
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Searchbar - Shape</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 class="ion-padding">
|
||||
<h5 class="ion-padding-start ion-padding-top">Search - Default</h5>
|
||||
<ion-searchbar></ion-searchbar>
|
||||
|
||||
<h5 class="ion-padding-start ion-padding-top">Search - Round</h5>
|
||||
<ion-searchbar shape="round"></ion-searchbar>
|
||||
|
||||
<h5 class="ion-padding-start ion-padding-top">Search - Soft</h5>
|
||||
<ion-searchbar shape="soft"></ion-searchbar>
|
||||
|
||||
<h5 class="ion-padding-start ion-padding-top">Search - Rectangular</h5>
|
||||
<ion-searchbar shape="rectangular"></ion-searchbar>
|
||||
</ion-content>
|
||||
</ion-app>
|
||||
</body>
|
||||
</html>
|
||||
32
core/src/components/searchbar/test/shape/searchbar.e2e.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
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: shape'), () => {
|
||||
['soft', 'round', 'rectangular'].forEach((shape) => {
|
||||
test(`${shape} - should not have visual regressions`, async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<style>
|
||||
/* Background styles to show the border radius */
|
||||
:root {
|
||||
background: #000;
|
||||
}
|
||||
</style>
|
||||
|
||||
<ion-searchbar shape="${shape}"></ion-searchbar>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const searchbar = page.locator('ion-searchbar');
|
||||
|
||||
await expect(searchbar).toHaveScreenshot(screenshot(`searchbar-shape-${shape}`));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
@@ -1900,7 +1900,7 @@ 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', 'shape', 'showCancelButton', 'showClearButton', 'spellcheck', 'theme', 'type', 'value'],
|
||||
methods: ['setFocus', 'getInputElement']
|
||||
})
|
||||
@Component({
|
||||
@@ -1908,7 +1908,7 @@ export declare interface IonRow extends Components.IonRow {}
|
||||
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', 'shape', 'showCancelButton', 'showClearButton', 'spellcheck', 'theme', 'type', 'value'],
|
||||
})
|
||||
export class IonSearchbar {
|
||||
protected el: HTMLElement;
|
||||
|
||||
@@ -737,6 +737,7 @@ export const IonSearchbar = /*@__PURE__*/ defineContainer<JSX.IonSearchbar, JSX.
|
||||
'spellcheck',
|
||||
'type',
|
||||
'value',
|
||||
'shape',
|
||||
'ionInput',
|
||||
'ionChange',
|
||||
'ionCancel',
|
||||
|
||||