diff --git a/angular/src/directives/proxies.ts b/angular/src/directives/proxies.ts index 62888e0592..00a615791f 100644 --- a/angular/src/directives/proxies.ts +++ b/angular/src/directives/proxies.ts @@ -643,8 +643,8 @@ export class IonRow { } export declare interface IonSearchbar extends Components.IonSearchbar { } -@ProxyCmp({ inputs: ["animated", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "mode", "placeholder", "searchIcon", "showCancelButton", "spellcheck", "type", "value"], "methods": ["setFocus", "getInputElement"] }) -@Component({ selector: "ion-searchbar", changeDetection: ChangeDetectionStrategy.OnPush, template: "", inputs: ["animated", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "mode", "placeholder", "searchIcon", "showCancelButton", "spellcheck", "type", "value"] }) +@ProxyCmp({ inputs: ["animated", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "mode", "placeholder", "searchIcon", "showCancelButton", "showClearButton", "spellcheck", "type", "value"], "methods": ["setFocus", "getInputElement"] }) +@Component({ selector: "ion-searchbar", changeDetection: ChangeDetectionStrategy.OnPush, template: "", inputs: ["animated", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "mode", "placeholder", "searchIcon", "showCancelButton", "showClearButton", "spellcheck", "type", "value"] }) export class IonSearchbar { ionInput!: EventEmitter; ionChange!: EventEmitter; diff --git a/core/api.txt b/core/api.txt index 19dfb8f108..77c6bf1bc5 100644 --- a/core/api.txt +++ b/core/api.txt @@ -987,6 +987,7 @@ ion-searchbar,prop,mode,"ios" | "md",undefined,false,false ion-searchbar,prop,placeholder,string,'Search',false,false ion-searchbar,prop,searchIcon,string | undefined,undefined,false,false ion-searchbar,prop,showCancelButton,"always" | "focus" | "never",'never',false,false +ion-searchbar,prop,showClearButton,"always" | "focus" | "never",'focus',false,false ion-searchbar,prop,spellcheck,boolean,false,false,false ion-searchbar,prop,type,"email" | "number" | "password" | "search" | "tel" | "text" | "url",'search',false,false ion-searchbar,prop,value,null | string | undefined,'',false,false diff --git a/core/src/components.d.ts b/core/src/components.d.ts index c1459603ce..a91597b370 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -2034,6 +2034,10 @@ export namespace Components { * 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. */ "showCancelButton": 'never' | 'focus' | 'always'; + /** + * 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'; /** * If `true`, enable spellcheck on the input. */ @@ -5336,6 +5340,10 @@ declare namespace LocalJSX { * 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. */ "showCancelButton"?: 'never' | 'focus' | 'always'; + /** + * 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'; /** * If `true`, enable spellcheck on the input. */ diff --git a/core/src/components/searchbar/readme.md b/core/src/components/searchbar/readme.md index 444f5c7226..8b1bbfcb2b 100644 --- a/core/src/components/searchbar/readme.md +++ b/core/src/components/searchbar/readme.md @@ -328,6 +328,7 @@ export default defineComponent({ | `placeholder` | `placeholder` | Set the input's placeholder. `placeholder` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) | `string` | `'Search'` | | `searchIcon` | `search-icon` | The icon to use as the search icon. Defaults to `"search-outline"` in `ios` mode and `"search-sharp"` in `md` mode. | `string \| undefined` | `undefined` | | `showCancelButton` | `show-cancel-button` | 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. | `"always" \| "focus" \| "never"` | `'never'` | +| `showClearButton` | `show-clear-button` | 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. | `"always" \| "focus" \| "never"` | `'focus'` | | `spellcheck` | `spellcheck` | If `true`, enable spellcheck on the input. | `boolean` | `false` | | `type` | `type` | Set the type of the input. | `"email" \| "number" \| "password" \| "search" \| "tel" \| "text" \| "url"` | `'search'` | | `value` | `value` | the value of the searchbar. | `null \| string \| undefined` | `''` | diff --git a/core/src/components/searchbar/searchbar.scss b/core/src/components/searchbar/searchbar.scss index 0b102ff9ea..3e4b2c1ef2 100644 --- a/core/src/components/searchbar/searchbar.scss +++ b/core/src/components/searchbar/searchbar.scss @@ -145,7 +145,7 @@ appearance: none; } -:host(.searchbar-has-value.searchbar-has-focus) .searchbar-clear-button { +:host(.searchbar-has-value.searchbar-should-show-clear) .searchbar-clear-button { display: block; } diff --git a/core/src/components/searchbar/searchbar.tsx b/core/src/components/searchbar/searchbar.tsx index 57b5842340..20eb9ff56a 100644 --- a/core/src/components/searchbar/searchbar.tsx +++ b/core/src/components/searchbar/searchbar.tsx @@ -121,6 +121,16 @@ export class Searchbar implements ComponentInterface { */ @Prop() showCancelButton: 'never' | 'focus' | 'always' = 'never'; + /** + * 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. + */ + @Prop() showClearButton: 'never' | 'focus' | 'always' = 'focus'; + /** * If `true`, enable spellcheck on the input. */ @@ -231,7 +241,7 @@ export class Searchbar implements ComponentInterface { /** * Clears the input field and triggers the control change. */ - private onClearInput = (ev?: Event) => { + private onClearInput = (ev?: Event, shouldFocus?: boolean) => { this.ionClear.emit(); if (ev) { @@ -246,6 +256,16 @@ export class Searchbar implements ComponentInterface { if (value !== '') { this.value = ''; this.ionInput.emit(); + + /** + * When tapping clear button + * ensure input is focused after + * clearing input so users + * can quickly start typing. + */ + if (shouldFocus && !this.focused) { + this.setFocus(); + } } }, 16 * 4); } @@ -419,6 +439,20 @@ export class Searchbar implements ComponentInterface { return true; } + /** + * Determines whether or not the clear button should be visible onscreen. + * Clear button should be shown if one of two conditions applies: + * 1. `showClearButton` is set to `always`. + * 2. `showClearButton` is set to `focus`, and the searchbar has been focused. + */ + private shouldShowClearButton(): boolean { + if ((this.showClearButton === 'never') || (this.showClearButton === 'focus' && !this.focused)) { + return false; + } + + return true; + } + render() { const { cancelButtonText } = this; const animated = this.animated && config.getBoolean('animated', true); @@ -460,6 +494,7 @@ export class Searchbar implements ComponentInterface { 'searchbar-has-value': this.hasValue(), 'searchbar-left-aligned': this.shouldAlignLeft, 'searchbar-has-focus': this.focused, + 'searchbar-should-show-clear': this.shouldShowClearButton(), 'searchbar-should-show-cancel': this.shouldShowCancelButton() })} > @@ -492,8 +527,8 @@ export class Searchbar implements ComponentInterface { type="button" no-blur class="searchbar-clear-button" - onMouseDown={this.onClearInput} - onTouchStart={this.onClearInput} + onMouseDown={ev => this.onClearInput(ev, true)} + onTouchStart={ev => this.onClearInput(ev, true)} > diff --git a/core/src/components/searchbar/test/basic/index.html b/core/src/components/searchbar/test/basic/index.html index aaf0a19870..b27558af8b 100644 --- a/core/src/components/searchbar/test/basic/index.html +++ b/core/src/components/searchbar/test/basic/index.html @@ -49,6 +49,14 @@ +
Search - No Clear Button
+ + + +
Search - Always Show Clear Button
+ + +
Search - Input mode set to numeric
diff --git a/packages/vue/src/proxies.ts b/packages/vue/src/proxies.ts index e8bda1f50a..a1f79c4db2 100644 --- a/packages/vue/src/proxies.ts +++ b/packages/vue/src/proxies.ts @@ -544,6 +544,7 @@ export const IonSearchbar = /*@__PURE__*/ defineContainer('ion 'placeholder', 'searchIcon', 'showCancelButton', + 'showClearButton', 'spellcheck', 'type', 'value',