Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 15 additions & 20 deletions ember-basic-dropdown/src/components/basic-dropdown-content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export default class BasicDropdownContent extends Component<BasicDropdownContent
private handleRootMouseDown?: RootMouseDownHandler;
private scrollableAncestors: Element[] = [];
private mutationObserver: MutationObserver | undefined;
private rootElement: HTMLElement | undefined;
@tracked private _contentWormhole?: Element;
@tracked animationClass = this.transitioningInClass;

Expand Down Expand Up @@ -186,16 +187,18 @@ export default class BasicDropdownContent extends Component<BasicDropdownContent
);

// We need to register closing event on shadow dom element, otherwise all clicks inside a shadow dom are not closing the dropdown
let rootElement;
// In additional store the rootElement for outside clicks (ensure that we do removeEventListener on correct element)
if (
this._contentWormhole &&
this._contentWormhole.getRootNode() instanceof ShadowRoot
) {
rootElement = this._contentWormhole.getRootNode() as HTMLElement;
this.rootElement = this._contentWormhole.getRootNode() as HTMLElement;
} else {
this.rootElement = undefined;
}

if (rootElement) {
rootElement.addEventListener(
if (this.rootElement) {
this.rootElement.addEventListener(
this.args.rootEventType || 'click',
this.handleRootMouseDown,
true,
Expand All @@ -216,13 +219,13 @@ export default class BasicDropdownContent extends Component<BasicDropdownContent
);
document.addEventListener('touchend', this.handleRootMouseDown, true);

if (rootElement) {
rootElement.addEventListener(
if (this.rootElement) {
this.rootElement.addEventListener(
'touchstart',
this.touchStartHandlerBound,
true,
);
rootElement.addEventListener(
this.rootElement.addEventListener(
'touchend',
this.handleRootMouseDown,
true,
Expand All @@ -247,16 +250,8 @@ export default class BasicDropdownContent extends Component<BasicDropdownContent
true,
);

let rootElement;
if (
this._contentWormhole &&
this._contentWormhole.getRootNode() instanceof ShadowRoot
) {
rootElement = this._contentWormhole.getRootNode() as HTMLElement;
}

if (rootElement) {
rootElement.removeEventListener(
if (this.rootElement) {
this.rootElement.removeEventListener(
this.args.rootEventType || 'click',
this.handleRootMouseDown as RootMouseDownHandler,
true,
Expand All @@ -275,13 +270,13 @@ export default class BasicDropdownContent extends Component<BasicDropdownContent
true,
);

if (rootElement) {
rootElement.removeEventListener(
if (this.rootElement) {
this.rootElement.removeEventListener(
'touchstart',
this.touchStartHandlerBound,
true,
);
rootElement.removeEventListener(
this.rootElement.removeEventListener(
'touchend',
this.handleRootMouseDown as RootMouseDownHandler,
true,
Expand Down
50 changes: 49 additions & 1 deletion test-app/tests/integration/components/basic-dropdown-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1397,6 +1397,54 @@ module('Integration | Component | basic-dropdown', function (hooks) {
wormhole.remove();
});

test('Shadow dom: Its `toggle` action opens and closes the dropdown with renderInPlace', async function (assert) {
await render(hbs`
<Shadow>
<BasicDropdown @renderInPlace={{true}} as |dropdown|>
<dropdown.Trigger>Click me</dropdown.Trigger>
<dropdown.Content>
<div style="height: 100px; width: 100px; background: black" id="dropdown-is-opened"></div>
</dropdown.Content>
</BasicDropdown>
</Shadow>
`);

assert
.dom('#dropdown-is-opened', this.element.getRootNode())
.doesNotExist('The dropdown is closed');

const triggerElement = find('[data-shadow]')?.shadowRoot.querySelector(
'.ember-basic-dropdown-trigger',
);

await click(triggerElement);

assert
.dom('.ember-basic-dropdown-content', find('[data-shadow]').shadowRoot)
.exists('The dropdown is rendered');


assert.dom('#dropdown-is-opened', find('[data-shadow]').shadowRoot).exists('The dropdown is opened');

await click(find('[data-shadow]').shadowRoot.getElementById('dropdown-is-opened'));

assert.dom('#dropdown-is-opened', find('[data-shadow]').shadowRoot).exists('The dropdown stays opened when clicking content');

await click(triggerElement);

assert
.dom('#dropdown-is-opened', find('[data-shadow]').shadowRoot)
.doesNotExist('The dropdown is closed again');

await click(triggerElement);

assert.dom('#dropdown-is-opened', find('[data-shadow]').shadowRoot).exists('The dropdown is opened 2d time');

await click(find('[data-shadow]').shadowRoot.getElementById('dropdown-is-opened'));

assert.dom('#dropdown-is-opened', find('[data-shadow]').shadowRoot).exists('The dropdown stays opened when clicking content after 2d open');
});

test('Shadow dom: Its `toggle` action opens and closes the dropdown when wormhole is inside shadow dom', async function (assert) {
await render(hbs`
<Shadow>
Expand All @@ -1406,7 +1454,7 @@ module('Integration | Component | basic-dropdown', function (hooks) {
<div id="dropdown-is-opened"></div>
</dropdown.Content>
</BasicDropdown>

<div id="wormhole-in-shadow-dom"></div>
</Shadow>
`);
Expand Down