Bug 1065275: add a TabView component to the panel. r=paolo,Niko.

This commit is contained in:
Mike de Boer 2014-09-11 19:14:30 +02:00
parent e2d7fd47e1
commit e3519febdf
5 changed files with 311 additions and 15 deletions

View File

@ -22,6 +22,57 @@ loop.panel = (function(_, mozL10n) {
*/ */
var router; var router;
var TabView = React.createClass({displayName: 'TabView',
getInitialState: function() {
return {
selectedTab: "call"
};
},
handleSelectTab: function(event) {
var tabName = event.target.dataset.tabName;
this.setState({selectedTab: tabName});
if (this.props.onSelect) {
this.props.onSelect(tabName);
}
},
render: function() {
var cx = React.addons.classSet;
var tabButtons = [];
var tabs = [];
React.Children.forEach(this.props.children, function(tab, i) {
var tabName = tab.props.name;
var isSelected = (this.state.selectedTab == tabName);
tabButtons.push(
React.DOM.li({className: cx({selected: isSelected}),
key: i,
'data-tab-name': tabName,
onClick: this.handleSelectTab}
)
);
tabs.push(
React.DOM.div({key: i, className: cx({tab: true, selected: isSelected})},
tab.props.children
)
);
}, this);
return (
React.DOM.div({className: "tab-view-container"},
React.DOM.ul({className: "tab-view"}, tabButtons),
tabs
)
);
}
});
var Tab = React.createClass({displayName: 'Tab',
render: function() {
return null;
}
});
/** /**
* Dropdown menu mixin. * Dropdown menu mixin.
* @type {Object} * @type {Object}
@ -424,10 +475,17 @@ loop.panel = (function(_, mozL10n) {
return ( return (
React.DOM.div(null, React.DOM.div(null,
NotificationListView({notifications: this.props.notifications}), NotificationListView({notifications: this.props.notifications}),
CallUrlResult({client: this.props.client, TabView({onSelect: this.selectTab},
notifications: this.props.notifications, Tab({name: "call"},
callUrl: this.props.callUrl}), CallUrlResult({client: this.props.client,
ToSView(null), notifications: this.props.notifications,
callUrl: this.props.callUrl}),
ToSView(null)
),
Tab({name: "contacts"},
React.DOM.span(null, "contacts")
)
),
React.DOM.div({className: "footer"}, React.DOM.div({className: "footer"},
AvailabilityDropdown(null), AvailabilityDropdown(null),
AuthLink(null), AuthLink(null),

View File

@ -22,6 +22,57 @@ loop.panel = (function(_, mozL10n) {
*/ */
var router; var router;
var TabView = React.createClass({
getInitialState: function() {
return {
selectedTab: "call"
};
},
handleSelectTab: function(event) {
var tabName = event.target.dataset.tabName;
this.setState({selectedTab: tabName});
if (this.props.onSelect) {
this.props.onSelect(tabName);
}
},
render: function() {
var cx = React.addons.classSet;
var tabButtons = [];
var tabs = [];
React.Children.forEach(this.props.children, function(tab, i) {
var tabName = tab.props.name;
var isSelected = (this.state.selectedTab == tabName);
tabButtons.push(
<li className={cx({selected: isSelected})}
key={i}
data-tab-name={tabName}
onClick={this.handleSelectTab}>
</li>
);
tabs.push(
<div key={i} className={cx({tab: true, selected: isSelected})}>
{tab.props.children}
</div>
);
}, this);
return (
<div className="tab-view-container">
<ul className="tab-view">{tabButtons}</ul>
{tabs}
</div>
);
}
});
var Tab = React.createClass({
render: function() {
return null;
}
});
/** /**
* Dropdown menu mixin. * Dropdown menu mixin.
* @type {Object} * @type {Object}
@ -424,10 +475,17 @@ loop.panel = (function(_, mozL10n) {
return ( return (
<div> <div>
<NotificationListView notifications={this.props.notifications} /> <NotificationListView notifications={this.props.notifications} />
<CallUrlResult client={this.props.client} <TabView onSelect={this.selectTab}>
notifications={this.props.notifications} <Tab name="call">
callUrl={this.props.callUrl} /> <CallUrlResult client={this.props.client}
<ToSView /> notifications={this.props.notifications}
callUrl={this.props.callUrl} />
<ToSView />
</Tab>
<Tab name="contacts">
<span>contacts</span>
</Tab>
</TabView>
<div className="footer"> <div className="footer">
<AvailabilityDropdown /> <AvailabilityDropdown />
<AuthLink /> <AuthLink />

View File

@ -4,12 +4,6 @@
/* Panel styles */ /* Panel styles */
.panel { .panel {
/* XXX force proper content positioning by adding extra margin space
* taken away by reset.css
*/
margin-top: 7px;
margin-bottom: 7px;
/* hide the extra margin space that the panel resizer now wants to show */ /* hide the extra margin space that the panel resizer now wants to show */
overflow: hidden; overflow: hidden;
} }
@ -18,6 +12,74 @@
margin-bottom: 1em; margin-bottom: 1em;
} }
.tab-view,
.tab-view > li {
margin: 0;
padding: 0;
border: 0;
vertical-align: baseline;
}
.tab-view {
display: flex;
flex-direction: row;
padding: 10px;
border-bottom: 1px solid #ccc;
background: #fafafa;
border-top-right-radius: 2px;
border-top-left-radius: 2px;
list-style: none;
}
.tab-view > li {
flex: 1;
text-align: center;
color: #ccc;
border-right: 1px solid #ccc;
padding: 0 10px;
height: 16px;
cursor: pointer;
background-repeat: no-repeat;
background-size: 16px 16px;
background-position: center;
}
.tab-view > li[data-tab-name="call"] {
background-image: url("../img/icons-16x16.svg#precall");
}
.tab-view > li[data-tab-name="call"]:hover {
background-image: url("../img/icons-16x16.svg#precall-hover");
}
.tab-view > li[data-tab-name="call"].selected {
background-image: url("../img/icons-16x16.svg#precall-active");
}
.tab-view > li[data-tab-name="contacts"] {
background-image: url("../img/icons-16x16.svg#contacts");
}
.tab-view > li[data-tab-name="contacts"]:hover {
background-image: url("../img/icons-16x16.svg#contacts-hover");
}
.tab-view > li[data-tab-name="contacts"].selected {
background-image: url("../img/icons-16x16.svg#contacts-active");
}
.tab-view > li:last-child {
border-right: 0;
}
.tab {
display: none;
}
.tab.selected {
display: block;
}
.share { .share {
background: #fbfbfb; background: #fbfbfb;
} }

