From cb7560b56584ab437c84672b625a1f5f47277fed Mon Sep 17 00:00:00 2001 From: Brandy Smith <6577830+brandyscarney@users.noreply.github.com> Date: Mon, 19 Jan 2026 16:46:05 -0500 Subject: [PATCH 1/2] feat(item-option): add inner and content parts --- core/api.txt | 2 ++ core/src/components/item-option/item-option.tsx | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) 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 })} > - + -
+
From 17b4ab6cbbae2e1728b726aee2e88644d17b2fd1 Mon Sep 17 00:00:00 2001 From: Brandy Smith <6577830+brandyscarney@users.noreply.github.com> Date: Tue, 20 Jan 2026 10:06:37 -0500 Subject: [PATCH 2/2] test(item-option): add e2e test for css shadow parts --- .../test/custom/item-option.e2e.ts | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 core/src/components/item-option/test/custom/item-option.e2e.ts 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)'); + }); + }); + }); +});