Merge branch 'main' into chore/update-from-main

This commit is contained in:
Brandy Smith
2025-06-04 10:33:07 -04:00
54 changed files with 863 additions and 375 deletions

View File

@ -720,6 +720,18 @@ export class Input implements ComponentInterface {
return this.label !== undefined || this.labelSlot !== null;
}
/**
* Stops propagation when the label is clicked,
* otherwise, two clicks will be triggered.
*/
private onLabelClick = (ev: MouseEvent) => {
// Only stop propagation if the click was directly on the label
// and not on the input or other child elements
if (ev.target === ev.currentTarget) {
ev.stopPropagation();
}
};
/**
* Renders the border container
* when fill="outline".
@ -815,9 +827,9 @@ export class Input implements ComponentInterface {
* interactable, clicking the label would focus that instead
* since it comes before the input in the DOM.
*/}
<label class="input-wrapper" htmlFor={inputId}>
<label class="input-wrapper" htmlFor={inputId} onClick={this.onLabelClick}>
{this.renderLabelContainer()}
<div class="native-wrapper">
<div class="native-wrapper" onClick={this.onLabelClick}>
<slot name="start"></slot>
<input
class="native-input"

View File

@ -130,4 +130,81 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, screenshot, c
await expect(item).toHaveScreenshot(screenshot(`input-with-clear-button-item-color`));
});
});
test.describe(title('input: click'), () => {
test('should trigger onclick only once when clicking the label', async ({ page }, testInfo) => {
testInfo.annotations.push({
type: 'issue',
description: 'https://github.com/ionic-team/ionic-framework/issues/30165',
});
// Create a spy function in page context
await page.setContent(
`
<ion-input
label="Click Me"
value="Test Value"
></ion-input>
`,
config
);
// Track calls to the exposed function
const clickEvent = await page.spyOnEvent('click');
const input = page.locator('label.input-wrapper');
// Use position to make sure we click into the label enough to trigger
// what would be the double click
await input.click({
position: {
x: 5,
y: 5,
},
});
// Verify the click was triggered exactly once
expect(clickEvent).toHaveReceivedEventTimes(1);
// Verify that the event target is the checkbox and not the item
const event = clickEvent.events[0];
expect((event.target as HTMLElement).tagName.toLowerCase()).toBe('ion-input');
});
test('should trigger onclick only once when clicking the wrapper', async ({ page }, testInfo) => {
testInfo.annotations.push({
type: 'issue',
description: 'https://github.com/ionic-team/ionic-framework/issues/30165',
});
// Create a spy function in page context
await page.setContent(
`
<ion-input
label="Click Me"
value="Test Value"
label-placement="floating"
></ion-input>
`,
config
);
// Track calls to the exposed function
const clickEvent = await page.spyOnEvent('click');
const input = page.locator('div.native-wrapper');
// Use position to make sure we click into the label enough to trigger
// what would be the double click
await input.click({
position: {
x: 1,
y: 1,
},
});
// Verify the click was triggered exactly once
expect(clickEvent).toHaveReceivedEventTimes(1);
// Verify that the event target is the checkbox and not the item
const event = clickEvent.events[0];
expect((event.target as HTMLElement).tagName.toLowerCase()).toBe('ion-input');
});
});
});