From 3e518e80403a28876638f4a561d1753cf0ee8f05 Mon Sep 17 00:00:00 2001 From: Leonard Kim Date: Mon, 17 Apr 2017 14:02:36 -0700 Subject: [PATCH] feat: convert device selection modal to use AtlasKit Dropdown Instead of using AtlasKit Single-Select, use Dropdown. Dropdown differs in that an icon can be specified for the trigger element, whereas Single-Select currently supports icons for all elements, and Dropdown can show all options incuding the already-selected option. This change does introduce the issue of the trigger element not taking up 100% width of the parent. Supporting such would involve overriding AtlasKit CSS. The compromise made here was to do a generic override of max-width so the trigger elements at least stay within the parent and aligning the trigger elements to the right. --- .../device-selection/_device-selection.scss | 49 ++++++--- package.json | 3 +- .../components/DeviceSelectionDialog.js | 17 +-- .../components/DeviceSelector.js | 102 +++++++++++++----- 4 files changed, 120 insertions(+), 51 deletions(-) diff --git a/css/modals/device-selection/_device-selection.scss b/css/modals/device-selection/_device-selection.scss index 971566b9c..0c87cc2f0 100644 --- a/css/modals/device-selection/_device-selection.scss +++ b/css/modals/device-selection/_device-selection.scss @@ -4,37 +4,58 @@ .device-selectors { font-size: 14px; + /* ensure all child components do not exceed parent width */ + button, + div { + max-width: 100%; + } + > div { + display: block; margin-bottom: 10px; } > div:last-child { margin-bottom: 5px; } + + .device-selector-icon { + color: inherit; + font-size: 20px; + } } - .device-selection-column-selectors, - .device-selection-column-video { - padding: 10px; + .device-selection-column { + box-sizing: border-box; display: inline-block; vertical-align: top; - } - .device-selection-column-selectors { - width: 46%; - } - .device-selection-column-video { - width: 49%; - padding: 10px 0; + + &.column-selectors { + margin-left: 15px; + width: 45%; + } + + &.column-video { + width: 50%; + } } .device-selection-video-container { + /* TOFIX: to be removed when we move out from muted preview */ background: black; - height: 156px; - margin: 15px 0 5px; + border-radius: 3px; + /* TOFIX-END */ + height: 160px; + margin-bottom: 5px; .video-input-preview { + margin-top: 2px; position: relative; + > video { + border-radius: 3px; + } + .video-input-preview-muted { color: $participantNameColor; display: none; @@ -58,8 +79,8 @@ } .audio-output-preview { - text-align: right; - + font-size: 14px; + margin-top: 10px; a { cursor: pointer; text-decoration: none; diff --git a/package.json b/package.json index 147a62cc5..3437bab4b 100644 --- a/package.json +++ b/package.json @@ -18,9 +18,10 @@ "dependencies": { "@atlaskit/button": "1.0.3", "@atlaskit/button-group": "1.0.0", + "@atlaskit/dropdown-menu": "1.1.12", "@atlaskit/field-text": "2.0.3", + "@atlaskit/icon": "6.0.0", "@atlaskit/modal-dialog": "1.2.4", - "@atlaskit/single-select": "1.6.1", "@atlaskit/tabs": "1.2.5", "@atlassian/aui": "6.0.6", "async": "0.9.0", diff --git a/react/features/device-selection/components/DeviceSelectionDialog.js b/react/features/device-selection/components/DeviceSelectionDialog.js index bb1fa4bbb..4eca98476 100644 --- a/react/features/device-selection/components/DeviceSelectionDialog.js +++ b/react/features/device-selection/components/DeviceSelectionDialog.js @@ -170,13 +170,7 @@ class DeviceSelectionDialog extends Component { onSubmit = { this._onSubmit } titleKey = 'deviceSelection.deviceSettings' >
-
-
- { this._renderSelectors() } -
- { this._renderAudioOutputPreview() } -
-
+
{ this._renderAudioInputPreview() }
+
+
+ { this._renderSelectors() } +
+ { this._renderAudioOutputPreview() } +
); @@ -543,6 +543,7 @@ class DeviceSelectionDialog extends Component { { devices: availableDevices.videoInput, hasPermission: this.props.hasVideoPermission, + icon: 'icon-camera', isDisabled: this.props.disableDeviceChange, key: 'videoInput', label: 'settings.selectCamera', @@ -552,6 +553,7 @@ class DeviceSelectionDialog extends Component { { devices: availableDevices.audioInput, hasPermission: this.props.hasAudioPermission, + icon: 'icon-microphone', isDisabled: this.props.disableAudioInputChange || this.props.disableDeviceChange, key: 'audioInput', @@ -566,6 +568,7 @@ class DeviceSelectionDialog extends Component { devices: availableDevices.audioOutput, hasPermission: this.props.hasAudioPermission || this.props.hasVideoPermission, + icon: 'icon-volume', isDisabled: this.props.disableDeviceChange, key: 'audioOutput', label: 'settings.selectAudioOutput', diff --git a/react/features/device-selection/components/DeviceSelector.js b/react/features/device-selection/components/DeviceSelector.js index 552306e51..827ae61c7 100644 --- a/react/features/device-selection/components/DeviceSelector.js +++ b/react/features/device-selection/components/DeviceSelector.js @@ -1,11 +1,15 @@ -import Select from '@atlaskit/single-select'; +import AKButton from '@atlaskit/button'; +import AKDropdownMenu from '@atlaskit/dropdown-menu'; +import ExpandIcon from '@atlaskit/icon/glyph/expand'; import React, { Component } from 'react'; import { translate } from '../../base/i18n'; +const EXPAND_ICON = ; + /** - * React component for selecting a device from a select element. Wraps Select - * with device selection specific logic. + * React component for selecting a device from a select element. Wraps + * AKDropdownMenu with device selection specific logic. * * @extends Component */ @@ -26,6 +30,11 @@ class DeviceSelector extends Component { */ hasPermission: React.PropTypes.bool, + /** + * CSS class for the icon to the left of the dropdown trigger. + */ + icon: React.PropTypes.string, + /** * If true, will render the selector disabled with a default selection. */ @@ -79,12 +88,12 @@ class DeviceSelector extends Component { return this._renderNoDevices(); } - const items = this.props.devices.map(this._createSelectItem); + const items = this.props.devices.map(this._createDropdownItem); const defaultSelected = items.find(item => item.value === this.props.selectedDeviceId ); - return this._createSelector({ + return this._createDropdown({ defaultSelected, isDisabled: this.props.isDisabled, items, @@ -93,14 +102,44 @@ class DeviceSelector extends Component { } /** - * Creates an object in the format expected by Select for an option element. + * Creates an AtlasKit Button. + * + * @param {string} buttonText - The text to display within the button. + * @private + * @returns {ReactElement} + */ + _createDropdownTrigger(buttonText) { + return ( + + { buttonText } + + ); + } + + /** + * Creates a ReactComponent for displaying an icon. + * + * @private + * @returns {ReactElement} + */ + _createDropdownIcon() { + return ( + + ); + } + + /** + * Creates an object in the format expected by AKDropdownMenu for an option. * * @param {MediaDeviceInfo} device - An object with a label and a deviceId. * @private * @returns {Object} The passed in media device description converted to a - * format recognized as a valid Select item. + * format recognized as a valid AKDropdownMenu item. */ - _createSelectItem(device) { + _createDropdownItem(device) { return { content: device.label, value: device.deviceId @@ -108,44 +147,49 @@ class DeviceSelector extends Component { } /** - * Creates a Select Component using passed in props and options. + * Creates a AKDropdownMenu Component using passed in props and options. * - * @param {Object} options - Additional configuration for display Select. + * @param {Object} options - Additional configuration for display. * @param {Object} options.defaultSelected - The option that should be set * as currently chosen. - * @param {boolean} options.isDisabled - If true Select will not open on - * click. + * @param {boolean} options.isDisabled - If true, AKDropdownMenu will not + * open on click. * @param {Array} options.items - All the selectable options to display. * @param {string} options.placeholder - The translation key to display when * no selection has been made. * @private * @returns {ReactElement} */ - _createSelector(options) { + _createDropdown(options) { + const triggerText + = (options.defaultSelected && options.defaultSelected.content) + || options.placeholder; + return ( -