Merge pull request #2038 from jitsi/apply-dark-theme

feat(dark-theme): Applies dark theme on inline-dialogs, tooltips, flags and more
This commit is contained in:
virtuacoplenny 2017-10-20 13:56:43 -07:00 committed by GitHub
commit 56887eb2fa
22 changed files with 253 additions and 329 deletions

View File

@ -1,7 +1,6 @@
%connection-info { %connection-info {
font-size: 12px; font-size: 12px;
font-weight: 400; font-weight: 400;
color: $modalTextColor;
td { td {
padding: 2px 0; padding: 2px 0;
@ -34,7 +33,6 @@
&__download &__download
{ {
@extend .connection-info__icon; @extend .connection-info__icon;
color: $downloadConnectionIconColor;
} }
&__status &__status
@ -45,7 +43,6 @@
&__upload &__upload
{ {
@extend .connection-info__icon; @extend .connection-info__icon;
color: $uploadConnectionIconColor;
} }
.showmore { .showmore {

View File

@ -86,26 +86,16 @@
width: 100%; width: 100%;
& button { & button {
background: $toolbarBackground;
flex-grow: 1; flex-grow: 1;
flex-shrink: 1; flex-shrink: 1;
overflow: hidden; overflow: hidden;
} }
& > * { & > * {
color: $toolbarButtonColor;
flex-grow: 0; flex-grow: 0;
flex-shrink: 0; flex-shrink: 0;
margin-left: 2px; margin-left: 2px;
} }
/**
* Making sure any svg-s in an invite button group will be
* colored the way we want.
*/
& path {
fill: $toolbarButtonColor;
}
} }
} }

View File

@ -19,7 +19,6 @@
// Link Appearance // Link Appearance
&__link, &__link,
&__contents { &__contents {
color: $modalTextColor;
display: block; display: block;
box-sizing: border-box; box-sizing: border-box;
text-decoration: none; text-decoration: none;
@ -30,7 +29,6 @@
padding: 0 5px; padding: 0 5px;
&.disabled { &.disabled {
color: gray !important;
pointer-events: none; pointer-events: none;
} }
} }

View File

@ -36,7 +36,6 @@
* Common toolbar styles. * Common toolbar styles.
*/ */
.toolbar { .toolbar {
color: $modalTextColor;
height: 100%; height: 100%;
pointer-events: auto; pointer-events: auto;
position: relative; position: relative;
@ -82,20 +81,21 @@
vertical-align: middle; vertical-align: middle;
width: $defaultToolbarSize; width: $defaultToolbarSize;
&_hangup {
color: $hangupColor;
font-size: $hangupFontSize;
}
&[disabled] { &[disabled] {
opacity: 0.5; opacity: 0.5;
} }
&:hover, &:active { &:hover, &:active {
color: $toolbarButtonColor;
cursor: pointer; cursor: pointer;
text-decoration: none; text-decoration: none;
} }
&_hangup, &_hangup:hover {
color: $hangupColor;
font-size: $hangupFontSize;
}
&:not(.toggled) { &:not(.toggled) {
&:hover, &:active { &:hover, &:active {
// sum opacity with background layer should give us 0.8 // sum opacity with background layer should give us 0.8

View File

@ -64,6 +64,7 @@ $connectionIndicatorBg: #165ecc;
$audioLevelShadow: rgba(9, 36, 77, 0.9); $audioLevelShadow: rgba(9, 36, 77, 0.9);
$videoStateIndicatorColor: $defaultColor; $videoStateIndicatorColor: $defaultColor;
$videoStateIndicatorBackground: $toolbarBackground; $videoStateIndicatorBackground: $toolbarBackground;
$videoStateIndicatorSize: 40px;
/** /**
* Feedback Modal * Feedback Modal

View File

@ -65,6 +65,15 @@
float: left; float: left;
pointer-events: all; pointer-events: all;
} }
/**
* Need to overwrite the background for the top toolbar dark theme div
* wrapper needed before we're able to move all top toolbar indicators
* creation to react.
*/
.ckAJgx {
background: none;
}
} }
&__toolbar { &__toolbar {

View File

@ -26,17 +26,6 @@
user-select: text; user-select: text;
} }
.dial-in-numbers-trigger {
position: relative;
width: 100%;
.dial-in-numbers-trigger-icon {
position: absolute;
right: 10px;
top: 4px;
}
}
.is-disabled, .is-disabled,
.is-loading { .is-loading {
.dial-in-numbers-trigger-icon { .dial-in-numbers-trigger-icon {
@ -62,6 +51,10 @@
&__input-container { &__input-container {
flex: 1; flex: 1;
margin-right: 10px; margin-right: 10px;
.dropdown-button-trigger {
text-align: left;
}
} }
} }

View File

@ -1,5 +1,4 @@
.video-quality-dialog { .video-quality-dialog {
color: $modalTextColor;
.hide-warning { .hide-warning {
height: 0; height: 0;
@ -12,7 +11,6 @@
.video-quality-dialog-contents { .video-quality-dialog-contents {
align-items: center; align-items: center;
color: $modalTextColor;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding: 10px; padding: 10px;
@ -29,7 +27,7 @@
@mixin sliderTrackStyles() { @mixin sliderTrackStyles() {
height: 15px; height: 15px;
border-radius: 10px; border-radius: 10px;
background: black; background: #0E1624;
} }
&::-ms-track { &::-ms-track {
@ -79,7 +77,6 @@
transform: translate(-50%, 0%); transform: translate(-50%, 0%);
&::before { &::before {
background: rgb(140, 156, 189);
content: ''; content: '';
border-radius: 50%; border-radius: 50%;
left: 0; left: 0;
@ -94,10 +91,10 @@
} }
.video-quality-dialog-label-container.active { .video-quality-dialog-label-container.active {
color: $toolbarToggleBackground; color: $videoQualityActive;
&::before { &::before {
background: $toolbarToggleBackground; background: $videoQualityActive;
height: 12px; height: 12px;
top: -19px; top: -19px;
width: 12px; width: 12px;
@ -117,26 +114,26 @@
.video-state-indicator { .video-state-indicator {
background: $videoStateIndicatorBackground; background: $videoStateIndicatorBackground;
color: $videoStateIndicatorColor;
cursor: default; cursor: default;
font-size: 13px; font-size: 13px;
height: 40px; height: $videoStateIndicatorSize;
line-height: 20px; line-height: 20px;
text-align: left; text-align: left;
min-width: 40px; min-width: $videoStateIndicatorSize;
border-radius: 50%; border-radius: 50%;
position: absolute; position: absolute;
box-sizing: border-box; box-sizing: border-box;
i { i {
cursor: pointer; line-height: $videoStateIndicatorSize;
} }
/** /**
* Give the label padding so it has more volume and can be easily clicked. * Give the label padding so it has more volume and can be easily clicked.
*/ */
.video-quality-label-status { .video-quality-label-status {
padding: 10px 5px; line-height: $videoStateIndicatorSize;
min-width: $videoStateIndicatorSize;
text-align: center; text-align: center;
} }
} }

View File

@ -44,12 +44,6 @@ $defaultBackground: #474747;
$filmstripOnlyOverlayBg: #000; $filmstripOnlyOverlayBg: #000;
$reloadProgressBarBg: #0074E0; $reloadProgressBarBg: #0074E0;
/**
* Connection indicator
**/
$downloadConnectionIconColor: #4abd04;
$uploadConnectionIconColor: #ffa800;
/** /**
* Dialog colors * Dialog colors
**/ **/
@ -111,3 +105,8 @@ $selectFontColor: $controlColor;
$selectBg: $controlBackground; $selectBg: $controlBackground;
$selectActiveBg: darken($controlBackground, 5%); $selectActiveBg: darken($controlBackground, 5%);
$selectActiveItemBg: darken($controlBackground, 20%); $selectActiveItemBg: darken($controlBackground, 20%);
/**
* TODO: Replace by themed component.
*/
$videoQualityActive: #4C9AFF;

View File

@ -5,6 +5,7 @@ import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import { I18nextProvider } from 'react-i18next'; import { I18nextProvider } from 'react-i18next';
import { AtlasKitThemeProvider } from '@atlaskit/theme';
import { i18next } from '../../../react/features/base/i18n'; import { i18next } from '../../../react/features/base/i18n';
import { import {
@ -167,15 +168,18 @@ RemoteVideo.prototype._generatePopupContent = function() {
ReactDOM.render( ReactDOM.render(
<Provider store = { APP.store }> <Provider store = { APP.store }>
<I18nextProvider i18n = { i18next }> <I18nextProvider i18n = { i18next }>
<AtlasKitThemeProvider mode = 'dark'>
<RemoteVideoMenuTriggerButton <RemoteVideoMenuTriggerButton
initialVolumeValue = { initialVolumeValue } initialVolumeValue = { initialVolumeValue }
isAudioMuted = { this.isAudioMuted } isAudioMuted = { this.isAudioMuted }
isModerator = { isModerator } isModerator = { isModerator }
onMenuDisplay = {this._onRemoteVideoMenuDisplay.bind(this)} onMenuDisplay
= {this._onRemoteVideoMenuDisplay.bind(this)}
onRemoteControlToggle = { onRemoteControlToggle } onRemoteControlToggle = { onRemoteControlToggle }
onVolumeChange = { onVolumeChange } onVolumeChange = { onVolumeChange }
participantID = { participantID } participantID = { participantID }
remoteControlState = { remoteControlState } /> remoteControlState = { remoteControlState } />
</AtlasKitThemeProvider>
</I18nextProvider> </I18nextProvider>
</Provider>, </Provider>,
remoteVideoMenuContainer); remoteVideoMenuContainer);

View File

@ -4,6 +4,7 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { I18nextProvider } from 'react-i18next'; import { I18nextProvider } from 'react-i18next';
import { AtlasKitThemeProvider } from '@atlaskit/theme';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import { i18next } from '../../../react/features/base/i18n'; import { i18next } from '../../../react/features/base/i18n';
@ -782,14 +783,17 @@ SmallVideo.prototype.updateIndicators = function() {
ReactDOM.render( ReactDOM.render(
<I18nextProvider i18n = { i18next }> <I18nextProvider i18n = { i18next }>
<div> <div>
<AtlasKitThemeProvider mode = 'dark'>
{ this._showConnectionIndicator { this._showConnectionIndicator
? <ConnectionIndicator ? <ConnectionIndicator
alwaysVisible = { showConnectionIndicator } alwaysVisible = { showConnectionIndicator }
connectionStatus = { this._connectionStatus } connectionStatus = { this._connectionStatus }
iconSize = { iconSize } iconSize = { iconSize }
isLocalVideo = { this.isLocal } isLocalVideo = { this.isLocal }
enableStatsDisplay = { !interfaceConfig.filmStripOnly } enableStatsDisplay
statsPopoverPosition = { this.statsPopoverLocation } = { !interfaceConfig.filmStripOnly }
statsPopoverPosition
= { this.statsPopoverLocation }
userID = { this.id } /> userID = { this.id } />
: null } : null }
{ this._showRaisedHand { this._showRaisedHand
@ -802,6 +806,7 @@ SmallVideo.prototype.updateIndicators = function() {
iconSize = { iconSize } iconSize = { iconSize }
tooltipPosition = { tooltipPosition } /> tooltipPosition = { tooltipPosition } />
: null } : null }
</AtlasKitThemeProvider>
</div> </div>
</I18nextProvider>, </I18nextProvider>,
indicatorToolbar indicatorToolbar

View File

@ -15,20 +15,23 @@
"author": "", "author": "",
"readmeFilename": "README.md", "readmeFilename": "README.md",
"dependencies": { "dependencies": {
"@atlaskit/avatar": "4.0.5", "@atlaskit/avatar": "8.0.5",
"@atlaskit/button": "3.0.0", "@atlaskit/button": "5.4.2",
"@atlaskit/button-group": "1.1.3", "@atlaskit/button-group": "1.5.3",
"@atlaskit/dropdown-menu": "1.4.0", "@atlaskit/dropdown-menu": "3.10.2",
"@atlaskit/field-text": "2.7.0", "@atlaskit/droplist": "4.11.1",
"@atlaskit/flag": "3.0.0", "@atlaskit/field-text": "4.0.1",
"@atlaskit/icon": "7.0.0", "@atlaskit/flag": "6.1.0",
"@atlaskit/inline-dialog": "3.2.0", "@atlaskit/icon": "10.0.0",
"@atlaskit/inline-message": "2.1.1", "@atlaskit/inline-dialog": "5.0.2",
"@atlaskit/modal-dialog": "2.1.2", "@atlaskit/inline-message": "3.0.1",
"@atlaskit/multi-select": "6.2.0", "@atlaskit/modal-dialog": "2.6.0",
"@atlaskit/spinner": "2.2.3", "@atlaskit/multi-select": "7.1.3",
"@atlaskit/tabs": "2.0.0", "@atlaskit/spinner": "4.0.0",
"@atlaskit/toggle": "2.0.4", "@atlaskit/tabs": "4.0.1",
"@atlaskit/theme": "2.2.0",
"@atlaskit/toggle": "2.6.1",
"@atlaskit/tooltip": "6.0.0",
"@atlassian/aui": "6.0.6", "@atlassian/aui": "6.0.6",
"autosize": "1.18.13", "autosize": "1.18.13",
"es6-iterator": "2.0.1", "es6-iterator": "2.0.1",

View File

@ -4,6 +4,7 @@ import { I18nextProvider } from 'react-i18next';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import { compose, createStore } from 'redux'; import { compose, createStore } from 'redux';
import Thunk from 'redux-thunk'; import Thunk from 'redux-thunk';
import { AtlasKitThemeProvider } from '@atlaskit/theme';
import { i18next } from '../../base/i18n'; import { i18next } from '../../base/i18n';
import { import {
@ -201,9 +202,11 @@ export class AbstractApp extends Component {
return ( return (
<I18nextProvider i18n = { i18next }> <I18nextProvider i18n = { i18next }>
<Provider store = { this._getStore() }> <Provider store = { this._getStore() }>
<AtlasKitThemeProvider mode = 'dark'>
{ {
this._createElement(component) this._createElement(component)
} }
</AtlasKitThemeProvider>
</Provider> </Provider>
</I18nextProvider> </I18nextProvider>
); );

View File

@ -1,6 +1,7 @@
import AKButton from '@atlaskit/button'; import AKButton from '@atlaskit/button';
import AKButtonGroup from '@atlaskit/button-group'; import AKButtonGroup from '@atlaskit/button-group';
import ModalDialog from '@atlaskit/modal-dialog'; import ModalDialog from '@atlaskit/modal-dialog';
import { AtlasKitThemeProvider } from '@atlaskit/theme';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, { Component } from 'react'; import React, { Component } from 'react';
@ -114,6 +115,12 @@ class StatelessDialog extends Component {
*/ */
render() { render() {
return ( return (
/**
* Enabled light theme for dialogs until all in-dialog components
* support dark theme.
*/
<AtlasKitThemeProvider mode = 'light'>
<div <div
onKeyDown = { this._onKeyDown } onKeyDown = { this._onKeyDown }
ref = { this._setDialogElement }> ref = { this._setDialogElement }>
@ -133,6 +140,7 @@ class StatelessDialog extends Component {
</div> </div>
</ModalDialog> </ModalDialog>
</div> </div>
</AtlasKitThemeProvider>
); );
} }

View File

@ -1,5 +1,5 @@
import AKDropdownMenu from '@atlaskit/dropdown-menu'; import AKDropdownMenu from '@atlaskit/dropdown-menu';
import ExpandIcon from '@atlaskit/icon/glyph/expand'; import ChevronDownIcon from '@atlaskit/icon/glyph/chevron-down';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, { Component } from 'react'; import React, { Component } from 'react';
@ -116,7 +116,7 @@ class DeviceSelector extends Component {
<span className = 'device-selector-trigger-text'> <span className = 'device-selector-trigger-text'>
{ triggerText } { triggerText }
</span> </span>
<ExpandIcon <ChevronDownIcon
label = 'expand' label = 'expand'
size = 'large' /> size = 'large' />
</div> </div>

View File

@ -1,6 +1,6 @@
import { StatelessDropdownMenu } from '@atlaskit/dropdown-menu'; import { DropdownMenuStateless as DropdownMenu } from '@atlaskit/dropdown-menu';
import AKFieldText, { FieldText } from '@atlaskit/field-text'; import { FieldTextStateless as TextField } from '@atlaskit/field-text';
import ExpandIcon from '@atlaskit/icon/glyph/expand'; import ChevronDownIcon from '@atlaskit/icon/glyph/chevron-down';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
@ -149,7 +149,7 @@ class DialOutNumbersForm extends Component {
{ _dialOutCodes ? this._createDropdownMenu( { _dialOutCodes ? this._createDropdownMenu(
this._formatCountryCodes(_dialOutCodes)) : null } this._formatCountryCodes(_dialOutCodes)) : null }
<div className = 'dial-out-input'> <div className = 'dial-out-input'>
<AKFieldText <TextField
autoFocus = { true } autoFocus = { true }
isLabelHidden = { true } isLabelHidden = { true }
label = { 'dial-out-input-field' } label = { 'dial-out-input-field' }
@ -164,7 +164,7 @@ class DialOutNumbersForm extends Component {
} }
/** /**
* Creates a {@code StatelessDropdownMenu} instance. * Creates a {@code DropdownMenu} instance.
* *
* @param {Array} items - The content to display within the dropdown. * @param {Array} items - The content to display within the dropdown.
* @returns {ReactElement} * @returns {ReactElement}
@ -174,14 +174,14 @@ class DialOutNumbersForm extends Component {
return ( return (
<div className = 'dropdown-container'> <div className = 'dropdown-container'>
<StatelessDropdownMenu <DropdownMenu
isOpen = { this.state.isDropdownOpen } isOpen = { this.state.isDropdownOpen }
items = { [ { items } ] } items = { [ { items } ] }
onItemActivated = { this._onSelect } onItemActivated = { this._onSelect }
onOpenChange = { this._onOpenChange } onOpenChange = { this._onOpenChange }
shouldFitContainer = { false }> shouldFitContainer = { false }>
{ this._createDropdownTrigger(dialCode, code) } { this._createDropdownTrigger(dialCode, code) }
</StatelessDropdownMenu> </DropdownMenu>
</div> </div>
); );
} }
@ -203,10 +203,10 @@ class DialOutNumbersForm extends Component {
className = 'dial-out-flag-icon' className = 'dial-out-flag-icon'
countryCode = { `${countryCode}` } /> countryCode = { `${countryCode}` } />
{ /** { /**
* FIXME Replace FieldText with AtlasKit Button when an issue * FIXME Replace TextField with AtlasKit Button when an issue
* with icons shrinking due to button text is fixed. * with icons shrinking due to button text is fixed.
*/ } */ }
<FieldText <TextField
className = 'input-control dial-out-code' className = 'input-control dial-out-code'
isLabelHidden = { true } isLabelHidden = { true }
isReadOnly = { true } isReadOnly = { true }
@ -215,9 +215,9 @@ class DialOutNumbersForm extends Component {
type = 'text' type = 'text'
value = { dialCode || '' } /> value = { dialCode || '' } />
<span className = 'dropdown-trigger-icon'> <span className = 'dropdown-trigger-icon'>
<ExpandIcon <ChevronDownIcon
label = 'expand' label = 'expand'
size = 'medium' /> size = 'small' />
</span> </span>
</div> </div>
); );
@ -225,7 +225,7 @@ class DialOutNumbersForm extends Component {
/** /**
* Transforms the passed in numbers object into an array of objects that can * Transforms the passed in numbers object into an array of objects that can
* be parsed by {@code StatelessDropdownMenu}. * be parsed by {@code DropdownMenu}.
* *
* @param {Object} countryCodes - The list of country codes. * @param {Object} countryCodes - The list of country codes.
* @private * @private
@ -259,8 +259,8 @@ class DialOutNumbersForm extends Component {
} }
/** /**
* This is a no-op function used to stub out FieldText's onChange in order * This is a no-op function used to stub out TextField's onChange in order
* to prevent FieldText from printing prop type validation errors. FieldText * to prevent TextField from printing prop type validation errors. TextField
* is used as a trigger for the dropdown in {@code DialOutNumbersForm} to * is used as a trigger for the dropdown in {@code DialOutNumbersForm} to
* get the desired AtlasKit input look for the UI. * get the desired AtlasKit input look for the UI.
* *

View File

@ -1,7 +1,7 @@
import AKFieldText from '@atlaskit/field-text';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { FieldTextStateless as TextField } from '@atlaskit/field-text';
import { Dialog } from '../../base/dialog'; import { Dialog } from '../../base/dialog';
import { translate } from '../../base/i18n'; import { translate } from '../../base/i18n';
@ -76,7 +76,7 @@ class DisplayNamePrompt extends Component {
onSubmit = { this._onSubmit } onSubmit = { this._onSubmit }
titleKey = 'dialog.displayNameRequired' titleKey = 'dialog.displayNameRequired'
width = 'small'> width = 'small'>
<AKFieldText <TextField
autoFocus = { true } autoFocus = { true }
compact = { true } compact = { true }
label = { this.props.t('dialog.enterDisplayName') } label = { this.props.t('dialog.enterDisplayName') }

View File

@ -1,5 +1,5 @@
import Button from '@atlaskit/button'; import Button from '@atlaskit/button';
import { FieldText } from '@atlaskit/field-text'; import { FieldTextStateless as TextField } from '@atlaskit/field-text';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
@ -106,7 +106,7 @@ class AddPasswordForm extends Component {
onSubmit = { this._onSubmit } > onSubmit = { this._onSubmit } >
<div className = 'form-control__container'> <div className = 'form-control__container'>
<div className = 'form-control__input-container'> <div className = 'form-control__input-container'>
<FieldText <TextField
autoFocus = { true } autoFocus = { true }
compact = { true } compact = { true }
id = 'newPasswordInput' id = 'newPasswordInput'
@ -123,7 +123,6 @@ class AddPasswordForm extends Component {
id = 'addPasswordBtn' id = 'addPasswordBtn'
isDisabled = { !this.state.password } isDisabled = { !this.state.password }
onClick = { this._onSubmit } onClick = { this._onSubmit }
shouldFitContainer = { true }
type = 'button'> type = 'button'>
{ t('dialog.add') } { t('dialog.add') }
</Button> </Button>

View File

@ -1,7 +1,6 @@
import Button from '@atlaskit/button'; import Button from '@atlaskit/button';
import { StatelessDropdownMenu } from '@atlaskit/dropdown-menu'; import DropdownMenu, {
import { FieldText } from '@atlaskit/field-text'; DropdownItem, DropdownItemGroup } from '@atlaskit/dropdown-menu';
import ExpandIcon from '@atlaskit/icon/glyph/expand';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
@ -95,8 +94,6 @@ class DialInNumbersForm extends Component {
// Bind event handlers so they are only bound once for every instance. // Bind event handlers so they are only bound once for every instance.
this._onCopyClick = this._onCopyClick.bind(this); this._onCopyClick = this._onCopyClick.bind(this);
this._onDropdownTriggerInputChange
= this._onDropdownTriggerInputChange.bind(this);
this._onOpenChange = this._onOpenChange.bind(this); this._onOpenChange = this._onOpenChange.bind(this);
this._onSelect = this._onSelect.bind(this); this._onSelect = this._onSelect.bind(this);
this._setCopyElement = this._setCopyElement.bind(this); this._setCopyElement = this._setCopyElement.bind(this);
@ -147,7 +144,7 @@ class DialInNumbersForm extends Component {
return null; return null;
} }
const items = this._formatNumbers(numbers); const items = this._renderDropdownItems(numbers);
return ( return (
<div className = 'form-control dial-in-numbers'> <div className = 'form-control dial-in-numbers'>
@ -158,11 +155,12 @@ class DialInNumbersForm extends Component {
</span> </span>
</label> </label>
<div className = 'form-control__container'> <div className = 'form-control__container'>
{ this._createDropdownMenu(items, selectedNumber.content) } <div className = 'form-control__input-container'>
{ this._createDropdownMenu(items, selectedNumber) }
</div>
<Button <Button
appearance = 'default' appearance = 'default'
onClick = { this._onCopyClick } onClick = { this._onCopyClick }
shouldFitContainer = { true }
type = 'button'> type = 'button'>
{ t('dialog.copy') } { t('dialog.copy') }
</Button> </Button>
@ -178,7 +176,7 @@ class DialInNumbersForm extends Component {
} }
/** /**
* Creates a {@code StatelessDropdownMenu} instance. * Creates a {@code DropdownMenu} instance.
* *
* @param {Array} items - The content to display within the dropdown. * @param {Array} items - The content to display within the dropdown.
* @param {string} triggerText - The text to display within the * @param {string} triggerText - The text to display within the
@ -187,116 +185,32 @@ class DialInNumbersForm extends Component {
*/ */
_createDropdownMenu(items, triggerText) { _createDropdownMenu(items, triggerText) {
return ( return (
<StatelessDropdownMenu <DropdownMenu
isOpen = { this.state.isDropdownOpen } isOpen = { this.state.isDropdownOpen }
items = { [ { items } ] }
onItemActivated = { this._onSelect }
onOpenChange = { this._onOpenChange } onOpenChange = { this._onOpenChange }
shouldFitContainer = { true }>
{ this._createDropdownTrigger(triggerText) }
</StatelessDropdownMenu>
);
}
/**
* Creates a React {@code Component} with a readonly HTMLInputElement as a
* trigger for displaying the dropdown menu. The {@code Component} will also
* display the currently selected number.
*
* @param {string} triggerText - Text to display in the HTMLInputElement.
* @private
* @returns {ReactElement}
*/
_createDropdownTrigger(triggerText) {
return (
<div className = 'dial-in-numbers-trigger'>
<div className = 'form-control__input-container'>
<FieldText
compact = { true }
isLabelHidden = { true }
isReadOnly = { true }
label = 'Select Dial-In Number'
onChange = { this._onDropdownTriggerInputChange }
ref = { this._setInput }
shouldFitContainer = { true } shouldFitContainer = { true }
type = 'text' trigger = { triggerText || '' }
value = { triggerText || '' } /> triggerButtonProps = {{
</div> className: 'dropdown-button-trigger',
<span className = 'dial-in-numbers-trigger-icon'> shouldFitContainer: true }}
<ExpandIcon triggerType = 'button'>
label = 'expand' <DropdownItemGroup>
size = 'medium' /> { items }
</span> </DropdownItemGroup>
</div> </DropdownMenu>
); );
} }
/** /**
* Detects whether the response from dialInNumbersUrl returned an array or * Formats the region and number string.
* an object with dial-in numbers and calls the appropriate method to
* transform the numbers into the format expected by
* {@code StatelessDropdownMenu}.
* *
* @param {Array<string>|Object} dialInNumbers - The numbers returned from * @param {string} region - The region string.
* requesting dialInNumbersUrl. * @param {string} number - The number string.
* @returns {string} - The new formatted string.
* @private * @private
* @returns {Array<Object>}
*/ */
_formatNumbers(dialInNumbers) { _formatRegionNumber(region, number) {
if (Array.isArray(dialInNumbers)) { return `${region}: ${number}`;
return this._formatNumbersArray(dialInNumbers);
}
return this._formatNumbersObject(dialInNumbers);
}
/**
* Transforms the passed in numbers array into an array of objects that can
* be parsed by {@code StatelessDropdownMenu}.
*
* @param {Array<string>} dialInNumbers - An array with dial-in numbers to
* display and copy.
* @private
* @returns {Array<Object>}
*/
_formatNumbersArray(dialInNumbers) {
return dialInNumbers.map(number => {
return {
content: number,
number
};
});
}
/**
* Transforms the passed in numbers object into an array of objects that can
* be parsed by {@code StatelessDropdownMenu}.
*
* @param {Object} dialInNumbers - The numbers object to parse. The
* expected format is an object with keys being the name of the country
* and the values being an array of numbers as strings.
* @private
* @returns {Array<Object>}
*/
_formatNumbersObject(dialInNumbers) {
const phoneRegions = Object.keys(dialInNumbers);
if (!phoneRegions.length) {
return [];
}
const formattedNumbers = phoneRegions.map(region => {
const numbers = dialInNumbers[region];
return numbers.map(number => {
return {
content: `${region}: ${number}`,
number
};
});
});
return Array.prototype.concat(...formattedNumbers);
} }
/** /**
@ -313,7 +227,7 @@ class DialInNumbersForm extends Component {
}); });
const callNumber = t('invite.callNumber', { const callNumber = t('invite.callNumber', {
number: this.state.selectedNumber.number number: this.state.selectedNumber
}); });
const stepOne = `1) ${callNumber}`; const stepOne = `1) ${callNumber}`;
@ -343,18 +257,6 @@ class DialInNumbersForm extends Component {
} }
} }
/**
* This is a no-op function used to stub out FieldText's onChange in order
* to prevent FieldText from printing prop type validation errors. FieldText
* is used as a trigger for the dropdown in {@code DialInNumbersForm} to
* get the desired AtlasKit input look for the UI.
*
* @returns {void}
*/
_onDropdownTriggerInputChange() {
// Intentionally left empty.
}
/** /**
* Sets the internal state to either open or close the dropdown. If the * Sets the internal state to either open or close the dropdown. If the
* dropdown is disabled, the state will always be set to false. * dropdown is disabled, the state will always be set to false.
@ -380,10 +282,71 @@ class DialInNumbersForm extends Component {
_onSelect(selection) { _onSelect(selection) {
this.setState({ this.setState({
isDropdownOpen: false, isDropdownOpen: false,
selectedNumber: selection.item selectedNumber: selection
}); });
} }
/**
* Renders a DropDownItem for the given id and text.
*
* @param {string} id - The key identifier of the DropdownItem.
* @param {string} text - The text to display in the dropdown item.
* @returns {React.Component}
* @private
*/
_renderDropDownItem(id, text) {
return (
/**
* Arrow functions are not allowed in props, but I leave this until
* I figure a better way to implement the same thing.
*/
/* eslint-disable react/jsx-no-bind */
<DropdownItem
key = { id }
onClick = { () => this._onSelect(text || id) }>
{ text }
</DropdownItem>
/* eslint-disable react/jsx-no-bind */
);
}
/**
* Detects whether the response from dialInNumbersUrl returned an array or
* an object with dial-in numbers and calls the appropriate method to
* transform the numbers into the format expected by
* {@code DropdownMenu}.
*
* @param {Array<string>|Object} dialInNumbers - The numbers returned from
* requesting dialInNumbersUrl.
* @private
* @returns {Array<Object>}
*/
_renderDropdownItems(dialInNumbers) {
if (Array.isArray(dialInNumbers)) {
return dialInNumbers.map(number =>
this._renderDropDownItem(number)
);
}
const phoneRegions = Object.keys(dialInNumbers);
if (!phoneRegions.length) {
return [];
}
const dropdownItems = phoneRegions.map(region => {
const numbers = dialInNumbers[region];
return numbers.map(number =>
this._renderDropDownItem(number,
this._formatRegionNumber(region, number))
);
});
return Array.prototype.concat(...dropdownItems);
}
/** /**
* Sets the internal reference to the DOM/HTML element backing the React * Sets the internal reference to the DOM/HTML element backing the React
* {@code Component} text area. * {@code Component} text area.
@ -406,10 +369,18 @@ class DialInNumbersForm extends Component {
* @returns {void} * @returns {void}
*/ */
_setDefaultNumber(dialInNumbers) { _setDefaultNumber(dialInNumbers) {
const numbers = this._formatNumbers(dialInNumbers); let number = '';
if (Array.isArray(dialInNumbers)) {
number = dialInNumbers[0];
} else if (Object.keys(dialInNumbers).length > 0) {
const region = Object.keys(dialInNumbers)[0];
number = this._formatRegionNumber(region, dialInNumbers[region]);
}
this.setState({ this.setState({
selectedNumber: numbers[0] selectedNumber: number
}); });
} }
} }

View File

@ -1,5 +1,5 @@
import Button from '@atlaskit/button'; import Button from '@atlaskit/button';
import { FieldText } from '@atlaskit/field-text'; import { FieldTextStateless as TextField } from '@atlaskit/field-text';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, { Component } from 'react'; import React, { Component } from 'react';
@ -71,8 +71,7 @@ class ShareLinkForm extends Component {
</label> </label>
<div className = 'form-control__container'> <div className = 'form-control__container'>
<div className = 'form-control__input-container'> <div className = 'form-control__input-container'>
<FieldText <TextField
compact = { true }
id = 'inviteLinkRef' id = 'inviteLinkRef'
isLabelHidden = { true } isLabelHidden = { true }
isReadOnly = { true } isReadOnly = { true }
@ -86,7 +85,6 @@ class ShareLinkForm extends Component {
<Button <Button
appearance = 'default' appearance = 'default'
onClick = { this._onClick } onClick = { this._onClick }
shouldFitContainer = { true }
type = 'button'> type = 'button'>
{ t('dialog.copy') } { t('dialog.copy') }
</Button> </Button>
@ -114,8 +112,8 @@ class ShareLinkForm extends Component {
} }
/** /**
* This is a no-op function used to stub out FieldText's onChange in order * This is a no-op function used to stub out TextField's onChange in order
* to prevent FieldText from printing prop type validation errors. FieldText * to prevent TextField from printing prop type validation errors. TextField
* is used as a trigger for the dropdown in {@code ShareLinkForm} to get the * is used as a trigger for the dropdown in {@code ShareLinkForm} to get the
* desired AtlasKit input look for the UI. * desired AtlasKit input look for the UI.
* *

View File

@ -1,9 +1,8 @@
// @flow // @flow
import AKFieldText from '@atlaskit/field-text';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { FieldTextStateless as TextField } from '@atlaskit/field-text';
import { setPassword } from '../../base/conference'; import { setPassword } from '../../base/conference';
import { Dialog } from '../../base/dialog'; import { Dialog } from '../../base/dialog';
@ -75,7 +74,7 @@ class PasswordRequiredPrompt extends Component {
_renderBody() { _renderBody() {
return ( return (
<div> <div>
<AKFieldText <TextField
autoFocus = { true } autoFocus = { true }
compact = { true } compact = { true }
label = { this.props.t('dialog.passwordLabel') } label = { this.props.t('dialog.passwordLabel') }

View File

@ -1,14 +1,13 @@
/* @flow */ /* @flow */
import AKInlineDialog from '@atlaskit/inline-dialog'; import InlineDialog from '@atlaskit/inline-dialog';
import { Tooltip } from '@atlaskit/tooltip'; import Tooltip from '@atlaskit/tooltip';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { translate } from '../../base/i18n'; import { translate } from '../../base/i18n';
import { TOOLTIP_TO_POPUP_POSITION } from '../constants'; import { TOOLTIP_TO_POPUP_POSITION } from '../constants';
import { isButtonEnabled } from '../functions';
import StatelessToolbarButton from './StatelessToolbarButton'; import StatelessToolbarButton from './StatelessToolbarButton';
declare var APP: Object; declare var APP: Object;
@ -24,20 +23,6 @@ class ToolbarButton extends Component {
_onClick: Function; _onClick: Function;
_onMouseOut: Function;
_onMouseOver: Function;
state: {
/**
* Whether or not the tooltip for the button should be displayed.
*
* @type {boolean}
*/
showTooltip: boolean
}
/** /**
* Toolbar button component's property types. * Toolbar button component's property types.
* *
@ -81,14 +66,8 @@ class ToolbarButton extends Component {
constructor(props: Object) { constructor(props: Object) {
super(props); super(props);
this.state = {
showTooltip: false
};
// Bind methods to save the context // Bind methods to save the context
this._onClick = this._onClick.bind(this); this._onClick = this._onClick.bind(this);
this._onMouseOut = this._onMouseOut.bind(this);
this._onMouseOver = this._onMouseOver.bind(this);
} }
/** /**
@ -134,10 +113,7 @@ class ToolbarButton extends Component {
const buttonComponent = ( // eslint-disable-line no-extra-parens const buttonComponent = ( // eslint-disable-line no-extra-parens
<Tooltip <Tooltip
description = { button.tooltipText || t(button.tooltipKey) } description = { button.tooltipText || t(button.tooltipKey) }
onMouseOut = { this._onMouseOut } position = { tooltipPosition }>
onMouseOver = { this._onMouseOver }
position = { tooltipPosition }
visible = { this.state.showTooltip }>
<StatelessToolbarButton { ...props }> <StatelessToolbarButton { ...props }>
{ this.props.children } { this.props.children }
</StatelessToolbarButton> </StatelessToolbarButton>
@ -151,12 +127,12 @@ class ToolbarButton extends Component {
const { dataAttr, dataInterpolate, position } = popupConfig; const { dataAttr, dataInterpolate, position } = popupConfig;
children = ( // eslint-disable-line no-extra-parens children = ( // eslint-disable-line no-extra-parens
<AKInlineDialog <InlineDialog
content = { t(dataAttr, dataInterpolate) } content = { t(dataAttr, dataInterpolate) }
isOpen = { Boolean(popupConfig) } isOpen = { Boolean(popupConfig) }
position = { position }> position = { position }>
{ buttonComponent } { buttonComponent }
</AKInlineDialog> </InlineDialog>
); );
} }
@ -176,7 +152,6 @@ class ToolbarButton extends Component {
*/ */
_onClick(event) { _onClick(event) {
this.props.onClick(event); this.props.onClick(event);
this.setState({ showTooltip: false });
} }
/** /**
@ -205,31 +180,6 @@ class ToolbarButton extends Component {
}); });
} }
/**
* Hides any displayed tooltip.
*
* @private
* @returns {void}
*/
_onMouseOut(): void {
this.setState({ showTooltip: false });
}
/**
* Hides any displayed tooltip.
*
* @private
* @returns {void}
*/
_onMouseOver(): void {
const { button } = this.props;
this.setState({
showTooltip: isButtonEnabled(button.buttonName)
&& !button.unclickable
});
}
/** /**
* Sets shortcut and tooltip for current toolbar button. * Sets shortcut and tooltip for current toolbar button.
* *