Fine-tune appearance of buttons in calling interface UI
GitLab: #97
Change-Id: Iecf16921171196547e2a392ba6826971ca23ac47
diff --git a/client/src/components/Button.tsx b/client/src/components/Button.tsx
index 8e695cb..268cab6 100644
--- a/client/src/components/Button.tsx
+++ b/client/src/components/Button.tsx
@@ -106,86 +106,102 @@
};
export type ExpandableButtonProps = IconButtonProps & {
+ hidden?: boolean;
Icon?: ComponentType<SvgIconProps>;
expandMenuOptions?: (ExpandMenuOption | ExpandMenuRadioOption)[];
+ IconButtonComp?: ComponentType<IconButtonProps>;
};
-export const ExpandableButton = styled(({ Icon, expandMenuOptions = [], ...props }: ExpandableButtonProps) => {
+export const ExpandableButton = ({
+ hidden,
+ Icon,
+ expandMenuOptions = undefined,
+ IconButtonComp = IconButton,
+ ...props
+}: ExpandableButtonProps) => {
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const handleClose = () => {
setAnchorEl(null);
};
- const hasExpandMenuOptions = expandMenuOptions.length > 0;
return (
<Box>
- <Menu
- anchorEl={anchorEl}
- open={!!anchorEl}
- onClose={handleClose}
- anchorOrigin={{
- vertical: 'top',
- horizontal: 'center',
- }}
- transformOrigin={{
- vertical: 'bottom',
- horizontal: 'center',
- }}
- >
- {expandMenuOptions.map((option, id) => {
- if ('options' in option) {
- const { options, defaultSelectedOption } = option;
- return (
- <RadioGroup key={id} defaultValue={defaultSelectedOption}>
- {options.map(({ description, key }) => {
- return (
- <MenuItem key={key}>
- <ListItemIcon>
- <Radio value={key} />
- </ListItemIcon>
- <ListItemText>{description}</ListItemText>
- </MenuItem>
- );
- })}
- </RadioGroup>
- );
- }
+ {expandMenuOptions && (
+ <Menu
+ anchorEl={anchorEl}
+ open={!!anchorEl}
+ onClose={handleClose}
+ anchorOrigin={{
+ vertical: !hidden ? 'top' : 'center',
+ horizontal: !hidden ? 'center' : 'left',
+ }}
+ transformOrigin={{
+ vertical: !hidden ? 'bottom' : 'center',
+ horizontal: !hidden ? 'center' : 'right',
+ }}
+ >
+ {expandMenuOptions?.map((option, id) => {
+ if ('options' in option) {
+ const { options, defaultSelectedOption } = option;
+ return (
+ <RadioGroup key={id} defaultValue={defaultSelectedOption}>
+ {options.map(({ description, key }) => {
+ return (
+ <MenuItem key={key}>
+ <ListItemIcon>
+ <Radio value={key} />
+ </ListItemIcon>
+ <ListItemText>{description}</ListItemText>
+ </MenuItem>
+ );
+ })}
+ </RadioGroup>
+ );
+ }
- return (
- <MenuItem key={id} onClick={handleClose}>
- <ListItemIcon>{option.icon}</ListItemIcon>
- <ListItemText>{option.description}</ListItemText>
- </MenuItem>
- );
- })}
- </Menu>
- <Box position="relative">
- {hasExpandMenuOptions && (
+ return (
+ <MenuItem key={id} onClick={handleClose}>
+ <ListItemIcon>{option.icon}</ListItemIcon>
+ <ListItemText>{option.description}</ListItemText>
+ </MenuItem>
+ );
+ })}
+ </Menu>
+ )}
+ <Box
+ position="relative"
+ display="flex"
+ justifyContent="center"
+ alignItems="center"
+ onClick={(e) => setAnchorEl(e.currentTarget)}
+ >
+ {expandMenuOptions && (
<IconButton
{...props}
- onClick={(e) => setAnchorEl(e.currentTarget)}
aria-label="expand options"
size="small"
sx={{
+ transform: !hidden ? 'scale(0.5)' : 'scale(0.5) rotate(-90deg)',
position: 'absolute',
- left: 0,
- right: 0,
- top: '-50%',
- color: 'white',
+ top: !hidden ? '-50%' : 0,
+ left: hidden ? '-50%' : 0,
+ width: '100%',
+ height: '100%',
}}
>
- <ExpandLessIcon sx={{ backgroundColor: '#555555', borderRadius: '5px' }} />
+ <ExpandLessIcon
+ sx={{
+ backgroundColor: '#444444',
+ borderRadius: '5px',
+ }}
+ />
</IconButton>
)}
- <IconButton {...props} disableRipple={true}>
- {Icon && <Icon fontSize="inherit" />}
- </IconButton>
+ <IconButtonComp {...props}>{Icon && <Icon />}</IconButtonComp>
</Box>
</Box>
);
-})(({ theme }) => ({
- color: 'white',
-}));
+};
export const CancelPictureButton = (props: IconButtonProps) => {
return <RoundButton {...props} aria-label="remove picture" Icon={CancelIcon} size="large" />;
@@ -273,6 +289,10 @@
return (
<IconButton
{...props}
+ sx={{
+ color: selected ? 'white' : 'red',
+ ...props.sx,
+ }}
onClick={() => {
toggle();
}}
diff --git a/client/src/components/CallButtons.tsx b/client/src/components/CallButtons.tsx
index 8c1660d..2392c00 100644
--- a/client/src/components/CallButtons.tsx
+++ b/client/src/components/CallButtons.tsx
@@ -16,11 +16,12 @@
* <https://www.gnu.org/licenses/>.
*/
+import { styled } from '@mui/material/styles';
import React, { useContext } from 'react';
import { Trans } from 'react-i18next';
import { WebRTCContext } from '../contexts/WebRTCProvider';
-import { ExpandableButton, ExpandableButtonProps, ToggleIconButton, ToggleIconButtonProps } from './Button';
+import { ExpandableButton, ExpandableButtonProps, ToggleIconButton } from './Button';
import {
CallEndIcon,
ChatBubbleIcon,
@@ -38,39 +39,59 @@
VideoCameraIcon,
VideoCameraOffIcon,
VolumeIcon,
+ WindowIcon,
} from './SvgIcon';
+const CallButton = styled((props: ExpandableButtonProps) => {
+ return <ExpandableButton {...props} />;
+})({
+ '&:hover': {
+ backgroundColor: 'rgba(255, 255, 255, 0.15)',
+ },
+ color: 'white',
+});
+
+const ColoredCallButton = styled((props: ExpandableButtonProps) => {
+ return <ExpandableButton {...props} />;
+})({
+ color: 'white',
+ backgroundColor: '#a30000',
+ '&:hover': {
+ backgroundColor: '#ff0000',
+ },
+});
+
export const CallingChatButton = (props: ExpandableButtonProps) => {
- return <ExpandableButton aria-label="chat" Icon={ChatBubbleIcon} {...props} />;
+ return <CallButton aria-label="chat" Icon={ChatBubbleIcon} {...props} />;
};
export const CallingEndButton = (props: ExpandableButtonProps) => {
- return <ExpandableButton aria-label="call end" Icon={CallEndIcon} sx={{ backgroundColor: 'red' }} {...props} />;
+ return <ColoredCallButton sx={{}} aria-label="call end" Icon={CallEndIcon} {...props} />;
};
export const CallingExtensionButton = (props: ExpandableButtonProps) => {
- return <ExpandableButton aria-label="extensions" Icon={ExtensionIcon} {...props} />;
+ return <CallButton aria-label="extensions" Icon={ExtensionIcon} {...props} />;
};
export const CallingFullScreenButton = (props: ExpandableButtonProps) => {
- return <ExpandableButton aria-label="full screen" Icon={FullScreenIcon} {...props} />;
+ return <CallButton aria-label="full screen" Icon={FullScreenIcon} {...props} />;
};
export const CallingGroupButton = (props: ExpandableButtonProps) => {
- return <ExpandableButton aria-label="group options" Icon={GroupAddIcon} {...props} />;
+ return <CallButton aria-label="group options" Icon={GroupAddIcon} {...props} />;
};
export const CallingMoreVerticalButton = (props: ExpandableButtonProps) => {
- return <ExpandableButton aria-label="more vertical" Icon={MoreVerticalIcon} {...props} />;
+ return <CallButton aria-label="more vertical" Icon={MoreVerticalIcon} {...props} />;
};
export const CallingRecordButton = (props: ExpandableButtonProps) => {
- return <ExpandableButton aria-label="recording options" Icon={RecordingIcon} {...props} />;
+ return <CallButton aria-label="recording options" Icon={RecordingIcon} {...props} />;
};
export const CallingScreenShareButton = (props: ExpandableButtonProps) => {
return (
- <ExpandableButton
+ <CallButton
aria-label="screen share"
Icon={ScreenShareArrowIcon}
expandMenuOptions={[
@@ -79,6 +100,10 @@
icon: <ScreenShareRegularIcon />,
},
{
+ description: <Trans i18nKey="share_window" />,
+ icon: <WindowIcon />,
+ },
+ {
description: <Trans i18nKey="share_screen_area" />,
icon: <ScreenShareScreenAreaIcon />,
},
@@ -94,7 +119,7 @@
export const CallingVolumeButton = (props: ExpandableButtonProps) => {
return (
- <ExpandableButton
+ <CallButton
aria-label="volume options"
Icon={VolumeIcon}
expandMenuOptions={[
@@ -111,33 +136,42 @@
/>
);
};
-export const CallingMicButton = (props: Partial<ToggleIconButtonProps>) => {
+
+export const CallingMicButton = (props: ExpandableButtonProps) => {
const { isAudioOn, setAudioStatus } = useContext(WebRTCContext);
return (
- <ToggleIconButton
+ <CallButton
aria-label="microphone options"
- sx={{ color: 'white' }}
- IconOn={MicroIcon}
- IconOff={MicroOffIcon}
- selected={isAudioOn}
- toggle={() => setAudioStatus(!isAudioOn)}
+ IconButtonComp={(props) => (
+ <ToggleIconButton
+ IconOn={MicroIcon}
+ IconOff={MicroOffIcon}
+ selected={isAudioOn}
+ toggle={() => setAudioStatus(!isAudioOn)}
+ {...props}
+ />
+ )}
{...props}
/>
);
};
-export const CallingVideoCameraButton = (props: Partial<ToggleIconButtonProps>) => {
+export const CallingVideoCameraButton = (props: ExpandableButtonProps) => {
const { isVideoOn, setVideoStatus } = useContext(WebRTCContext);
return (
- <ToggleIconButton
+ <CallButton
aria-label="camera options"
- sx={{ color: 'white' }}
- IconOn={VideoCameraIcon}
- IconOff={VideoCameraOffIcon}
- selected={isVideoOn}
- toggle={() => setVideoStatus(!isVideoOn)}
+ IconButtonComp={(props) => (
+ <ToggleIconButton
+ IconOn={VideoCameraIcon}
+ IconOff={VideoCameraOffIcon}
+ selected={isVideoOn}
+ toggle={() => setVideoStatus(!isVideoOn)}
+ {...props}
+ />
+ )}
{...props}
/>
);
diff --git a/client/src/components/SvgIcon.tsx b/client/src/components/SvgIcon.tsx
index 0b8b9ed..88423b1 100644
--- a/client/src/components/SvgIcon.tsx
+++ b/client/src/components/SvgIcon.tsx
@@ -799,3 +799,15 @@
</SvgIcon>
);
};
+
+export const WindowIcon = (props: SvgIconProps) => {
+ return (
+ <SvgIcon {...props} viewBox="0 0 24 24">
+ <path
+ d="M20.5,0.8h-17C2,0.8,0.8,2,0.8,3.5v17c0,1.5,1.2,2.7,2.7,2.7h17c1.5,0,2.7-1.2,2.7-2.7v-17C23.2,2,22,0.8,20.5,0.8z
+ M3.5,2.2h17c0.7,0,1.3,0.6,1.3,1.3v0.1H2.2V3.5C2.2,2.8,2.8,2.2,3.5,2.2z M7.7,21.8H3.5c-0.7,0-1.3-0.6-1.3-1.3V5h5.5h1.4h12.7
+ v15.5c0,0.7-0.6,1.3-1.3,1.3H9.1H7.7z"
+ />
+ </SvgIcon>
+ );
+};