fix(item): emit click event once when clicking padded space on item and emit correct element (#30373)

Issue number: resolves #29758 resolves #29761

---------

## What is the current behavior?

When an `ion-item` has a click event listener, the following issues
occur:

1. **Double Click Events**:
- Clicking the padding around interactive elements (`ion-checkbox`,
`ion-toggle`, `ion-radio`, `ion-textarea`, `ion-input`) triggers the
click event twice.
2. **Incorrect Event Targets**:
- For `ion-input` and `ion-textarea`, clicking their native inputs
reports the wrong element as the event target.
- Clicking the padding within the `native-wrapper` of `ion-input` emits
a separate click event with an incorrect target element.

## What is the new behavior?
- Fires `firstInteractive.click()` in Item for all interactives (no
longer excludes input/textarea).
- Stops immediate propagation in item when the click event is in the
padding of an item, preventing two click events from firing.
- Updates input and textarea to always emit from their host elements
`ion-input`/`ion-textarea` instead of the native input elements.
- Updates input to make the native input take up 100% height. This is
necessary to avoid the `native-wrapper` triggering its own click event
when clicking on its padding.
- Adds e2e tests to check for the above behavior to avoid future
regressions.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

## Other information

**Dev build**: `8.5.6-dev.11745613928.16440384`

**Previews**:
- [Checkbox
Preview](https://ionic-framework-git-fw-6503-ionic1.vercel.app/src/components/checkbox/test/item)
- [Input
Preview](https://ionic-framework-git-fw-6503-ionic1.vercel.app/src/components/input/test/item)
- [Radio
Preview](https://ionic-framework-git-fw-6503-ionic1.vercel.app/src/components/radio/test/item)
- [Select
Preview](https://ionic-framework-git-fw-6503-ionic1.vercel.app/src/components/select/test/item)
- [Textarea
Preview](https://ionic-framework-git-fw-6503-ionic1.vercel.app/src/components/textarea/test/item)
- [Toggle
Preview](https://ionic-framework-git-fw-6503-ionic1.vercel.app/src/components/toggle/test/item)

---------

Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
This commit is contained in:
Brandy Smith
2025-04-30 13:12:54 -04:00
committed by GitHub
parent 8ef79cf4fb
commit 7a9d138e3d
12 changed files with 437 additions and 64 deletions

View File

@ -78,9 +78,16 @@ configs({ directions: ['ltr'], modes: ['md'] }).forEach(({ title, screenshot, co
await expect(list).toHaveScreenshot(screenshot(`radio-stacked-label-in-item`));
});
});
});
test.describe(title('radio: ionChange'), () => {
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
test.describe(title('radio: item functionality'), () => {
test('clicking padded space within item should click the radio', async ({ page }) => {
test.info().annotations.push({
type: 'issue',
description: 'https://github.com/ionic-team/ionic-framework/issues/27169',
});
await page.setContent(
`
<ion-radio-group>
@ -93,11 +100,11 @@ configs({ directions: ['ltr'], modes: ['md'] }).forEach(({ title, screenshot, co
`,
config
);
const itemNative = page.locator('.item-native');
const item = page.locator('ion-item');
const ionChange = await page.spyOnEvent('ionChange');
// Clicks the padded space within the item
await itemNative.click({
await item.click({
position: {
x: 5,
y: 5,
@ -106,5 +113,40 @@ configs({ directions: ['ltr'], modes: ['md'] }).forEach(({ title, screenshot, co
expect(ionChange).toHaveReceivedEvent();
});
test('clicking padded space within item should fire one click event', async ({ page }) => {
test.info().annotations.push({
type: 'issue',
description: 'https://github.com/ionic-team/ionic-framework/issues/29758',
});
await page.setContent(
`
<ion-item>
<ion-radio>
Radio
</ion-radio>
</ion-item>
`,
config
);
const item = page.locator('ion-item');
const onClick = await page.spyOnEvent('click');
// Click the padding area (5px from left edge)
await item.click({
position: {
x: 5,
y: 5,
},
});
expect(onClick).toHaveReceivedEventTimes(1);
// Verify that the event target is the radio and not the item
const event = onClick.events[0];
expect((event.target as HTMLElement).tagName.toLowerCase()).toBe('ion-radio');
});
});
});