improve collapsed LHS implementation - split the tooltip into its own component; position it with javascript as overflow-y + position absolute = clipping hell; preserve the collapse state between MatrixChat re-renders; fix positioning of the 'show' button; switch to dispatcher for show/hide LHS; remove errant scrollbars

kegan/timestamp-hover
Matthew Hodgson 2015-10-11 13:54:38 +01:00
parent 8bdb5c0745
commit 93de2307c1
12 changed files with 128 additions and 62 deletions

View File

@ -52,6 +52,11 @@ module.exports = {
case 'call_state':
this._recheckCallElement(this.props.selectedRoom);
break;
case 'view_tooltip':
this.tooltip = payload.tooltip;
this._repositionTooltip();
if (this.tooltip) this.tooltip.style.display = 'block';
break
}
},
@ -150,6 +155,13 @@ module.exports = {
});
},
_repositionTooltip: function(e) {
if (this.tooltip && this.tooltip.parentElement) {
var scroll = this.getDOMNode();
this.tooltip.style.top = (scroll.parentElement.offsetTop + this.tooltip.parentElement.offsetTop - scroll.scrollTop) + "px";
}
},
makeRoomTiles: function() {
var self = this;
var RoomTile = sdk.getComponent("molecules.RoomTile");

View File

@ -16,7 +16,7 @@ limitations under the License.
.mx_RoomTile {
cursor: pointer;
display: table-row;
/* display: table-row; */
color: #818794;
}
@ -45,27 +45,6 @@ limitations under the License.
padding-right: 16px;
}
.mx_RoomTile_tooltip {
border: 1px solid #a9dbf4;
border-radius: 8px;
background-color: #fff;
position: absolute;
z-index: 1000;
margin-top: 6px;
left: 64px;
padding: 6px;
}
.mx_RoomTile_chevron {
position: absolute;
left: -9px;
top: 8px;
}
.mx_RoomTile_tooltip {
position: absolute;
}
.collapsed .mx_RoomTile_name {
display: none;
}

View File

@ -0,0 +1,33 @@
/*
Copyright 2015 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_RoomTooltip {
display: none;
position: fixed;
border: 1px solid #a9dbf4;
border-radius: 8px;
background-color: #fff;
z-index: 1000;
margin-top: 6px;
left: 64px;
padding: 6px;
}
.mx_RoomTooltip_chevron {
position: absolute;
left: -9px;
top: 8px;
}

View File

@ -33,13 +33,6 @@ limitations under the License.
cursor: pointer;
}
.mx_LeftPanel_showButton {
position: absolute;
top: 18px;
left: 16px;
cursor: pointer;
}
.mx_LeftPanel .mx_RoomList {
-webkit-box-ordinal-group: 1;
-moz-box-ordinal-group: 1;
@ -47,7 +40,7 @@ limitations under the License.
-webkit-order: 1;
order: 1;
overflow-y: scroll;
overflow-y: auto;
-webkit-flex: 1 1 0;
flex: 1 1 0;
}
@ -69,10 +62,6 @@ limitations under the License.
color: #378bb4;
}
.mx_LeftPanel .mx_BottomLeftMenu .mx_RoomTile_avatar {
padding-left: 14px;
}
.mx_LeftPanel .mx_BottomLeftMenu .mx_BottomLeftMenu_options {
margin-top: 12px;
width: 100%;

View File

@ -57,7 +57,7 @@ limitations under the License.
}
.mx_RoomDirectory_tableWrapper {
overflow-y: scroll;
overflow-y: auto;
-webkit-flex: 1 1 0;
flex: 1 1 0;
}

View File

@ -109,7 +109,7 @@ limitations under the License.
margin-top: 18px;
margin-bottom: 18px;
overflow-y: scroll;
overflow-y: auto;
}
.mx_RoomView_messageListWrapper {

View File

@ -57,6 +57,7 @@ skin['molecules.RoomDropTarget'] = require('./views/molecules/RoomDropTarget');
skin['molecules.RoomHeader'] = require('./views/molecules/RoomHeader');
skin['molecules.RoomSettings'] = require('./views/molecules/RoomSettings');
skin['molecules.RoomTile'] = require('./views/molecules/RoomTile');
skin['molecules.RoomTooltip'] = require('./views/molecules/RoomTooltip');
skin['molecules.SenderProfile'] = require('./views/molecules/SenderProfile');
skin['molecules.ServerConfig'] = require('./views/molecules/ServerConfig');
skin['molecules.UnknownMessageTile'] = require('./views/molecules/UnknownMessageTile');

View File

@ -71,15 +71,13 @@ module.exports = React.createClass({
}
*/
var nameElement;
var label;
if (!this.props.collapsed) {
nameElement = <div className="mx_RoomTile_name">{name}</div>;
label = <div className="mx_RoomTile_name">{name}</div>;
}
else if (this.state.hover) {
nameElement = <div className="mx_RoomTile_tooltip">
<img className="mx_RoomTile_chevron" src="img/chevron-left.png" width="9" height="16"/>
{ name }
</div>;
var RoomTooltip = sdk.getComponent("molecules.RoomTooltip");
label = <RoomTooltip room={this.props.room} ref="roomTooltip"/>;
}
var RoomAvatar = sdk.getComponent('atoms.RoomAvatar');
@ -89,7 +87,7 @@ module.exports = React.createClass({
<RoomAvatar room={this.props.room} />
{ badge }
</div>
{ nameElement }
{ label }
</div>
);
}

