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,14 +1757,17 @@ 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
ion-select,part,icon
ion-select,part,inner
ion-select,part,label
ion-select,part,placeholder
ion-select,part,supporting-text
ion-select,part,text
ion-select,part,wrapper

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 inner - The inner element of the wrapper that manages the slots, selected values or placeholder, and toggle icons.
*/
@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">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is likely fine, let's just make sure we all agree on this name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on the our internal conversation, this works.

{this.renderLabelContainer()}
<div class="select-wrapper-inner">
<div class="select-wrapper-inner" part="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(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