mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2026-05-19 05:27:51 +00:00
feat(ui-components) Add button component (#11868)
This commit is contained in:
195
react/features/base/components/common/Button.tsx
Normal file
195
react/features/base/components/common/Button.tsx
Normal file
@@ -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;
|
||||
29
react/features/base/components/common/types.ts
Normal file
29
react/features/base/components/common/types.ts
Normal file
@@ -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.
|
||||
@@ -82,12 +84,12 @@ type Props = {
|
||||
*/
|
||||
ariaControls?: string,
|
||||
|
||||
/**
|
||||
/**
|
||||
* TabIndex for the Icon.
|
||||
*/
|
||||
tabIndex?: number,
|
||||
|
||||
/**
|
||||
/**
|
||||
* Role for the Icon.
|
||||
*/
|
||||
role?: string,
|
||||
@@ -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`
|
||||
Reference in New Issue
Block a user