View File

@ -0,0 +1,53 @@
/*
Copyright 2015 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
'use strict';
var React = require('react');
var classNames = require('classnames');
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
var sdk = require('matrix-react-sdk')
var dis = require('matrix-react-sdk/lib/dispatcher');
module.exports = React.createClass({
displayName: 'RoomTooltip',
componentDidMount: function() {
// tell the roomlist about us
dis.dispatch({
action: 'view_tooltip',
tooltip: this.getDOMNode(),
});
},
componentDidUnmount: function() {
dis.dispatch({
action: 'view_tooltip',
tooltip: null,
});
},
render: function() {
return (
<div className="mx_RoomTooltip">
<img className="mx_RoomTooltip_chevron" src="img/chevron-left.png" width="9" height="16"/>
{ this.props.room.name }
</div>
);
}
});

View File

@ -18,22 +18,15 @@ limitations under the License.
var React = require('react');
var sdk = require('matrix-react-sdk')
var dis = require('matrix-react-sdk/lib/dispatcher');
module.exports = React.createClass({
displayName: 'LeftPanel',
getInitialState: function() {
return {
collapsed: false,
};
},
onShowClick: function() {
this.setState({ collapsed : false });
},
onHideClick: function() {
this.setState({ collapsed : true });
dis.dispatch({
action: 'hide_left_panel',
});
},
render: function() {
@ -43,9 +36,8 @@ module.exports = React.createClass({
var collapseButton;
var classes = "mx_LeftPanel";
if (this.state.collapsed) {
if (this.props.collapsed) {
classes += " collapsed";
collapseButton = <img className="mx_LeftPanel_showButton" onClick={ this.onShowClick } src="img/menu.png" width="27" height="20" alt=">"/>
}
else {
collapseButton = <img className="mx_LeftPanel_hideButton" onClick={ this.onHideClick } src="img/hide.png" width="12" height="20" alt="<"/>
@ -55,7 +47,7 @@ module.exports = React.createClass({
<aside className={classes}>
{ collapseButton }
<IncomingCallBox />
<RoomList selectedRoom={this.props.selectedRoom} collapsed={this.state.collapsed}/>
<RoomList selectedRoom={this.props.selectedRoom} collapsed={this.props.collapsed}/>
<BottomLeftMenu />
</aside>
);

View File

@ -18,6 +18,7 @@ limitations under the License.
var React = require('react');
var sdk = require('matrix-react-sdk')
var dis = require('matrix-react-sdk/lib/dispatcher');
var RoomListController = require('../../../../controllers/organisms/RoomList')
@ -25,6 +26,12 @@ module.exports = React.createClass({
displayName: 'RoomList',
mixins: [RoomListController],
onShowClick: function() {
dis.dispatch({
action: 'show_left_panel',
});
},
render: function() {
var CallView = sdk.getComponent('molecules.voip.CallView');
var RoomDropTarget = sdk.getComponent('molecules.RoomDropTarget');
@ -34,15 +41,17 @@ module.exports = React.createClass({
callElement = <CallView className="mx_MatrixChat_callView"/>
}
var recentsLabel = this.props.collapsed ? "" : "Recents";
var recentsLabel = this.props.collapsed ?
<img onClick={ this.onShowClick } src="img/menu.png" width="27" height="20" alt=">"/> :
"Recents";
return (
<div className="mx_RoomList">
<div className="mx_RoomList" onScroll={this._repositionTooltip}>
{callElement}
<h2 className="mx_RoomList_favourites_label">Favourites</h2>
<RoomDropTarget text="Drop here to favourite"/>
<h2 className="mx_RoomList_recents_label">{ recentsLabel }&nbsp;</h2>
<h2 className="mx_RoomList_recents_label">{ recentsLabel }</h2>
<div className="mx_RoomList_recents">
{this.makeRoomTiles()}
</div>

View File

@ -79,7 +79,7 @@ module.exports = React.createClass({
<div className="mx_MatrixChat_wrapper">
<MatrixToolbar />
<div className="mx_MatrixChat mx_MatrixChat_toolbarShowing">
<LeftPanel selectedRoom={this.state.currentRoom} />
<LeftPanel selectedRoom={this.state.currentRoom} collapsed={this.state.collapse_lhs} />
<main className="mx_MatrixChat_middlePanel">
{page_element}
</main>
@ -91,7 +91,7 @@ module.exports = React.createClass({
else {
return (
<div className="mx_MatrixChat">
<LeftPanel selectedRoom={this.state.currentRoom} />
<LeftPanel selectedRoom={this.state.currentRoom} collapsed={this.state.collapse_lhs} />
<main className="mx_MatrixChat_middlePanel">
{page_element}
</main>