It looks like `::part()` will not actually work. It works in CSS and in `Element.matches()`, but not in `Element.querySelector()`. Instead, I think we'll need to introduce a new system to [FeatureCallout](https://searchfox.org/mozilla-central/rev/31965f055fd6b00e3cdd4ff9492a18fe15383a21/browser/components/asrouter/modules/FeatureCallout.sys.mjs#593-614) that allows traversing through the DOM in multiple steps, similar to [this package](https://github.com/webdriverio/query-selector-shadow-dom). The anchor could then be written like this: ```js { "selectors": [ [ "#sidebar-main > sidebar-main", "%shadowRoot%", "moz-button[view='review-checker']:not(.tools-overflow)" ] ], "panel_position": { "anchor_attachment": "rightcenter", "callout_attachment": "leftcenter" } } ``` This is better to some extent, since it doesn't run into the issue Katherine mentioned [in the other bug](https://bugzilla.mozilla.org/show_bug.cgi?id=1919914#c8). With the `::part()` selector, you can't interrogate anything else within the shadow tree or about the target, besides pseudo-classes.
Bug 1920235 Comment 1 Edit History
Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.
It looks like `::part()` will not actually work. It works in CSS and in `Element.matches()`, but not in `Element.querySelector()`. Instead, I think we'll need to introduce a new system to [FeatureCallout](https://searchfox.org/mozilla-central/rev/31965f055fd6b00e3cdd4ff9492a18fe15383a21/browser/components/asrouter/modules/FeatureCallout.sys.mjs#593-614) that allows traversing through the DOM in multiple steps, similar to [this package](https://github.com/webdriverio/query-selector-shadow-dom). The anchor could then be written like this: ```js { "selectors": [ [ "#sidebar-main > sidebar-main", "%shadowRoot%", "moz-button[view='review-checker']:not(.tools-overflow)" ] ], "panel_position": { "anchor_attachment": "rightcenter", "callout_attachment": "leftcenter" } } ``` This is better to some extent, since it doesn't run into the issue Katherine mentioned [in the other bug](https://bugzilla.mozilla.org/show_bug.cgi?id=1919914#c8). With the `::part()` selector, you can't interrogate anything else within the shadow tree or about the target, besides pseudo-classes. It could be handled as just a string, like `#sidebar-main > sidebar-main::%shadow% moz-button[view='review-checker']:not(.tools-overflow)`, and then parse out the left side from the right side. ```js if (selector.includes("::%shadow%")) { let [hostSelector, partSelector] = selector.split("::%shadow%"); scope = scope.querySelector(hostSelector).shadowRoot; selector = partSelector; } let element = scope.querySelector(selector); if (!element && scope.matches?.(selector)) { element = scope; } ``` I don't have a preference, either would be fine.
It looks like `::part()` will not actually work. It works in CSS and in `Element.matches()`, but not in `Element.querySelector()`. Instead, I think we'll need to introduce a new system to [FeatureCallout](https://searchfox.org/mozilla-central/rev/31965f055fd6b00e3cdd4ff9492a18fe15383a21/browser/components/asrouter/modules/FeatureCallout.sys.mjs#593-614) that allows traversing through the DOM in multiple steps, similar to [this package](https://github.com/webdriverio/query-selector-shadow-dom). The anchor could then be written like this: ```js { "selectors": [ "#sidebar-main > sidebar-main::%shadow% .tools-and-extensions[orientation='vertical']%shadow% moz-button[view='review-checker']" ], "panel_position": { "anchor_attachment": "rightcenter", "callout_attachment": "leftcenter" } } ``` This is better to some extent, since it doesn't run into the issue Katherine mentioned [in the other bug](https://bugzilla.mozilla.org/show_bug.cgi?id=1919914#c8). With the `::part()` selector, you can't interrogate anything else within the shadow tree or about the target, besides pseudo-classes. And I think reaching this button requires traversing two shadow trees rather than one, so we'd also need to use `exportparts` if we used `::part()`. So not being able to use it might be lucky after all. The get anchor code can parse out the individual components and manually traverse over them: ```js if (selector.includes("::%shadow%")) { let parts = selector.split("::%shadow%"); for (let i = 0; i < parts.length; i++) { selector = parts[i].trim(); if (i === parts.length - 1) { break; } let el = scope.querySelector(selector); if (!el) { break; } if (el.shadowRoot) { scope = el.shadowRoot; } } } let element = scope.querySelector(selector); if (!element && scope.matches?.(selector)) { element = scope; } ```
It looks like `::part()` will not actually work. It works in CSS and in `Element.matches()`, but not in `Element.querySelector()`. Instead, I think we'll need to introduce a new system to [FeatureCallout](https://searchfox.org/mozilla-central/rev/31965f055fd6b00e3cdd4ff9492a18fe15383a21/browser/components/asrouter/modules/FeatureCallout.sys.mjs#593-614) that allows traversing through the DOM in multiple steps, similar to [this package](https://github.com/webdriverio/query-selector-shadow-dom). The anchor could then be written like this: ```js { "selectors": [ "#sidebar-main > sidebar-main::%shadow% .tools-and-extensions[orientation='vertical']::%shadow% moz-button[view='review-checker']" ], "panel_position": { "anchor_attachment": "rightcenter", "callout_attachment": "leftcenter" } } ``` This is better to some extent, since it doesn't run into the issue Katherine mentioned [in the other bug](https://bugzilla.mozilla.org/show_bug.cgi?id=1919914#c8). With the `::part()` selector, you can't interrogate anything else within the shadow tree or about the target, besides pseudo-classes. And I think reaching this button requires traversing two shadow trees rather than one, so we'd also need to use `exportparts` if we used `::part()`. So not being able to use it might be lucky after all. The get anchor code can parse out the individual components and manually traverse over them: ```js if (selector.includes("::%shadow%")) { let parts = selector.split("::%shadow%"); for (let i = 0; i < parts.length; i++) { selector = parts[i].trim(); if (i === parts.length - 1) { break; } let el = scope.querySelector(selector); if (!el) { break; } if (el.shadowRoot) { scope = el.shadowRoot; } } } let element = scope.querySelector(selector); if (!element && scope.matches?.(selector)) { element = scope; } ```
It looks like `::part()` will not actually work. It works in CSS and in `Element.matches()`, but not in `Element.querySelector()`. Instead, I think we'll need to introduce a new system to [FeatureCallout](https://searchfox.org/mozilla-central/rev/31965f055fd6b00e3cdd4ff9492a18fe15383a21/browser/components/asrouter/modules/FeatureCallout.sys.mjs#593-614) that allows traversing through the DOM in multiple steps, similar to [this package](https://github.com/webdriverio/query-selector-shadow-dom). The anchor could then be written like this: ```js { "selectors": [ "#sidebar-main > sidebar-main::%shadow% .tools-and-extensions[orientation='vertical']::%shadow% moz-button[view='review-checker']" ], "panel_position": { "anchor_attachment": "rightcenter", "callout_attachment": "leftcenter" } } ``` This is better to some extent, since it doesn't run into the issue Katherine mentioned [in the other bug](https://bugzilla.mozilla.org/show_bug.cgi?id=1919914#c8). With the `::part()` selector, you can't interrogate anything else within the shadow tree or about the target, besides pseudo-classes. And I think reaching this button requires traversing two shadow trees rather than one, so we'd also need to use `exportparts` if we used `::part()`. So not being able to use it might be lucky after all. The [get anchor code](https://searchfox.org/mozilla-central/rev/31965f055fd6b00e3cdd4ff9492a18fe15383a21/browser/components/asrouter/modules/FeatureCallout.sys.mjs#607-614) can parse out the individual components and manually traverse over them: ```js if (selector.includes("::%shadow%")) { let parts = selector.split("::%shadow%"); for (let i = 0; i < parts.length; i++) { selector = parts[i].trim(); if (i === parts.length - 1) { break; } let el = scope.querySelector(selector); if (!el) { break; } if (el.shadowRoot) { scope = el.shadowRoot; } } } let element = scope.querySelector(selector); if (!element && scope.matches?.(selector)) { element = scope; } ```