View File

@ -0,0 +1,117 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px"
viewBox="0 0 16 16"
enable-background="new 0 0 16 16"
xml:space="preserve">
<style>
use:not(:target) {
display: none;
}
use {
fill: #ccc;
}
use[id$="-hover"] {
fill: #444;
}
use[id$="-active"] {
fill: #0095dd;
}
</style>
<defs style="display:none">
<path id="audio-shape" fill-rule="evenodd" clip-rule="evenodd" d="M11.429,6.857v2.286c0,1.894-1.535,3.429-3.429,3.429
c-1.894,0-3.429-1.535-3.429-3.429V6.857H3.429v2.286c0,2.129,1.458,3.913,3.429,4.422v1.293H6.286
c-0.746,0-1.379,0.477-1.615,1.143h6.658c-0.236-0.665-0.869-1.143-1.615-1.143H9.143v-1.293c1.971-0.508,3.429-2.292,3.429-4.422
V6.857H11.429z M8,12c1.578,0,2.857-1.279,2.857-2.857V2.857C10.857,1.279,9.578,0,8,0C6.422,0,5.143,1.279,5.143,2.857v6.286
C5.143,10.721,6.422,12,8,12z"/>
<path id="block-shape" fill-rule="evenodd" clip-rule="evenodd" d="M8,0C3.582,0,0,3.582,0,8c0,4.418,3.582,8,8,8
c4.418,0,8-3.582,8-8C16,3.582,12.418,0,8,0z M8,2.442c1.073,0,2.075,0.301,2.926,0.821l-7.673,7.673
C2.718,10.085,2.408,9.079,2.408,8C2.408,4.931,4.911,2.442,8,2.442z M8,13.557c-1.073,0-2.075-0.301-2.926-0.821l7.673-7.673
C13.282,5.915,13.592,6.921,13.592,8C13.592,11.069,11.089,13.557,8,13.557z"/>
<path id="contacts-shape" fill-rule="evenodd" clip-rule="evenodd" d="M8,6.526c1.802,0,3.263-1.461,3.263-3.263
C11.263,1.461,9.802,0,8,0C6.198,0,4.737,1.461,4.737,3.263C4.737,5.066,6.198,6.526,8,6.526z M14.067,11.421c0,0,0-0.001,0-0.001
c0-1.676-1.397-3.119-3.419-3.807L8.001,10.26L5.354,7.613C3.331,8.3,1.933,9.744,1.933,11.42v0.001H1.93
c0,1.679,0.328,3.246,0.896,4.579h10.348c0.568-1.333,0.896-2.9,0.896-4.579H14.067z"/>
<g id="google-shape">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.001,9.278c-0.9,0.03-1.989,0.454-2.144,1.274
c-0.292,1.54,1.284,2.004,2.455,1.932c1.097-0.067,1.737-0.593,1.813-1.26c0.063-0.554-0.184-1.153-0.959-1.644
c-0.142-0.09-0.28-0.185-0.413-0.282C8.504,9.291,8.25,9.27,8.001,9.278z"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.381,3.409C6.638,3.64,6.32,4.405,6.627,5.61
C6.908,6.708,7.78,7.322,8.569,7.104c0.77-0.213,0.987-1.021,0.847-1.873C9.201,3.929,8.261,3.136,7.381,3.409z"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M8,0C3.582,0,0,3.582,0,8s3.582,8,8,8c4.418,0,8-3.582,8-8
S12.418,0,8,0z M10.544,4.471c0.17,0.453,0.194,0.954,0.021,1.416c-0.163,0.436-0.495,0.811-0.982,1.096
C9.307,7.146,9.167,7.351,9.151,7.548c-0.045,0.575,0.658,0.993,1.064,1.297c0.889,0.666,1.236,1.758,0.648,2.813
c-0.562,1.007-1.901,1.457-3.322,1.462c-1.766-0.008-2.88-0.817-2.938-1.918C4.527,9.779,5.987,9.101,7.307,8.947
c0.369-0.043,0.7-0.036,1.01-0.014C7.85,8.625,7.675,7.998,7.914,7.58c0.062-0.109,0.023-0.072-0.095-0.054
C6.739,7.689,5.628,6.985,5.367,5.92c-0.132-0.54-0.05-1.105,0.156-1.547C5.97,3.413,6.964,2.88,8.067,2.88
c1.147,0,2.209,0,3.334,0.009L10.612,3.4H9.714C10.093,3.665,10.384,4.046,10.544,4.471z"/>
</g>
<path id="history-shape" fill-rule="evenodd" clip-rule="evenodd" d="M8,16c-4.418,0-8-3.582-8-8c0-4.418,3.582-8,8-8
c4.418,0,8,3.582,8,8C16,12.418,12.418,16,8,16z M8,2.442C4.911,2.442,2.408,4.931,2.408,8c0,3.069,2.504,5.557,5.592,5.557
S13.592,11.069,13.592,8C13.592,4.931,11.089,2.442,8,2.442z M7.649,9.048C7.206,8.899,6.882,8.493,6.882,8V4.645
c0-0.618,0.501-1.119,1.118-1.119c0.618,0,1.119,0.501,1.119,1.119v3.078c1.176,1.22,2.237,3.633,2.237,3.633
S8.844,10.252,7.649,9.048z"/>
<path id="precall-shape" fill-rule="evenodd" clip-rule="evenodd" d="M8.014,0.003c-4.411,0-7.987,3.576-7.987,7.986
c0,1.642,0.496,3.168,1.346,4.437L0,15.997l3.568-1.372c1.271,0.853,2.8,1.352,4.446,1.352c4.411,0,7.986-3.576,7.986-7.987
C16,3.579,12.424,0.003,8.014,0.003z"/>
<path id="settings-shape" fill-rule="evenodd" clip-rule="evenodd" d="M14.77,8c0,0.804,0.262,1.548,0.634,1.678L16,9.887
c-0.205,0.874-0.553,1.692-1.011,2.434l-0.567-0.272c-0.355-0.171-1.066,0.17-1.635,0.738c-0.569,0.569-0.909,1.279-0.738,1.635
l0.273,0.568c-0.741,0.46-1.566,0.79-2.438,0.998l-0.205-0.584c-0.13-0.372-0.874-0.634-1.678-0.634s-1.548,0.262-1.678,0.634
l-0.209,0.596c-0.874-0.205-1.692-0.553-2.434-1.011l0.272-0.567c0.171-0.355-0.17-1.066-0.739-1.635
c-0.568-0.568-1.279-0.909-1.635-0.738l-0.568,0.273c-0.46-0.741-0.79-1.566-0.998-2.439l0.584-0.205
C0.969,9.547,1.231,8.804,1.231,8c0-0.804-0.262-1.548-0.634-1.678L0,6.112c0.206-0.874,0.565-1.685,1.025-2.427l0.554,0.266
c0.355,0.171,1.066-0.17,1.635-0.738c0.569-0.568,0.909-1.28,0.739-1.635L3.686,1.025c0.742-0.46,1.553-0.818,2.427-1.024
l0.209,0.596C6.453,0.969,7.197,1.23,8.001,1.23s1.548-0.262,1.678-0.634l0.209-0.596c0.874,0.205,1.692,0.553,2.434,1.011
l-0.272,0.567c-0.171,0.355,0.17,1.066,0.738,1.635c0.569,0.568,1.279,0.909,1.635,0.738l0.568-0.273
c0.46,0.741,0.79,1.566,0.998,2.438l-0.584,0.205C15.032,6.452,14.77,7.196,14.77,8z M8.001,3.661C5.604,3.661,3.661,5.603,3.661,8
c0,2.397,1.943,4.34,4.339,4.34c2.397,0,4.339-1.943,4.339-4.34C12.34,5.603,10.397,3.661,8.001,3.661z"/>
<path id="tag-shape" fill-rule="evenodd" clip-rule="evenodd" d="M15.578,7.317L9.659,1.398
C9.374,1.033,8.955,0.777,8.471,0.761L2.556,0C1.72-0.027-0.027,1.72,0,2.556l0.761,5.916c0.016,0.484,0.272,0.902,0.637,1.188
l5.919,5.919c0.591,0.591,1.584,0.557,2.218-0.076l5.966-5.966C16.135,8.902,16.169,7.909,15.578,7.317z M4.222,4.163
c-0.511,0.511-1.339,0.511-1.85,0c-0.511-0.511-0.511-1.339,0-1.85c0.511-0.511,1.339-0.511,1.85,0
C4.733,2.823,4.733,3.652,4.222,4.163z"/>
<path id="unblock-shape" fill-rule="evenodd" clip-rule="evenodd" d="M8,16c-4.418,0-8-3.582-8-8c0-4.418,3.582-8,8-8
c4.418,0,8,3.582,8,8C16,12.418,12.418,16,8,16z M8,2.442C4.911,2.442,2.408,4.931,2.408,8c0,3.069,2.504,5.557,5.592,5.557
S13.592,11.069,13.592,8C13.592,4.931,11.089,2.442,8,2.442z"/>
<path id="video-shape" fill-rule="evenodd" clip-rule="evenodd" d="M14.9,3.129l-3.476,3.073V3.873c0-0.877-0.663-1.587-1.482-1.587
H1.482C0.663,2.286,0,2.996,0,3.873v8.254c0,0.877,0.663,1.587,1.482,1.587h8.461c0.818,0,1.482-0.711,1.482-1.587V9.762
l3.476,3.073c0.3,0.321,0.714,0.416,1.1,0.331V2.798C15.614,2.713,15.2,2.808,14.9,3.129z"/>
</defs>
<use id="audio" xlink:href="#audio-shape"/>
<use id="audio-hover" xlink:href="#audio-shape"/>
<use id="audio-active" xlink:href="#audio-shape"/>
<use id="block" xlink:href="#block-shape"/>
<use id="block-hover" xlink:href="#block-shape"/>
<use id="block-active" xlink:href="#block-shape"/>
<use id="contacts" xlink:href="#contacts-shape"/>
<use id="contacts-hover" xlink:href="#contacts-shape"/>
<use id="contacts-active" xlink:href="#contacts-shape"/>
<use id="google" xlink:href="#google-shape"/>
<use id="google-hover" xlink:href="#google-shape"/>
<use id="google-active" xlink:href="#google-shape"/>
<use id="history" xlink:href="#history-shape"/>
<use id="history-hover" xlink:href="#history-shape"/>
<use id="history-active" xlink:href="#history-shape"/>
<use id="precall" xlink:href="#precall-shape"/>
<use id="precall-hover" xlink:href="#precall-shape"/>
<use id="precall-active" xlink:href="#precall-shape"/>
<use id="settings" xlink:href="#settings-shape"/>
<use id="settings-hover" xlink:href="#settings-shape"/>
<use id="settings-active" xlink:href="#settings-shape"/>
<use id="tag" xlink:href="#tag-shape"/>
<use id="tag-hover" xlink:href="#tag-shape"/>
<use id="tag-active" xlink:href="#tag-shape"/>
<use id="unblock" xlink:href="#unblock-shape"/>
<use id="unblock-hover" xlink:href="#unblock-shape"/>
<use id="unblock-active" xlink:href="#unblock-shape"/>
<use id="video" xlink:href="#video-shape"/>
<use id="video-hover" xlink:href="#video-shape"/>
<use id="video-active" xlink:href="#video-shape"/>
</svg>

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@ -44,7 +44,8 @@ browser.jar:
content/browser/loop/shared/img/svg/glyph-account-16x16.svg (content/shared/img/svg/glyph-account-16x16.svg) content/browser/loop/shared/img/svg/glyph-account-16x16.svg (content/shared/img/svg/glyph-account-16x16.svg)
content/browser/loop/shared/img/svg/glyph-signin-16x16.svg (content/shared/img/svg/glyph-signin-16x16.svg) content/browser/loop/shared/img/svg/glyph-signin-16x16.svg (content/shared/img/svg/glyph-signin-16x16.svg)
content/browser/loop/shared/img/svg/glyph-signout-16x16.svg (content/shared/img/svg/glyph-signout-16x16.svg) content/browser/loop/shared/img/svg/glyph-signout-16x16.svg (content/shared/img/svg/glyph-signout-16x16.svg)
content/browser/loop/shared/img/audio-call-avatar.svg (content/shared/img/audio-call-avatar.svg) content/browser/loop/shared/img/audio-call-avatar.svg (content/shared/img/audio-call-avatar.svg)
content/browser/loop/shared/img/icons-16x16.svg (content/shared/img/icons-16x16.svg)
# Shared scripts # Shared scripts
content/browser/loop/shared/js/feedbackApiClient.js (content/shared/js/feedbackApiClient.js) content/browser/loop/shared/js/feedbackApiClient.js (content/shared/js/feedbackApiClient.js)