diff --git a/bigbluebutton-html5/imports/ui/components/button/component.jsx b/bigbluebutton-html5/imports/ui/components/button/component.jsx index d15656fedd7fc503618946249006d47f3d71ea82..d1021d82be4415edf08ae1e279941485e04570ba 100644 --- a/bigbluebutton-html5/imports/ui/components/button/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/button/component.jsx @@ -1,6 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import cx from 'classnames'; +import Tooltip from '/imports/ui/components/tooltip/component'; import styles from './styles'; import Icon from '../icon/component'; import BaseButton from './base/component'; @@ -86,7 +87,6 @@ const defaultProps = { }; export default class Button extends BaseButton { - _getClassNames() { const { size, @@ -113,8 +113,23 @@ export default class Button extends BaseButton { } render() { - const renderFuncName = this.props.circle ? - 'renderCircle' : 'renderDefault'; + const { + circle, + hideLabel, + label, + } = this.props; + + const renderFuncName = circle ? 'renderCircle' : 'renderDefault'; + + if (hideLabel) { + return ( + <Tooltip + title={label} + > + {this[renderFuncName]()} + </Tooltip> + ); + } return this[renderFuncName](); } diff --git a/bigbluebutton-html5/imports/ui/components/chat/chat-dropdown/component.jsx b/bigbluebutton-html5/imports/ui/components/chat/chat-dropdown/component.jsx index c63a4f1958430b71208d1e967174168dfb0868af..bc7fdc6b87d69f8654c022bc1206241724d6cadf 100644 --- a/bigbluebutton-html5/imports/ui/components/chat/chat-dropdown/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/chat/chat-dropdown/component.jsx @@ -128,6 +128,7 @@ class ChatDropdown extends Component { hideLabel color="primary" aria-label={intl.formatMessage(intlMessages.options)} + label={intl.formatMessage(intlMessages.options)} /> </DropdownTrigger> <DropdownContent placement="bottom right"> diff --git a/bigbluebutton-html5/imports/ui/components/chat/component.jsx b/bigbluebutton-html5/imports/ui/components/chat/component.jsx index 75ab3deeddd6cfdea4004c67878d1e4354331a12..6c9f7966b3386fcac5ec3c6b1dea6b236eed8757 100644 --- a/bigbluebutton-html5/imports/ui/components/chat/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/chat/component.jsx @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import { Link } from 'react-router'; import { defineMessages, injectIntl } from 'react-intl'; import injectWbResizeEvent from '/imports/ui/components/presentation/resize-wrapper/component'; +import Button from '/imports/ui/components/button/component'; import styles from './styles'; import MessageForm from './message-form/component'; import MessageList from './message-list/component'; @@ -56,10 +57,18 @@ const Chat = (props) => { <Link to="/users" role="button" - className={styles.closeIcon} aria-label={intl.formatMessage(intlMessages.closeChatLabel, { 0: title })} + tabIndex={-1} > - <Icon iconName="close" onClick={() => actions.handleClosePrivateChat(chatID)} /> + <Button + className={styles.closeBtn} + label={intl.formatMessage(intlMessages.closeChatLabel, { 0: title })} + icon="close" + size="md" + hideLabel + onClick={() => actions.handleClosePrivateChat(chatID)} + aria-label={intl.formatMessage(intlMessages.closeChatLabel, { 0: title })} + /> </Link> : <ChatDropdown /> } diff --git a/bigbluebutton-html5/imports/ui/components/chat/styles.scss b/bigbluebutton-html5/imports/ui/components/chat/styles.scss index 3fb72049bdb51b8700ba500b6147faca4d6901d0..fc45c9915d073631aae5e273506aa5c945f94c06 100644 --- a/bigbluebutton-html5/imports/ui/components/chat/styles.scss +++ b/bigbluebutton-html5/imports/ui/components/chat/styles.scss @@ -1,6 +1,8 @@ @import "/imports/ui/stylesheets/mixins/focus"; @import "/imports/ui/stylesheets/variables/_all"; +$icon-offset: -.4em; + .chat { background-color: #fff; padding: $md-padding-x; @@ -36,7 +38,22 @@ flex: 1; } -.closeIcon { +.closeBtn { + background-color: $color-white; flex: 0 0; - margin-left: $sm-padding-x / 2; + padding: 0 0.25rem !important; + + i { + font-size: 0.85em; + color: $color-gray-dark !important; + top: $icon-offset; + } + + &:focus, + &:hover{ + background-color: $color-white !important; + i{ + color: $color-gray; + } + } } diff --git a/bigbluebutton-html5/imports/ui/components/tooltip/component.jsx b/bigbluebutton-html5/imports/ui/components/tooltip/component.jsx new file mode 100644 index 0000000000000000000000000000000000000000..93756b19eb7aa1ad5564641117ee70959f4b2baa --- /dev/null +++ b/bigbluebutton-html5/imports/ui/components/tooltip/component.jsx @@ -0,0 +1,94 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import Tippy from 'tippy.js'; +import _ from 'lodash'; +import cx from 'classnames'; + +const propTypes = { + +}; + +const defaultProps = { + position: 'bottom' +}; + +class Tooltip extends Component { + constructor(props) { + super(props); + + this.state = { + tippySelector: _.uniqueId('tippy-'), + }; + + this.onShow = this.onShow.bind(this); + this.onHide = this.onHide.bind(this); + this.handleEscapeHide = this.handleEscapeHide.bind(this); + } + + componentDidMount() { + const { + tippySelector, + } = this.state; + + const { + position + } = this.props; + + const options = { + position, + onShow: this.onShow, + onHide: this.onHide, + }; + + this.setState({ + tooltip: Tippy(`#${tippySelector}`, options), + }); + } + + onShow() { + document.addEventListener('keyup', this.handleEscapeHide); + } + + onHide() { + document.removeEventListener('keyup', this.handleEscapeHide); + } + + handleEscapeHide(e) { + const { + tooltip, + } = this.state; + + const popper = tooltip.tooltips[0]; + + return e.keyCode === 27 ? popper.hide() : null; + } + + render() { + const { + tippySelector, + } = this.state; + + const { + children, + className, + title, + ...restProps + } = this.props; + + const WrappedComponent = React.Children.only(children); + + const WrappedComponentBound = React.cloneElement(WrappedComponent, { + ...restProps, + title, + id: tippySelector, + className: cx(children.props.className, className), + }); + + return WrappedComponentBound; + } +} + +export default Tooltip; + +Tooltip.defaultProps = defaultProps; +Tooltip.propTypes = propTypes; diff --git a/bigbluebutton-html5/package-lock.json b/bigbluebutton-html5/package-lock.json index 759240950ac7240db1e39ab69d5984252504b7f4..f4798f2b93be27ea001c29e45916bfd5f038c07d 100644 --- a/bigbluebutton-html5/package-lock.json +++ b/bigbluebutton-html5/package-lock.json @@ -215,10 +215,6 @@ "integrity": "sha1-lfE2KbEsOlGl0hWr3OKqnzL4B3M=", "dev": true }, - "attr-accept": { - "version": "https://registry.npmjs.org/attr-accept/-/attr-accept-1.1.0.tgz", - "integrity": "sha1-tc01In8WOTWo8d4Q7T66FpQfa+Y=" - }, "autoprefixer": { "version": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-7.1.6.tgz", "integrity": "sha1-+5MwOfdK90qD5xIlznjZ/Vi6hNc=", @@ -1282,7 +1278,7 @@ }, "fibers": { "version": "https://registry.npmjs.org/fibers/-/fibers-2.0.0.tgz", - "integrity": "sha1-8m0Krx+ZmV++HLPzQO+sCL2p3Es=", + "integrity": "sha512-sLxo4rZVk7xLgAjb/6zEzHJfSALx6u6coN1z61XCOF7i6CyTdJawF4+RdpjCSeS8AP66eR2InScbYAz9RAVOgA==", "dev": true }, "figures": { @@ -1427,7 +1423,7 @@ }, "glob": { "version": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "requires": { "fs.realpath": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "inflight": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -1593,7 +1589,7 @@ }, "humanize-duration": { "version": "https://registry.npmjs.org/humanize-duration/-/humanize-duration-3.10.1.tgz", - "integrity": "sha1-ZbVQwKoJUVbst8NA20TuC99xr0s=", + "integrity": "sha512-FHD+u5OKj8TSsSdMHJxSCC78N5Rt4ecil6sWvI+xPbUKhxvHmkKo/V8imbR1m2dXueZYLIl7PcSYX9i/oEiOIA==", "dev": true }, "husky": { @@ -1629,7 +1625,7 @@ }, "immutability-helper": { "version": "https://registry.npmjs.org/immutability-helper/-/immutability-helper-2.4.0.tgz", - "integrity": "sha1-ANQh4pV8F/DweBR18F/9g35zRY0=", + "integrity": "sha512-rW/L/56ZMo9NStMK85kFrUFFGy4NeJbCdhfrDHIZrFfxYtuwuxD+dT3mWMcdmrNO61hllc60AeGglCRhfZ1dZw==", "requires": { "invariant": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz" } @@ -3503,6 +3499,12 @@ "integrity": "sha1-KYuJ34uTsCIdv0Ia0rGx6iP8Z3c=", "dev": true }, + "popper.js": { + "version": "1.12.9", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.12.9.tgz", + "integrity": "sha1-DfvC3/lsRRuzMu3Pz6r1ZtMx1bM=", + "dev": true + }, "postcss": { "version": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", "integrity": "sha1-ueyrTuAMids+yTEUW9lZC78/El8=", @@ -3745,14 +3747,6 @@ "prop-types": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.0.tgz" } }, - "react-dropzone": { - "version": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-4.2.1.tgz", - "integrity": "sha1-aV6AvQsGXxGB5p8tD20dXMcmZMk=", - "requires": { - "attr-accept": "https://registry.npmjs.org/attr-accept/-/attr-accept-1.1.0.tgz", - "prop-types": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.0.tgz" - } - }, "react-intl": { "version": "https://registry.npmjs.org/react-intl/-/react-intl-2.4.0.tgz", "integrity": "sha1-ZsFNyd+ac7L7v71gIXJugKYT6xU=", @@ -3784,20 +3778,13 @@ "warning": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz" } }, - "react-tabs": { - "version": "https://registry.npmjs.org/react-tabs/-/react-tabs-2.1.0.tgz", - "integrity": "sha1-uhhKUZ4KCAPPeQoesZvE/bpf0Oo=", - "requires": { - "classnames": "https://registry.npmjs.org/classnames/-/classnames-2.2.5.tgz", - "prop-types": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.0.tgz" - } - }, - "react-toastify": { - "version": "https://registry.npmjs.org/react-toastify/-/react-toastify-2.1.6.tgz", - "integrity": "sha1-Gkh/rSekjZ6u9FaDXpVevnmxp5A=", + "react-tippy": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/react-tippy/-/react-tippy-1.2.2.tgz", + "integrity": "sha512-xqmymAhKub1JGtLJ+HncUauBpwJjHAp6EkKBLeGtuhneaGQ3GnRp5aEd/YRNc4NmIb6o1lbf/Z6R9G3/VjnjYA==", + "dev": true, "requires": { - "prop-types": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.0.tgz", - "react-transition-group": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.2.1.tgz" + "popper.js": "1.12.9" } }, "react-toggle": { @@ -4396,7 +4383,7 @@ }, "tiny-emitter": { "version": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.0.2.tgz", - "integrity": "sha1-gtJ0aKylrejl/R5tIrV91D69+3w=" + "integrity": "sha512-2NM0auVBGft5tee/OxP4PI3d8WItkDM+fPnaRAVo6xTDI2knbz9eC5ArWGqtGlYqiH3RU5yMpdyTTO7MguC4ow==" }, "tinycolor2": { "version": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz", diff --git a/bigbluebutton-html5/package.json b/bigbluebutton-html5/package.json index 031ba58a0fa4bc8f9c2e1404d918969a1f8d41a5..8a4c07336f1a5f5ca0cff7998ec0bf9339bff61d 100755 --- a/bigbluebutton-html5/package.json +++ b/bigbluebutton-html5/package.json @@ -41,11 +41,12 @@ "react-modal": "~3.0.4", "react-router": "~3.0.2", "react-tabs": "~2.1.0", - "react-toggle": "~4.0.2", "react-toastify": "~2.1.2", + "react-toggle": "~4.0.2", "react-transition-group": "~2.2.1", "redis": "~2.8.0", "string-hash": "~1.1.3", + "tippy.js": "^2.0.2", "winston": "~2.4.0", "xml2js": "~0.4.19" }, @@ -65,6 +66,7 @@ "postcss-modules-scope": "1.1.0", "postcss-modules-values": "1.3.0", "postcss-nested": "2.1.2", + "react-tippy": "^1.2.2", "wdio-jasmine-framework": "~0.3.2", "wdio-junit-reporter": "~0.3.1", "wdio-spec-reporter": "~0.1.2",