mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
feat(item-option): add inner and container parts (#30929)
Issue number: N/A --------- ## What is the current behavior? The inner structural elements of item-option are not exposed as shadow parts, preventing users from being able to customize their styles directly. ## What is the new behavior? - Exposes `inner` and `container` shadow parts - Adds e2e test coverage for customizing the shadow parts ## Does this introduce a breaking change? - [ ] Yes - [x] No --------- Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
This commit is contained in:
@@ -987,6 +987,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
|
||||
|
||||
@@ -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 wrapper element that arranges 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
|
||||
})}
|
||||
>
|
||||
<TagType {...attrs} class="button-native" part="native" disabled={disabled}>
|
||||
<span class="button-inner">
|
||||
<span class="button-inner" part="inner">
|
||||
<slot name="top"></slot>
|
||||
<div class="horizontal-wrapper">
|
||||
<div class="horizontal-wrapper" part="container">
|
||||
<slot name="start"></slot>
|
||||
<slot name="icon-only"></slot>
|
||||
<slot></slot>
|
||||
|
||||
@@ -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('CSS shadow parts', () => {
|
||||
test('should be able to customize native part', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<style>
|
||||
ion-item-option::part(native) {
|
||||
background-color: red;
|
||||
}
|
||||
</style>
|
||||
|
||||
<ion-item-option>Option</ion-item-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(
|
||||
`
|
||||
<style>
|
||||
ion-item-option::part(inner) {
|
||||
background-color: green;
|
||||
}
|
||||
</style>
|
||||
|
||||
<ion-item-option>Option</ion-item-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(
|
||||
`
|
||||
<style>
|
||||
ion-item-option::part(container) {
|
||||
background-color: blue;
|
||||
}
|
||||
</style>
|
||||
|
||||
<ion-item-option>Option</ion-item-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)');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user