feat(ui-components) Add button component (#11868)
This commit is contained in:
parent
718d32990d
commit
b08ed3ade4
|
@ -0,0 +1,4 @@
|
|||
declare module '*.svg' {
|
||||
const content: any;
|
||||
export default content;
|
||||
}
|
|
@ -17,7 +17,9 @@ module.exports = {
|
|||
'@typescript-eslint/no-empty-function': 'off',
|
||||
'@typescript-eslint/ban-types': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'no-prototype-builtins': 'off'
|
||||
'no-prototype-builtins': 'off',
|
||||
'no-shadow': 'off',
|
||||
'@typescript-eslint/no-shadow': [ 'error' ]
|
||||
},
|
||||
'plugins': [ '@typescript-eslint' ],
|
||||
'extends': [
|
||||
|
|
|
@ -0,0 +1,195 @@
|
|||
import { makeStyles } from '@material-ui/core';
|
||||
import clsx from 'clsx';
|
||||
import React from 'react';
|
||||
|
||||
import Icon from '../../icons/components/Icon';
|
||||
import { BUTTON_TYPES } from '../../react/constants';
|
||||
import { withPixelLineHeight } from '../../styles/functions.web';
|
||||
|
||||
import { ButtonProps } from './types';
|
||||
|
||||
interface IButtonProps extends ButtonProps {
|
||||
|
||||
/**
|
||||
* Whether or not the button should be full width.
|
||||
*/
|
||||
fullWidth?: boolean,
|
||||
|
||||
/**
|
||||
* The id of the button.
|
||||
*/
|
||||
id?: string;
|
||||
|
||||
/**
|
||||
* Click callback.
|
||||
*/
|
||||
onClick: () => void;
|
||||
|
||||
/**
|
||||
* Which size the button should be.
|
||||
*/
|
||||
size?: 'small' | 'medium' | 'large';
|
||||
}
|
||||
|
||||
const useStyles = makeStyles((theme: any) => {
|
||||
return {
|
||||
button: {
|
||||
backgroundColor: theme.palette.action01,
|
||||
color: theme.palette.text01,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
padding: '10px 16px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
border: 0,
|
||||
...withPixelLineHeight(theme.typography.bodyShortBold),
|
||||
transition: 'background .2s',
|
||||
cursor: 'pointer',
|
||||
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.action01Hover
|
||||
},
|
||||
|
||||
'&:active': {
|
||||
backgroundColor: theme.palette.action01Active
|
||||
},
|
||||
|
||||
'&:focus': {
|
||||
outline: 0,
|
||||
boxShadow: `0px 0px 0px 2px ${theme.palette.focus01}`
|
||||
},
|
||||
|
||||
'& svg': {
|
||||
fill: theme.palette.icon01
|
||||
}
|
||||
},
|
||||
|
||||
primary: {},
|
||||
|
||||
secondary: {
|
||||
backgroundColor: theme.palette.action02,
|
||||
color: theme.palette.text04,
|
||||
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.action02Hover
|
||||
},
|
||||
|
||||
'&:active': {
|
||||
backgroundColor: theme.palette.action02Active
|
||||
},
|
||||
|
||||
'& svg': {
|
||||
fill: theme.palette.icon04
|
||||
}
|
||||
},
|
||||
|
||||
tertiary: {
|
||||
backgroundColor: theme.palette.action03,
|
||||
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.action03Hover
|
||||
},
|
||||
|
||||
'&:active': {
|
||||
backgroundColor: theme.palette.action03Active
|
||||
}
|
||||
},
|
||||
|
||||
destructive: {
|
||||
backgroundColor: theme.palette.actionDanger,
|
||||
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.actionDangerHover
|
||||
},
|
||||
|
||||
'&:active': {
|
||||
backgroundColor: theme.palette.actionDangerActive
|
||||
}
|
||||
},
|
||||
|
||||
disabled: {
|
||||
backgroundColor: theme.palette.disabled01,
|
||||
color: theme.palette.text03,
|
||||
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.disabled01,
|
||||
color: theme.palette.text03
|
||||
},
|
||||
|
||||
'&:active': {
|
||||
backgroundColor: theme.palette.disabled01,
|
||||
color: theme.palette.text03
|
||||
},
|
||||
|
||||
'& svg': {
|
||||
fill: theme.palette.icon03
|
||||
}
|
||||
},
|
||||
|
||||
iconButton: {
|
||||
padding: '10px'
|
||||
},
|
||||
|
||||
textWithIcon: {
|
||||
marginLeft: `${theme.spacing(2)}px`
|
||||
},
|
||||
|
||||
small: {
|
||||
padding: '8px 16px',
|
||||
...withPixelLineHeight(theme.typography.labelBold),
|
||||
|
||||
'&.iconButton': {
|
||||
padding: '6px'
|
||||
}
|
||||
},
|
||||
|
||||
medium: {},
|
||||
|
||||
large: {
|
||||
padding: '13px 16px',
|
||||
...withPixelLineHeight(theme.typography.bodyShortBoldLarge),
|
||||
|
||||
'&.iconButton': {
|
||||
padding: '14px'
|
||||
}
|
||||
},
|
||||
|
||||
fullWidth: {
|
||||
width: '100%'
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
const Button = ({
|
||||
accessibilityLabel,
|
||||
disabled,
|
||||
fullWidth,
|
||||
icon,
|
||||
id,
|
||||
label,
|
||||
onClick,
|
||||
size = 'medium',
|
||||
type = BUTTON_TYPES.PRIMARY
|
||||
}: IButtonProps) => {
|
||||
const styles = useStyles();
|
||||
|
||||
return (
|
||||
<button
|
||||
aria-label = { accessibilityLabel }
|
||||
className = { clsx(styles.button, styles[type],
|
||||
disabled && styles.disabled,
|
||||
icon && !label && `${styles.iconButton} iconButton`,
|
||||
styles[size], fullWidth && styles.fullWidth) }
|
||||
disabled = { disabled }
|
||||
{ ...(id ? { id } : {}) }
|
||||
onClick = { onClick }
|
||||
type = 'button'>
|
||||
{icon && <Icon
|
||||
size = { 20 }
|
||||
src = { icon } />}
|
||||
{label && <span className = { icon ? styles.textWithIcon : '' }>{label}</span>}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
export default Button;
|
|
@ -0,0 +1,29 @@
|
|||
import { BUTTON_TYPES } from '../../react/constants';
|
||||
|
||||
export interface ButtonProps {
|
||||
|
||||
/**
|
||||
* Label used for accessibility.
|
||||
*/
|
||||
accessibilityLabel: string;
|
||||
|
||||
/**
|
||||
* Whether or not the button is disabled.
|
||||
*/
|
||||
disabled?: boolean;
|
||||
|
||||
/**
|
||||
* The icon to be displayed on the button.
|
||||
*/
|
||||
icon?: Function;
|
||||
|
||||
/**
|
||||
* The text to be displayed on the button.
|
||||
*/
|
||||
label?: string;
|
||||
|
||||
/**
|
||||
* The type of button to be displayed.
|
||||
*/
|
||||
type?: BUTTON_TYPES;
|
||||
}
|
|
@ -1,8 +1,10 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable import/order */
|
||||
import React, { useCallback } from 'react';
|
||||
|
||||
// @ts-ignore
|
||||
import { Container } from '../../react/base';
|
||||
|
||||
// @ts-ignore
|
||||
import { styleTypeToObject } from '../../styles';
|
||||
|
||||
type Props = {
|
||||
|
@ -15,7 +17,7 @@ type Props = {
|
|||
/**
|
||||
* Color of the icon (if not provided by the style object).
|
||||
*/
|
||||
color?: ?string,
|
||||
color?: string,
|
||||
|
||||
/**
|
||||
* Id prop (mainly for autotests).
|
||||
|
@ -35,7 +37,7 @@ type Props = {
|
|||
/**
|
||||
* The size of the icon (if not provided by the style object).
|
||||
*/
|
||||
size?: ?number | string,
|
||||
size?: number | string,
|
||||
|
||||
/**
|
||||
* The preloaded icon component to render.
|
||||
|
@ -110,7 +112,7 @@ export const DEFAULT_SIZE = navigator.product === 'ReactNative' ? 36 : 22;
|
|||
* Implements an Icon component that takes a loaded SVG file as prop and renders it as an icon.
|
||||
*
|
||||
* @param {Props} props - The props of the component.
|
||||
* @returns {Reactelement}
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
export default function Icon(props: Props) {
|
||||
const {
|
|
@ -1,5 +1,3 @@
|
|||
// @flow
|
||||
|
||||
export { default as IconAdd } from './add.svg';
|
||||
export { default as IconAddPeople } from './link.svg';
|
||||
export { default as IconArrowBack } from './arrow_back.svg';
|
|
@ -11,13 +11,13 @@ import {
|
|||
import BaseTheme from '../../../ui/components/BaseTheme.native';
|
||||
// @ts-ignore
|
||||
import { BUTTON_MODES, BUTTON_TYPES } from '../../constants';
|
||||
import { ButtonProps } from '../../types';
|
||||
import { IButtonProps } from '../../types';
|
||||
|
||||
// @ts-ignore
|
||||
import styles from './styles';
|
||||
|
||||
|
||||
const Button: React.FC<ButtonProps> = ({
|
||||
const Button: React.FC<IButtonProps> = ({
|
||||
accessibilityLabel,
|
||||
color: buttonColor,
|
||||
disabled,
|
||||
|
@ -27,7 +27,7 @@ const Button: React.FC<ButtonProps> = ({
|
|||
onPress,
|
||||
style,
|
||||
type
|
||||
}: ButtonProps) => {
|
||||
}: IButtonProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { CONTAINED } = BUTTON_MODES;
|
||||
const { DESTRUCTIVE, PRIMARY, SECONDARY, TERTIARY } = BUTTON_TYPES;
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
// @flow
|
||||
|
||||
/**
|
||||
* Z-index for components that are to be rendered like an overlay, to be over
|
||||
* everything, such as modal-type of components, or dialogs.
|
||||
|
@ -9,12 +7,12 @@ export const OVERLAY_Z_INDEX = 1000;
|
|||
/**
|
||||
* The types of the buttons.
|
||||
*/
|
||||
export const BUTTON_TYPES = {
|
||||
PRIMARY: 'primary',
|
||||
SECONDARY: 'secondary',
|
||||
TERTIARY: 'tertiary',
|
||||
DESTRUCTIVE: 'destructive'
|
||||
};
|
||||
export enum BUTTON_TYPES {
|
||||
PRIMARY = 'primary',
|
||||
SECONDARY = 'secondary',
|
||||
TERTIARY = 'tertiary',
|
||||
DESTRUCTIVE = 'destructive'
|
||||
}
|
||||
|
||||
/**
|
||||
* The modes of the buttons.
|
|
@ -1,13 +1,10 @@
|
|||
export interface ButtonProps {
|
||||
accessibilityLabel?: string;
|
||||
import { ButtonProps } from '../components/common/types';
|
||||
|
||||
export interface IButtonProps extends ButtonProps {
|
||||
color?: string;
|
||||
disabled?: boolean;
|
||||
icon?: JSX.Element;
|
||||
label?: string;
|
||||
labelStyle?: Object|undefined;
|
||||
onPress?: Function;
|
||||
style?: Object|undefined;
|
||||
type?: string;
|
||||
}
|
||||
|
||||
export interface IconButtonProps {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// @flow
|
||||
|
||||
import { type StyleType } from './functions.any';
|
||||
// @ts-ignore
|
||||
import { StyleType } from './functions.any';
|
||||
|
||||
// @ts-ignore
|
||||
export * from './functions.any';
|
||||
|
||||
/**
|
||||
|
@ -32,7 +32,7 @@ export function getFixedPlatformStyle(style: StyleType): StyleType {
|
|||
* @param {Object} base - The base object containing the `lineHeight` property.
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function withPixelLineHeight(base: Object): Object {
|
||||
export function withPixelLineHeight(base: any): Object {
|
||||
return {
|
||||
...base,
|
||||
lineHeight: `${base.lineHeight}px`
|
|
@ -1,36 +1,27 @@
|
|||
// @flow
|
||||
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
/* eslint-disable lines-around-comment */
|
||||
import React, { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
import Button from '../../../../../base/components/common/Button';
|
||||
import { BUTTON_TYPES } from '../../../../../base/react/constants';
|
||||
// @ts-ignore
|
||||
import { createBreakoutRoom } from '../../../../../breakout-rooms/actions';
|
||||
import ParticipantPaneBaseButton from '../../../web/ParticipantPaneBaseButton';
|
||||
|
||||
const useStyles = makeStyles(() => {
|
||||
return {
|
||||
button: {
|
||||
width: '100%'
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
export const AddBreakoutRoomButton = () => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
const styles = useStyles();
|
||||
|
||||
const onAdd = useCallback(() =>
|
||||
dispatch(createBreakoutRoom())
|
||||
, [ dispatch ]);
|
||||
|
||||
return (
|
||||
<ParticipantPaneBaseButton
|
||||
<Button
|
||||
accessibilityLabel = { t('breakoutRooms.actions.add') }
|
||||
className = { styles.button }
|
||||
onClick = { onAdd }>
|
||||
{t('breakoutRooms.actions.add')}
|
||||
</ParticipantPaneBaseButton>
|
||||
fullWidth = { true }
|
||||
label = { t('breakoutRooms.actions.add') }
|
||||
onClick = { onAdd }
|
||||
type = { BUTTON_TYPES.SECONDARY } />
|
||||
);
|
||||
};
|
|
@ -1,42 +0,0 @@
|
|||
// @flow
|
||||
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
import { autoAssignToBreakoutRooms } from '../../../../../breakout-rooms/actions';
|
||||
import ParticipantPaneBaseButton from '../../../web/ParticipantPaneBaseButton';
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
return {
|
||||
button: {
|
||||
color: theme.palette.link01,
|
||||
width: '100%',
|
||||
backgroundColor: 'transparent',
|
||||
|
||||
'&:hover': {
|
||||
backgroundColor: 'transparent'
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
export const AutoAssignButton = () => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
const styles = useStyles();
|
||||
|
||||
const onAutoAssign = useCallback(() => {
|
||||
dispatch(autoAssignToBreakoutRooms());
|
||||
}, [ dispatch ]);
|
||||
|
||||
return (
|
||||
<ParticipantPaneBaseButton
|
||||
accessibilityLabel = { t('breakoutRooms.actions.autoAssign') }
|
||||
className = { styles.button }
|
||||
onClick = { onAutoAssign }>
|
||||
{t('breakoutRooms.actions.autoAssign')}
|
||||
</ParticipantPaneBaseButton>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,27 @@
|
|||
/* eslint-disable lines-around-comment */
|
||||
import React, { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
import Button from '../../../../../base/components/common/Button';
|
||||
import { BUTTON_TYPES } from '../../../../../base/react/constants';
|
||||
// @ts-ignore
|
||||
import { autoAssignToBreakoutRooms } from '../../../../../breakout-rooms/actions';
|
||||
|
||||
export const AutoAssignButton = () => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const onAutoAssign = useCallback(() => {
|
||||
dispatch(autoAssignToBreakoutRooms());
|
||||
}, [ dispatch ]);
|
||||
|
||||
return (
|
||||
<Button
|
||||
accessibilityLabel = { t('breakoutRooms.actions.autoAssign') }
|
||||
fullWidth = { true }
|
||||
label = { t('breakoutRooms.actions.autoAssign') }
|
||||
onClick = { onAutoAssign }
|
||||
type = { BUTTON_TYPES.TERTIARY } />
|
||||
);
|
||||
};
|
|
@ -1,44 +0,0 @@
|
|||
// @flow
|
||||
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
import { createBreakoutRoomsEvent, sendAnalytics } from '../../../../../analytics';
|
||||
import { moveToRoom } from '../../../../../breakout-rooms/actions';
|
||||
import ParticipantPaneBaseButton from '../../../web/ParticipantPaneBaseButton';
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
return {
|
||||
button: {
|
||||
color: theme.palette.textError,
|
||||
backgroundColor: 'transparent',
|
||||
width: '100%',
|
||||
|
||||
'&:hover': {
|
||||
backgroundColor: 'transparent'
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
export const LeaveButton = () => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
const styles = useStyles();
|
||||
|
||||
const onLeave = useCallback(() => {
|
||||
sendAnalytics(createBreakoutRoomsEvent('leave'));
|
||||
dispatch(moveToRoom());
|
||||
}, [ dispatch ]);
|
||||
|
||||
return (
|
||||
<ParticipantPaneBaseButton
|
||||
accessibilityLabel = { t('breakoutRooms.actions.leaveBreakoutRoom') }
|
||||
className = { styles.button }
|
||||
onClick = { onLeave }>
|
||||
{t('breakoutRooms.actions.leaveBreakoutRoom')}
|
||||
</ParticipantPaneBaseButton>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,30 @@
|
|||
/* eslint-disable lines-around-comment */
|
||||
import React, { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
// @ts-ignore
|
||||
import { createBreakoutRoomsEvent, sendAnalytics } from '../../../../../analytics';
|
||||
import Button from '../../../../../base/components/common/Button';
|
||||
import { BUTTON_TYPES } from '../../../../../base/react/constants';
|
||||
// @ts-ignore
|
||||
import { moveToRoom } from '../../../../../breakout-rooms/actions';
|
||||
|
||||
export const LeaveButton = () => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const onLeave = useCallback(() => {
|
||||
sendAnalytics(createBreakoutRoomsEvent('leave'));
|
||||
dispatch(moveToRoom());
|
||||
}, [ dispatch ]);
|
||||
|
||||
return (
|
||||
<Button
|
||||
accessibilityLabel = { t('breakoutRooms.actions.leaveBreakoutRoom') }
|
||||
fullWidth = { true }
|
||||
label = { t('breakoutRooms.actions.leaveBreakoutRoom') }
|
||||
onClick = { onLeave }
|
||||
type = { BUTTON_TYPES.DESTRUCTIVE } />
|
||||
);
|
||||
};
|
|
@ -1,57 +0,0 @@
|
|||
// @flow
|
||||
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import React from 'react';
|
||||
|
||||
import ParticipantPaneBaseButton from './ParticipantPaneBaseButton';
|
||||
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* Label used for accessibility.
|
||||
*/
|
||||
accessibilityLabel: String,
|
||||
|
||||
/**
|
||||
* Children of the component.
|
||||
*/
|
||||
children: string | React$Node,
|
||||
|
||||
/**
|
||||
* Button id.
|
||||
*/
|
||||
id?: string,
|
||||
|
||||
/**
|
||||
* Whether or not the button is icon button (no text).
|
||||
*/
|
||||
isIconButton?: boolean,
|
||||
|
||||
/**
|
||||
* Click handler.
|
||||
*/
|
||||
onClick: Function
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
return {
|
||||
button: {
|
||||
padding: `${theme.spacing(2)}px`
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
const FooterButton = ({ accessibilityLabel, children, id, isIconButton = false, onClick }: Props) => {
|
||||
const styles = useStyles();
|
||||
|
||||
return (<ParticipantPaneBaseButton
|
||||
accessibilityLabel = { accessibilityLabel }
|
||||
className = { isIconButton ? styles.button : '' }
|
||||
id = { id }
|
||||
onClick = { onClick }>
|
||||
{children}
|
||||
</ParticipantPaneBaseButton>
|
||||
);
|
||||
};
|
||||
|
||||
export default FooterButton;
|
|
@ -1,48 +0,0 @@
|
|||
// @flow
|
||||
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
import { createToolbarEvent, sendAnalytics } from '../../../analytics';
|
||||
import { Icon, IconInviteMore } from '../../../base/icons';
|
||||
import { beginAddPeople } from '../../../invite';
|
||||
|
||||
import ParticipantPaneBaseButton from './ParticipantPaneBaseButton';
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
return {
|
||||
button: {
|
||||
width: '100%',
|
||||
|
||||
'& > *:not(:last-child)': {
|
||||
marginRight: `${theme.spacing(2)}px`
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
export const InviteButton = () => {
|
||||
const dispatch = useDispatch();
|
||||
const { t } = useTranslation();
|
||||
const styles = useStyles();
|
||||
|
||||
const onInvite = useCallback(() => {
|
||||
sendAnalytics(createToolbarEvent('invite'));
|
||||
dispatch(beginAddPeople());
|
||||
}, [ dispatch ]);
|
||||
|
||||
return (
|
||||
<ParticipantPaneBaseButton
|
||||
accessibilityLabel = { t('participantsPane.actions.invite') }
|
||||
className = { styles.button }
|
||||
onClick = { onInvite }
|
||||
primary = { true }>
|
||||
<Icon
|
||||
size = { 20 }
|
||||
src = { IconInviteMore } />
|
||||
<span>{t('participantsPane.actions.invite')}</span>
|
||||
</ParticipantPaneBaseButton>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,32 @@
|
|||
/* eslint-disable lines-around-comment */
|
||||
import React, { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
// @ts-ignore
|
||||
import { createToolbarEvent, sendAnalytics } from '../../../analytics';
|
||||
import Button from '../../../base/components/common/Button';
|
||||
import { IconInviteMore } from '../../../base/icons/svg/index';
|
||||
import { BUTTON_TYPES } from '../../../base/react/constants';
|
||||
// @ts-ignore
|
||||
import { beginAddPeople } from '../../../invite';
|
||||
|
||||
export const InviteButton = () => {
|
||||
const dispatch = useDispatch();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const onInvite = useCallback(() => {
|
||||
sendAnalytics(createToolbarEvent('invite'));
|
||||
dispatch(beginAddPeople());
|
||||
}, [ dispatch ]);
|
||||
|
||||
return (
|
||||
<Button
|
||||
accessibilityLabel = { t('participantsPane.actions.invite') }
|
||||
fullWidth = { true }
|
||||
icon = { IconInviteMore }
|
||||
label = { t('participantsPane.actions.invite') }
|
||||
onClick = { onInvite }
|
||||
type = { BUTTON_TYPES.PRIMARY } />
|
||||
);
|
||||
};
|
|
@ -1,98 +0,0 @@
|
|||
// @flow
|
||||
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import React from 'react';
|
||||
|
||||
import participantsPaneTheme from '../../../base/components/themes/participantsPaneTheme.json';
|
||||
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* Label used for accessibility.
|
||||
*/
|
||||
accessibilityLabel: String,
|
||||
|
||||
/**
|
||||
* Additional class name for custom styles.
|
||||
*/
|
||||
className?: string,
|
||||
|
||||
/**
|
||||
* Children of the component.
|
||||
*/
|
||||
children: string | React$Node,
|
||||
|
||||
/**
|
||||
* Button id.
|
||||
*/
|
||||
id?: string,
|
||||
|
||||
/**
|
||||
* Click handler.
|
||||
*/
|
||||
onClick: Function,
|
||||
|
||||
/**
|
||||
* Whether or not the button should have primary button style.
|
||||
*/
|
||||
primary?: boolean
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
return {
|
||||
button: {
|
||||
alignItems: 'center',
|
||||
backgroundColor: theme.palette.ui03,
|
||||
border: 0,
|
||||
borderRadius: `${theme.shape.borderRadius}px`,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
minHeight: '40px',
|
||||
padding: `${theme.spacing(2)}px ${theme.spacing(3)}px`,
|
||||
...theme.typography.labelButton,
|
||||
lineHeight: `${theme.typography.labelButton.lineHeight}px`,
|
||||
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.ui04
|
||||
},
|
||||
|
||||
[`@media (max-width: ${participantsPaneTheme.MD_BREAKPOINT})`]: {
|
||||
...theme.typography.labelButtonLarge,
|
||||
lineHeight: `${theme.typography.labelButtonLarge.lineHeight}px`,
|
||||
minWidth: '48px',
|
||||
minHeight: '48px'
|
||||
}
|
||||
},
|
||||
|
||||
buttonPrimary: {
|
||||
backgroundColor: theme.palette.action01,
|
||||
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.action01Hover
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
const ParticipantPaneBaseButton = ({
|
||||
accessibilityLabel,
|
||||
className,
|
||||
children,
|
||||
id,
|
||||
onClick,
|
||||
primary = false
|
||||
}: Props) => {
|
||||
const styles = useStyles();
|
||||
|
||||
return (
|
||||
<button
|
||||
aria-label = { accessibilityLabel }
|
||||
className = { `${styles.button} ${primary ? styles.buttonPrimary : ''} ${className ?? ''}` }
|
||||
id = { id }
|
||||
onClick = { onClick }>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
export default ParticipantPaneBaseButton;
|
|
@ -3,11 +3,13 @@
|
|||
import { withStyles } from '@material-ui/core';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import Button from '../../../base/components/common/Button';
|
||||
import participantsPaneTheme from '../../../base/components/themes/participantsPaneTheme.json';
|
||||
import { openDialog } from '../../../base/dialog';
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { Icon, IconClose, IconHorizontalPoints } from '../../../base/icons';
|
||||
import { isLocalParticipantModerator } from '../../../base/participants/functions';
|
||||
import { BUTTON_TYPES } from '../../../base/react/constants';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { isAddBreakoutRoomButtonVisible } from '../../../breakout-rooms/functions';
|
||||
import { MuteEveryoneDialog } from '../../../video-menu/components/';
|
||||
|
@ -21,7 +23,6 @@ import {
|
|||
import { AddBreakoutRoomButton } from '../breakout-rooms/components/web/AddBreakoutRoomButton';
|
||||
import { RoomList } from '../breakout-rooms/components/web/RoomList';
|
||||
|
||||
import FooterButton from './FooterButton';
|
||||
import { FooterContextMenu } from './FooterContextMenu';
|
||||
import LobbyParticipants from './LobbyParticipants';
|
||||
import MeetingParticipants from './MeetingParticipants';
|
||||
|
@ -258,21 +259,20 @@ class ParticipantsPane extends Component<Props, State> {
|
|||
{_showFooter && (
|
||||
<div className = { classes.footer }>
|
||||
{_showMuteAllButton && (
|
||||
<FooterButton
|
||||
<Button
|
||||
accessibilityLabel = { t('participantsPane.actions.muteAll') }
|
||||
onClick = { this._onMuteAll }>
|
||||
{t('participantsPane.actions.muteAll')}
|
||||
</FooterButton>
|
||||
label = { t('participantsPane.actions.muteAll') }
|
||||
onClick = { this._onMuteAll }
|
||||
type = { BUTTON_TYPES.SECONDARY } />
|
||||
)}
|
||||
{_showMoreActionsButton && (
|
||||
<div className = { classes.footerMoreContainer }>
|
||||
<FooterButton
|
||||
<Button
|
||||
accessibilityLabel = { t('participantsPane.actions.moreModerationActions') }
|
||||
icon = { IconHorizontalPoints }
|
||||
id = 'participants-pane-context-menu'
|
||||
isIconButton = { true }
|
||||
onClick = { this._onToggleContext }>
|
||||
<Icon src = { IconHorizontalPoints } />
|
||||
</FooterButton>
|
||||
onClick = { this._onToggleContext }
|
||||
type = { BUTTON_TYPES.SECONDARY } />
|
||||
<FooterContextMenu
|
||||
isOpen = { contextOpen }
|
||||
onDrawerClose = { this._onDrawerClose }
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"include": ["react/features/**/*.ts", "react/features/**/*.tsx"],
|
||||
"include": ["react/features/**/*.ts", "react/features/**/*.tsx", "./custom.d.ts"],
|
||||
"compilerOptions": {
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"module": "es6",
|
||||
|
|
Loading…
Reference in New Issue