Skip to content

Commit d4d43db

Browse files
Jentobrschristian
andauthored
fix: Resolve issue with shadow DOM (#80)
* fix: Resolve issue with shadow DOM Router should now be able to find <a> tags within open shadow DOMs. * test: Add test case for shadow DOM * Update src/router.js Co-authored-by: Ryan Christian <[email protected]> --------- Co-authored-by: Ryan Christian <[email protected]>
1 parent dba70b7 commit d4d43db

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

src/router.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const UPDATE = (state, url) => {
1616
return state;
1717
}
1818

19-
const link = url.target.closest('a[href]'),
19+
const link = url.composedPath().find(el => el.nodeName == 'A' && el.href),
2020
href = link && link.getAttribute('href');
2121
if (
2222
!link ||

test/router.test.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -927,6 +927,41 @@ describe('Router', () => {
927927
await sleep(10);
928928
expect(scratch).to.have.property('textContent', 'data');
929929
});
930+
931+
it('should intercept clicks on links inside open shadow DOM', async () => {
932+
const shadowlink = document.createElement('a');
933+
shadowlink.href = '/shadow';
934+
shadowlink.textContent = 'Shadow Link';
935+
shadowlink.addEventListener('click', e => e.preventDefault());
936+
937+
const attachShadow = (el) => {
938+
if (!el || el.shadowRoot) return;
939+
const shadowroot = el.attachShadow({ mode: 'open' });
940+
shadowroot.appendChild(shadowlink);
941+
}
942+
943+
const Home = sinon.fake(() => <div ref={attachShadow}></div>);
944+
const Shadow = sinon.fake(() => <div>Shadow Route</div>);
945+
946+
render(
947+
<LocationProvider>
948+
<Router>
949+
<Route path="/" component={Home} />
950+
<Route path="/shadow" component={Shadow}/>
951+
</Router>
952+
<ShallowLocation />
953+
</LocationProvider>,
954+
scratch
955+
);
956+
957+
shadowlink.click();
958+
959+
await sleep(1);
960+
961+
expect(loc).to.deep.include({ url: '/shadow' });
962+
expect(Shadow).to.have.been.calledOnce;
963+
expect(scratch).to.have.property('textContent', 'Shadow Route');
964+
});
930965
});
931966

932967
const MODE_HYDRATE = 1 << 5;

0 commit comments

Comments
 (0)