Skip to content

Commit d0cfeed

Browse files
Merge pull request #713 from KittyGiraudel/openers-closers-shadow-boundaries
Fix web components as openers/closers not working properly
2 parents 1afc984 + 7a203e4 commit d0cfeed

File tree

2 files changed

+17
-18
lines changed

2 files changed

+17
-18
lines changed

cypress/e2e/webComponents.cy.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,22 +37,22 @@ describe('Web Components', () => {
3737
const handlers = {
3838
show: event => {
3939
expect(event.detail.target.tagName).to.eq('MY-DIALOG')
40-
expect(event.detail.composedPath()[0].tagName).to.eq('FANCY-BUTTON')
40+
expect(event.detail.composedPath()[0].tagName).to.eq('SLOT')
4141
},
4242
hide: event => {
4343
expect(event.detail.target.tagName).to.eq('MY-DIALOG')
44-
expect(event.detail.composedPath()[0].tagName).to.eq('FANCY-BUTTON')
44+
expect(event.detail.composedPath()[0].tagName).to.eq('SLOT')
4545
},
4646
}
4747

4848
cy.spy(handlers, 'show').as('show')
4949
cy.spy(handlers, 'hide').as('hide')
5050
cy.window().its('instance').invoke('on', 'show', handlers.show)
5151
cy.window().its('instance').invoke('on', 'hide', handlers.hide)
52-
cy.get('my-dialog').shadow().find('fancy-button').first().click()
52+
cy.get('my-dialog').shadow().find('fancy-button').first().realClick()
5353
cy.get('@show').should('have.been.called')
5454
cy.get('my-dialog').then(shouldBeVisible)
55-
cy.get('my-dialog').shadow().find('fancy-button').last().click()
55+
cy.get('my-dialog').shadow().find('fancy-button').last().realClick()
5656
cy.get('@hide').should('have.been.called')
5757
cy.get('my-dialog').then(shouldBeHidden)
5858
cy.window().its('instance').invoke('off', 'show', handlers.show)

src/a11y-dialog.ts

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -192,20 +192,19 @@ export default class A11yDialog {
192192
// target
193193
// See: https://github.com/KittyGiraudel/a11y-dialog/issues/582
194194
const target = event.composedPath()[0] as HTMLElement
195-
196-
// We use `.closest(..)` and not `.matches(..)` here so that clicking
197-
// an element nested within a dialog opener does cause the dialog to open
198-
if (target.closest(`[${SCOPE}-show="${this.id}"]`)) {
199-
this.show(event)
200-
}
201-
202-
if (
203-
target.closest(`[${SCOPE}-hide="${this.id}"]`) ||
204-
(target.closest(`[${SCOPE}-hide]`) &&
205-
target.closest('[aria-modal="true"]') === this.$el)
206-
) {
207-
this.hide(event)
208-
}
195+
const opener = closest(`[${SCOPE}-show="${this.id}"]`, target)
196+
const explicitCloser = closest(`[${SCOPE}-hide="${this.id}"]`, target)
197+
const implicitCloser =
198+
closest(`[${SCOPE}-hide]`, target) &&
199+
closest('[aria-modal="true"]', target) === this.$el
200+
201+
// We use `closest(..)` (instead of `matches(..)`) so that clicking an
202+
// element nested within a dialog opener does cause the dialog to open, and
203+
// we use our custom `closest(..)` function so that it can cross shadow
204+
// boundaries
205+
// See: https://github.com/KittyGiraudel/a11y-dialog/issues/712
206+
if (opener) this.show(event)
207+
if (explicitCloser || implicitCloser) this.hide(event)
209208
}
210209

211210
/**

0 commit comments

Comments
 (0)