feat(small-video): use AtlasKit tooltip

This commit is contained in:
Leonard Kim 2017-08-15 15:14:49 -07:00 committed by yanas
parent 2356238887
commit 38e2443ab7
12 changed files with 208 additions and 118 deletions

View File

@ -11,13 +11,13 @@
right: 0; right: 0;
padding: 10px 5px; padding: 10px 5px;
@extend %align-right; @extend %align-right;
z-index: $filmstripVideosZ;
&__toolbar { &__toolbar {
@include flex(); @include flex();
flex-direction: column-reverse; flex-direction: column-reverse;
flex-wrap: nowrap; flex-wrap: nowrap;
position: relative; position: relative;
z-index: $zindex1; // Set z-index to make element visible.
width: $filmstripToggleButtonWidth; width: $filmstripToggleButtonWidth;
button { button {
@ -53,7 +53,6 @@
/* The filmstrip should not be covered by the left toolbar. */ /* The filmstrip should not be covered by the left toolbar. */
bottom: 0; bottom: 0;
width:auto; width:auto;
z-index: $filmstripVideosZ;
transition: bottom 2s; transition: bottom 2s;
overflow: visible !important; overflow: visible !important;
/*!!! Removes the gap between the local video container and the remote /*!!! Removes the gap between the local video container and the remote

View File

@ -112,7 +112,7 @@
&__toolbar { &__toolbar {
text-align: right; text-align: right;
.toolbar-icon { .right {
float: none; float: none;
margin: auto; margin: auto;
} }
@ -193,9 +193,28 @@
*/ */
.connection-indicator, .connection-indicator,
.remote-video-menu-trigger, .remote-video-menu-trigger,
.videocontainer__toolbar, .indicator-icon-container {
.raisehandindicator,
#dominantspeakerindicator {
transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0);
} }
.indicator-container {
float: none;
}
/**
* FIXME: disable pointer to allow any elements moved below to still be
* clickable. The real fix would to make sure those moved elements are
* actually part of the toolbar instead of positioning being faked.
*/
.videocontainer__toolbar {
pointer-events: none;
> div {
pointer-events: none;
}
.toolbar-icon {
pointer-events: all;
}
}
} }

View File

