Skip to content

Commit 215eb5d

Browse files
feat(searchbar): add showClearIcon property (#22759)
resolves #22738 Co-authored-by: Liam DeBeasi <[email protected]>
1 parent 677d55e commit 215eb5d

File tree

8 files changed

+60
-6
lines changed

8 files changed

+60
-6
lines changed

angular/src/directives/proxies.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -643,8 +643,8 @@ export class IonRow {
643643
}
644644
export declare interface IonSearchbar extends Components.IonSearchbar {
645645
}
646-
@ProxyCmp({ inputs: ["animated", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "mode", "placeholder", "searchIcon", "showCancelButton", "spellcheck", "type", "value"], "methods": ["setFocus", "getInputElement"] })
647-
@Component({ selector: "ion-searchbar", changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content></ng-content>", inputs: ["animated", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "mode", "placeholder", "searchIcon", "showCancelButton", "spellcheck", "type", "value"] })
646+
@ProxyCmp({ inputs: ["animated", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "mode", "placeholder", "searchIcon", "showCancelButton", "showClearButton", "spellcheck", "type", "value"], "methods": ["setFocus", "getInputElement"] })
647+
@Component({ selector: "ion-searchbar", changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content></ng-content>", inputs: ["animated", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "mode", "placeholder", "searchIcon", "showCancelButton", "showClearButton", "spellcheck", "type", "value"] })
648648
export class IonSearchbar {
649649
ionInput!: EventEmitter<CustomEvent>;
650650
ionChange!: EventEmitter<CustomEvent>;

core/api.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -987,6 +987,7 @@ ion-searchbar,prop,mode,"ios" | "md",undefined,false,false
987987
ion-searchbar,prop,placeholder,string,'Search',false,false
988988
ion-searchbar,prop,searchIcon,string | undefined,undefined,false,false
989989
ion-searchbar,prop,showCancelButton,"always" | "focus" | "never",'never',false,false
990+
ion-searchbar,prop,showClearButton,"always" | "focus" | "never",'focus',false,false
990991
ion-searchbar,prop,spellcheck,boolean,false,false,false
991992
ion-searchbar,prop,type,"email" | "number" | "password" | "search" | "tel" | "text" | "url",'search',false,false
992993
ion-searchbar,prop,value,null | string | undefined,'',false,false

core/src/components.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2034,6 +2034,10 @@ export namespace Components {
20342034
* 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.
20352035
*/
20362036
"showCancelButton": 'never' | 'focus' | 'always';
2037+
/**
2038+
* 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.
2039+
*/
2040+
"showClearButton": 'never' | 'focus' | 'always';
20372041
/**
20382042
* If `true`, enable spellcheck on the input.
20392043
*/
@@ -5336,6 +5340,10 @@ declare namespace LocalJSX {
53365340
* 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.
53375341
*/
53385342
"showCancelButton"?: 'never' | 'focus' | 'always';
5343+
/**
5344+
* 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.
5345+
*/
5346+
"showClearButton"?: 'never' | 'focus' | 'always';
53395347
/**
53405348
* If `true`, enable spellcheck on the input.
53415349
*/

core/src/components/searchbar/readme.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ export default defineComponent({
328328
| `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 `<Ionic>` would become `&lt;Ionic&gt;` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) | `string` | `'Search'` |
329329
| `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` |
330330
| `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'` |
331+
| `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'` |
331332
| `spellcheck` | `spellcheck` | If `true`, enable spellcheck on the input. | `boolean` | `false` |
332333
| `type` | `type` | Set the type of the input. | `"email" \| "number" \| "password" \| "search" \| "tel" \| "text" \| "url"` | `'search'` |
333334
| `value` | `value` | the value of the searchbar. | `null \| string \| undefined` | `''` |

core/src/components/searchbar/searchbar.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@
145145
appearance: none;
146146
}
147147

148-
:host(.searchbar-has-value.searchbar-has-focus) .searchbar-clear-button {
148+
:host(.searchbar-has-value.searchbar-should-show-clear) .searchbar-clear-button {
149149
display: block;
150150
}
151151

core/src/components/searchbar/searchbar.tsx

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,16 @@ export class Searchbar implements ComponentInterface {
121121
*/
122122
@Prop() showCancelButton: 'never' | 'focus' | 'always' = 'never';
123123

124+
/**
125+
* Sets the behavior for the clear button. Defaults to `"focus"`.
126+
* Setting to `"focus"` shows the clear button on focus if the
127+
* input is not empty.
128+
* Setting to `"never"` hides the clear button.
129+
* Setting to `"always"` shows the clear button regardless
130+
* of focus state, but only if the input is not empty.
131+
*/
132+
@Prop() showClearButton: 'never' | 'focus' | 'always' = 'focus';
133+
124134
/**
125135
* If `true`, enable spellcheck on the input.
126136
*/
@@ -231,7 +241,7 @@ export class Searchbar implements ComponentInterface {
231241
/**
232242
* Clears the input field and triggers the control change.
233243
*/
234-
private onClearInput = (ev?: Event) => {
244+
private onClearInput = (ev?: Event, shouldFocus?: boolean) => {
235245
this.ionClear.emit();
236246

237247
if (ev) {
@@ -246,6 +256,16 @@ export class Searchbar implements ComponentInterface {
246256
if (value !== '') {
247257
this.value = '';
248258
this.ionInput.emit();
259+
260+
/**
261+
* When tapping clear button
262+
* ensure input is focused after
263+
* clearing input so users
264+
* can quickly start typing.
265+
*/
266+
if (shouldFocus && !this.focused) {
267+
this.setFocus();
268+
}
249269
}
250270
}, 16 * 4);
251271
}
@@ -419,6 +439,20 @@ export class Searchbar implements ComponentInterface {
419439
return true;
420440
}
421441

442+
/**
443+
* Determines whether or not the clear button should be visible onscreen.
444+
* Clear button should be shown if one of two conditions applies:
445+
* 1. `showClearButton` is set to `always`.
446+
* 2. `showClearButton` is set to `focus`, and the searchbar has been focused.
447+
*/
448+
private shouldShowClearButton(): boolean {
449+
if ((this.showClearButton === 'never') || (this.showClearButton === 'focus' && !this.focused)) {
450+
return false;
451+
}
452+
453+
return true;
454+
}
455+
422456
render() {
423457
const { cancelButtonText } = this;
424458
const animated = this.animated && config.getBoolean('animated', true);
@@ -460,6 +494,7 @@ export class Searchbar implements ComponentInterface {
460494
'searchbar-has-value': this.hasValue(),
461495
'searchbar-left-aligned': this.shouldAlignLeft,
462496
'searchbar-has-focus': this.focused,
497+
'searchbar-should-show-clear': this.shouldShowClearButton(),
463498
'searchbar-should-show-cancel': this.shouldShowCancelButton()
464499
})}
465500
>
@@ -492,8 +527,8 @@ export class Searchbar implements ComponentInterface {
492527
type="button"
493528
no-blur
494529
class="searchbar-clear-button"
495-
onMouseDown={this.onClearInput}
496-
onTouchStart={this.onClearInput}
530+
onMouseDown={ev => this.onClearInput(ev, true)}
531+
onTouchStart={ev => this.onClearInput(ev, true)}
497532
>
498533
<ion-icon aria-hidden="true" mode={mode} icon={clearIcon} lazy={false} class="searchbar-clear-icon"></ion-icon>
499534
</button>

core/src/components/searchbar/test/basic/index.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ <h5 class="ion-padding-start ion-padding-top"> Search - Cancel Button set to tru
4949
<ion-searchbar id="noCancel" value="after view" autocorrect="off" autocomplete="off" spellcheck="true" type="text" show-cancel-button="focus">
5050
</ion-searchbar>
5151

52+
<h5 class="ion-padding-start ion-padding-top"> Search - No Clear Button </h5>
53+
<ion-searchbar id="noCancel" value="after view" type="text" show-clear-button="never">
54+
</ion-searchbar>
55+
56+
<h5 class="ion-padding-start ion-padding-top"> Search - Always Show Clear Button </h5>
57+
<ion-searchbar id="noCancel" value="after view" type="text" show-clear-button="always">
58+
</ion-searchbar>
59+
5260
<h5 class="ion-padding-start ion-padding-top"> Search - Input mode set to numeric</h5>
5361
<ion-searchbar id="noCancel" value="after view" inputmode="numeric" autocorrect="off" autocomplete="off" spellcheck="true" type="text" show-cancel-button="focus">
5462
</ion-searchbar>

packages/vue/src/proxies.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,7 @@ export const IonSearchbar = /*@__PURE__*/ defineContainer<JSX.IonSearchbar>('ion
544544
'placeholder',
545545
'searchIcon',
546546
'showCancelButton',
547+
'showClearButton',
547548
'spellcheck',
548549
'type',
549550
'value',

0 commit comments

Comments
 (0)