🚸(frontend) enhance accessibility of 'copy link' button

Added user feedback for actions with explicit text indicating
URL will be copied to clipboard. Modeled after Jitsi's button
behavior for clarity and consistency in user experience.
This commit is contained in:
lebaudantoine
2024-09-09 18:20:16 +02:00
committed by aleb_the_flash
parent e9210213b1
commit 80cc7c723f
4 changed files with 64 additions and 35 deletions

View File

@@ -4,7 +4,13 @@ import { Div, Button, type DialogProps, P } from '@/primitives'
import { HStack, styled, VStack } from '@/styled-system/jsx'
import { Heading, Dialog } from 'react-aria-components'
import { Text, text } from '@/primitives/Text'
import { RiCloseLine, RiFileCopyLine, RiSpam2Fill } from '@remixicon/react'
import {
RiCheckLine,
RiCloseLine,
RiFileCopyLine,
RiSpam2Fill,
} from '@remixicon/react'
import { useEffect, useState } from 'react'
// fixme - extract in a proper primitive this dialog without overlay
const StyledRACDialog = styled(Dialog, {
@@ -34,17 +40,25 @@ export const InviteDialog = ({
const { t } = useTranslation('rooms')
const roomUrl = getRouteUrl('room', roomId)
const [isCopied, setIsCopied] = useState(false)
useEffect(() => {
if (isCopied) {
const timeout = setTimeout(() => setIsCopied(false), 3000)
return () => clearTimeout(timeout)
}
}, [isCopied])
const [isHovered, setIsHovered] = useState(false)
return (
<StyledRACDialog {...dialogProps}>
{({ close }) => (
<VStack
alignItems={'left'}
alignItems="left"
justify="start"
gap={0}
style={{
maxWidth: '100%',
overflow: 'hidden',
}}
style={{ maxWidth: '100%', overflow: 'hidden' }}
>
<Heading slot="title" level={3} className={text({ variant: 'h2' })}>
{t('shareDialog.heading')}
@@ -63,36 +77,48 @@ export const InviteDialog = ({
</Button>
</Div>
<P>{t('shareDialog.description')}</P>
<HStack
justify={'space-between'}
alignItems="center"
<Button
variant={isCopied ? 'success' : 'primary'}
size="sm"
fullWidth
aria-label={t('shareDialog.copy')}
style={{
backgroundColor: '#f1f3f4',
borderRadius: '4px',
maxWidth: '100%',
justifyContent: 'start',
}}
gap={0}
onPress={() => {
navigator.clipboard.writeText(roomUrl)
setIsCopied(true)
}}
onHoverChange={setIsHovered}
>
<div
style={{
paddingLeft: '0.75rem',
textOverflow: 'ellipsis',
overflow: 'hidden',
textWrap: 'nowrap',
userSelect: 'none',
}}
>
{roomUrl.replace(/^https?:\/\//, '')}
</div>
<Button
square
invisible
tooltip={t('shareDialog.copy')}
onPress={() => navigator.clipboard.writeText(roomUrl)}
>
<RiFileCopyLine size={24} />
</Button>
</HStack>
{isCopied ? (
<>
<RiCheckLine size={18} style={{ marginRight: '8px' }} />
{t('shareDialog.copied')}
</>
) : (
<>
<RiFileCopyLine
size={18}
style={{ marginRight: '8px', minWidth: '18px' }}
/>
{isHovered ? (
t('shareDialog.copy')
) : (
<div
style={{
textOverflow: 'ellipsis',
overflow: 'hidden',
userSelect: 'none',
textWrap: 'nowrap',
}}
>
{roomUrl.replace(/^https?:\/\//, '')}
</div>
)}
</>
)}
</Button>
<HStack>
<div
style={{

View File

@@ -13,6 +13,7 @@
"leaveRoomPrompt": "",
"shareDialog": {
"copy": "",
"copied": "",
"heading": "",
"description": "",
"permissions": ""

View File

@@ -12,7 +12,8 @@
},
"leaveRoomPrompt": "This will make you leave the meeting.",
"shareDialog": {
"copy": "Copy link",
"copy": "Copy the meeting link",
"copied": "Link copied to clipboard",
"heading": "Your meeting is ready",
"description": "Share this link with people you want to invite to the meeting.",
"permissions": "People with this link do not need your permission to join this meeting."

View File

@@ -12,7 +12,8 @@
},
"leaveRoomPrompt": "Revenir à l'accueil vous fera quitter la réunion.",
"shareDialog": {
"copy": "Copier le lien",
"copy": "Copier le lien de la réunion",
"copied": "Lien copié dans le presse-papiers",
"heading": "Votre réunion est prête",
"description": "Partagez ce lien avec les personnes que vous souhaitez inviter à la réunion.",
"permissions": "Les personnes disposant de ce lien n'ont pas besoin de votre autorisation pour rejoindre cette réunion."