feat(select): add sizes for ionic theme (#30018)
Co-authored-by: Brandy Carney <brandyscarney@users.noreply.github.com>
@ -2065,6 +2065,7 @@ ion-select,prop,okText,string,'OK',false,false
|
|||||||
ion-select,prop,placeholder,string | undefined,undefined,false,false
|
ion-select,prop,placeholder,string | undefined,undefined,false,false
|
||||||
ion-select,prop,selectedText,null | string | undefined,undefined,false,false
|
ion-select,prop,selectedText,null | string | undefined,undefined,false,false
|
||||||
ion-select,prop,shape,"rectangular" | "round" | "soft" | undefined,undefined,false,false
|
ion-select,prop,shape,"rectangular" | "round" | "soft" | undefined,undefined,false,false
|
||||||
|
ion-select,prop,size,"large" | "medium" | "small" | undefined,undefined,false,false
|
||||||
ion-select,prop,theme,"ios" | "md" | "ionic",undefined,false,false
|
ion-select,prop,theme,"ios" | "md" | "ionic",undefined,false,false
|
||||||
ion-select,prop,toggleIcon,string | undefined,undefined,false,false
|
ion-select,prop,toggleIcon,string | undefined,undefined,false,false
|
||||||
ion-select,prop,value,any,undefined,false,false
|
ion-select,prop,value,any,undefined,false,false
|
||||||
|
8
core/src/components.d.ts
vendored
@ -3283,6 +3283,10 @@ export namespace Components {
|
|||||||
* 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.
|
* 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.
|
||||||
*/
|
*/
|
||||||
"shape"?: 'soft' | 'round' | 'rectangular';
|
"shape"?: 'soft' | 'round' | 'rectangular';
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
"size"?: 'small' | 'medium' | 'large';
|
||||||
/**
|
/**
|
||||||
* The theme determines the visual appearance of the component.
|
* The theme determines the visual appearance of the component.
|
||||||
*/
|
*/
|
||||||
@ -8707,6 +8711,10 @@ declare namespace LocalJSX {
|
|||||||
* 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.
|
* 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.
|
||||||
*/
|
*/
|
||||||
"shape"?: 'soft' | 'round' | 'rectangular';
|
"shape"?: 'soft' | 'round' | 'rectangular';
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
"size"?: 'small' | 'medium' | 'large';
|
||||||
/**
|
/**
|
||||||
* The theme determines the visual appearance of the component.
|
* The theme determines the visual appearance of the component.
|
||||||
*/
|
*/
|
||||||
|
@ -84,8 +84,6 @@
|
|||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
height: globals.$ion-scale-1200;
|
|
||||||
|
|
||||||
background: var(--background);
|
background: var(--background);
|
||||||
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@ -197,3 +195,18 @@
|
|||||||
:host(.select-shape-rectangular) {
|
:host(.select-shape-rectangular) {
|
||||||
--border-radius: #{globals.$ion-border-radius-0};
|
--border-radius: #{globals.$ion-border-radius-0};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sizes
|
||||||
|
// ----------------------------------------------------------------
|
||||||
|
|
||||||
|
:host(.select-size-small) .select-wrapper-inner {
|
||||||
|
height: globals.$ion-scale-1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host(.select-size-medium) .select-wrapper-inner {
|
||||||
|
height: globals.$ion-scale-1200;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host(.select-size-large) .select-wrapper-inner {
|
||||||
|
height: globals.$ion-scale-1400;
|
||||||
|
}
|
||||||
|
@ -204,6 +204,14 @@ export class Select implements ComponentInterface {
|
|||||||
*/
|
*/
|
||||||
@Prop({ mutable: true }) value?: any | null;
|
@Prop({ mutable: true }) value?: any | null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
@Prop() size?: 'small' | 'medium' | 'large';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emitted when the value has changed.
|
* Emitted when the value has changed.
|
||||||
*
|
*
|
||||||
@ -820,6 +828,22 @@ export class Select implements ComponentInterface {
|
|||||||
this.ionBlur.emit();
|
this.ionBlur.emit();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private getSize(): string | undefined {
|
||||||
|
const theme = getIonTheme(this);
|
||||||
|
const { size } = this;
|
||||||
|
|
||||||
|
// TODO(ROU-11370): Remove theme check when sizes are defined for all themes.
|
||||||
|
if (theme !== 'ionic') {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size === undefined) {
|
||||||
|
return 'medium';
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
private renderLabel() {
|
private renderLabel() {
|
||||||
const { label } = this;
|
const { label } = this;
|
||||||
|
|
||||||
@ -1071,6 +1095,7 @@ export class Select implements ComponentInterface {
|
|||||||
const justifyEnabled = !hasFloatingOrStackedLabel && justify !== undefined;
|
const justifyEnabled = !hasFloatingOrStackedLabel && justify !== undefined;
|
||||||
const rtl = isRTL(el) ? 'rtl' : 'ltr';
|
const rtl = isRTL(el) ? 'rtl' : 'ltr';
|
||||||
const inItem = hostContext('ion-item', this.el);
|
const inItem = hostContext('ion-item', this.el);
|
||||||
|
const size = this.getSize();
|
||||||
const shouldRenderHighlight = theme === 'md' && fill !== 'outline' && !inItem;
|
const shouldRenderHighlight = theme === 'md' && fill !== 'outline' && !inItem;
|
||||||
|
|
||||||
const hasValue = this.hasValue();
|
const hasValue = this.hasValue();
|
||||||
@ -1117,6 +1142,7 @@ export class Select implements ComponentInterface {
|
|||||||
[`select-justify-${justify}`]: justifyEnabled,
|
[`select-justify-${justify}`]: justifyEnabled,
|
||||||
[`select-shape-${shape}`]: shape !== undefined,
|
[`select-shape-${shape}`]: shape !== undefined,
|
||||||
[`select-label-placement-${labelPlacement}`]: true,
|
[`select-label-placement-${labelPlacement}`]: true,
|
||||||
|
[`select-size-${size}`]: size !== undefined,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<label class="select-wrapper" id="select-label">
|
<label class="select-wrapper" id="select-label">
|
||||||
|
69
core/src/components/select/test/size/index.html
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" dir="ltr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>Select - Size</title>
|
||||||
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
||||||
|
/>
|
||||||
|
<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>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
h2 {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: normal;
|
||||||
|
|
||||||
|
color: #6f7378;
|
||||||
|
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<ion-app>
|
||||||
|
<ion-header>
|
||||||
|
<ion-toolbar>
|
||||||
|
<ion-title>Select - Size</ion-title>
|
||||||
|
</ion-toolbar>
|
||||||
|
</ion-header>
|
||||||
|
|
||||||
|
<ion-content class="ion-padding">
|
||||||
|
<div class="grid">
|
||||||
|
<div class="grid-item">
|
||||||
|
<h2>Default</h2>
|
||||||
|
<ion-select fill="outline" label="Label" label-placement="stacked" value="filledText">
|
||||||
|
<ion-select-option value="filledText">Filled text</ion-select-option>
|
||||||
|
</ion-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid-item">
|
||||||
|
<h2>Small</h2>
|
||||||
|
<ion-select size="small" fill="outline" label="Label" label-placement="stacked" value="filledText">
|
||||||
|
<ion-select-option value="filledText">Filled text</ion-select-option>
|
||||||
|
</ion-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid-item">
|
||||||
|
<h2>Medium</h2>
|
||||||
|
<ion-select size="medium" fill="outline" label="Label" label-placement="stacked" value="filledText">
|
||||||
|
<ion-select-option value="filledText">Filled text</ion-select-option>
|
||||||
|
</ion-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid-item">
|
||||||
|
<h2>Large</h2>
|
||||||
|
<ion-select size="large" fill="outline" label="Label" label-placement="stacked" value="filledText">
|
||||||
|
<ion-select-option value="filledText">Filled text</ion-select-option>
|
||||||
|
</ion-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ion-content>
|
||||||
|
</ion-app>
|
||||||
|
</body>
|
||||||
|
</html>
|
33
core/src/components/select/test/size/select.e2e.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { expect } from '@playwright/test';
|
||||||
|
import { configs, test } from '@utils/test/playwright';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This behavior does not vary across directions.
|
||||||
|
* This behavior is only in the `ionic` theme.
|
||||||
|
*/
|
||||||
|
configs({ modes: ['ionic-md'], directions: ['ltr'] }).forEach(({ config, screenshot, title }) => {
|
||||||
|
test.describe(title('select: size'), () => {
|
||||||
|
['small', 'medium', 'large'].forEach((size) => {
|
||||||
|
test(`${size} - should not have visual regressions`, async ({ page }) => {
|
||||||
|
await page.setContent(
|
||||||
|
`
|
||||||
|
<ion-select
|
||||||
|
size="${size}"
|
||||||
|
fill="outline"
|
||||||
|
label="Label"
|
||||||
|
label-placement="stacked"
|
||||||
|
value="filledText"
|
||||||
|
>
|
||||||
|
<ion-select-option value="filledText">Filled text</ion-select-option>
|
||||||
|
</ion-select>
|
||||||
|
`,
|
||||||
|
config
|
||||||
|
);
|
||||||
|
|
||||||
|
const select = page.locator('ion-select');
|
||||||
|
|
||||||
|
await expect(select).toHaveScreenshot(screenshot(`select-size-${size}`));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 2.5 KiB |
@ -2066,7 +2066,7 @@ export declare interface IonSegmentView extends Components.IonSegmentView {
|
|||||||
|
|
||||||
|
|
||||||
@ProxyCmp({
|
@ProxyCmp({
|
||||||
inputs: ['cancelText', 'color', 'compareWith', 'disabled', 'expandedIcon', 'fill', 'interface', 'interfaceOptions', 'justify', 'label', 'labelPlacement', 'mode', 'multiple', 'name', 'okText', 'placeholder', 'selectedText', 'shape', 'theme', 'toggleIcon', 'value'],
|
inputs: ['cancelText', 'color', 'compareWith', 'disabled', 'expandedIcon', 'fill', 'interface', 'interfaceOptions', 'justify', 'label', 'labelPlacement', 'mode', 'multiple', 'name', 'okText', 'placeholder', 'selectedText', 'shape', 'size', 'theme', 'toggleIcon', 'value'],
|
||||||
methods: ['open']
|
methods: ['open']
|
||||||
})
|
})
|
||||||
@Component({
|
@Component({
|
||||||
@ -2074,7 +2074,7 @@ export declare interface IonSegmentView extends Components.IonSegmentView {
|
|||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
template: '<ng-content></ng-content>',
|
template: '<ng-content></ng-content>',
|
||||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
||||||
inputs: ['cancelText', 'color', 'compareWith', 'disabled', 'expandedIcon', 'fill', 'interface', 'interfaceOptions', 'justify', 'label', 'labelPlacement', 'mode', 'multiple', 'name', 'okText', 'placeholder', 'selectedText', 'shape', 'theme', 'toggleIcon', 'value'],
|
inputs: ['cancelText', 'color', 'compareWith', 'disabled', 'expandedIcon', 'fill', 'interface', 'interfaceOptions', 'justify', 'label', 'labelPlacement', 'mode', 'multiple', 'name', 'okText', 'placeholder', 'selectedText', 'shape', 'size', 'theme', 'toggleIcon', 'value'],
|
||||||
})
|
})
|
||||||
export class IonSelect {
|
export class IonSelect {
|
||||||
protected el: HTMLElement;
|
protected el: HTMLElement;
|
||||||
|
@ -800,6 +800,7 @@ export const IonSelect = /*@__PURE__*/ defineContainer<JSX.IonSelect, JSX.IonSel
|
|||||||
'expandedIcon',
|
'expandedIcon',
|
||||||
'shape',
|
'shape',
|
||||||
'value',
|
'value',
|
||||||
|
'size',
|
||||||
'ionChange',
|
'ionChange',
|
||||||
'ionCancel',
|
'ionCancel',
|
||||||
'ionDismiss',
|
'ionDismiss',
|
||||||
|