@ -41,9 +41,30 @@
&__toptoolbar { &__toptoolbar {
position: absolute; position: absolute;
left: 0; left: 0;
z-index: $zindex3; pointer-events: none;
z-index: $zindex10;
width: 100%; width: 100%;
box-sizing: border-box; // Includes the padding in the 100% width. box-sizing: border-box; // Includes the padding in the 100% width.
/**
* FIXME (lenny): Disabling pointer-events is a pretty big sin that
* sidesteps the problems. There are z-index wars occurring within
* videocontainer and AtlasKit Tooltips rely on their parent z-indexe
* being higher than whatever they need to appear over. So set a higher
* z-index for the tooltip containers but make any empty space not block
* mouse overs for various mouseover triggers.
*/
pointer-events: none;
* {
pointer-events: auto;
}
.indicator-container {
display: inline-block;
float: left;
pointer-events: all;
}
} }
&__toolbar { &__toolbar {
@ -69,24 +90,21 @@
margin-top: $toolbarIconMargin; margin-top: $toolbarIconMargin;
} }
.indicator:nth-child(1) { .indicator-container:nth-child(1) .indicator {
margin-left: $toolbarIconMargin; margin-left: $toolbarIconMargin;
} }
.connection-indicator, .connection-indicator,
span.indicator { div.indicator-container,
margin-right: em(5, 8); {
margin-right: 4px;
} }
span.indicator { div.indicator:last-child {
display: none; margin-right: 0;
&:last-child {
margin-right: 0;
}
} }
.connection-indicator-container { .indicator-container {
display: inline-block; display: inline-block;
vertical-align: top; vertical-align: top;
@ -96,7 +114,7 @@
} }
.connection-indicator, .connection-indicator,
span.indicator { .indicator {
position: relative; position: relative;
font-size: 8px; font-size: 8px;
text-align: center; text-align: center;
@ -307,7 +325,6 @@
padding: 0; padding: 0;
border: 0; border: 0;
margin: 0px 5px 0px 0px; margin: 0px 5px 0px 0px;
float: left;
} }
/** /**
@ -320,9 +337,17 @@
/** /**
* Toolbar icons positioned on the right. * Toolbar icons positioned on the right.
*/ */
.toolbar-icon.right { .moderator-icon {
float: right; display: inline-block;
margin: 0px 0px 0px 5px;
&.right {
float: right;
margin: 0px 0px 0px 5px;
}
.toolbar-icon {
margin: 0;
}
} }
.raisehandindicator { .raisehandindicator {
@ -340,7 +365,7 @@
position: absolute; position: absolute;
top: 0px; top: 0px;
right: 0; right: 0;
z-index: $zindex3; z-index: $zindex2;
width: 18px; width: 18px;
height: 13px; height: 13px;
color: #FFF; color: #FFF;

View File

@ -168,9 +168,8 @@
}, },
"videothumbnail": "videothumbnail":
{ {
"editnickname": "Click to edit your<br/>display name", "moderator": "Moderator",
"moderator": "The owner of<br/>this conference", "videomute": "Participant has stopped the camera",
"videomute": "Participant has<br/>stopped the camera",
"mute": "Participant is muted", "mute": "Participant is muted",
"kick": "Kick out", "kick": "Kick out",
"muted": "Muted", "muted": "Muted",

View File

@ -316,16 +316,27 @@ SmallVideo.prototype.setVideoMutedView = function(isMuted) {
SmallVideo.prototype.updateStatusBar = function () { SmallVideo.prototype.updateStatusBar = function () {
const statusBarContainer const statusBarContainer
= this.container.querySelector('.videocontainer__toolbar'); = this.container.querySelector('.videocontainer__toolbar');
const tooltipPosition = interfaceConfig.VERTICAL_FILMSTRIP ? 'left' : 'top';
/* jshint ignore:start */ /* jshint ignore:start */
ReactDOM.render( ReactDOM.render(
<div> <I18nextProvider i18n = { i18next }>
{ this.isAudioMuted ? <AudioMutedIndicator /> : null } <div>
{ this.isVideoMuted ? <VideoMutedIndicator /> : null } { this.isAudioMuted
{ this._isModerator ? <AudioMutedIndicator
&& !interfaceConfig.DISABLE_FOCUS_INDICATOR tooltipPosition = { tooltipPosition } />
? <ModeratorIndicator /> : null } : null }
</div>, { this.isVideoMuted
? <VideoMutedIndicator
tooltipPosition = { tooltipPosition } />
: null }
{ this._isModerator
&& !interfaceConfig.DISABLE_FOCUS_INDICATOR
? <ModeratorIndicator
tooltipPosition = { tooltipPosition } />
: null }
</div>
</I18nextProvider>,
statusBarContainer); statusBarContainer);
/* jshint ignore:end */ /* jshint ignore:end */
}; };
@ -744,6 +755,7 @@ SmallVideo.prototype.updateIndicators = function () {
= this.container.querySelector('.videocontainer__toptoolbar'); = this.container.querySelector('.videocontainer__toptoolbar');
const iconSize = UIUtil.getIndicatorFontSize(); const iconSize = UIUtil.getIndicatorFontSize();
const tooltipPosition = interfaceConfig.VERTICAL_FILMSTRIP ? 'left' : 'top';
/* jshint ignore:start */ /* jshint ignore:start */
ReactDOM.render( ReactDOM.render(
@ -758,10 +770,14 @@ SmallVideo.prototype.updateIndicators = function () {
userID = { this.id } /> userID = { this.id } />
: null } : null }
{ this._showRaisedHand { this._showRaisedHand
? <RaisedHandIndicator iconSize = { iconSize } /> ? <RaisedHandIndicator
iconSize = { iconSize }
tooltipPosition = { tooltipPosition } />
: null } : null }
{ this._showDominantSpeaker { this._showDominantSpeaker
? <DominantSpeakerIndicator iconSize = { iconSize } /> ? <DominantSpeakerIndicator
iconSize = { iconSize }
tooltipPosition = { tooltipPosition } />
: null } : null }
</div> </div>
</I18nextProvider>, </I18nextProvider>,

View File

@ -175,7 +175,7 @@ class ConnectionIndicator extends Component {
*/ */
render() { render() {
return ( return (
<div className = 'connection-indicator-container'> <div className = 'indicator-container'>
<AKInlineDialog <AKInlineDialog
content = { this._renderStatisticsTable() } content = { this._renderStatisticsTable() }
isOpen = { this.state.showStats } isOpen = { this.state.showStats }

View File

@ -8,6 +8,18 @@ import BaseIndicator from './BaseIndicator';
* @extends Component * @extends Component
*/ */
class AudioMutedIndicator extends Component { class AudioMutedIndicator extends Component {
/**
* {@code AudioMutedIndicator} component's property types.
*
* @static
*/
static propTypes = {
/**
* From which side of the indicator the tooltip should appear from.
*/
tooltipPosition: React.PropTypes.string
};
/** /**
* Implements React's {@link Component#render()}. * Implements React's {@link Component#render()}.
* *
@ -19,7 +31,8 @@ class AudioMutedIndicator extends Component {
<BaseIndicator <BaseIndicator
className = 'audioMuted toolbar-icon' className = 'audioMuted toolbar-icon'
iconClassName = 'icon-mic-disabled' iconClassName = 'icon-mic-disabled'
tooltipKey = 'videothumbnail.mute' /> tooltipKey = 'videothumbnail.mute'
tooltipPosition = { this.props.tooltipPosition } />
); );
} }
} }

View File

@ -1,6 +1,7 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import Tooltip from '@atlaskit/tooltip';
import { setTooltip } from '../../../../../modules/UI/util/Tooltip'; import { translate } from '../../../base/i18n';
/** /**
* React {@code Component} for showing an icon with a tooltip. * React {@code Component} for showing an icon with a tooltip.
@ -8,16 +9,27 @@ import { setTooltip } from '../../../../../modules/UI/util/Tooltip';
* @extends Component * @extends Component
*/ */
class BaseIndicator extends Component { class BaseIndicator extends Component {
/**
* Default values for {@code BaseIndicator} component's properties.
*
* @static
*/
static defaultProps = { static defaultProps = {
className: '', className: '',
iconClassName: '', iconClassName: '',
iconSize: 'auto', iconSize: 'auto',
id: '' id: '',
tooltipPosition: 'top'
}; };
/**
* {@code BaseIndicator} component's property types.
*
* @static
*/
static propTypes = { static propTypes = {
/** /**
* The CSS class names to set on the root element of the component. * Additional CSS class names to set on the icon container.
*/ */
className: React.PropTypes.string, className: React.PropTypes.string,
@ -36,44 +48,23 @@ class BaseIndicator extends Component {
*/ */
id: React.PropTypes.string, id: React.PropTypes.string,
/**
* Invoked to obtain translated strings.
*/
t: React.PropTypes.func,
/** /**
* The translation key to use for displaying a tooltip when hovering * The translation key to use for displaying a tooltip when hovering
* over the component. * over the component.
*/ */
tooltipKey: React.PropTypes.string tooltipKey: React.PropTypes.string,
};
/**
* Initializes a new {@code BaseIndicator} instance.
*
* @param {Object} props - The read-only properties with which the new
* instance is to be initialized.
*/
constructor(props) {
super(props);
/** /**
* An internal reference to the HTML element at the top of the * From which side of the indicator the tooltip should appear from.
* component's DOM hierarchy. The reference is needed for attaching a * Defaults to "top".
* tooltip.
*
* @type {HTMLElement}
*/ */
this._rootElement = null; tooltipPosition: React.PropTypes.string
};
// Bind event handler so it is only bound once for every instance.
this._setRootElementRef = this._setRootElementRef.bind(this);
}
/**
* Sets a tooltip which will display when hovering over the component.
*
* @inheritdoc
* @returns {void}
*/
componentDidMount() {
this._setTooltip();
}
/** /**
* Implements React's {@link Component#render()}. * Implements React's {@link Component#render()}.
@ -82,46 +73,34 @@ class BaseIndicator extends Component {
* @returns {ReactElement} * @returns {ReactElement}
*/ */
render() { render() {
const {
className,
iconClassName,
iconSize,
id,
t,
tooltipKey,
tooltipPosition
} = this.props;
const iconContainerClassName = `indicator-icon-container ${className}`;
return ( return (
<span <div className = 'indicator-container'>
className = { this.props.className } <Tooltip
id = { this.props.id } description = { t(tooltipKey) }
ref = { this._setRootElementRef }> position = { tooltipPosition }>
<i <span
className = { this.props.iconClassName } className = { iconContainerClassName }
style = {{ fontSize: this.props.iconSize }} /> id = { id }>
</span> <i
); className = { iconClassName }
} style = {{ fontSize: iconSize }} />
</span>
/** </Tooltip>
* Sets the internal reference to the root HTML element for the component. </div>
*
* @param {HTMLIconElement} element - The root HTML element of the
* component.
* @private
* @returns {void}
*/
_setRootElementRef(element) {
this._rootElement = element;
}
/**
* Associate the component as a tooltip trigger so a tooltip may display on
* hover.
*
* @private
* @returns {void}
*/
_setTooltip() {
// TODO Replace UIUtil with an AtlasKit component when a suitable one
// becomes available for tooltips.
setTooltip(
this._rootElement,
this.props.tooltipKey,
'top'
); );
} }
} }
export default BaseIndicator; export default translate(BaseIndicator);

View File

@ -20,7 +20,12 @@ class DominantSpeakerIndicator extends Component {
* *
* @type {number} * @type {number}
*/ */
iconSize: React.PropTypes.number iconSize: React.PropTypes.number,
/**
* From which side of the indicator the tooltip should appear from.
*/
tooltipPosition: React.PropTypes.string
}; };
/** /**
@ -35,7 +40,8 @@ class DominantSpeakerIndicator extends Component {
iconClassName = 'indicatoricon fa fa-bullhorn' iconClassName = 'indicatoricon fa fa-bullhorn'
iconSize = { `${this.props.iconSize}px` } iconSize = { `${this.props.iconSize}px` }
id = 'dominantspeakerindicator' id = 'dominantspeakerindicator'
tooltipKey = 'speaker' /> tooltipKey = 'speaker'
tooltipPosition = { this.props.tooltipPosition } />
); );
} }
} }

View File

@ -8,6 +8,18 @@ import BaseIndicator from './BaseIndicator';
* @extends Component * @extends Component
*/ */
class ModeratorIndicator extends Component { class ModeratorIndicator extends Component {
/**
* {@code ModeratorIndicator} component's property types.
*
* @static
*/
static propTypes = {
/**
* From which side of the indicator the tooltip should appear from.
*/
tooltipPosition: React.PropTypes.string
};
/** /**
* Implements React's {@link Component#render()}. * Implements React's {@link Component#render()}.
* *
@ -16,10 +28,13 @@ class ModeratorIndicator extends Component {
*/ */
render() { render() {
return ( return (
<BaseIndicator <div className = 'moderator-icon right'>
className = 'focusindicator toolbar-icon right' <BaseIndicator
iconClassName = 'icon-star' className = 'focusindicator toolbar-icon'
tooltipKey = 'videothumbnail.moderator' /> iconClassName = 'icon-star'
tooltipKey = 'videothumbnail.moderator'
tooltipPosition = { this.props.tooltipPosition } />
</div>
); );
} }
} }

View File

@ -19,7 +19,12 @@ class RaisedHandIndicator extends Component {
* *
* @type {number} * @type {number}
*/ */
iconSize: React.PropTypes.number iconSize: React.PropTypes.number,
/**
* From which side of the indicator the tooltip should appear from.
*/
tooltipPosition: React.PropTypes.string
}; };
/** /**
@ -33,7 +38,8 @@ class RaisedHandIndicator extends Component {
className = 'raisehandindicator indicator show-inline' className = 'raisehandindicator indicator show-inline'
iconClassName = 'icon-raised-hand indicatoricon' iconClassName = 'icon-raised-hand indicatoricon'
iconSize = { `${this.props.iconSize}px` } iconSize = { `${this.props.iconSize}px` }
tooltipKey = 'raisedHand' /> tooltipKey = 'raisedHand'
tooltipPosition = { this.props.tooltipPosition } />
); );
} }
} }

View File

@ -7,6 +7,18 @@ import BaseIndicator from './BaseIndicator';
* @extends Component * @extends Component
*/ */
class VideoMutedIndicator extends Component { class VideoMutedIndicator extends Component {
/**
* {@code VideoMutedIndicator} component's property types.
*
* @static
*/
static propTypes = {
/**
* From which side of the indicator the tooltip should appear from.
*/
tooltipPosition: React.PropTypes.string
};
/** /**
* Implements React's {@link Component#render()}. * Implements React's {@link Component#render()}.
* *
@ -17,7 +29,8 @@ class VideoMutedIndicator extends Component {
<BaseIndicator <BaseIndicator
className = 'videoMuted toolbar-icon' className = 'videoMuted toolbar-icon'
iconClassName = 'icon-camera-disabled' iconClassName = 'icon-camera-disabled'
tooltipKey = 'videothumbnail.videomute' /> tooltipKey = 'videothumbnail.videomute'
tooltipPosition = { this.props.tooltipPosition } />
); );
} }
} }