feat(ui-components) Add toggle component (#11933)

This commit is contained in:
Robert Pintilii 2022-08-02 13:31:11 +03:00 committed by GitHub
parent 3e66e0009d
commit db54c45b13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 142 additions and 24 deletions

View File

@ -0,0 +1,117 @@
import { makeStyles } from '@material-ui/core';
import clsx from 'clsx';
import React, { useCallback } from 'react';
import { isMobileBrowser } from '../../../environment/utils';
interface SwitchProps {
/**
* Whether or not the toggle is on.
*/
checked: boolean;
/**
* Whether or not the toggle is disabled.
*/
disabled?: boolean;
/**
* Id of the toggle.
*/
id?: string;
/**
* Toggle change callback.
*/
onChange: (on?: boolean) => void;
}
const useStyles = makeStyles((theme: any) => {
return {
container: {
position: 'relative',
backgroundColor: theme.palette.ui05,
borderRadius: '12px',
width: '40px',
height: '24px',
border: 0,
outline: 0,
cursor: 'pointer',
transition: '.3s',
display: 'inline-block',
'&.disabled': {
backgroundColor: theme.palette.ui05,
cursor: 'default',
'& .toggle': {
backgroundColor: theme.palette.ui03
}
},
'&.is-mobile': {
height: '32px',
width: '50px',
borderRadius: '32px'
}
},
containerOn: {
backgroundColor: theme.palette.action01
},
toggle: {
width: '16px',
height: '16px',
position: 'absolute',
top: '4px',
left: '4px',
backgroundColor: theme.palette.ui10,
borderRadius: '100%',
transition: '.3s',
'&.is-mobile': {
width: '24px',
height: '24px'
}
},
toggleOn: {
left: '20px',
'&.is-mobile': {
left: '22px'
}
},
checkbox: {
height: 0,
width: 0
}
};
});
const Switch = ({ id, checked, disabled, onChange }: SwitchProps) => {
const styles = useStyles();
const isMobile = isMobileBrowser();
const change = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
onChange(e.target.checked);
}, []);
return (<label
className = { clsx('toggle-container', styles.container, checked && styles.containerOn,
isMobile && 'is-mobile', disabled && 'disabled') }>
<input
type = 'checkbox'
{ ...(id ? { id } : {}) }
checked = { checked }
className = { styles.checkbox }
disabled = { disabled }
onChange = { change } />
<div className = { clsx('toggle', styles.toggle, checked && styles.toggleOn, isMobile && 'is-mobile') } />
</label>);
};
export default Switch;

View File

