Skip to content

Commit 5cea5ae

Browse files
authored
feat(select): add wrapper and bottom shadow parts (#30951)
1 parent 55735df commit 5cea5ae

File tree

3 files changed

+64
-3
lines changed

3 files changed

+64
-3
lines changed

core/api.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1758,14 +1758,17 @@ ion-select,css-prop,--placeholder-opacity,ios
17581758
ion-select,css-prop,--placeholder-opacity,md
17591759
ion-select,css-prop,--ripple-color,ios
17601760
ion-select,css-prop,--ripple-color,md
1761+
ion-select,part,bottom
17611762
ion-select,part,container
17621763
ion-select,part,error-text
17631764
ion-select,part,helper-text
17641765
ion-select,part,icon
1766+
ion-select,part,inner
17651767
ion-select,part,label
17661768
ion-select,part,placeholder
17671769
ion-select,part,supporting-text
17681770
ion-select,part,text
1771+
ion-select,part,wrapper
17691772

17701773
ion-select-modal,scoped
17711774
ion-select-modal,prop,cancelText,string,'Close',false,false

core/src/components/select/select.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ import type { SelectChangeEventDetail, SelectInterface, SelectCompareFn } from '
4545
* @part supporting-text - Supporting text displayed beneath the select.
4646
* @part helper-text - Supporting text displayed beneath the select when the select is valid.
4747
* @part error-text - Supporting text displayed beneath the select when the select is invalid and touched.
48+
* @part bottom - The container element for helper text, error text, and counter.
49+
* @part wrapper - The clickable label element that wraps the entire form field (label text, slots, selected values or placeholder, and toggle icons).
50+
* @part inner - The inner element of the wrapper that manages the slots, selected values or placeholder, and toggle icons.
4851
*/
4952
@Component({
5053
tag: 'ion-select',
@@ -1173,7 +1176,11 @@ export class Select implements ComponentInterface {
11731176
return;
11741177
}
11751178

1176-
return <div class="select-bottom">{this.renderHintText()}</div>;
1179+
return (
1180+
<div class="select-bottom" part="bottom">
1181+
{this.renderHintText()}
1182+
</div>
1183+
);
11771184
}
11781185

11791186
render() {
@@ -1246,9 +1253,9 @@ export class Select implements ComponentInterface {
12461253
[`select-label-placement-${labelPlacement}`]: true,
12471254
})}
12481255
>
1249-
<label class="select-wrapper" id="select-label" onClick={this.onLabelClick}>
1256+
<label class="select-wrapper" id="select-label" onClick={this.onLabelClick} part="wrapper">
12501257
{this.renderLabelContainer()}
1251-
<div class="select-wrapper-inner">
1258+
<div class="select-wrapper-inner" part="inner">
12521259
<slot name="start"></slot>
12531260
<div class="native-wrapper" ref={(el) => (this.nativeWrapperEl = el)} part="container">
12541261
{this.renderSelectText()}

core/src/components/select/test/custom/select.e2e.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,57 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
7373
await expect(wrapper).toHaveScreenshot(screenshot(`select-custom-parts-diff`));
7474
});
7575

76+
test('should be able to customize wrapper and bottom using css parts', async ({ page }) => {
77+
test.info().annotations.push({
78+
type: 'issue',
79+
description: 'https://github.com/ionic-team/ionic-framework/issues/29918',
80+
});
81+
82+
await page.setContent(
83+
`
84+
<style>
85+
ion-select::part(wrapper) {
86+
background-color: red;
87+
}
88+
89+
ion-select::part(inner) {
90+
background-color: orange;
91+
}
92+
93+
ion-select::part(bottom) {
94+
background-color: green;
95+
}
96+
</style>
97+
98+
<ion-select label="Select" label-placement="stacked" placeholder="Fruits" helper-text="Helper text">
99+
<ion-select-option value="a">Apple</ion-select-option>
100+
</ion-select>
101+
`,
102+
config
103+
);
104+
105+
const select = page.locator('ion-select');
106+
const wrapper = select.locator('.select-wrapper');
107+
const wrapperInner = select.locator('.select-wrapper-inner');
108+
const bottom = select.locator('.select-bottom');
109+
110+
const wrapperBackgroundColor = await wrapper.evaluate((el) => {
111+
return window.getComputedStyle(el).backgroundColor;
112+
});
113+
114+
const wrapperInnerBackgroundColor = await wrapperInner.evaluate((el) => {
115+
return window.getComputedStyle(el).backgroundColor;
116+
});
117+
118+
const bottomBackgroundColor = await bottom.evaluate((el) => {
119+
return window.getComputedStyle(el).backgroundColor;
120+
});
121+
122+
expect(wrapperBackgroundColor).toBe('rgb(255, 0, 0)');
123+
expect(wrapperInnerBackgroundColor).toBe('rgb(255, 165, 0)');
124+
expect(bottomBackgroundColor).toBe('rgb(0, 128, 0)');
125+
});
126+
76127
test('should render custom cancel text when prop is provided with alert interface', async ({ page }) => {
77128
await page.setContent(
78129
`

0 commit comments

Comments
 (0)