From ab81f3de7e117ea11b66a84d01542d642b36f793 Mon Sep 17 00:00:00 2001 From: Maria Hutt Date: Tue, 4 Mar 2025 11:23:38 -0800 Subject: [PATCH] feat(searchbar): add sizes for ionic theme (#30211) --- core/api.txt | 1 + core/src/components.d.ts | 12 +- .../components/searchbar/searchbar.ionic.scss | 175 ++++++++++++++---- core/src/components/searchbar/searchbar.tsx | 27 +++ .../searchbar/test/basic/index.html | 13 ++ ...ionic-md-ltr-light-Mobile-Chrome-linux.png | Bin 3120 -> 3043 bytes ...onic-md-ltr-light-Mobile-Firefox-linux.png | Bin 4063 -> 4024 bytes ...ionic-md-ltr-light-Mobile-Safari-linux.png | Bin 3136 -> 3083 bytes ...ionic-md-ltr-light-Mobile-Chrome-linux.png | Bin 1760 -> 1712 bytes ...onic-md-ltr-light-Mobile-Firefox-linux.png | Bin 2104 -> 2078 bytes ...ionic-md-ltr-light-Mobile-Safari-linux.png | Bin 1734 -> 1689 bytes ...ionic-md-rtl-light-Mobile-Chrome-linux.png | Bin 1744 -> 1694 bytes ...onic-md-rtl-light-Mobile-Firefox-linux.png | Bin 2093 -> 2078 bytes ...ionic-md-rtl-light-Mobile-Safari-linux.png | Bin 1726 -> 1677 bytes ...ionic-md-ltr-light-Mobile-Chrome-linux.png | Bin 1932 -> 1889 bytes ...onic-md-ltr-light-Mobile-Firefox-linux.png | Bin 2284 -> 2257 bytes ...ionic-md-ltr-light-Mobile-Safari-linux.png | Bin 1956 -> 1918 bytes ...ionic-md-rtl-light-Mobile-Chrome-linux.png | Bin 1915 -> 1876 bytes ...onic-md-rtl-light-Mobile-Firefox-linux.png | Bin 2283 -> 2255 bytes ...ionic-md-rtl-light-Mobile-Safari-linux.png | Bin 1940 -> 1906 bytes .../components/searchbar/test/size/index.html | 34 ++++ .../searchbar/test/size/searchbar.e2e.ts | 25 +++ ...ionic-md-ltr-light-Mobile-Chrome-linux.png | Bin 0 -> 2144 bytes ...onic-md-ltr-light-Mobile-Firefox-linux.png | Bin 0 -> 2655 bytes ...ionic-md-ltr-light-Mobile-Safari-linux.png | Bin 0 -> 2271 bytes ...ionic-md-ltr-light-Mobile-Chrome-linux.png | Bin 0 -> 1966 bytes ...onic-md-ltr-light-Mobile-Firefox-linux.png | Bin 0 -> 2402 bytes ...ionic-md-ltr-light-Mobile-Safari-linux.png | Bin 0 -> 2064 bytes ...ionic-md-ltr-light-Mobile-Chrome-linux.png | Bin 0 -> 1917 bytes ...onic-md-ltr-light-Mobile-Firefox-linux.png | Bin 0 -> 2295 bytes ...ionic-md-ltr-light-Mobile-Safari-linux.png | Bin 0 -> 2019 bytes ...ionic-md-ltr-light-Mobile-Chrome-linux.png | Bin 1771 -> 1746 bytes ...onic-md-ltr-light-Mobile-Firefox-linux.png | Bin 2124 -> 2117 bytes ...ionic-md-ltr-light-Mobile-Safari-linux.png | Bin 1773 -> 1755 bytes ...ionic-md-ltr-light-Mobile-Chrome-linux.png | Bin 2106 -> 2023 bytes ...onic-md-ltr-light-Mobile-Firefox-linux.png | Bin 2542 -> 2449 bytes ...ionic-md-ltr-light-Mobile-Safari-linux.png | Bin 2074 -> 2018 bytes ...ionic-md-ltr-light-Mobile-Chrome-linux.png | Bin 2320 -> 2214 bytes ...onic-md-ltr-light-Mobile-Firefox-linux.png | Bin 2894 -> 2793 bytes ...ionic-md-ltr-light-Mobile-Safari-linux.png | Bin 2458 -> 2361 bytes ...ionic-md-ltr-light-Mobile-Chrome-linux.png | Bin 2695 -> 2707 bytes ...onic-md-ltr-light-Mobile-Firefox-linux.png | Bin 3380 -> 3384 bytes ...ionic-md-ltr-light-Mobile-Safari-linux.png | Bin 2695 -> 2665 bytes packages/angular/src/directives/proxies.ts | 4 +- packages/vue/src/proxies.ts | 1 + 45 files changed, 254 insertions(+), 38 deletions(-) create mode 100644 core/src/components/searchbar/test/size/index.html create mode 100644 core/src/components/searchbar/test/size/searchbar.e2e.ts create mode 100644 core/src/components/searchbar/test/size/searchbar.e2e.ts-snapshots/searchbar-size-large-ionic-md-ltr-light-Mobile-Chrome-linux.png create mode 100644 core/src/components/searchbar/test/size/searchbar.e2e.ts-snapshots/searchbar-size-large-ionic-md-ltr-light-Mobile-Firefox-linux.png create mode 100644 core/src/components/searchbar/test/size/searchbar.e2e.ts-snapshots/searchbar-size-large-ionic-md-ltr-light-Mobile-Safari-linux.png create mode 100644 core/src/components/searchbar/test/size/searchbar.e2e.ts-snapshots/searchbar-size-medium-ionic-md-ltr-light-Mobile-Chrome-linux.png create mode 100644 core/src/components/searchbar/test/size/searchbar.e2e.ts-snapshots/searchbar-size-medium-ionic-md-ltr-light-Mobile-Firefox-linux.png create mode 100644 core/src/components/searchbar/test/size/searchbar.e2e.ts-snapshots/searchbar-size-medium-ionic-md-ltr-light-Mobile-Safari-linux.png create mode 100644 core/src/components/searchbar/test/size/searchbar.e2e.ts-snapshots/searchbar-size-small-ionic-md-ltr-light-Mobile-Chrome-linux.png create mode 100644 core/src/components/searchbar/test/size/searchbar.e2e.ts-snapshots/searchbar-size-small-ionic-md-ltr-light-Mobile-Firefox-linux.png create mode 100644 core/src/components/searchbar/test/size/searchbar.e2e.ts-snapshots/searchbar-size-small-ionic-md-ltr-light-Mobile-Safari-linux.png diff --git a/core/api.txt b/core/api.txt index 213baad7f7..803e5cab56 100644 --- a/core/api.txt +++ b/core/api.txt @@ -1890,6 +1890,7 @@ 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,size,"large" | "medium" | "small" | undefined,undefined,false,false ion-searchbar,prop,spellcheck,boolean,false,false,false ion-searchbar,prop,theme,"ios" | "md" | "ionic",undefined,false,false ion-searchbar,prop,type,"email" | "number" | "password" | "search" | "tel" | "text" | "url",'search',false,false diff --git a/core/src/components.d.ts b/core/src/components.d.ts index 8f00696077..e1290295a1 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -3113,7 +3113,7 @@ export namespace Components { */ "setFocus": () => Promise; /** - * 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. + * 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'; /** @@ -3124,6 +3124,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, while "small" and "medium" provide progressively smaller heights. Defaults to `"medium"` for the ionic theme, and `undefined` for all other themes. + */ + "size"?: 'small' | 'medium' | 'large'; /** * If `true`, enable spellcheck on the input. */ @@ -8528,7 +8532,7 @@ declare namespace LocalJSX { */ "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. + * 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'; /** @@ -8539,6 +8543,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, while "small" and "medium" provide progressively smaller heights. Defaults to `"medium"` for the ionic theme, and `undefined` for all other themes. + */ + "size"?: 'small' | 'medium' | 'large'; /** * If `true`, enable spellcheck on the input. */ diff --git a/core/src/components/searchbar/searchbar.ionic.scss b/core/src/components/searchbar/searchbar.ionic.scss index 35040d293d..deeb07ed73 100644 --- a/core/src/components/searchbar/searchbar.ionic.scss +++ b/core/src/components/searchbar/searchbar.ionic.scss @@ -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; } @@ -39,25 +36,7 @@ // ----------------------------------------- .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( - 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; } @@ -66,9 +45,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; @@ -83,13 +59,8 @@ // ----------------------------------------- .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); + width: globals.$ion-scale-400; + height: globals.$ion-scale-400; background-color: transparent; @@ -102,7 +73,11 @@ .searchbar-search-icon, .searchbar-clear-button, .searchbar-cancel-button { + @include globals.position(50%, null); + position: absolute; + + transform: translateY(-50%); } // Clear Icon & Cancel Icon @@ -120,8 +95,25 @@ // Searchbar in Toolbar // ----------------------------------------- -:host-context(ion-toolbar) { - min-height: globals.$ion-scale-1200; +:host-context(ion-toolbar).searchbar-should-show-cancel .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 regardless of + * the searchbar size. + */ + @include globals.position-horizontal(9px, null); +} + +:host-context(ion-toolbar).searchbar-should-show-cancel .searchbar-input { + /** + * Padding start is based on + * the alignment of the back button, + * the size of the leading icon (search or cancel), + * and the gap between the icon and the input. + */ + padding-inline-start: calc(9px + globals.$ion-scale-400 + globals.$ion-space-200); } // Searchbar States @@ -172,3 +164,118 @@ :host(.searchbar-shape-rectangular) { --border-radius: #{globals.$ion-border-radius-0}; } + +// Searchbar Sizes +// -------------------------------------------------- + +/* Small */ +:host(.searchbar-size-small) .searchbar-input { + /** + * Padding start is based on + * desired padding from design, + * the size of the leading icon (search or cancel), + * and the gap between the icon and the input. + * + * Padding end is based on + * desired padding from design, + * the size of the trailing icon (clear), + * and the gap between the icon and the input. + */ + @include globals.padding-horizontal(calc(globals.$ion-space-300 + globals.$ion-scale-400 + globals.$ion-space-200)); + + height: globals.$ion-scale-1000; +} + +:host(.searchbar-size-small) .searchbar-search-icon, +:host(.searchbar-size-small) .searchbar-cancel-button { + // Start is based on the desired padding start from design. + @include globals.position-horizontal(globals.$ion-space-300, null); +} + +:host(.searchbar-size-small) .searchbar-clear-button { + // End is based on the desired padding end from design. + @include globals.position-horizontal(null, globals.$ion-space-300); +} + +/* Medium */ +:host(.searchbar-size-medium) .searchbar-input { + /** + * Padding start is based on + * desired padding from design, + * the size of the leading icon (search or cancel), + * and the gap between the icon and the input. + * + * Padding end is based on + * desired padding from design, + * the size of the trailing icon (clear), + * 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)); + + 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-space-400); +} + +/* Large */ +:host(.searchbar-size-large) .searchbar-search-icon, +:host(.searchbar-size-large) .searchbar-cancel-button { + width: globals.$ion-scale-500; + height: globals.$ion-scale-500; +} + +:host(.searchbar-size-large) .searchbar-cancel-button { + font-size: globals.$ion-font-size-500; +} + +:host-context(ion-toolbar).searchbar-size-large.searchbar-should-show-cancel .searchbar-input { + /** + * Padding start is based on + * the alignment of the back button, + * the size of the leading icon (search or cancel), + * and the gap between the icon and the input. + */ + padding-inline-start: calc(9px + globals.$ion-scale-500 + globals.$ion-space-200); +} + +:host(.searchbar-size-large) .searchbar-input { + @include globals.padding(globals.$ion-space-400, null); + + /** + * Padding start is based on + * desired padding from design, + * the size of the leading icon (search or cancel), + * and the gap between the icon and the input. + * + * Padding end is based on + * desired padding from design, + * the size of the trailing icon (clear), + * and the gap between the icon and the input. + */ + @include globals.padding-horizontal( + calc(globals.$ion-space-500 + globals.$ion-scale-500 + globals.$ion-space-200), + calc(globals.$ion-space-500 + globals.$ion-scale-400 + globals.$ion-space-200) + ); + + 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-space-500); +} diff --git a/core/src/components/searchbar/searchbar.tsx b/core/src/components/searchbar/searchbar.tsx index 352a534a16..15270c2dfd 100644 --- a/core/src/components/searchbar/searchbar.tsx +++ b/core/src/components/searchbar/searchbar.tsx @@ -220,10 +220,19 @@ export class Searchbar implements ComponentInterface { * 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'; + /** + * Set to `"large"` for a searchbar with an increase in height, + * while "small" and "medium" provide progressively smaller heights. + * + * Defaults to `"medium"` for the ionic theme, and `undefined` for all other themes. + */ + @Prop() size?: 'small' | 'medium' | 'large'; + /** * Emitted when the `value` of the `ion-searchbar` element has changed. */ @@ -636,6 +645,22 @@ export class Searchbar implements ComponentInterface { return shape; } + 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. @@ -723,6 +748,7 @@ export class Searchbar implements ComponentInterface { const theme = getIonTheme(this); const shouldShowCancelButton = this.shouldShowCancelButton(); const shape = this.getShape(); + const size = this.getSize(); const cancelButton = this.showCancelButton !== 'never' && (