Bug 1212357 - Update the layout of the rooms list items for user journey. r=mikedeboer
authorManuel Casas <manuel.casasbarrado@gmail.com>
Wed, 28 Oct 2015 09:42:20 -0700
changeset 305199 c85260a0fcf3018b789037a48ec7228a43ff24b2
parent 305198 0160ff5dfde28032fb5f752d81e72e1ffc964271
child 305200 96b588073732da89239d89e723245d09bab01ca9
push id1001
push userraliiev@mozilla.com
push dateMon, 18 Jan 2016 19:06:03 +0000
treeherdermozilla-release@8b89261f3ac4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmikedeboer
bugs1212357
milestone44.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1212357 - Update the layout of the rooms list items for user journey. r=mikedeboer
browser/components/loop/content/css/panel.css
browser/components/loop/content/js/panel.js
browser/components/loop/content/js/panel.jsx
browser/components/loop/content/shared/img/icons-10x10.svg
browser/components/loop/test/desktop-local/panel_test.js
--- a/browser/components/loop/content/css/panel.css
+++ b/browser/components/loop/content/css/panel.css
@@ -181,36 +181,35 @@ body {
 .rooms {
   flex: 1;
   display: flex;
   flex-flow: column nowrap;
   width: 100%;
 }
 
 .rooms > h1 {
-  font-weight: bold;
   color: #666;
+  font-size: 1rem;
   padding: .5rem 0;
   height: 3rem;
   line-height: 3rem;
-  font-size: 1.1rem;
   margin: 0 15px;
 }
 
 .new-room-view {
   border-bottom: 1px solid #d8d8d8;
   display: flex;
   flex-direction: column;
 }
 
 .new-room-view > .btn {
   border-radius: 5px;
   font-size: 1.2rem;
   font-weight: bold;
-  margin: 1rem;
+  margin: 1.5rem;
   padding: 1rem;
 }
 
 .new-room-view > .stop-sharing-button {
   background-color: #d13f1a;
   border-color: #d13f1a;
 }
 
@@ -247,18 +246,18 @@ body {
 }
 
 .room-list > .room-entry > h2 {
   display: inline-block;
   font-size: 1.3rem;
   line-height: 2.4rem;
   color: #000;
   /* See .room-entry-context-item for the margin/size reductions.
-    * An extra 40px to make space for the call button and chevron. */
-  width: calc(100% - 1rem - 56px);
+   * An extra 16px to make space for the edit button. */
+  width: calc(100% - 1rem - 32px);
 }
 
 .room-list > .room-entry.room-active:not(.room-opened) > h2 {
   font-weight: bold;
 }
 
 .room-list > .room-entry:not(.room-opened):hover {
   background: #dbf7ff;
@@ -326,105 +325,58 @@ body {
 }
 
 /* keep the various room-entry row pieces aligned with each other */
 .room-list > .room-entry > h2 > button,
 .room-list > .room-entry > h2 > span {
   vertical-align: middle;
 }
 
-.room-list > .room-entry > h2:before {
-  content: "";
-  display: inline-block;
-  background-image: url("../shared/img/icons-14x14.svg#hello");
-  background-repeat: no-repeat;
-  background-size: cover;
-  width: 13px;
-  height: 13px;
-  -moz-margin-end: 1rem;
-  margin-bottom: -3px;
-}
-
-.room-list > .room-entry.room-active > h2:before {
-  background-image: url("../shared/img/icons-14x14.svg#hello-active");
-}
-
-/* Room entry context button (call button + chevron) */
+/* Room entry context button (edit button) */
 .room-entry-context-actions {
   display: none;
-  border-radius: 30px;
-  background: #56b397;
   vertical-align: top;
 }
 
 .room-entry:hover .room-entry-context-actions {
   display: inline-block;
 }
 
-.room-entry:hover .room-entry-context-actions:hover {
-  background: #50e3c2;
-}
-
-/* Room entry call button */
-.room-entry-call-btn {
-  border-top-left-radius: 30px;
-  border-bottom-left-radius: 30px;
-  background-color: transparent;
-  background-image: url("../shared/img/icons-14x14.svg#video-white");
-  background-position: right center;
-}
-
-html[dir="rtl"] .room-entry-call-btn {
-  background-position: left center;
-}
-
-/* Room entry context menu */
-.room-entry-context-menu-chevron {
+/* Room entry edit button */
+.room-entry-context-edit-btn {
+  background-image: url("../shared/img/icons-10x10.svg#edit-darkgrey");
+  background-position: center;
+  background-repeat: no-repeat;
+  background-size: 12px;
+  cursor: pointer;
   display: inline-block;
-  border-top-right-radius: 30px;
-  border-bottom-right-radius: 30px;
-  background-image: url("../shared/img/icons-10x10.svg#dropdown-white");
-  background-position: center;
-  cursor: pointer;
-}
-
-/* Common styles for chevron and call button. */
-.room-entry-context-menu-chevron,
-.room-entry-call-btn {
-  width: 30px;
   height: 24px;
-  background-size: 12px;
-  background-repeat: no-repeat;
   vertical-align: middle;
+  width: 16px;
 }
 
 html[dir="rtl"] .room-entry-context-actions > .dropdown-menu {
   right: auto;
   left: 21px;
 }
 
 .room-entry-context-actions > .dropdown-menu {
   right: 21px;
   bottom: auto;
   left: auto;
 }
 
 /* Keep ".room-list > .room-entry > h2" in sync with these. */
 .room-entry-context-item {
   display: inline-block;
+  -moz-margin-end: 1rem;
   vertical-align: middle;
-  -moz-margin-start: 1rem;
-  height: 16px;
 }
 
-.room-entry:not(.room-opened):hover .room-entry-context-item {
-  display: none;
-}
-
-.room-entry-context-item > a > img {
+.room-entry-context-item > img {
   height: 16px;
   width: 16px;
 }
 
 .button-close {
   background-color: transparent;
   background-image: url(../shared/img/icons-10x10.svg#close);
   background-repeat: no-repeat;
--- a/browser/components/loop/content/js/panel.js
+++ b/browser/components/loop/content/js/panel.js
@@ -335,33 +335,49 @@ loop.panel = (function(_, mozL10n) {
     propTypes: {
       mozLoop: React.PropTypes.object.isRequired,
       roomUrls: React.PropTypes.array
     },
 
     handleClick: function(event) {
       event.stopPropagation();
       event.preventDefault();
-      this.props.mozLoop.openURL(event.currentTarget.href);
-      this.closeWindow();
+      if (event.currentTarget.href) {
+        this.props.mozLoop.openURL(event.currentTarget.href);
+        this.closeWindow();
+      }
+    },
+
+    _renderDefaultIcon: function() {
+      return (
+        React.createElement("div", {className: "room-entry-context-item"}, 
+          React.createElement("img", {src: "loop/shared/img/icons-16x16.svg#globe"})
+        )
+      );
+    },
+
+    _renderIcon: function(roomUrl) {
+      return (
+        React.createElement("div", {className: "room-entry-context-item"}, 
+          React.createElement("a", {href: roomUrl.location, 
+            onClick: this.handleClick, 
+            title: roomUrl.description}, 
+            React.createElement("img", {src: roomUrl.thumbnail || "loop/shared/img/icons-16x16.svg#globe"})
+          )
+        )
+      );
     },
 
     render: function() {
       var roomUrl = this.props.roomUrls && this.props.roomUrls[0];
-      if (!roomUrl) {
-        return null;
+      if (roomUrl && roomUrl.location) {
+        return this._renderIcon(roomUrl);
+      } else {
+        return this._renderDefaultIcon();
       }
-
-      return (
-        React.createElement("div", {className: "room-entry-context-item"}, 
-          React.createElement("a", {href: roomUrl.location, onClick: this.handleClick, title: roomUrl.description}, 
-            React.createElement("img", {src: roomUrl.thumbnail || "loop/shared/img/icons-16x16.svg#globe"})
-          )
-        )
-      );
     }
   });
 
   /**
    * Room list entry.
    *
    * Active Room means there are participants in the room.
    * Opened Room means the user is in the room.
@@ -393,17 +409,17 @@ loop.panel = (function(_, mozL10n) {
       event.preventDefault();
 
       this.props.dispatcher.dispatch(new sharedActions.OpenRoom({
         roomToken: this.props.room.roomToken
       }));
       this.closeWindow();
     },
 
-    handleContextChevronClick: function(e) {
+    handleClick: function(e) {
       e.preventDefault();
       e.stopPropagation();
 
       this.setState({
         eventPosY: e.pageY
       });
 
       this.toggleDropdownMenu();
@@ -430,50 +446,44 @@ loop.panel = (function(_, mozL10n) {
         this.props.room.decryptedContext.urls[0].description ||
         this.props.room.decryptedContext.urls[0].location;
 
       return (
         React.createElement("div", {className: roomClasses, 
           onClick: this.props.isOpenedRoom ? null : this.handleClickEntry, 
           onMouseLeave: this.props.isOpenedRoom ? null : this._handleMouseOut, 
           ref: "roomEntry"}, 
-          React.createElement("h2", null, 
-            roomTitle
-          ), 
           React.createElement(RoomEntryContextItem, {
             mozLoop: this.props.mozLoop, 
             roomUrls: this.props.room.decryptedContext.urls}), 
+          React.createElement("h2", null, roomTitle), 
           this.props.isOpenedRoom ? null :
             React.createElement(RoomEntryContextButtons, {
               dispatcher: this.props.dispatcher, 
               eventPosY: this.state.eventPosY, 
-              handleClickEntry: this.handleClickEntry, 
-              handleContextChevronClick: this.handleContextChevronClick, 
+              handleClick: this.handleClick, 
               ref: "contextActions", 
               room: this.props.room, 
               showMenu: this.state.showMenu, 
               toggleDropdownMenu: this.toggleDropdownMenu})
-          
         )
       );
     }
   });
 
   /**
    * Buttons corresponding to each conversation entry.
-   * This component renders the video icon call button and chevron button for
-   * displaying contextual dropdown menu for conversation entries.
-   * It also holds the dropdown menu.
+   * This component renders the edit button for displaying contextual dropdown
+   * menu for conversation entries. It also holds the dropdown menu.
    */
   var RoomEntryContextButtons = React.createClass({displayName: "RoomEntryContextButtons",
     propTypes: {
       dispatcher: React.PropTypes.object.isRequired,
       eventPosY: React.PropTypes.number.isRequired,
-      handleClickEntry: React.PropTypes.func.isRequired,
-      handleContextChevronClick: React.PropTypes.func.isRequired,
+      handleClick: React.PropTypes.func.isRequired,
       room: React.PropTypes.object.isRequired,
       showMenu: React.PropTypes.bool.isRequired,
       toggleDropdownMenu: React.PropTypes.func.isRequired
     },
 
     handleEmailButtonClick: function(event) {
       event.preventDefault();
       event.stopPropagation();
@@ -509,23 +519,19 @@ loop.panel = (function(_, mozL10n) {
       }));
 
       this.props.toggleDropdownMenu();
     },
 
     render: function() {
       return (
         React.createElement("div", {className: "room-entry-context-actions"}, 
-          React.createElement("button", {
-            className: "btn room-entry-call-btn", 
-            onClick: this.props.handleClickEntry, 
-            ref: "callButton"}), 
           React.createElement("div", {
-            className: "room-entry-context-menu-chevron dropdown-menu-button", 
-            onClick: this.props.handleContextChevronClick, 
+            className: "room-entry-context-edit-btn dropdown-menu-button", 
+            onClick: this.props.handleClick, 
             ref: "menu-button"}), 
           this.props.showMenu ?
             React.createElement(ConversationDropdown, {
               eventPosY: this.props.eventPosY, 
               handleCopyButtonClick: this.handleCopyButtonClick, 
               handleDeleteButtonClick: this.handleDeleteButtonClick, 
               handleEmailButtonClick: this.handleEmailButtonClick, 
               ref: "menu"}) :
@@ -558,17 +564,17 @@ loop.panel = (function(_, mozL10n) {
 
     componentDidMount: function() {
       var menuNode = this.getDOMNode();
       var menuNodeRect = menuNode.getBoundingClientRect();
 
       // Get the parent element and make sure the menu does not overlow its
       // container.
       var listNode = loop.shared.utils.findParentNode(this.getDOMNode(),
-                                                      ".rooms");
+                                                      "rooms");
       var listNodeRect = listNode.getBoundingClientRect();
 
       // Click offset to not display the menu right next to the area clicked.
       var offset = 10;
 
       if (this.props.eventPosY + menuNodeRect.height >=
           listNodeRect.top + listNodeRect.height) {
         // Position above click area.
--- a/browser/components/loop/content/js/panel.jsx
+++ b/browser/components/loop/content/js/panel.jsx
@@ -335,33 +335,49 @@ loop.panel = (function(_, mozL10n) {
     propTypes: {
       mozLoop: React.PropTypes.object.isRequired,
       roomUrls: React.PropTypes.array
     },
 
     handleClick: function(event) {
       event.stopPropagation();
       event.preventDefault();
-      this.props.mozLoop.openURL(event.currentTarget.href);
-      this.closeWindow();
+      if (event.currentTarget.href) {
+        this.props.mozLoop.openURL(event.currentTarget.href);
+        this.closeWindow();
+      }
+    },
+
+    _renderDefaultIcon: function() {
+      return (
+        <div className="room-entry-context-item">
+          <img src="loop/shared/img/icons-16x16.svg#globe" />
+        </div>
+      );
+    },
+
+    _renderIcon: function(roomUrl) {
+      return (
+        <div className="room-entry-context-item">
+          <a href={roomUrl.location}
+            onClick={this.handleClick}
+            title={roomUrl.description}>
+            <img src={roomUrl.thumbnail || "loop/shared/img/icons-16x16.svg#globe"} />
+          </a>
+        </div>
+      );
     },
 
     render: function() {
       var roomUrl = this.props.roomUrls && this.props.roomUrls[0];
-      if (!roomUrl) {
-        return null;
+      if (roomUrl && roomUrl.location) {
+        return this._renderIcon(roomUrl);
+      } else {
+        return this._renderDefaultIcon();
       }
-
-      return (
-        <div className="room-entry-context-item">
-          <a href={roomUrl.location} onClick={this.handleClick} title={roomUrl.description}>
-            <img src={roomUrl.thumbnail || "loop/shared/img/icons-16x16.svg#globe"} />
-          </a>
-        </div>
-      );
     }
   });
 
   /**
    * Room list entry.
    *
    * Active Room means there are participants in the room.
    * Opened Room means the user is in the room.
@@ -393,17 +409,17 @@ loop.panel = (function(_, mozL10n) {
       event.preventDefault();
 
       this.props.dispatcher.dispatch(new sharedActions.OpenRoom({
         roomToken: this.props.room.roomToken
       }));
       this.closeWindow();
     },
 
-    handleContextChevronClick: function(e) {
+    handleClick: function(e) {
       e.preventDefault();
       e.stopPropagation();
 
       this.setState({
         eventPosY: e.pageY
       });
 
       this.toggleDropdownMenu();
@@ -430,50 +446,44 @@ loop.panel = (function(_, mozL10n) {
         this.props.room.decryptedContext.urls[0].description ||
         this.props.room.decryptedContext.urls[0].location;
 
       return (
         <div className={roomClasses}
           onClick={this.props.isOpenedRoom ? null : this.handleClickEntry}
           onMouseLeave={this.props.isOpenedRoom ? null : this._handleMouseOut}
           ref="roomEntry">
-          <h2>
-            {roomTitle}
-          </h2>
           <RoomEntryContextItem
             mozLoop={this.props.mozLoop}
             roomUrls={this.props.room.decryptedContext.urls} />
+          <h2>{roomTitle}</h2>
           {this.props.isOpenedRoom ? null :
             <RoomEntryContextButtons
               dispatcher={this.props.dispatcher}
               eventPosY={this.state.eventPosY}
-              handleClickEntry={this.handleClickEntry}
-              handleContextChevronClick={this.handleContextChevronClick}
+              handleClick={this.handleClick}
               ref="contextActions"
               room={this.props.room}
               showMenu={this.state.showMenu}
-              toggleDropdownMenu={this.toggleDropdownMenu} />
-          }
+              toggleDropdownMenu={this.toggleDropdownMenu} />}
         </div>
       );
     }
   });
 
   /**
    * Buttons corresponding to each conversation entry.
-   * This component renders the video icon call button and chevron button for
-   * displaying contextual dropdown menu for conversation entries.
-   * It also holds the dropdown menu.
+   * This component renders the edit button for displaying contextual dropdown
+   * menu for conversation entries. It also holds the dropdown menu.
    */
   var RoomEntryContextButtons = React.createClass({
     propTypes: {
       dispatcher: React.PropTypes.object.isRequired,
       eventPosY: React.PropTypes.number.isRequired,
-      handleClickEntry: React.PropTypes.func.isRequired,
-      handleContextChevronClick: React.PropTypes.func.isRequired,
+      handleClick: React.PropTypes.func.isRequired,
       room: React.PropTypes.object.isRequired,
       showMenu: React.PropTypes.bool.isRequired,
       toggleDropdownMenu: React.PropTypes.func.isRequired
     },
 
     handleEmailButtonClick: function(event) {
       event.preventDefault();
       event.stopPropagation();
@@ -509,23 +519,19 @@ loop.panel = (function(_, mozL10n) {
       }));
 
       this.props.toggleDropdownMenu();
     },
 
     render: function() {
       return (
         <div className="room-entry-context-actions">
-          <button
-            className="btn room-entry-call-btn"
-            onClick={this.props.handleClickEntry}
-            ref="callButton" />
           <div
-            className="room-entry-context-menu-chevron dropdown-menu-button"
-            onClick={this.props.handleContextChevronClick}
+            className="room-entry-context-edit-btn dropdown-menu-button"
+            onClick={this.props.handleClick}
             ref="menu-button" />
           {this.props.showMenu ?
             <ConversationDropdown
               eventPosY={this.props.eventPosY}
               handleCopyButtonClick={this.handleCopyButtonClick}
               handleDeleteButtonClick={this.handleDeleteButtonClick}
               handleEmailButtonClick={this.handleEmailButtonClick}
               ref="menu" /> :
@@ -558,17 +564,17 @@ loop.panel = (function(_, mozL10n) {
 
     componentDidMount: function() {
       var menuNode = this.getDOMNode();
       var menuNodeRect = menuNode.getBoundingClientRect();
 
       // Get the parent element and make sure the menu does not overlow its
       // container.
       var listNode = loop.shared.utils.findParentNode(this.getDOMNode(),
-                                                      ".rooms");
+                                                      "rooms");
       var listNodeRect = listNode.getBoundingClientRect();
 
       // Click offset to not display the menu right next to the area clicked.
       var offset = 10;
 
       if (this.props.eventPosY + menuNodeRect.height >=
           listNodeRect.top + listNodeRect.height) {
         // Position above click area.
--- a/browser/components/loop/content/shared/img/icons-10x10.svg
+++ b/browser/components/loop/content/shared/img/icons-10x10.svg
@@ -17,16 +17,19 @@
       fill: #0095dd;
     }
     use[id$="-white"] {
       fill: #fff;
     }
     use[id$="-disabled"] {
       fill: rgba(255,255,255,0.4);
     }
+    use[id$="-darkgrey"] {
+      fill: #565656;
+    }
   </style>
   <defs>
     <polygon id="close-shape" points="10,1.717 8.336,0.049 5.024,3.369 1.663,0 0,1.668 3.36,5.037 0.098,8.307 1.762,9.975 5.025,6.705 8.311,10 9.975,8.332 6.688,5.037"/>
     <path id="dropdown-shape" fill-rule="evenodd" d="M9,3L4.984,7L1,3H9z"/>
     <polygon id="expand-shape" points="10,0 4.838,0 6.506,1.669 0,8.175 1.825,10 8.331,3.494 10,5.162"/>
     <path id="edit-shape" d="M5.493,1.762l2.745,2.745L2.745,10H0V7.255L5.493,1.762z M2.397,9.155l0.601-0.601L1.446,7.002L0.845,7.603 V8.31H1.69v0.845H2.397z M5.849,3.028c0-0.096-0.048-0.144-0.146-0.144c-0.044,0-0.081,0.015-0.112,0.046L2.014,6.508 C1.983,6.538,1.968,6.577,1.968,6.619c0,0.098,0.048,0.146,0.144,0.146c0.044,0,0.081-0.015,0.112-0.046l3.579-3.577 C5.834,3.111,5.849,3.073,5.849,3.028z M10,2.395c0,0.233-0.081,0.431-0.245,0.595L8.66,4.085L5.915,1.34L7.01,0.25 C7.168,0.083,7.366,0,7.605,0c0.233,0,0.433,0.083,0.601,0.25l1.55,1.544C9.919,1.966,10,2.166,10,2.395z"/>
     <rect id="minimize-shape" y="3.6" width="10" height="2.8"/>
     <path id="cog-shape" d="M122.285722,122.071424 C122.285722,122.936938 121.579806,123.642854 120.714291,123.642854 C119.848777,123.642854 119.142861,122.936938 119.142861,122.071424 C119.142861,121.205909 119.848777,120.499993 120.714291,120.499993 C121.579806,120.499993 122.285722,121.205909 122.285722,122.071424 L122.285722,122.071424 Z M125.428583,121.402338 C125.428583,121.297985 125.354922,121.199771 125.250569,121.181356 L124.127242,121.009481 C124.065858,120.806913 123.97992,120.604346 123.875567,120.407917 C124.084273,120.119413 124.311394,119.849323 124.520099,119.566957 C124.550791,119.523988 124.569207,119.481019 124.569207,119.425773 C124.569207,119.376666 124.55693,119.327559 124.526238,119.290729 C124.268425,118.928563 123.838737,118.547982 123.513402,118.247201 C123.470433,118.21037 123.415187,118.185817 123.359942,118.185817 C123.304696,118.185817 123.249451,118.204232 123.21262,118.241062 L122.340967,118.897871 C122.162954,118.805795 121.978802,118.732134 121.788511,118.67075 L121.616636,117.541285 C121.604359,117.436932 121.506145,117.357133 121.395654,117.357133 L120.032929,117.357133 C119.922438,117.357133 119.8365,117.430793 119.811947,117.529008 C119.713732,117.897312 119.676902,118.296308 119.633933,118.67075 C119.443642,118.732134 119.253352,118.811933 119.075338,118.904009 L118.228239,118.247201 C118.179132,118.21037 118.123886,118.185817 118.068641,118.185817 C117.859935,118.185817 117.031251,119.082023 116.88393,119.28459 C116.853238,119.327559 116.828684,119.370528 116.828684,119.425773 C116.828684,119.481019 116.853238,119.530126 116.890068,119.573095 C117.117189,119.849323 117.338171,120.125551 117.546877,120.420194 C117.448662,120.604346 117.368863,120.788498 117.307479,120.984927 L116.165737,121.156802 C116.073661,121.175217 116,121.285709 116,121.377785 L116,122.74051 C116,122.844862 116.073661,122.943077 116.178014,122.961492 L117.301341,123.127229 C117.362725,123.335934 117.448662,123.538502 117.553015,123.73493 C117.34431,124.023435 117.117189,124.293525 116.908483,124.575891 C116.877791,124.61886 116.859376,124.661829 116.859376,124.717074 C116.859376,124.766182 116.871653,124.815289 116.902345,124.858258 C117.160158,125.214285 117.589846,125.594866 117.915181,125.889509 C117.95815,125.932478 118.013395,125.957031 118.068641,125.957031 C118.123886,125.957031 118.179132,125.938616 118.222101,125.901786 L119.087615,125.244977 C119.265629,125.337053 119.449781,125.410714 119.640071,125.472098 L119.811947,126.601563 C119.824223,126.705916 119.922438,126.785715 120.032929,126.785715 L121.395654,126.785715 C121.506145,126.785715 121.592083,126.712054 121.616636,126.61384 C121.714851,126.245536 121.751681,125.84654 121.79465,125.472098 C121.98494,125.410714 122.175231,125.330914 122.353244,125.238838 L123.200343,125.901786 C123.249451,125.932478 123.304696,125.957031 123.359942,125.957031 C123.568647,125.957031 124.397331,125.054686 124.544653,124.858258 C124.581483,124.815289 124.599899,124.77232 124.599899,124.717074 C124.599899,124.661829 124.575345,124.606583 124.538515,124.563614 C124.311394,124.287386 124.090411,124.017297 123.881706,123.716515 C123.97992,123.538502 124.053581,123.35435 124.121103,123.157921 L125.256707,122.986046 C125.354922,122.96763 125.428583,122.857139 125.428583,122.765063 L125.428583,121.402338 Z" transform="translate(-116 -117)" fill="#666" fill-rule="evenodd"/>
@@ -38,16 +41,17 @@
   <use id="dropdown" xlink:href="#dropdown-shape"/>
   <use id="dropdown-white" xlink:href="#dropdown-shape"/>
   <use id="dropdown-active" xlink:href="#dropdown-shape"/>
   <use id="dropdown-disabled" xlink:href="#dropdown-shape"/>
   <use id="edit" xlink:href="#edit-shape"/>
   <use id="edit-active" xlink:href="#edit-shape"/>
   <use id="edit-disabled" xlink:href="#edit-shape"/>
   <use id="edit-white" xlink:href="#edit-shape"/>
+  <use id="edit-darkgrey" xlink:href="#edit-shape"/>
   <use id="expand" xlink:href="#expand-shape"/>
   <use id="expand-active" xlink:href="#expand-shape"/>
   <use id="expand-disabled" xlink:href="#expand-shape"/>
   <use id="minimize" xlink:href="#minimize-shape"/>
   <use id="minimize-active" xlink:href="#minimize-shape"/>
   <use id="minimize-disabled" xlink:href="#minimize-shape"/>
   <use id="settings-cog" xlink:href="#cog-shape"/>
 </svg>
--- a/browser/components/loop/test/desktop-local/panel_test.js
+++ b/browser/components/loop/test/desktop-local/panel_test.js
@@ -588,17 +588,17 @@ describe("loop.panel", function() {
       props = _.extend({
         dispatcher: dispatcher,
         mozLoop: fakeMozLoop
       }, props);
       return TestUtils.renderIntoDocument(
         React.createElement(loop.panel.RoomEntry, props));
     }
 
-    describe("handleContextChevronClick", function() {
+    describe("handleClick", function() {
       var view;
 
       beforeEach(function() {
         // Stub to prevent warnings due to stores not being set up to handle
         // the actions we are triggering.
         sandbox.stub(dispatcher, "dispatch");
 
         view = mountRoomEntry({
@@ -608,25 +608,25 @@ describe("loop.panel", function() {
       });
 
       // XXX Current version of React cannot use TestUtils.Simulate, please
       // enable when we upgrade.
       it.skip("should close the menu when you move out the cursor", function() {
         expect(view.refs.contextActions.state.showMenu).to.eql(false);
       });
 
-      it("should set eventPosY when handleContextChevronClick is called", function() {
-        view.handleContextChevronClick(fakeEvent);
+      it("should set eventPosY when handleClick is called", function() {
+        view.handleClick(fakeEvent);
 
         expect(view.state.eventPosY).to.eql(fakeEvent.pageY);
       });
 
-      it("toggle state.showMenu when handleContextChevronClick is called", function() {
+      it("toggle state.showMenu when handleClick is called", function() {
         var prevState = view.state.showMenu;
-        view.handleContextChevronClick(fakeEvent);
+        view.handleClick(fakeEvent);
 
         expect(view.state.showMenu).to.eql(!prevState);
       });
 
       it("should toggle the menu when the button is clicked", function() {
         var prevState = view.state.showMenu;
         var node = view.refs.contextActions.refs["menu-button"].getDOMNode();
 
@@ -697,20 +697,20 @@ describe("loop.panel", function() {
 
       function mountEntryForContext() {
         return mountRoomEntry({
           isOpenedRoom: false,
           room: new loop.store.Room(roomData)
         });
       }
 
-      it("should not display a context indicator if the room doesn't have any", function() {
+      it("should display a default context indicator if the room doesn't have any", function() {
         roomEntry = mountEntryForContext();
 
-        expect(roomEntry.getDOMNode().querySelector(".room-entry-context-item")).eql(null);
+        expect(roomEntry.getDOMNode().querySelector(".room-entry-context-item")).not.eql(null);
       });
 
       it("should a context indicator if the room specifies context", function() {
         roomData.decryptedContext.urls = [{
           description: "invalid entry",
           location: "http://invalid",
           thumbnail: "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
         }];
@@ -1124,21 +1124,20 @@ describe("loop.panel", function() {
 
   describe("RoomEntryContextButtons", function() {
     var view, dispatcher;
 
     function createTestComponent(extraProps) {
       var props = _.extend({
         dispatcher: dispatcher,
         eventPosY: 0,
-        handleClickEntry: sandbox.stub(),
         showMenu: false,
         room: roomData,
         toggleDropdownMenu: sandbox.stub(),
-        handleContextChevronClick: sandbox.stub()
+        handleClick: sandbox.stub()
       }, extraProps);
       return TestUtils.renderIntoDocument(
         React.createElement(loop.panel.RoomEntryContextButtons, props));
     }
 
     beforeEach(function() {
       dispatcher = new loop.Dispatcher();
       sandbox.stub(dispatcher, "dispatch");
@@ -1187,16 +1186,10 @@ describe("loop.panel", function() {
     });
 
     it("should dispatch a delete action when callback is called", function() {
       view.handleDeleteButtonClick(fakeEvent);
 
       sinon.assert.calledWithExactly(dispatcher.dispatch,
         new sharedActions.DeleteRoom({ roomToken: roomData.roomToken }));
     });
-
-    it("should trigger handleClickEntry when button is clicked", function() {
-      TestUtils.Simulate.click(view.refs.callButton.getDOMNode());
-
-      sinon.assert.calledOnce(view.props.handleClickEntry);
-    });
   });
 });