Skip to content

Commit

Permalink
[BUGFIX] Dropdowns rendered in place have corrent animation flow
Browse files Browse the repository at this point in the history
  • Loading branch information
svyatoslav dardalan authored and svyatoslav dardalan committed Aug 23, 2021
1 parent 6e529ca commit f60a8fe
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 9 deletions.
14 changes: 6 additions & 8 deletions addon/components/basic-dropdown-content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,13 @@ export default class BasicDropdownContent extends Component<Args> {
private handleRootMouseDown?: RootMouseDownHandler
private scrollableAncestors: Element[] = []
private mutationObserver?: MutationObserver
@tracked animationClass = this.animationEnabled ? this.transitioningInClass : ''
@tracked animationClass = this.transitioningInClass


get destinationElement(): Element | null {
return document.getElementById(this.args.destination);
}

get animationEnabled(): boolean {
return !isTesting();
}

/**
* Allows similair behaviour to `ember-composable-helpers`' `optional` helper.
* Avoids adding extra dependencies.
Expand Down Expand Up @@ -116,27 +112,29 @@ export default class BasicDropdownContent extends Component<Args> {

@action
animateIn(dropdownElement: Element): void {
if (!this.animationEnabled) return;
waitForAnimations(dropdownElement, () => {
this.animationClass = this.transitionedInClass;
});
}

@action
animateOut(dropdownElement: Element): void {
if (!this.animationEnabled) return;
let parentElement = dropdownElement.parentElement;
if (parentElement === null) return;
if (this.args.renderInPlace) {
parentElement = parentElement.parentElement

if (isTesting() && parentElement === null) {
parentElement = document.querySelector('.ember-basic-dropdown');
}
}
if (parentElement === null) return;
let clone = dropdownElement.cloneNode(true) as Element;
clone.id = `${clone.id}--clone`;
clone.classList.remove(...this.transitioningInClass.split(' '));
clone.classList.add(...this.transitioningOutClass.split(' '));
parentElement.appendChild(clone);
this.animationClass = this.transitionedInClass;
this.animationClass = this.transitioningInClass;
waitForAnimations(clone, function() {
(parentElement as HTMLElement).removeChild(clone);
});
Expand Down
81 changes: 80 additions & 1 deletion tests/integration/components/basic-dropdown-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { registerDeprecationHandler } from '@ember/debug';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { hbs } from 'ember-cli-htmlbars';
import { render, click, focus, triggerEvent } from '@ember/test-helpers';
import { render, click, focus, triggerEvent, waitUntil, find } from '@ember/test-helpers';

let deprecations = [];

Expand Down Expand Up @@ -1004,4 +1004,83 @@ module('Integration | Component | basic-dropdown', function (hooks) {
.dom('.ember-basic-dropdown-content')
.hasAttribute('style', /max-height: 500px; overflow-y: auto/);
});

/**
* Tests related to https://github.com/cibernox/ember-basic-dropdown/issues/615
*/

test('[BUGFIX] Dropdowns rendered in place have correct animation flow', async function (assert) {
assert.expect(4);

const basicDropdownContentClass = 'ember-basic-dropdown-content';
const transitioningInClass = 'ember-basic-dropdown--transitioning-in';
const transitionedInClass = 'ember-basic-dropdown--transitioned-in';
const transitioningOutClass = 'ember-basic-dropdown--transitioning-out';

document.head.insertAdjacentHTML(
'beforeend',
`<style>
@keyframes grow-out{0%{opacity: 0;transform: scale(0);}100%{opacity: 1;transform: scale(1);}}
@keyframes drop-fade-below {0%{opacity:0;transform: translateY(-5px);}100%{opacity: 1;transform: translateY(0);}}
.ember-basic-dropdown--transitioning-in{animation: grow-out 1s ease-out;}
.ember-basic-dropdown--transitioning-out{animation: drop-fade-below 1s reverse;}
</style>
`
);

await render(hbs`
<BasicDropdown @renderInPlace={{true}} as |dropdown|>
<dropdown.Trigger><button>Open me</button></dropdown.Trigger>
<dropdown.Content><div id="dropdown-is-opened">CONTENT</div></dropdown.Content>
</BasicDropdown>
`);

await click('.ember-basic-dropdown-trigger');

assert
.dom(`.${basicDropdownContentClass}`)
.hasClass(
transitioningInClass,
`The dropdown content has .${transitioningInClass} class`
);

await waitUntil(() =>
find('.ember-basic-dropdown-content').classList.contains(
transitionedInClass
)
);

await click('.ember-basic-dropdown-trigger');

assert
.dom(`.${basicDropdownContentClass}`)
.hasClass(
transitioningOutClass,
`The dropdown content has .${transitioningOutClass} class`
);

await click('.ember-basic-dropdown-trigger');

assert
.dom(`.${basicDropdownContentClass}`)
.hasClass(
transitioningInClass,
`After closing dropdown, the dropdown content has .${transitioningInClass} class again as initial value`
);

await waitUntil(() =>
find('.ember-basic-dropdown-content').classList.contains(
transitionedInClass
)
);

await click('.ember-basic-dropdown-trigger');

assert
.dom(`.${basicDropdownContentClass}`)
.hasClass(
transitioningOutClass,
`The dropdown content has .${transitioningOutClass} class`
);
});
});

0 comments on commit f60a8fe

Please sign in to comment.