Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions core/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1757,6 +1757,7 @@ ion-select,css-prop,--placeholder-opacity,ios
ion-select,css-prop,--placeholder-opacity,md
ion-select,css-prop,--ripple-color,ios
ion-select,css-prop,--ripple-color,md
ion-select,part,bottom
ion-select,part,container
ion-select,part,error-text
ion-select,part,helper-text
Expand All @@ -1765,6 +1766,8 @@ ion-select,part,label
ion-select,part,placeholder
ion-select,part,supporting-text
ion-select,part,text
ion-select,part,wrapper
ion-select,part,wrapper-inner

ion-select-modal,scoped
ion-select-modal,prop,cancelText,string,'Close',false,false
Expand Down
13 changes: 10 additions & 3 deletions core/src/components/select/select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ import type { SelectChangeEventDetail, SelectInterface, SelectCompareFn } from '
* @part supporting-text - Supporting text displayed beneath the select.
* @part helper-text - Supporting text displayed beneath the select when the select is valid.
* @part error-text - Supporting text displayed beneath the select when the select is invalid and touched.
* @part bottom - The container element for helper text, error text, and counter.
* @part wrapper - The clickable label element that wraps the entire form field (label text, slots, selected values or placeholder, and toggle icons).
* @part wrapper-inner - The inner element of the wrapper that does not include the label text.
*/
@Component({
tag: 'ion-select',
Expand Down Expand Up @@ -1173,7 +1176,11 @@ export class Select implements ComponentInterface {
return;
}

return <div class="select-bottom">{this.renderHintText()}</div>;
return (
<div class="select-bottom" part="bottom">
{this.renderHintText()}
</div>
);
}

render() {
Expand Down Expand Up @@ -1246,9 +1253,9 @@ export class Select implements ComponentInterface {
[`select-label-placement-${labelPlacement}`]: true,
})}
>
<label class="select-wrapper" id="select-label" onClick={this.onLabelClick}>
<label class="select-wrapper" id="select-label" onClick={this.onLabelClick} part="wrapper">
{this.renderLabelContainer()}
<div class="select-wrapper-inner">
<div class="select-wrapper-inner" part="wrapper-inner">
<slot name="start"></slot>
<div class="native-wrapper" ref={(el) => (this.nativeWrapperEl = el)} part="container">
{this.renderSelectText()}
Expand Down
51 changes: 51 additions & 0 deletions core/src/components/select/test/custom/select.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,57 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
await expect(wrapper).toHaveScreenshot(screenshot(`select-custom-parts-diff`));
});

test('should be able to customize wrapper and bottom using css parts', async ({ page }) => {
test.info().annotations.push({
type: 'issue',
description: 'https://github.com/ionic-team/ionic-framework/issues/29918',
});

await page.setContent(
`
<style>
ion-select::part(wrapper) {
background-color: red;
}

ion-select::part(wrapper-inner) {
background-color: orange;
}

ion-select::part(bottom) {
background-color: green;
}
</style>

<ion-select label="Select" label-placement="stacked" placeholder="Fruits" helper-text="Helper text">
<ion-select-option value="a">Apple</ion-select-option>
</ion-select>
`,
config
);

const select = page.locator('ion-select');
const wrapper = select.locator('.select-wrapper');
const wrapperInner = select.locator('.select-wrapper-inner');
const bottom = select.locator('.select-bottom');

const wrapperBackgroundColor = await wrapper.evaluate((el) => {
return window.getComputedStyle(el).backgroundColor;
});

const wrapperInnerBackgroundColor = await wrapperInner.evaluate((el) => {
return window.getComputedStyle(el).backgroundColor;
});

const bottomBackgroundColor = await bottom.evaluate((el) => {
return window.getComputedStyle(el).backgroundColor;
});

expect(wrapperBackgroundColor).toBe('rgb(255, 0, 0)');
expect(wrapperInnerBackgroundColor).toBe('rgb(255, 165, 0)');
expect(bottomBackgroundColor).toBe('rgb(0, 128, 0)');
});

test('should render custom cancel text when prop is provided with alert interface', async ({ page }) => {
await page.setContent(
`
Expand Down
Loading