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
1 change: 1 addition & 0 deletions core/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1889,6 +1889,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
Expand Down
12 changes: 10 additions & 2 deletions core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3108,7 +3108,7 @@ export namespace Components {
*/
"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.
* 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';
/**
Expand All @@ -3119,6 +3119,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.
*/
Expand Down Expand Up @@ -8519,7 +8523,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';
/**
Expand All @@ -8530,6 +8534,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.
*/
Expand Down
167 changes: 130 additions & 37 deletions core/src/components/searchbar/searchbar.ionic.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,36 +28,15 @@
// -----------------------------------------

.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;
width: globals.$ion-scale-500;
height: globals.$ion-scale-500;
}

// Searchbar Input Field
// -----------------------------------------

.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;
}
Expand All @@ -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;

Expand All @@ -83,17 +59,12 @@
// -----------------------------------------

.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-500;
height: globals.$ion-scale-500;

background-color: transparent;

font-size: globals.$ion-font-size-400;
font-size: globals.$ion-font-size-500;
}

// Searchbar Search & Clear Icon & Cancel Icon
Expand All @@ -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
Expand All @@ -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-500 + globals.$ion-space-200);
}

// Searchbar States
Expand Down Expand Up @@ -172,3 +164,104 @@
: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-500 + globals.$ion-space-200),
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-500 + globals.$ion-space-200),
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-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);
}
27 changes: 27 additions & 0 deletions core/src/components/searchbar/searchbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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' && (
<button
Expand Down Expand Up @@ -760,6 +786,7 @@ export class Searchbar implements ComponentInterface {
'searchbar-should-show-clear': this.shouldShowClearButton(),
'searchbar-should-show-cancel': this.shouldShowCancelButton(),
[`searchbar-shape-${shape}`]: shape !== undefined,
[`searchbar-size-${size}`]: size !== undefined,
})}
>
<div class="searchbar-input-container">
Expand Down
13 changes: 13 additions & 0 deletions core/src/components/searchbar/test/basic/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,19 @@ <h5 class="ion-padding-start ion-padding-top">Search - Never Show Cancel Button<
<h5 class="ion-padding-start ion-padding-top">Search - Show Cancel Button on Focus</h5>
<ion-searchbar id="focusCancel" value="after view" animated="true" show-cancel-button="focus"> </ion-searchbar>

<h5 class="ion-padding-start ion-padding-top">Search - Show Cancel Button within Toolbar</h5>
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button default-href="#"></ion-back-button>
</ion-buttons>
<ion-title>Test</ion-title>
</ion-toolbar>
<ion-toolbar>
<ion-searchbar show-cancel-button="always"></ion-searchbar>
</ion-toolbar>
</ion-header>

<h5 class="ion-padding-start ion-padding-top">Search - No Clear Button</h5>
<ion-searchbar id="noClear" value="after view" type="text" show-clear-button="never"> </ion-searchbar>

Expand Down
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.
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.
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.
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.
34 changes: 34 additions & 0 deletions core/src/components/searchbar/test/size/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<!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 - Small</h5>
<ion-searchbar size="small" 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>
Loading
Loading