mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-01 05:48:26 +00:00
Bug 1212357 - Update the layout of the rooms list items for user journey. r=mikedeboer
This commit is contained in:
parent
f4b96d2bbe
commit
6ecd092dbf
@ -186,12 +186,11 @@ body {
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
@ -205,7 +204,7 @@ body {
|
||||
border-radius: 5px;
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
margin: 1rem;
|
||||
margin: 1.5rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
@ -252,8 +251,8 @@ body {
|
||||
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 {
|
||||
@ -331,27 +330,9 @@ body {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -359,41 +340,17 @@ body {
|
||||
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 {
|
||||
display: inline-block;
|
||||
border-top-right-radius: 30px;
|
||||
border-bottom-right-radius: 30px;
|
||||
background-image: url("../shared/img/icons-10x10.svg#dropdown-white");
|
||||
/* Room entry edit button */
|
||||
.room-entry-context-edit-btn {
|
||||
background-image: url("../shared/img/icons-10x10.svg#edit-darkgrey");
|
||||
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;
|
||||
background-size: 12px;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
height: 24px;
|
||||
vertical-align: middle;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .room-entry-context-actions > .dropdown-menu {
|
||||
@ -410,16 +367,11 @@ html[dir="rtl"] .room-entry-context-actions > .dropdown-menu {
|
||||
/* 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;
|
||||
}
|
||||
|
@ -340,23 +340,39 @@ loop.panel = (function(_, mozL10n) {
|
||||
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();
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var roomUrl = this.props.roomUrls && this.props.roomUrls[0];
|
||||
if (!roomUrl) {
|
||||
return null;
|
||||
}
|
||||
|
||||
_renderDefaultIcon: function() {
|
||||
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: "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 && roomUrl.location) {
|
||||
return this._renderIcon(roomUrl);
|
||||
} else {
|
||||
return this._renderDefaultIcon();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -398,7 +414,7 @@ loop.panel = (function(_, mozL10n) {
|
||||
this.closeWindow();
|
||||
},
|
||||
|
||||
handleContextChevronClick: function(e) {
|
||||
handleClick: function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
@ -435,23 +451,19 @@ loop.panel = (function(_, mozL10n) {
|
||||
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})
|
||||
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -459,16 +471,14 @@ loop.panel = (function(_, mozL10n) {
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -514,13 +524,9 @@ loop.panel = (function(_, mozL10n) {
|
||||
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, {
|
||||
@ -563,7 +569,7 @@ loop.panel = (function(_, mozL10n) {
|
||||
// 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.
|
||||
|
@ -340,23 +340,39 @@ loop.panel = (function(_, mozL10n) {
|
||||
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();
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var roomUrl = this.props.roomUrls && this.props.roomUrls[0];
|
||||
if (!roomUrl) {
|
||||
return null;
|
||||
}
|
||||
|
||||
_renderDefaultIcon: function() {
|
||||
return (
|
||||
<div className="room-entry-context-item">
|
||||
<a href={roomUrl.location} onClick={this.handleClick} title={roomUrl.description}>
|
||||
<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 && roomUrl.location) {
|
||||
return this._renderIcon(roomUrl);
|
||||
} else {
|
||||
return this._renderDefaultIcon();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -398,7 +414,7 @@ loop.panel = (function(_, mozL10n) {
|
||||
this.closeWindow();
|
||||
},
|
||||
|
||||
handleContextChevronClick: function(e) {
|
||||
handleClick: function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
@ -435,23 +451,19 @@ loop.panel = (function(_, mozL10n) {
|
||||
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>
|
||||
);
|
||||
}
|
||||
@ -459,16 +471,14 @@ loop.panel = (function(_, mozL10n) {
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -514,13 +524,9 @@ loop.panel = (function(_, mozL10n) {
|
||||
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
|
||||
@ -563,7 +569,7 @@ loop.panel = (function(_, mozL10n) {
|
||||
// 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.
|
||||
|
@ -22,6 +22,9 @@
|
||||
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"/>
|
||||
@ -43,6 +46,7 @@
|
||||
<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"/>
|
||||
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 6.0 KiB |
@ -593,7 +593,7 @@ describe("loop.panel", function() {
|
||||
React.createElement(loop.panel.RoomEntry, props));
|
||||
}
|
||||
|
||||
describe("handleContextChevronClick", function() {
|
||||
describe("handleClick", function() {
|
||||
var view;
|
||||
|
||||
beforeEach(function() {
|
||||
@ -613,15 +613,15 @@ describe("loop.panel", 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);
|
||||
});
|
||||
@ -702,10 +702,10 @@ describe("loop.panel", function() {
|
||||
});
|
||||
}
|
||||
|
||||
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() {
|
||||
@ -1129,11 +1129,10 @@ describe("loop.panel", function() {
|
||||
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));
|
||||
@ -1192,11 +1191,5 @@ describe("loop.panel", function() {
|
||||
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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user