Bug 429825 - UI Style Tweaks
- Sections got a makeover and an animation on expand/collapse
- Dropdown selection and file explorer "checkedRow" class has bold accent color on left side with lighter tint of the same color throughout.
- Dropdown menu trigger buttons now look as though they are part of the menu when it is open.

--Signed-off-by: Elijah El-Haddad <elijahe@ca.ibm.com>
diff --git a/bundles/org.eclipse.orion.client.ui/web/css/ide.css b/bundles/org.eclipse.orion.client.ui/web/css/ide.css
index f14edd5..9c03491 100644
--- a/bundles/org.eclipse.orion.client.ui/web/css/ide.css
+++ b/bundles/org.eclipse.orion.client.ui/web/css/ide.css
@@ -651,6 +651,7 @@
 }
 
 .treetable {
+	border-collapse: collapse;
 	border-spacing: 0;
 	width:100%;
 }
@@ -658,8 +659,7 @@
 .miniNavTreeTable {
 	border-spacing: 0;
 	width:100%;
-	padding-left:10px;
-	padding-right:10px;
+	padding-left:4px;
 }
 
 .secondaryColumn {
@@ -896,40 +896,6 @@
 	padding-right: 3px;
 }
 
-.dropDownContainer{
-	border-radius:1px;
-	background:#fefefe;
-	border: 1px solid #DDD;
-	padding:10px;
-	margin-top: 5px;
-	outline: none;
-	position:absolute;
-	z-index:100;
-	box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.2);
-}
-
-
-.dropDownContainer ul {
-	list-style: none;
-	padding:0;
-}
-
-.dropDownContainer ul li a {
-	display: block;
-	padding: 5px 15px;
-	color:#3087B3;
-	line-height: 1;
-}
-
-.dropDownContainer ul li a:focus,
-.dropDownContainer ul li a:hover {
-	color:#F58B0F;
-}
-
-.dropDownContainer ul li a:active {
-	background: #ddd;
-}	
-
 .groupedContentDivider{
 	float: left;
 	width: 1px;
@@ -993,9 +959,8 @@
 	border-collapse: collapse;
 	border-spacing: 0;
 	padding: 0;
-	margin-left: 5%;
-	margin-right: 5%;
 	margin-top: 30px;
+	overflow-y: hidden; /* prevent vertical scrollbar from showing during expand/collapse */
 }
 
 .mainpane .sectionTable .treetable, .mainpane .sectionWrapper .treetable, .mainpane .sectionTable .treetable .actionsColumn{
@@ -1011,18 +976,37 @@
 
 .sectionTable {
 	margin-top: 0;
+	margin-left: 6%;
+	margin-right: 6%;
 	border: 1px solid;
+	border-bottom-left-radius: 3px;
+	border-bottom-right-radius: 3px;
 	border-color:#dadada;
+	box-shadow: 0 1px 2px 0 rgba(0,0,0,0.1);
+	-webkit-transition: all 0.5s ease;
+	transition: all 0.5s ease;
 }
 
-.sectionWrapperClosed{
-	border-bottom: 1px solid;
+/* sectionTable preceeded by a sectionWrapper */
+.sectionWrapper+.sectionTable {
+	margin-top: 2px;
+	border-top: none;
+}
+
+.sectionTable:last-child {
+	margin-bottom: 20px;
+}
+
+.sectionTable.sectionClosed {
+	height: 0;
+	border-bottom-color: transparent;
+	box-shadow: none;
 }
 
 .sectionWrapper{
-	border-top: 1px solid;
-	border-left: 1px solid;
-	border-right: 1px solid;
+	border: 1px solid;
+	margin-left: 5%;
+	margin-right: 5%;
 	background: none repeat scroll 0 0 #f4f4f4;
 	vertical-align: middle;
 	font-weight: bold;
@@ -1030,6 +1014,20 @@
 	color: gray;
 	margin-bottom: 0;
 	border-color: #dadada;
+	box-shadow: 0 1px 2px 0 rgba(0,0,0,0.2);
+	transition: all 0.5s ease;
+}
+
+.sectionWrapper.sectionClosed {
+	box-shadow: none;
+	opacity: 0.9;
+	background: none;
+}
+
+.sectionWrapper.sectionClosed:hover {
+	box-shadow: 0 1px 2px 0 rgba(0,0,0,0.2);
+	opacity: 1;
+	transition: all 0.3s;
 }
 
 .sectionTable td {
@@ -1083,7 +1081,7 @@
 }
 
 .orionProject .discreetInput {
-	border: none;
+	border: 1px solid transparent; /* prevent movement on hover */
 	color: gray;
 	font: 8pt Lucida Sans Unicode,Lucida Grande,Verdana,Arial,Helvetica,Myriad,Tahoma,clean,sans-serif;
 	width: 90%;
diff --git a/bundles/org.eclipse.orion.client.ui/web/css/theme.css b/bundles/org.eclipse.orion.client.ui/web/css/theme.css
index 43b6767..58bf5ff 100644
--- a/bundles/org.eclipse.orion.client.ui/web/css/theme.css
+++ b/bundles/org.eclipse.orion.client.ui/web/css/theme.css
@@ -91,6 +91,19 @@
 	background-color: #cedce7 !important; /* was e3e3e3 */

 }

 

+.navRow > td:first-child {

+	border-left: 6px solid transparent;

+}

+

+.navRow.checkedRow > td:first-child {

+	border-left-color: #7fa4c0;

+}

+

+.navbar-item-selected {

+	background: #FEC;

+	color: black;

+}

+
 /* Breadcrumbs */

 

 .breadcrumb {

@@ -126,6 +139,7 @@
 	text-decoration: none;

 	line-height: 10pt;

 	white-space:nowrap;

+	text-shadow: rgba(0,0,0,0.25) 0 2px 2px;

 }

 

 a.currentLocation:hover {

@@ -246,10 +260,13 @@
 	background-color: #ddd;

 	border-radius: 2px;

 	vertical-align:middle;

+	-webkit-transition: all 0.2s ease;

+	transition: all 0.2s ease;

 }

 

 .commandButton:hover, .commandButton:focus {

 	background-color: #eee;

+	box-shadow: 0 1px 2px 0 rgba(0,0,0,0.2);

 }

 

 .commandButton.disabled {

@@ -346,7 +363,7 @@
 

 .dropdownTrigger:not(.dropdownDefaultButton) {

 	font-weight: normal;

-	background: none !important;

+	background: none;

 	border-color: transparent;

 }

 

@@ -359,8 +376,12 @@
 }

 

 .dropdownMenu {

+	box-shadow: 2px 2px 5px 3px rgba(0, 0, 0, .2);

 	color: #555;

-	background-color: #fbfbfb;

+	background-color: white;

+	border-collapse: separate;

+	border: 1px solid #bbbbbb;

+	border-radius: 1px;

 	visibility: hidden;

 	z-index: 150;

 	position: absolute;

@@ -368,20 +389,6 @@
 	display: none; /* don't take part in layout until open */

 	line-height: normal; /* don't want to inherit strange line-heights from ancestor elements */

 	margin: 0; /* needed for context menu positioning to work properly */

-

-

-	-webkit-border-radius: 0;

-	-moz-border-radius: 0;

-	border-radius: 0;

-	-webkit-box-shadow: 0 2px 4px rgba(0,0,0,0.2);

-	-moz-box-shadow: 0 2px 4px rgba(0,0,0,0.2);

-	box-shadow: 0 2px 4px rgba(0,0,0,0.2);

-	-webkit-transition: opacity 0.218s;

-	-moz-transition: opacity 0.218s;

-	-o-transition: opacity 0.218s;

-	transition: opacity 0.218s;

-	background: #ffffff;

-	border: 1px solid #ddd;

 	cursor: default;

 	font-size: 12px;

 	margin: 0;

@@ -407,8 +414,7 @@
 

 .dropdownMenu > li {

 	min-width: 120px;

-	padding: 0 2px;

-	display: block;

+	display: flex;

 }

 

 .dropdownMenu > li > a, .dropdownMenu > li > span {

@@ -418,12 +424,6 @@
 

 .dropdownMenu > li > *:focus {

 	outline: none;

-	background: #f3f6fe;

-}

-

-.dropdownMenu > li:hover {

-	text-decoration: none;

-	background: #ffeecc;

 }

 

 

@@ -439,7 +439,7 @@
 	display: inline-block;

 	vertical-align: middle;

 	color: #555 !important;

-	padding: 3px 5px;

+	padding: 3px 3px 3px 5px;

 	cursor: pointer;

 	-webkit-touch-callout: none;

 	-webkit-user-select: none;

@@ -448,6 +448,12 @@
 	-ms-user-select: none;

 	user-select: none;

 	white-space: nowrap;

+	border-left: 6px solid transparent;

+}

+

+.dropdownMenu .dropdownMenuItemSelected {

+	background-color: #FEEFDE;

+	border-left-color: #F58B0F;

 }

 

 .dropdownMenuItem .check {

@@ -469,8 +475,19 @@
 }

 

 .dropdownSelection {

-	background-color: #e6e6e6 !important;

-	border: 1px solid #ccc !important;

+/* Using !important everywhere because this class is used by

+ * a variety of elements making it difficult to increase the

+ * specificity correctly for all users.

+ */

+	background-color: white !important;

+	border: 1px solid #bbbbbb !important;

+	border-bottom: none !important;

+	border-bottom-left-radius: 0 !important;

+	border-bottom-right-radius: 0 !important;

+	box-shadow: -1px -1px 2px 0 rgba(0, 0, 0, .2) !important;

+	margin-bottom: -1px !important;

+	position: relative !important;

+	z-index: 200 !important;

 }

 

 .checkedMenuItem {

diff --git a/bundles/org.eclipse.orion.client.ui/web/orion/section.js b/bundles/org.eclipse.orion.client.ui/web/orion/section.js
index 86965d7..a63207f 100644
--- a/bundles/org.eclipse.orion.client.ui/web/orion/section.js
+++ b/bundles/org.eclipse.orion.client.ui/web/orion/section.js
@@ -8,7 +8,7 @@
  * 
  * Contributors: IBM Corporation - initial API and implementation
  ******************************************************************************/
- /*global define window document*/
+ /*global define window document MutationObserver*/
 define(['orion/webui/littlelib', 'orion/selection', 'orion/commandRegistry', 'orion/commonHTMLFragments', 'orion/objects', 	'orion/selection'], function(lib, mSelection, mCommands, mHTMLFragments, objects, Selection){
 	
 	/**
@@ -68,7 +68,7 @@
 			this.domNode.appendChild(this.twistie);
 			this.domNode.tabIndex = 0; //$NON-NLS-0$
 			this.domNode.addEventListener("click", function(evt) { //$NON-NLS-0$
-				if (evt.target === that.titleNode || evt.target === that.twistie) {
+				if (evt.target === that.titleNode || evt.target === that.twistie || evt.target === that.domNode) {
 					that._changeExpandedState();
 				}
 			}, false);
@@ -158,7 +158,37 @@
 		this._contentParent.classList.add("sectionTable"); //$NON-NLS-0$
 		this._contentParent.setAttribute("aria-labelledby", this.titleNode.id); //$NON-NLS-0$
 		parent.appendChild(this._contentParent);
-
+		
+		try {
+			// setup observer which sets the appropriate height on this._contentParent 
+			// when its contents have been modified, allowing smooth CSS transitions
+			this._mutationObserver = new MutationObserver((function(mutations, observer){
+				var removedNodes = mutations.some(function(mutation){
+					return mutation.removedNodes;
+				});
+				if (removedNodes) {
+					this._contentParent.style.height = "auto"; //$NON-NLS-0$
+					if (this._resizeTimeoutID) {
+						window.clearTimeout(this._resizeTimeoutID);
+					}
+					this._resizeTimeoutID = window.setTimeout((function() {
+						this._contentParent.style.height = this._contentParent.scrollHeight + "px"; //$NON-NLS-0$
+					}).bind(this), 200);
+				} else {
+					this._contentParent.style.height = this._contentParent.scrollHeight + "px"; //$NON-NLS-0$	
+				}
+			}).bind(this));
+	
+			this._mutationObserverConfig = {childList: true, subtree: true};	
+		} catch (err) {
+			if (err instanceof ReferenceError){
+				//ignore, MutationObserver is not supported
+			} else {
+				throw err;
+			}
+			
+		}
+				
 		if(options.content){
 			this.setContent(options.content);
 		}
@@ -169,8 +199,7 @@
 		}
 		this._preferenceService = options.preferenceService;
 		// initially style as hidden until we determine what needs to happen
-		this._contentParent.style.display = "none"; //$NON-NLS-0$
-		this.domNode.classList.add("sectionWrapperClosed");
+		this._collapse();
 		// should we consult a preference?
 		if (this._preferenceService) {
 			var self = this;
@@ -183,16 +212,14 @@
 				}
 
 				if (!self.hidden) {
-					self._contentParent.style.display = "block"; //$NON-NLS-0$
-					self.domNode.classList.remove("sectionWrapperClosed");
+					self._expand();
 				}
 				
 				self._updateExpandedState(!self.hidden, false);
 			});
 		} else {
-			if (!this.hidden) {
-				this._contentParent.style.display = "block"; //$NON-NLS-0$
-				this.domNode.classList.remove("sectionWrapperClosed");
+			if (!options.hidden) {
+				this._expand();
 			}
 			this._updateExpandedState(!this.hidden, false);
 		}
@@ -382,15 +409,10 @@
 		},
 		
 		_changeExpandedState: function() {
-			// TODO we could use classes with CSS transitions to animate				
-			if (!this.hidden){
-				this._contentParent.style.display = "none"; //$NON-NLS-0$
-				this.domNode.classList.add("sectionWrapperClosed");
-				this.hidden = true;
+			if (this.hidden){
+				this._expand();
 			} else {
-				this._contentParent.style.display = "block"; //$NON-NLS-0$
-				this.domNode.classList.remove("sectionWrapperClosed");
-				this.hidden = false;
+				this._collapse();
 			}
 			
 			this._updateExpandedState(!this.hidden, true);
@@ -414,6 +436,40 @@
 			if (this._onExpandCollapse) {
 				this._onExpandCollapse(isExpanded, this);
 			}
+		},
+		
+		_expand: function() {
+			this._contentParent.classList.remove("sectionClosed"); //$NON-NLS-0$
+			this.domNode.classList.remove("sectionClosed"); //$NON-NLS-0$
+			
+			if (this._mutationObserver) {
+				if (this._contentParent.innerHTML && this._contentParent.scrollHeight) {
+					// must set a concrete height in order for transition animation to work properly
+					this._contentParent.style.height = this._contentParent.scrollHeight + "px"; //$NON-NLS-0$
+				} else {
+					this._contentParent.style.height = "auto"; //$NON-NLS-0$
+				}
+				
+				// listen for DOM node changes
+				this._mutationObserver.observe(this._contentParent, this._mutationObserverConfig);	
+			} else {
+				this._contentParent.style.display = ""; //$NON-NLS-0$
+			}
+			
+			this.hidden = false;
+		},
+		
+		_collapse: function() {
+			if (this._mutationObserver) {
+				this._mutationObserver.disconnect();
+				this._contentParent.style.height = "0"; //$NON-NLS-0$ // setting it directly in element to override any previous direct height modification
+			} else {
+				this._contentParent.style.display = "none"; //$NON-NLS-0$
+			}
+			
+			this.hidden = true;
+			this._contentParent.classList.add("sectionClosed"); //$NON-NLS-0$
+			this.domNode.classList.add("sectionClosed"); //$NON-NLS-0$
 		}
 	};
 	
diff --git a/bundles/org.eclipse.orion.client.ui/web/orion/widgets/input/DropDownMenu.js b/bundles/org.eclipse.orion.client.ui/web/orion/widgets/input/DropDownMenu.js
index 5e2b58b..0a89fd2 100644
--- a/bundles/org.eclipse.orion.client.ui/web/orion/widgets/input/DropDownMenu.js
+++ b/bundles/org.eclipse.orion.client.ui/web/orion/widgets/input/DropDownMenu.js
@@ -40,7 +40,8 @@
 		

 		// Create dropdown container and append to parent dom

 		var dropDownContainer = document.createElement("div"); //$NON-NLS-0$

-		dropDownContainer.classList.add("dropDownContainer"); //$NON-NLS-0$

+		dropDownContainer.classList.add("dropdownMenu"); //$NON-NLS-0$

+		dropDownContainer.classList.add("dropdownMenuOpen"); //$NON-NLS-0$

 		dropDownContainer.id = this.navDropDownId; 

 		dropDownContainer.style.display = 'none'; //$NON-NLS-0$

 		this._parent.appendChild(dropDownContainer);