@ -1,14 +1,18 @@
/* @flow */ /* eslint-disable lines-around-comment */
import React, { Component } from 'react'; import React, { Component } from 'react';
import type { Dispatch } from 'redux'; import type { Dispatch } from 'redux';
// @ts-ignore
import { createE2EEEvent, sendAnalytics } from '../../analytics'; import { createE2EEEvent, sendAnalytics } from '../../analytics';
// @ts-ignore
import { translate } from '../../base/i18n'; import { translate } from '../../base/i18n';
import { Switch } from '../../base/react'; import { connect } from '../../base/redux/functions';
import { connect } from '../../base/redux'; import Switch from '../../base/ui/components/web/Switch';
// @ts-ignore
import { toggleE2EE } from '../actions'; import { toggleE2EE } from '../actions';
// @ts-ignore
import { MAX_MODE } from '../constants'; import { MAX_MODE } from '../constants';
// @ts-ignore
import { doesEveryoneSupportE2EE } from '../functions'; import { doesEveryoneSupportE2EE } from '../functions';
type Props = { type Props = {
@ -21,7 +25,7 @@ type Props = {
/** /**
* Custom e2ee labels. * Custom e2ee labels.
*/ */
_e2eeLabels: Object, _e2eeLabels: any,
/** /**
* Whether the switch is currently enabled or not. * Whether the switch is currently enabled or not.
@ -69,7 +73,7 @@ class E2EESection extends Component<Props, State> {
* *
* @inheritdoc * @inheritdoc
*/ */
static getDerivedStateFromProps(props: Props, state: Object) { static getDerivedStateFromProps(props: Props, state: State) {
if (props._toggled !== state.toggled) { if (props._toggled !== state.toggled) {
return { return {
@ -124,17 +128,15 @@ class E2EESection extends Component<Props, State> {
{ label } { label }
</label> </label>
<Switch <Switch
checked = { toggled }
disabled = { !_enabled } disabled = { !_enabled }
id = 'e2ee-section-switch' id = 'e2ee-section-switch'
onValueChange = { this._onToggle } onChange = { this._onToggle } />
value = { toggled } />
</div> </div>
</div> </div>
); );
} }
_onToggle: () => void;
/** /**
* Callback to be invoked when the user toggles E2EE on or off. * Callback to be invoked when the user toggles E2EE on or off.
* *
@ -160,11 +162,11 @@ class E2EESection extends Component<Props, State> {
* @private * @private
* @returns {Props} * @returns {Props}
*/ */
function mapStateToProps(state) { function mapStateToProps(state: any) {
const { enabled: e2eeEnabled, maxMode } = state['features/e2ee']; const { enabled: e2eeEnabled, maxMode } = state['features/e2ee'];
const { e2eeLabels } = state['features/base/config']; const { e2eeLabels } = state['features/base/config'];
let descriptionResource = ''; let descriptionResource: string|undefined = '';
if (e2eeLabels) { if (e2eeLabels) {
// When e2eeLabels are present, the descriptionResouse is ignored. // When e2eeLabels are present, the descriptionResouse is ignored.

View File

@ -1,12 +1,15 @@
// @flow /* eslint-disable lines-around-comment */
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
// @ts-ignore
import { translate } from '../../../base/i18n'; import { translate } from '../../../base/i18n';
// @ts-ignore
import { isLocalParticipantModerator } from '../../../base/participants'; import { isLocalParticipantModerator } from '../../../base/participants';
import { Switch } from '../../../base/react'; import { connect } from '../../../base/redux/functions';
import { connect } from '../../../base/redux'; import Switch from '../../../base/ui/components/web/Switch';
// @ts-ignore
import { isInBreakoutRoom } from '../../../breakout-rooms/functions'; import { isInBreakoutRoom } from '../../../breakout-rooms/functions';
// @ts-ignore
import { toggleLobbyMode } from '../../actions'; import { toggleLobbyMode } from '../../actions';
type Props = { type Props = {
@ -64,7 +67,7 @@ class LobbySection extends PureComponent<Props, State> {
* *
* @inheritdoc * @inheritdoc
*/ */
static getDerivedStateFromProps(props: Props, state: Object) { static getDerivedStateFromProps(props: Props, state: State) {
if (props._lobbyEnabled !== state.lobbyEnabled) { if (props._lobbyEnabled !== state.lobbyEnabled) {
return { return {
@ -100,9 +103,9 @@ class LobbySection extends PureComponent<Props, State> {
{ t('lobby.toggleLabel') } { t('lobby.toggleLabel') }
</label> </label>
<Switch <Switch
checked = { this.state.lobbyEnabled }
id = 'lobby-section-switch' id = 'lobby-section-switch'
onValueChange = { this._onToggleLobby } onChange = { this._onToggleLobby } />
value = { this.state.lobbyEnabled } />
</div> </div>
</div> </div>
<div className = 'separator-line' /> <div className = 'separator-line' />
@ -110,8 +113,6 @@ class LobbySection extends PureComponent<Props, State> {
); );
} }
_onToggleLobby: () => void;
/** /**
* Callback to be invoked when the user toggles the lobby feature on or off. * Callback to be invoked when the user toggles the lobby feature on or off.
* *
@ -134,14 +135,12 @@ class LobbySection extends PureComponent<Props, State> {
* @param {Object} state - The Redux state. * @param {Object} state - The Redux state.
* @returns {Props} * @returns {Props}
*/ */
function mapStateToProps(state: Object): $Shape<Props> { function mapStateToProps(state: any): Partial<Props> {
const { conference } = state['features/base/conference']; const { conference } = state['features/base/conference'];
const { hideLobbyButton } = state['features/base/config']; const { hideLobbyButton } = state['features/base/config'];
return { return {
_lobbyEnabled: state['features/lobby'].lobbyEnabled, _lobbyEnabled: state['features/lobby'].lobbyEnabled,
// $FlowExpectedError
_visible: conference?.isLobbySupported() && isLocalParticipantModerator(state) _visible: conference?.isLobbySupported() && isLocalParticipantModerator(state)
&& !hideLobbyButton && !isInBreakoutRoom(state) && !hideLobbyButton && !isInBreakoutRoom(state)
}; };