diff --git a/core/api.txt b/core/api.txt index 745d82786af..edc993c3af6 100644 --- a/core/api.txt +++ b/core/api.txt @@ -974,6 +974,8 @@ ion-item-option,css-prop,--background,ios ion-item-option,css-prop,--background,md ion-item-option,css-prop,--color,ios ion-item-option,css-prop,--color,md +ion-item-option,part,container +ion-item-option,part,inner ion-item-option,part,native ion-item-options,none diff --git a/core/src/components/item-option/item-option.tsx b/core/src/components/item-option/item-option.tsx index 81bee8b8fef..7ea1bc2fd4b 100644 --- a/core/src/components/item-option/item-option.tsx +++ b/core/src/components/item-option/item-option.tsx @@ -17,6 +17,8 @@ import type { Color } from '../../interface'; * @slot end - Content is placed to the right of the option text in LTR, and to the left in RTL. * * @part native - The native HTML button or anchor element that wraps all child elements. + * @part inner - The inner container element that wraps the option content. + * @part container - The container element that wraps the start, icon-only, default, and end slots. */ @Component({ tag: 'ion-item-option', @@ -109,9 +111,9 @@ export class ItemOption implements ComponentInterface, AnchorInterface, ButtonIn })} > - + -
+
diff --git a/core/src/components/item-option/test/custom/item-option.e2e.ts b/core/src/components/item-option/test/custom/item-option.e2e.ts new file mode 100644 index 00000000000..678f1c9d523 --- /dev/null +++ b/core/src/components/item-option/test/custom/item-option.e2e.ts @@ -0,0 +1,80 @@ +import { expect } from '@playwright/test'; +import { configs, test } from '@utils/test/playwright'; + +/** + * This behavior does not vary across modes/directions + */ +configs({ directions: ['ltr'], modes: ['md'] }).forEach(({ title, config }) => { + test.describe(title('item-option: custom'), () => { + test.describe(title('CSS shadow parts'), () => { + test('should be able to customize native part', async ({ page }) => { + await page.setContent( + ` + + + Option + `, + config + ); + + const itemOption = page.locator('ion-item-option'); + const backgroundColor = await itemOption.evaluate((el) => { + const shadowRoot = el.shadowRoot; + const native = shadowRoot?.querySelector('.button-native'); + return native ? window.getComputedStyle(native).backgroundColor : ''; + }); + expect(backgroundColor).toBe('rgb(255, 0, 0)'); + }); + + test('should be able to customize inner part', async ({ page }) => { + await page.setContent( + ` + + + Option + `, + config + ); + + const itemOption = page.locator('ion-item-option'); + const backgroundColor = await itemOption.evaluate((el) => { + const shadowRoot = el.shadowRoot; + const inner = shadowRoot?.querySelector('.button-inner'); + return inner ? window.getComputedStyle(inner).backgroundColor : ''; + }); + expect(backgroundColor).toBe('rgb(0, 128, 0)'); + }); + + test('should be able to customize container part', async ({ page }) => { + await page.setContent( + ` + + + Option + `, + config + ); + + const itemOption = page.locator('ion-item-option'); + const backgroundColor = await itemOption.evaluate((el) => { + const shadowRoot = el.shadowRoot; + const container = shadowRoot?.querySelector('.horizontal-wrapper'); + return container ? window.getComputedStyle(container).backgroundColor : ''; + }); + expect(backgroundColor).toBe('rgb(0, 0, 255)'); + }); + }); + }); +});