Skip to content

Commit 5bf48cb

Browse files
feat(select): add sizes for ionic theme (#30018)
Co-authored-by: Brandy Carney <[email protected]>
1 parent bc3d30c commit 5bf48cb

17 files changed

+155
-4
lines changed

core/api.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2065,6 +2065,7 @@ ion-select,prop,okText,string,'OK',false,false
20652065
ion-select,prop,placeholder,string | undefined,undefined,false,false
20662066
ion-select,prop,selectedText,null | string | undefined,undefined,false,false
20672067
ion-select,prop,shape,"rectangular" | "round" | "soft" | undefined,undefined,false,false
2068+
ion-select,prop,size,"large" | "medium" | "small" | undefined,undefined,false,false
20682069
ion-select,prop,theme,"ios" | "md" | "ionic",undefined,false,false
20692070
ion-select,prop,toggleIcon,string | undefined,undefined,false,false
20702071
ion-select,prop,value,any,undefined,false,false

core/src/components.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3283,6 +3283,10 @@ export namespace Components {
32833283
* Set to `"soft"` for a select with slightly rounded corners, `"round"` for a select with fully rounded corners, or `"rectangular"` for a select without rounded corners. Defaults to `"round"` for the `"ionic"` theme, undefined for all other themes.
32843284
*/
32853285
"shape"?: 'soft' | 'round' | 'rectangular';
3286+
/**
3287+
* The size of the select. If "large" it will increase the height of the select, while "small" and "medium" provide progressively smaller heights. Defaults to `"medium"` for the ionic theme, and undefined for all other themes.
3288+
*/
3289+
"size"?: 'small' | 'medium' | 'large';
32863290
/**
32873291
* The theme determines the visual appearance of the component.
32883292
*/
@@ -8707,6 +8711,10 @@ declare namespace LocalJSX {
87078711
* Set to `"soft"` for a select with slightly rounded corners, `"round"` for a select with fully rounded corners, or `"rectangular"` for a select without rounded corners. Defaults to `"round"` for the `"ionic"` theme, undefined for all other themes.
87088712
*/
87098713
"shape"?: 'soft' | 'round' | 'rectangular';
8714+
/**
8715+
* The size of the select. If "large" it will increase the height of the select, while "small" and "medium" provide progressively smaller heights. Defaults to `"medium"` for the ionic theme, and undefined for all other themes.
8716+
*/
8717+
"size"?: 'small' | 'medium' | 'large';
87108718
/**
87118719
* The theme determines the visual appearance of the component.
87128720
*/

core/src/components/select/select.ionic.scss

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,6 @@
8484

8585
position: relative;
8686

87-
height: globals.$ion-scale-1200;
88-
8987
background: var(--background);
9088

9189
box-sizing: border-box;
@@ -197,3 +195,18 @@
197195
:host(.select-shape-rectangular) {
198196
--border-radius: #{globals.$ion-border-radius-0};
199197
}
198+
199+
// Sizes
200+
// ----------------------------------------------------------------
201+
202+
:host(.select-size-small) .select-wrapper-inner {
203+
height: globals.$ion-scale-1000;
204+
}
205+
206+
:host(.select-size-medium) .select-wrapper-inner {
207+
height: globals.$ion-scale-1200;
208+
}
209+
210+
:host(.select-size-large) .select-wrapper-inner {
211+
height: globals.$ion-scale-1400;
212+
}

core/src/components/select/select.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,14 @@ export class Select implements ComponentInterface {
204204
*/
205205
@Prop({ mutable: true }) value?: any | null;
206206

207+
/**
208+
* The size of the select. If "large" it will increase the height of the select, while
209+
* "small" and "medium" provide progressively smaller heights.
210+
*
211+
* Defaults to `"medium"` for the ionic theme, and undefined for all other themes.
212+
*/
213+
@Prop() size?: 'small' | 'medium' | 'large';
214+
207215
/**
208216
* Emitted when the value has changed.
209217
*
@@ -820,6 +828,22 @@ export class Select implements ComponentInterface {
820828
this.ionBlur.emit();
821829
};
822830

831+
private getSize(): string | undefined {
832+
const theme = getIonTheme(this);
833+
const { size } = this;
834+
835+
// TODO(ROU-11370): Remove theme check when sizes are defined for all themes.
836+
if (theme !== 'ionic') {
837+
return undefined;
838+
}
839+
840+
if (size === undefined) {
841+
return 'medium';
842+
}
843+
844+
return size;
845+
}
846+
823847
private renderLabel() {
824848
const { label } = this;
825849

@@ -1071,6 +1095,7 @@ export class Select implements ComponentInterface {
10711095
const justifyEnabled = !hasFloatingOrStackedLabel && justify !== undefined;
10721096
const rtl = isRTL(el) ? 'rtl' : 'ltr';
10731097
const inItem = hostContext('ion-item', this.el);
1098+
const size = this.getSize();
10741099
const shouldRenderHighlight = theme === 'md' && fill !== 'outline' && !inItem;
10751100

10761101
const hasValue = this.hasValue();
@@ -1117,6 +1142,7 @@ export class Select implements ComponentInterface {
11171142
[`select-justify-${justify}`]: justifyEnabled,
11181143
[`select-shape-${shape}`]: shape !== undefined,
11191144
[`select-label-placement-${labelPlacement}`]: true,
1145+
[`select-size-${size}`]: size !== undefined,
11201146
})}
11211147
>
11221148
<label class="select-wrapper" id="select-label">
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<!DOCTYPE html>
2+
<html lang="en" dir="ltr">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<title>Select - Size</title>
6+
<meta
7+
name="viewport"
8+
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
9+
/>
10+
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
11+
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
12+
<script src="../../../../../scripts/testing/scripts.js"></script>
13+
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
14+
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
15+
16+
<style>
17+
h2 {
18+
font-size: 12px;
19+
font-weight: normal;
20+
21+
color: #6f7378;
22+
23+
margin-top: 10px;
24+
}
25+
</style>
26+
</head>
27+
28+
<body>
29+
<ion-app>
30+
<ion-header>
31+
<ion-toolbar>
32+
<ion-title>Select - Size</ion-title>
33+
</ion-toolbar>
34+
</ion-header>
35+
36+
<ion-content class="ion-padding">
37+
<div class="grid">
38+
<div class="grid-item">
39+
<h2>Default</h2>
40+
<ion-select fill="outline" label="Label" label-placement="stacked" value="filledText">
41+
<ion-select-option value="filledText">Filled text</ion-select-option>
42+
</ion-select>
43+
</div>
44+
45+
<div class="grid-item">
46+
<h2>Small</h2>
47+
<ion-select size="small" fill="outline" label="Label" label-placement="stacked" value="filledText">
48+
<ion-select-option value="filledText">Filled text</ion-select-option>
49+
</ion-select>
50+
</div>
51+
52+
<div class="grid-item">
53+
<h2>Medium</h2>
54+
<ion-select size="medium" fill="outline" label="Label" label-placement="stacked" value="filledText">
55+
<ion-select-option value="filledText">Filled text</ion-select-option>
56+
</ion-select>
57+
</div>
58+
59+
<div class="grid-item">
60+
<h2>Large</h2>
61+
<ion-select size="large" fill="outline" label="Label" label-placement="stacked" value="filledText">
62+
<ion-select-option value="filledText">Filled text</ion-select-option>
63+
</ion-select>
64+
</div>
65+
</div>
66+
</ion-content>
67+
</ion-app>
68+
</body>
69+
</html>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { expect } from '@playwright/test';
2+
import { configs, test } from '@utils/test/playwright';
3+
4+
/**
5+
* This behavior does not vary across directions.
6+
* This behavior is only in the `ionic` theme.
7+
*/
8+
configs({ modes: ['ionic-md'], directions: ['ltr'] }).forEach(({ config, screenshot, title }) => {
9+
test.describe(title('select: size'), () => {
10+
['small', 'medium', 'large'].forEach((size) => {
11+
test(`${size} - should not have visual regressions`, async ({ page }) => {
12+
await page.setContent(
13+
`
14+
<ion-select
15+
size="${size}"
16+
fill="outline"
17+
label="Label"
18+
label-placement="stacked"
19+
value="filledText"
20+
>
21+
<ion-select-option value="filledText">Filled text</ion-select-option>
22+
</ion-select>
23+
`,
24+
config
25+
);
26+
27+
const select = page.locator('ion-select');
28+
29+
await expect(select).toHaveScreenshot(screenshot(`select-size-${size}`));
30+
});
31+
});
32+
});
33+
});
2.61 KB
Loading
3.45 KB
Loading
2.62 KB
Loading
2.57 KB
Loading

0 commit comments

Comments
 (0)