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 type { Dispatch } from 'redux';
// @ts-ignore
import { createE2EEEvent, sendAnalytics } from '../../analytics';
// @ts-ignore
import { translate } from '../../base/i18n';
import { Switch } from '../../base/react';
import { connect } from '../../base/redux';
import { connect } from '../../base/redux/functions';
import Switch from '../../base/ui/components/web/Switch';
// @ts-ignore
import { toggleE2EE } from '../actions';
// @ts-ignore
import { MAX_MODE } from '../constants';
// @ts-ignore
import { doesEveryoneSupportE2EE } from '../functions';
type Props = {
@ -21,7 +25,7 @@ type Props = {
/**
* Custom e2ee labels.
*/
_e2eeLabels: Object,
_e2eeLabels: any,
/**
* Whether the switch is currently enabled or not.
@ -69,7 +73,7 @@ class E2EESection extends Component<Props, State> {
*
* @inheritdoc
*/
static getDerivedStateFromProps(props: Props, state: Object) {
static getDerivedStateFromProps(props: Props, state: State) {
if (props._toggled !== state.toggled) {
return {
@ -124,17 +128,15 @@ class E2EESection extends Component<Props, State> {
{ label }
</label>
<Switch
checked = { toggled }
disabled = { !_enabled }
id = 'e2ee-section-switch'
onValueChange = { this._onToggle }
value = { toggled } />
onChange = { this._onToggle } />
</div>
</div>
);
}
_onToggle: () => void;
/**
* Callback to be invoked when the user toggles E2EE on or off.
*
@ -160,11 +162,11 @@ class E2EESection extends Component<Props, State> {
* @private
* @returns {Props}
*/
function mapStateToProps(state) {
function mapStateToProps(state: any) {
const { enabled: e2eeEnabled, maxMode } = state['features/e2ee'];
const { e2eeLabels } = state['features/base/config'];
let descriptionResource = '';
let descriptionResource: string|undefined = '';
if (e2eeLabels) {
// 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';
// @ts-ignore
import { translate } from '../../../base/i18n';
// @ts-ignore
import { isLocalParticipantModerator } from '../../../base/participants';
import { Switch } from '../../../base/react';
import { connect } from '../../../base/redux';
import { connect } from '../../../base/redux/functions';
import Switch from '../../../base/ui/components/web/Switch';
// @ts-ignore
import { isInBreakoutRoom } from '../../../breakout-rooms/functions';
// @ts-ignore
import { toggleLobbyMode } from '../../actions';
type Props = {
@ -64,7 +67,7 @@ class LobbySection extends PureComponent<Props, State> {
*
* @inheritdoc
*/
static getDerivedStateFromProps(props: Props, state: Object) {
static getDerivedStateFromProps(props: Props, state: State) {
if (props._lobbyEnabled !== state.lobbyEnabled) {
return {
@ -100,9 +103,9 @@ class LobbySection extends PureComponent<Props, State> {
{ t('lobby.toggleLabel') }
</label>
<Switch
checked = { this.state.lobbyEnabled }
id = 'lobby-section-switch'
onValueChange = { this._onToggleLobby }
value = { this.state.lobbyEnabled } />
onChange = { this._onToggleLobby } />
</div>
</div>
<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.
*
@ -134,14 +135,12 @@ class LobbySection extends PureComponent<Props, State> {
* @param {Object} state - The Redux state.
* @returns {Props}
*/
function mapStateToProps(state: Object): $Shape<Props> {
function mapStateToProps(state: any): Partial<Props> {
const { conference } = state['features/base/conference'];
const { hideLobbyButton } = state['features/base/config'];
return {
_lobbyEnabled: state['features/lobby'].lobbyEnabled,
// $FlowExpectedError
_visible: conference?.isLobbySupported() && isLocalParticipantModerator(state)
&& !hideLobbyButton && !isInBreakoutRoom(state)
};