diff --git a/client/src/components/Button.tsx b/client/src/components/Button.tsx index 13a0621142090341fd1fd25b5105fce5d95c1f5f..f71e662096877c8e790f38bbc70b3d5a2f146c3d 100644 --- a/client/src/components/Button.tsx +++ b/client/src/components/Button.tsx @@ -34,10 +34,12 @@ import { RadioGroupProps, SvgIconProps, Theme, + Tooltip, } from '@mui/material' import { PaletteColor, styled, useTheme } from '@mui/material/styles' import EmojiPicker, { EmojiClickData } from 'emoji-picker-react' import { ComponentType, ReactNode, useCallback, useState } from 'react' +import { useTranslation } from 'react-i18next' import { Arrow2Icon, @@ -66,6 +68,7 @@ import CustomTooltip from './Tooltip' export type ShapedButtonProps = IconButtonProps & { Icon: ComponentType<SvgIconProps> + tooltip?: string } export const RoundButton = styled(({ Icon, ...props }: ShapedButtonProps) => ( @@ -363,10 +366,12 @@ export const ToggleVisibilityButton = styled(({ visible, ...props }: ToggleVisib }, })) -export const SquareButton = styled(({ Icon, ...props }: ShapedButtonProps) => ( - <IconButton {...props} disableRipple={true}> - <Icon fontSize="inherit" /> - </IconButton> +export const SquareButton = styled(({ Icon, tooltip, ...props }: ShapedButtonProps) => ( + <Tooltip title={tooltip}> + <IconButton {...props} disableRipple={true}> + <Icon fontSize="inherit" /> + </IconButton> + </Tooltip> ))(({ theme }) => ({ color: theme.Buttons.color, fontSize: '25px', @@ -386,11 +391,27 @@ export const AddParticipantButton = (props: IconButtonProps) => { } export const RecordVideoMessageButton = (props: IconButtonProps) => { - return <SquareButton {...props} aria-label="record video message" Icon={CameraInBubbleIcon} /> + const { t } = useTranslation() + return ( + <SquareButton + tooltip={t('button_record_video_message')} + {...props} + aria-label="record video message" + Icon={CameraInBubbleIcon} + /> + ) } export const RecordVoiceMessageButton = (props: IconButtonProps) => { - return <SquareButton {...props} aria-label="record voice message" Icon={MicroInBubbleIcon} /> + const { t } = useTranslation() + return ( + <SquareButton + tooltip={t('button_record_voice_message')} + {...props} + aria-label="record voice message" + Icon={MicroInBubbleIcon} + /> + ) } export const ShowOptionsMenuButton = (props: IconButtonProps) => { @@ -406,11 +427,13 @@ export const StartAudioCallButton = (props: IconButtonProps) => { } export const UploadFileButton = (props: IconButtonProps) => { - return <SquareButton {...props} aria-label="upload file" Icon={PaperClipIcon} /> + const { t } = useTranslation() + return <SquareButton tooltip={t('button_upload_file')} {...props} aria-label="upload file" Icon={PaperClipIcon} /> } export const SendMessageButton = (props: IconButtonProps) => { - return <SquareButton {...props} aria-label="send message" Icon={Arrow2Icon} /> + const { t } = useTranslation() + return <SquareButton tooltip={t('button_send_message')} {...props} aria-label="send message" Icon={Arrow2Icon} /> } export const ReplyMessageButton = styled((props: IconButtonProps) => ( @@ -447,7 +470,7 @@ type SelectEmojiButtonProps = { } export const SelectEmojiButton = ({ onEmojiSelected }: SelectEmojiButtonProps) => { const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null) - + const { t } = useTranslation() const handleOpenEmojiPicker = useCallback((e: any) => setAnchorEl(anchorEl ? null : e.currentTarget), [anchorEl]) const theme = useTheme() const handleClose = useCallback(() => setAnchorEl(null), [setAnchorEl]) @@ -471,6 +494,7 @@ export const SelectEmojiButton = ({ onEmojiSelected }: SelectEmojiButtonProps) = aria-label="select emoji" Icon={EmojiIcon} onClick={handleOpenEmojiPicker} + tooltip={t('button_select_emoji')} /> <Popper sx={{ zIndex: 2 }} id={id} open={open} anchorEl={anchorEl}> <EmojiPicker diff --git a/client/src/components/SendMessageForm.tsx b/client/src/components/SendMessageForm.tsx index 05dc3aee38e027034263630f5694c10b37c00083..fd28ba97938b9379181c4b8b76509f95aa72fdcf 100644 --- a/client/src/components/SendMessageForm.tsx +++ b/client/src/components/SendMessageForm.tsx @@ -16,8 +16,9 @@ * <https://www.gnu.org/licenses/>. */ import DeleteIcon from '@mui/icons-material/Delete' -import { Box, Card, CardContent, TextareaAutosize, useTheme } from '@mui/material' +import { Box, Card, CardContent, TextareaAutosize, Tooltip, useTheme } from '@mui/material' import { Stack, useMediaQuery } from '@mui/system' +import { t } from 'i18next' import { WebSocketMessageType } from 'jami-web-common' import { ChangeEvent, FormEvent, useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' @@ -490,10 +491,12 @@ export default function SendMessageForm({ openFilePicker }: SendMessageFormProps )} <Box sx={{ display: 'flex', alignItems: 'center', alignContent: 'center' }}> {isRecordingVoice ? ( - <DeleteIcon - onClick={voiceRecordingStatusChange} - style={{ color: 'red', width: '30px', height: '30px', cursor: 'pointer' }} - /> + <Tooltip title={t('button_cancel_voice_recording')}> + <DeleteIcon + onClick={voiceRecordingStatusChange} + style={{ color: 'red', width: '30px', height: '30px', cursor: 'pointer' }} + /> + </Tooltip> ) : ( <SelectEmojiButton onEmojiSelected={onEmojiSelected} /> )} diff --git a/server/locale/en/translation.json b/server/locale/en/translation.json index 45ea7291d4d42f83aa375c331c8c24e484bbbd46..9912fae5d662103d980a3f20b0a7310a64365621 100644 --- a/server/locale/en/translation.json +++ b/server/locale/en/translation.json @@ -39,6 +39,12 @@ "artwork_by": "Artwork by", "back_to_conversations": "Back to conversations", "banned": "Blocked", + "button_cancel_voice_recording": "Cancel voice recording", + "button_record_video_message": "Record video message", + "button_record_voice_message": "Record voice message", + "button_upload_file": "Upload file", + "button_select_emoji": "Select an emoji", + "button_send_message": "Send message", "authentication": "Authentication", "calling": "Calling {{member0}}", "cannot_load_messages": "An error occurred while loading the message.",