Merge pull request #2764 from matrix-org/travis/fix-hover
Fix sticky hover state by listening for hover on the documentpull/21833/head
commit
7eea62a22b
|
@ -28,6 +28,14 @@ limitations under the License.
|
||||||
padding-right: 30px;
|
padding-right: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_EntityTile .mx_PresenceLabel {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_EntityTile:not(.mx_EntityTile_noHover):hover .mx_PresenceLabel {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
.mx_EntityTile_invite {
|
.mx_EntityTile_invite {
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
@ -67,7 +75,7 @@ limitations under the License.
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_EntityTile_name_hover {
|
.mx_EntityTile:not(.mx_EntityTile_noHover):hover .mx_EntityTile_name {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,24 +91,20 @@ limitations under the License.
|
||||||
|
|
||||||
.mx_EntityTile_unavailable .mx_EntityTile_avatar,
|
.mx_EntityTile_unavailable .mx_EntityTile_avatar,
|
||||||
.mx_EntityTile_unavailable .mx_EntityTile_name,
|
.mx_EntityTile_unavailable .mx_EntityTile_name,
|
||||||
.mx_EntityTile_unavailable .mx_EntityTile_name_hover,
|
|
||||||
.mx_EntityTile_offline_beenactive .mx_EntityTile_avatar,
|
.mx_EntityTile_offline_beenactive .mx_EntityTile_avatar,
|
||||||
.mx_EntityTile_offline_beenactive .mx_EntityTile_name,
|
.mx_EntityTile_offline_beenactive .mx_EntityTile_name,
|
||||||
.mx_EntityTile_offline_beenactive .mx_EntityTile_name_hover
|
|
||||||
{
|
{
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_EntityTile_offline_neveractive .mx_EntityTile_avatar,
|
.mx_EntityTile_offline_neveractive .mx_EntityTile_avatar,
|
||||||
.mx_EntityTile_offline_neveractive .mx_EntityTile_name,
|
.mx_EntityTile_offline_neveractive .mx_EntityTile_name,
|
||||||
.mx_EntityTile_offline_neveractive .mx_EntityTile_name_hover
|
|
||||||
{
|
{
|
||||||
opacity: 0.25;
|
opacity: 0.25;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_EntityTile_unknown .mx_EntityTile_avatar,
|
.mx_EntityTile_unknown .mx_EntityTile_avatar,
|
||||||
.mx_EntityTile_unknown .mx_EntityTile_name,
|
.mx_EntityTile_unknown .mx_EntityTile_name,
|
||||||
.mx_EntityTile_unknown .mx_EntityTile_name_hover
|
|
||||||
{
|
{
|
||||||
opacity: 0.25;
|
opacity: 0.25;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,10 @@ limitations under the License.
|
||||||
|
|
||||||
const React = require('react');
|
const React = require('react');
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
const MatrixClientPeg = require('../../../MatrixClientPeg');
|
|
||||||
const sdk = require('../../../index');
|
const sdk = require('../../../index');
|
||||||
import AccessibleButton from '../elements/AccessibleButton';
|
import AccessibleButton from '../elements/AccessibleButton';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
|
import classNames from "classnames";
|
||||||
|
|
||||||
|
|
||||||
const PRESENCE_CLASS = {
|
const PRESENCE_CLASS = {
|
||||||
|
@ -97,45 +96,39 @@ const EntityTile = React.createClass({
|
||||||
return this.props.shouldComponentUpdate(nextProps, nextState);
|
return this.props.shouldComponentUpdate(nextProps, nextState);
|
||||||
},
|
},
|
||||||
|
|
||||||
mouseEnter: function(e) {
|
|
||||||
this.setState({ 'hover': true });
|
|
||||||
},
|
|
||||||
|
|
||||||
mouseLeave: function(e) {
|
|
||||||
this.setState({ 'hover': false });
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
|
const mainClassNames = {
|
||||||
|
"mx_EntityTile": true,
|
||||||
|
"mx_EntityTile_noHover": this.props.suppressOnHover,
|
||||||
|
};
|
||||||
|
if (this.props.className) mainClassNames[this.props.className] = true;
|
||||||
|
|
||||||
const presenceClass = presenceClassForMember(
|
const presenceClass = presenceClassForMember(
|
||||||
this.props.presenceState, this.props.presenceLastActiveAgo, this.props.showPresence,
|
this.props.presenceState, this.props.presenceLastActiveAgo, this.props.showPresence,
|
||||||
);
|
);
|
||||||
|
mainClassNames[presenceClass] = true;
|
||||||
|
|
||||||
let mainClassName = "mx_EntityTile ";
|
|
||||||
mainClassName += presenceClass + (this.props.className ? (" " + this.props.className) : "");
|
|
||||||
let nameEl;
|
let nameEl;
|
||||||
const {name} = this.props;
|
const {name} = this.props;
|
||||||
|
|
||||||
const EmojiText = sdk.getComponent('elements.EmojiText');
|
const EmojiText = sdk.getComponent('elements.EmojiText');
|
||||||
if (this.state.hover && !this.props.suppressOnHover) {
|
if (!this.props.suppressOnHover) {
|
||||||
const activeAgo = this.props.presenceLastActiveAgo ?
|
const activeAgo = this.props.presenceLastActiveAgo ?
|
||||||
(Date.now() - (this.props.presenceLastTs - this.props.presenceLastActiveAgo)) : -1;
|
(Date.now() - (this.props.presenceLastTs - this.props.presenceLastActiveAgo)) : -1;
|
||||||
|
|
||||||
mainClassName += " mx_EntityTile_hover";
|
|
||||||
const PresenceLabel = sdk.getComponent("rooms.PresenceLabel");
|
const PresenceLabel = sdk.getComponent("rooms.PresenceLabel");
|
||||||
let presenceLabel = null;
|
let presenceLabel = null;
|
||||||
let nameClasses = 'mx_EntityTile_name';
|
|
||||||
if (this.props.showPresence) {
|
if (this.props.showPresence) {
|
||||||
presenceLabel = <PresenceLabel activeAgo={activeAgo}
|
presenceLabel = <PresenceLabel activeAgo={activeAgo}
|
||||||
currentlyActive={this.props.presenceCurrentlyActive}
|
currentlyActive={this.props.presenceCurrentlyActive}
|
||||||
presenceState={this.props.presenceState} />;
|
presenceState={this.props.presenceState} />;
|
||||||
nameClasses += ' mx_EntityTile_name_hover';
|
|
||||||
}
|
}
|
||||||
if (this.props.subtextLabel) {
|
if (this.props.subtextLabel) {
|
||||||
presenceLabel = <span className="mx_EntityTile_subtext">{this.props.subtextLabel}</span>;
|
presenceLabel = <span className="mx_EntityTile_subtext">{this.props.subtextLabel}</span>;
|
||||||
}
|
}
|
||||||
nameEl = (
|
nameEl = (
|
||||||
<div className="mx_EntityTile_details">
|
<div className="mx_EntityTile_details">
|
||||||
<EmojiText element="div" className={nameClasses} dir="auto">
|
<EmojiText element="div" className="mx_EntityTile_name" dir="auto">
|
||||||
{ name }
|
{ name }
|
||||||
</EmojiText>
|
</EmojiText>
|
||||||
{presenceLabel}
|
{presenceLabel}
|
||||||
|
@ -183,10 +176,11 @@ const EntityTile = React.createClass({
|
||||||
|
|
||||||
const av = this.props.avatarJsx || <BaseAvatar name={this.props.name} width={36} height={36} />;
|
const av = this.props.avatarJsx || <BaseAvatar name={this.props.name} width={36} height={36} />;
|
||||||
|
|
||||||
|
// The wrapping div is required to make the magic mouse listener work, for some reason.
|
||||||
return (
|
return (
|
||||||
<AccessibleButton className={mainClassName} title={this.props.title}
|
<div ref={(c) => this.container = c} >
|
||||||
onClick={this.props.onClick} onMouseEnter={this.mouseEnter}
|
<AccessibleButton className={classNames(mainClassNames)} title={this.props.title}
|
||||||
onMouseLeave={this.mouseLeave}>
|
onClick={this.props.onClick}>
|
||||||
<div className="mx_EntityTile_avatar">
|
<div className="mx_EntityTile_avatar">
|
||||||
{ av }
|
{ av }
|
||||||
{ power }
|
{ power }
|
||||||
|
@ -194,6 +188,7 @@ const EntityTile = React.createClass({
|
||||||
{ nameEl }
|
{ nameEl }
|
||||||
{ inviteButton }
|
{ inviteButton }
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue