use Link for a11y

This commit is contained in:
Samuel Newman
2026-03-04 10:33:10 +02:00
parent 763e4f6e29
commit 93857f78be
+48 -21
View File
@@ -1,5 +1,5 @@
import {useCallback, useMemo} from 'react' import {useCallback, useMemo} from 'react'
import {Platform, View} from 'react-native' import {type GestureResponderEvent, Platform, View} from 'react-native'
import {type AppBskyFeedDefs} from '@atproto/api' import {type AppBskyFeedDefs} from '@atproto/api'
import {Trans, useLingui} from '@lingui/react/macro' import {Trans, useLingui} from '@lingui/react/macro'
@@ -9,20 +9,23 @@ import {useTranslate} from '#/lib/translation'
import {type TranslationFunction} from '#/lib/translation/types' import {type TranslationFunction} from '#/lib/translation/types'
import { import {
codeToLanguageName, codeToLanguageName,
getTranslatorLink,
isPostInLanguage, isPostInLanguage,
languageName, languageName,
} from '#/locale/helpers' } from '#/locale/helpers'
import {LANGUAGES} from '#/locale/languages' import {LANGUAGES} from '#/locale/languages'
import {useLanguagePrefs} from '#/state/preferences' import {useLanguagePrefs} from '#/state/preferences'
import {atoms as a, native, useTheme} from '#/alf' import {atoms as a, native, useTheme, web} from '#/alf'
import {Button} from '#/components/Button' import {Button} from '#/components/Button'
import {ArrowRight_Stroke2_Corner0_Rounded as ArrowRightIcon} from '#/components/icons/Arrow' import {ArrowRight_Stroke2_Corner0_Rounded as ArrowRightIcon} from '#/components/icons/Arrow'
import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Times' import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Times'
import {Warning_Stroke2_Corner0_Rounded as WarningIcon} from '#/components/icons/Warning' import {Warning_Stroke2_Corner0_Rounded as WarningIcon} from '#/components/icons/Warning'
import {Link} from '#/components/Link'
import {Loader} from '#/components/Loader' import {Loader} from '#/components/Loader'
import * as Select from '#/components/Select' import * as Select from '#/components/Select'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
import {useAnalytics} from '#/analytics' import {useAnalytics} from '#/analytics'
import {IS_WEB} from '#/env'
export function TranslatedPost({ export function TranslatedPost({
post, post,
@@ -108,18 +111,25 @@ function TranslationLink({
const {t: l} = useLingui() const {t: l} = useLingui()
const ax = useAnalytics() const ax = useAnalytics()
const handleTranslate = useCallback(() => { const handleTranslate = useCallback(
void translate({ (evt: GestureResponderEvent) => {
text: postText, evt.preventDefault()
targetLangCode: primaryLanguage,
})
ax.metric('translate', { void translate({
sourceLanguages: [], text: postText,
targetLanguage: primaryLanguage, targetLangCode: primaryLanguage,
textLength: postText.length, })
})
}, [ax, postText, primaryLanguage, translate]) ax.metric('translate', {
sourceLanguages: [],
targetLanguage: primaryLanguage,
textLength: postText.length,
})
return false
},
[ax, postText, primaryLanguage, translate],
)
return ( return (
<View <View
@@ -131,15 +141,20 @@ function TranslationLink({
a.align_center, a.align_center,
a.gap_xs, a.gap_xs,
]}> ]}>
<Button <Link
to={getTranslatorLink(postText, primaryLanguage)}
role={IS_WEB ? 'link' : 'button'}
onPress={handleTranslate} onPress={handleTranslate}
label={l`Translate`} label={l`Translate`}
hoverStyle={native({opacity: 0.5})} hoverStyle={[
native({opacity: 0.5}),
web([a.underline, {textDecorationColor: t.palette.primary_500}]),
]}
hitSlop={HITSLOP_30}> hitSlop={HITSLOP_30}>
<Text style={[a.text_sm, {color: t.palette.primary_500}]}> <Text style={[a.text_sm, {color: t.palette.primary_500}]}>
<Trans>Translate</Trans> <Trans>Translate</Trans>
</Text> </Text>
</Button> </Link>
</View> </View>
) )
} }
@@ -159,6 +174,14 @@ function TranslationError({
const {t: l} = useLingui() const {t: l} = useLingui()
const translate = useGoogleTranslate() const translate = useGoogleTranslate()
const handleFallback = (evt: GestureResponderEvent) => {
evt.preventDefault()
void translate(postText, primaryLanguage)
return false
}
return ( return (
<View <View
style={[ style={[
@@ -182,23 +205,27 @@ function TranslationError({
<Button <Button
label={l`Hide translation`} label={l`Hide translation`}
hitSlop={HITSLOP_30} hitSlop={HITSLOP_30}
hoverStyle={native({opacity: 0.5})} hoverStyle={{opacity: 0.5}}
onPress={clearTranslation}> onPress={clearTranslation}>
<XIcon size="sm" fill={t.atoms.text_contrast_medium.color} /> <XIcon size="sm" fill={t.atoms.text_contrast_medium.color} />
</Button> </Button>
</View> </View>
</View> </View>
<View style={[a.flex_row, a.align_center]}> <View style={[a.flex_row, a.align_center]}>
<Button <Link
onPress={() => void translate(postText, primaryLanguage)} to={getTranslatorLink(postText, primaryLanguage)}
onPress={handleFallback}
label={l`Try Google Translate`} label={l`Try Google Translate`}
hoverStyle={native({opacity: 0.5})} hoverStyle={[
native({opacity: 0.5}),
web([a.underline, {textDecorationColor: t.palette.primary_500}]),
]}
hitSlop={HITSLOP_30}> hitSlop={HITSLOP_30}>
<Text <Text
style={[a.text_xs, a.font_medium, {color: t.palette.primary_500}]}> style={[a.text_xs, a.font_medium, {color: t.palette.primary_500}]}>
<Trans>Try Google Translate</Trans> <Trans>Try Google Translate</Trans>
</Text> </Text>
</Button> </Link>
</View> </View>
</View> </View>
) )