diff --git a/packages/marble-dropdown/src/Dropdown.js b/packages/marble-dropdown/src/Dropdown.js
index 1574ea6..1a622f2 100644
--- a/packages/marble-dropdown/src/Dropdown.js
+++ b/packages/marble-dropdown/src/Dropdown.js
@@ -133,8 +133,28 @@ class Dropdown extends Component {
* Toggles the dropdown, closing it when open or opening it when closed.
*/
toggle() {
- this.expanded = !this.expanded;
- this.hideConfirmation();
+ if (this.expanded) {
+ this.hiding = true;
+
+ this.callAsync_(() => {
+ this.expanded = !this.expanded;
+ this.hiding = false;
+ this.hideConfirmation();
+ }, 300);
+ } else {
+ this.expanded = !this.expanded;
+ this.hideConfirmation();
+ }
+ }
+
+ /**
+ * @param {!function()} fn
+ * @param {number} delay
+ * @private
+ */
+ callAsync_(fn, delay) {
+ clearTimeout(this.delay_);
+ this.delay_ = setTimeout(fn.bind(this), delay);
}
/**
@@ -280,6 +300,16 @@ Dropdown.STATE = {
internal: true,
},
+ /**
+ * Flag indicating if the dropdown is hiding or not.
+ * @type {boolean}
+ * @default false
+ */
+ hiding: {
+ value: false,
+ internal: true,
+ },
+
/**
* The position of the dropdown (either 'up', 'down' or any of the position
* constants available in `Align`).
diff --git a/packages/marble-dropdown/src/Dropdown.soy b/packages/marble-dropdown/src/Dropdown.soy
index 087e21b..1de1e87 100644
--- a/packages/marble-dropdown/src/Dropdown.soy
+++ b/packages/marble-dropdown/src/Dropdown.soy
@@ -5,6 +5,7 @@
* @param? classMap
* @param? elementClasses
* @param? expanded
+ * @param? hiding
* @param? position
* @param? positionClassOnMenu
* @param? showConfirmationBody
@@ -17,7 +18,7 @@
{let $classes: $classMap ? $classMap : ['dropup', 'dropup', 'dropright', 'dropdown', 'dropdown', 'dropdown', 'dropleft', 'dropup'] /}
{let $currentPosition: isNonnull($alignedPosition) ? $alignedPosition : $position /}
{let $positionClass: isNonnull($currentPosition) ? $classes[$currentPosition] : 'dropdown' /}
-
+
{if $header}
{$header}
{/if}
diff --git a/packages/marble-dropdown/src/Dropdown.soy.js b/packages/marble-dropdown/src/Dropdown.soy.js
index 7218ecb..8a7c99f 100644
--- a/packages/marble-dropdown/src/Dropdown.soy.js
+++ b/packages/marble-dropdown/src/Dropdown.soy.js
@@ -27,6 +27,7 @@ var soyIdom = goog.require('soy.idom');
* classMap: (?),
* elementClasses: (?),
* expanded: (?),
+ * hiding: (?),
* position: (?),
* positionClassOnMenu: (?),
* showConfirmationBody: (?),
@@ -52,7 +53,7 @@ function $render(opt_data, opt_ijData, opt_ijData_deprecated) {
var currentPosition__soy9 = (opt_data.alignedPosition != null) ? opt_data.alignedPosition : opt_data.position;
var positionClass__soy11 = (currentPosition__soy9 != null) ? classes__soy7[currentPosition__soy9] : 'dropdown';
incrementalDom.elementOpenStart('div');
- incrementalDom.attr('class', (opt_data.positionClassOnMenu ? 'dropdown' : positionClass__soy11) + (opt_data.elementClasses ? ' ' + opt_data.elementClasses : '') + (opt_data.expanded ? ' open' : ''));
+ incrementalDom.attr('class', (opt_data.positionClassOnMenu ? 'dropdown' : positionClass__soy11) + (opt_data.elementClasses ? ' ' + opt_data.elementClasses : '') + (opt_data.expanded ? ' open' : '') + (opt_data.hiding ? ' hiding' : ''));
incrementalDom.elementOpenEnd();
if (header) {
header();
@@ -81,6 +82,7 @@ exports.render = $render;
* classMap: (?),
* elementClasses: (?),
* expanded: (?),
+ * hiding: (?),
* position: (?),
* positionClassOnMenu: (?),
* showConfirmationBody: (?),
@@ -94,8 +96,8 @@ if (goog.DEBUG) {
$render.soyTemplateName = 'Dropdown.render';
}
-exports.render.params = ["body","confirmationBody","header","alignedPosition","classMap","elementClasses","expanded","position","positionClassOnMenu","showConfirmationBody"];
-exports.render.types = {"body":"html","confirmationBody":"html","header":"html","alignedPosition":"any","classMap":"any","elementClasses":"any","expanded":"any","position":"any","positionClassOnMenu":"any","showConfirmationBody":"any"};
+exports.render.params = ["body","confirmationBody","header","alignedPosition","classMap","elementClasses","expanded","hiding","position","positionClassOnMenu","showConfirmationBody"];
+exports.render.types = {"body":"html","confirmationBody":"html","header":"html","alignedPosition":"any","classMap":"any","elementClasses":"any","expanded":"any","hiding":"any","position":"any","positionClassOnMenu":"any","showConfirmationBody":"any"};
templates = exports;
return exports;
diff --git a/packages/marble-dropdown/test/Dropdown.js b/packages/marble-dropdown/test/Dropdown.js
index e66b50e..f0e9c11 100644
--- a/packages/marble-dropdown/test/Dropdown.js
+++ b/packages/marble-dropdown/test/Dropdown.js
@@ -88,10 +88,12 @@ describe('Dropdown', () => {
expect(dom.hasClass(component.element, 'open')).toBeTruthy();
component.toggle();
component.once('stateChanged', () => {
- expect(!component.expanded).toBeTruthy();
- expect(!dom.hasClass(component.element, 'open')).toBeTruthy();
- component.dispose();
- done();
+ component.once('stateChanged', () => {
+ expect(!component.expanded).toBeTruthy();
+ expect(!dom.hasClass(component.element, 'open')).toBeTruthy();
+ component.dispose();
+ done();
+ });
});
});
});
diff --git a/packages/marble/src/_animations.scss b/packages/marble/src/_animations.scss
index ae5d898..7472ceb 100644
--- a/packages/marble/src/_animations.scss
+++ b/packages/marble/src/_animations.scss
@@ -12,6 +12,16 @@
}
}
+@keyframes fadeOut {
+ 0% {
+ opacity: 1;
+ }
+
+ 100% {
+ opacity: 0;
+ }
+}
+
@keyframes fadeInToRight {
0% {
opacity: 0;
diff --git a/packages/marble/src/_dropdowns.scss b/packages/marble/src/_dropdowns.scss
index cf48403..9e24c98 100644
--- a/packages/marble/src/_dropdowns.scss
+++ b/packages/marble/src/_dropdowns.scss
@@ -45,9 +45,14 @@
}
.open .dropdown-menu {
+ animation: fadeIn 300ms cubic-bezier(0.455, 0.03, 0.515, 0.955) forwards;
display: inline-block;
}
+.hiding .dropdown-menu {
+ animation: fadeOut 300ms cubic-bezier(0.455, 0.03, 0.515, 0.955) forwards;
+}
+
.dropdown-section-title {
color: rgba($white, 0.4);
display: block;