Skip to content

Commit

Permalink
fix: prevent click event loop on form-associated custom element (#1238
Browse files Browse the repository at this point in the history
)

Co-authored-by: Katja Potensky <785327-hesxenon@users.noreply.gitlab.com>
Co-authored-by: Philipp Fritsche <ph.fritsche@gmail.com>
  • Loading branch information
3 people authored Jan 21, 2025
1 parent 65c1f6c commit 465fc7e
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/event/behavior/click.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {behavior} from './registry'
behavior.click = (event, target, instance) => {
const context = target.closest('button,input,label,select,textarea')
const control = context && isElementType(context, 'label') && context.control
if (control) {
if (control && control !== target) {
return () => {
if (isFocusable(control)) {
focusElement(control)
Expand Down
32 changes: 31 additions & 1 deletion tests/pointer/click.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {setup} from '#testHelpers'
import {isJsdomEnv, setup} from '#testHelpers'

test('click element', async () => {
const {element, getClickEventsSnapshot, getEvents, user} = setup('<div />')
Expand Down Expand Up @@ -236,6 +236,29 @@ describe('label', () => {
expect(getEvents('click')).toHaveLength(2)
})

test('click nested FACE per label', async () => {
const {element, getEvents, user} = setup(`<label><fa-ce></fa-ce></label>`)

await user.pointer({
keys: '[MouseLeft]',
target: element,
})

// JSDOM does not set `HTMLLabelElement.control` to the form-associated custom element
expect(getEvents('click')).toHaveLength(isJsdomEnv() ? 1 : 2)
})

test('click nested FACE', async () => {
const {element, getEvents, user} = setup(`<label><fa-ce></fa-ce></label>`)

await user.pointer({
keys: '[MouseLeft]',
target: element.firstChild as Element,
})

expect(getEvents('click')).toHaveLength(1)
})

test('do not click associated non-focusable control per label', async () => {
const {element, getEvents, user} = setup(
`<label for="in">foo</label><input disabled id="in"/>`,
Expand Down Expand Up @@ -404,3 +427,10 @@ test('preventDefault on pointer down prevents compatibility events works with po
`)
expect(getEvents('click')).toHaveLength(1)
})

customElements.define(
'fa-ce',
class FaCe extends globalThis.window.HTMLElement {
static formAssociated = true
},
)

0 comments on commit 465fc7e

Please sign in to comment.