From 5b49584d79fd709712817f07ab833f958de09549 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 6 Mar 2019 16:27:29 -0700 Subject: [PATCH 1/2] Fix sticky hover state by listening for hover on the document --- src/components/views/rooms/EntityTile.js | 45 ++++++++++++++++-------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/src/components/views/rooms/EntityTile.js b/src/components/views/rooms/EntityTile.js index 009da0ebd4..e99f0a6746 100644 --- a/src/components/views/rooms/EntityTile.js +++ b/src/components/views/rooms/EntityTile.js @@ -92,17 +92,31 @@ const EntityTile = React.createClass({ }; }, + componentWillMount: function() { + // We use a listener on the document so we can find out when the cursor leaves the element more + // safely. This is a workaround for https://github.com/facebook/react/issues/4492 and + // https://github.com/vector-im/riot-web/issues/1997 + document.addEventListener("mouseover", this.mouseEnter); + }, + + componentWillUnmount: function() { + document.removeEventListener("mouseover", this.mouseEnter); + }, + shouldComponentUpdate: function(nextProps, nextState) { if (this.state.hover !== nextState.hover) return true; return this.props.shouldComponentUpdate(nextProps, nextState); }, - mouseEnter: function(e) { - this.setState({ 'hover': true }); - }, + mouseEnter: function(ev) { + let targetHover = false; + if (this.container && (this.container === ev.target || this.container.contains(ev.target))) { + targetHover = true; + } - mouseLeave: function(e) { - this.setState({ 'hover': false }); + if (targetHover !== this.state.hover) { + this.setState({hover: targetHover}); + } }, render: function() { @@ -183,17 +197,18 @@ const EntityTile = React.createClass({ const av = this.props.avatarJsx || ; + // The wrapping div is required to make the magic mouse listener work, for some reason. return ( - -
- { av } - { power } -
- { nameEl } - { inviteButton } -
+
this.container = c} > + +
+ { av } + { power } +
+ { nameEl } + { inviteButton } +
+
); }, }); From 241309ab83a8260f5d872323caa9b0f8f57286cb Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 7 Mar 2019 14:55:17 -0700 Subject: [PATCH 2/2] Use CSS for hovering the tile --- res/css/views/rooms/_EntityTile.scss | 14 +++++--- src/components/views/rooms/EntityTile.js | 44 +++++++----------------- 2 files changed, 21 insertions(+), 37 deletions(-) diff --git a/res/css/views/rooms/_EntityTile.scss b/res/css/views/rooms/_EntityTile.scss index 7fb61989f9..68a9d61edb 100644 --- a/res/css/views/rooms/_EntityTile.scss +++ b/res/css/views/rooms/_EntityTile.scss @@ -28,6 +28,14 @@ limitations under the License. padding-right: 30px; } +.mx_EntityTile .mx_PresenceLabel { + display: none; +} + +.mx_EntityTile:not(.mx_EntityTile_noHover):hover .mx_PresenceLabel { + display: block; +} + .mx_EntityTile_invite { display: table-cell; vertical-align: middle; @@ -67,7 +75,7 @@ limitations under the License. overflow: hidden; } -.mx_EntityTile_name_hover { +.mx_EntityTile:not(.mx_EntityTile_noHover):hover .mx_EntityTile_name { font-size: 13px; } @@ -83,24 +91,20 @@ limitations under the License. .mx_EntityTile_unavailable .mx_EntityTile_avatar, .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_name, -.mx_EntityTile_offline_beenactive .mx_EntityTile_name_hover { opacity: 0.5; } .mx_EntityTile_offline_neveractive .mx_EntityTile_avatar, .mx_EntityTile_offline_neveractive .mx_EntityTile_name, -.mx_EntityTile_offline_neveractive .mx_EntityTile_name_hover { opacity: 0.25; } .mx_EntityTile_unknown .mx_EntityTile_avatar, .mx_EntityTile_unknown .mx_EntityTile_name, -.mx_EntityTile_unknown .mx_EntityTile_name_hover { opacity: 0.25; } diff --git a/src/components/views/rooms/EntityTile.js b/src/components/views/rooms/EntityTile.js index e99f0a6746..d2ae6217b7 100644 --- a/src/components/views/rooms/EntityTile.js +++ b/src/components/views/rooms/EntityTile.js @@ -19,11 +19,10 @@ limitations under the License. const React = require('react'); import PropTypes from 'prop-types'; - -const MatrixClientPeg = require('../../../MatrixClientPeg'); const sdk = require('../../../index'); import AccessibleButton from '../elements/AccessibleButton'; import { _t } from '../../../languageHandler'; +import classNames from "classnames"; const PRESENCE_CLASS = { @@ -92,64 +91,44 @@ const EntityTile = React.createClass({ }; }, - componentWillMount: function() { - // We use a listener on the document so we can find out when the cursor leaves the element more - // safely. This is a workaround for https://github.com/facebook/react/issues/4492 and - // https://github.com/vector-im/riot-web/issues/1997 - document.addEventListener("mouseover", this.mouseEnter); - }, - - componentWillUnmount: function() { - document.removeEventListener("mouseover", this.mouseEnter); - }, - shouldComponentUpdate: function(nextProps, nextState) { if (this.state.hover !== nextState.hover) return true; return this.props.shouldComponentUpdate(nextProps, nextState); }, - mouseEnter: function(ev) { - let targetHover = false; - if (this.container && (this.container === ev.target || this.container.contains(ev.target))) { - targetHover = true; - } - - if (targetHover !== this.state.hover) { - this.setState({hover: targetHover}); - } - }, - 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( 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; const {name} = this.props; const EmojiText = sdk.getComponent('elements.EmojiText'); - if (this.state.hover && !this.props.suppressOnHover) { + if (!this.props.suppressOnHover) { const activeAgo = this.props.presenceLastActiveAgo ? (Date.now() - (this.props.presenceLastTs - this.props.presenceLastActiveAgo)) : -1; - mainClassName += " mx_EntityTile_hover"; const PresenceLabel = sdk.getComponent("rooms.PresenceLabel"); let presenceLabel = null; - let nameClasses = 'mx_EntityTile_name'; if (this.props.showPresence) { presenceLabel = ; - nameClasses += ' mx_EntityTile_name_hover'; } if (this.props.subtextLabel) { presenceLabel = {this.props.subtextLabel}; } nameEl = (
- + { name } {presenceLabel} @@ -200,7 +179,8 @@ const EntityTile = React.createClass({ // The wrapping div is required to make the magic mouse listener work, for some reason. return (
this.container = c} > - +
{ av } { power }