Skip to content

Commit

Permalink
Merge pull request #713 from KittyGiraudel/openers-closers-shadow-bou…
Browse files Browse the repository at this point in the history
…ndaries

 Fix web components as openers/closers not working properly
  • Loading branch information
KittyGiraudel authored Sep 9, 2024
2 parents 1afc984 + 7a203e4 commit d0cfeed
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 18 deletions.
8 changes: 4 additions & 4 deletions cypress/e2e/webComponents.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,22 @@ describe('Web Components', () => {
const handlers = {
show: event => {
expect(event.detail.target.tagName).to.eq('MY-DIALOG')
expect(event.detail.composedPath()[0].tagName).to.eq('FANCY-BUTTON')
expect(event.detail.composedPath()[0].tagName).to.eq('SLOT')
},
hide: event => {
expect(event.detail.target.tagName).to.eq('MY-DIALOG')
expect(event.detail.composedPath()[0].tagName).to.eq('FANCY-BUTTON')
expect(event.detail.composedPath()[0].tagName).to.eq('SLOT')
},
}

cy.spy(handlers, 'show').as('show')
cy.spy(handlers, 'hide').as('hide')
cy.window().its('instance').invoke('on', 'show', handlers.show)
cy.window().its('instance').invoke('on', 'hide', handlers.hide)
cy.get('my-dialog').shadow().find('fancy-button').first().click()
cy.get('my-dialog').shadow().find('fancy-button').first().realClick()
cy.get('@show').should('have.been.called')
cy.get('my-dialog').then(shouldBeVisible)
cy.get('my-dialog').shadow().find('fancy-button').last().click()
cy.get('my-dialog').shadow().find('fancy-button').last().realClick()
cy.get('@hide').should('have.been.called')
cy.get('my-dialog').then(shouldBeHidden)
cy.window().its('instance').invoke('off', 'show', handlers.show)
Expand Down
27 changes: 13 additions & 14 deletions src/a11y-dialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,20 +192,19 @@ export default class A11yDialog {
// target
// See: https://github.com/KittyGiraudel/a11y-dialog/issues/582
const target = event.composedPath()[0] as HTMLElement

// We use `.closest(..)` and not `.matches(..)` here so that clicking
// an element nested within a dialog opener does cause the dialog to open
if (target.closest(`[${SCOPE}-show="${this.id}"]`)) {
this.show(event)
}

if (
target.closest(`[${SCOPE}-hide="${this.id}"]`) ||
(target.closest(`[${SCOPE}-hide]`) &&
target.closest('[aria-modal="true"]') === this.$el)
) {
this.hide(event)
}
const opener = closest(`[${SCOPE}-show="${this.id}"]`, target)
const explicitCloser = closest(`[${SCOPE}-hide="${this.id}"]`, target)
const implicitCloser =
closest(`[${SCOPE}-hide]`, target) &&
closest('[aria-modal="true"]', target) === this.$el

// We use `closest(..)` (instead of `matches(..)`) so that clicking an
// element nested within a dialog opener does cause the dialog to open, and
// we use our custom `closest(..)` function so that it can cross shadow
// boundaries
// See: https://github.com/KittyGiraudel/a11y-dialog/issues/712
if (opener) this.show(event)
if (explicitCloser || implicitCloser) this.hide(event)
}

/**
Expand Down

0 comments on commit d0cfeed

Please sign in to comment.