Skip to content

Commit edc4f12

Browse files
stevematneydiasbruno
authored andcommitted
[fixed] Ensure we don't check for hidden on Shadow DOM.
When inside a Shadow DOM, the loop will eventually reach the Shadow DOM element itself, which cannot be checked for visibility. We can continue our upwards check by skipping to the Shadow DOM host.
1 parent ffbaf0e commit edc4f12

File tree

4 files changed

+67
-0
lines changed

4 files changed

+67
-0
lines changed

Diff for: package-lock.json

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: package.json

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
],
2424
"license": "MIT",
2525
"devDependencies": {
26+
"@webcomponents/custom-elements": "^1.5.0",
2627
"babel-cli": "^6.26.0",
2728
"babel-core": "^6.25.0",
2829
"babel-eslint": "^8.0.1",

Diff for: specs/Modal.helpers.spec.js

+55
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/* eslint-env mocha */
22
import "should";
3+
import "@webcomponents/custom-elements/src/native-shim";
34
import tabbable from "../src/helpers/tabbable";
45
import "sinon";
56

@@ -114,6 +115,60 @@ export default () => {
114115
elem.appendChild(button);
115116
tabbable(elem).should.not.containEql(button);
116117
});
118+
119+
describe("inside Web Components", () => {
120+
let wc;
121+
let input;
122+
class TestWebComponent extends HTMLElement {
123+
constructor() {
124+
super();
125+
}
126+
127+
connectedCallback() {
128+
this.attachShadow({
129+
mode: "open"
130+
});
131+
this.style.display = "block";
132+
this.style.width = "100px";
133+
this.style.height = "25px";
134+
}
135+
}
136+
137+
const registerTestComponent = () => {
138+
if (window.customElements.get("test-web-component")) {
139+
return;
140+
}
141+
window.customElements.define("test-web-component", TestWebComponent);
142+
};
143+
144+
beforeEach(() => {
145+
registerTestComponent();
146+
wc = document.createElement("test-web-component");
147+
148+
input = document.createElement("input");
149+
elem.appendChild(input);
150+
151+
document.body.appendChild(wc);
152+
wc.shadowRoot.appendChild(elem);
153+
});
154+
155+
afterEach(() => {
156+
// re-add elem to body for the next afterEach
157+
document.body.appendChild(elem);
158+
159+
// remove Web Component
160+
document.body.removeChild(wc);
161+
});
162+
163+
it("includes elements when inside a Shadow DOM", () => {
164+
tabbable(elem).should.containEql(input);
165+
});
166+
167+
it("excludes elements when hidden inside a Shadow DOM", () => {
168+
wc.style.display = "none";
169+
tabbable(elem).should.not.containEql(input);
170+
});
171+
});
117172
});
118173
});
119174
};

Diff for: src/helpers/tabbable.js

+5
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,13 @@ function hidesContents(element) {
3535

3636
function visible(element) {
3737
let parentElement = element;
38+
let rootNode =
39+
typeof element.getRootNode === "function"
40+
? element.getRootNode()
41+
: undefined;
3842
while (parentElement) {
3943
if (parentElement === document.body) break;
44+
if (rootNode && parentElement === rootNode) parentElement = rootNode.host;
4045
if (hidesContents(parentElement)) return false;
4146
parentElement = parentElement.parentNode;
4247
}

0 commit comments

Comments
 (0)