fix(a11y): avoid plain divs as button or tabs (#6084)
Co-authored-by: Hailey <me@haileyok.com>
This commit is contained in:
@@ -46,7 +46,7 @@ export function Root({
|
|||||||
return <Context.Provider value={context}>{children}</Context.Provider>
|
return <Context.Provider value={context}>{children}</Context.Provider>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Trigger({children, label}: TriggerProps) {
|
export function Trigger({children, label, role = 'button'}: TriggerProps) {
|
||||||
const {control} = React.useContext(Context)
|
const {control} = React.useContext(Context)
|
||||||
const {state: focused, onIn: onFocus, onOut: onBlur} = useInteractionState()
|
const {state: focused, onIn: onFocus, onOut: onBlur} = useInteractionState()
|
||||||
const {
|
const {
|
||||||
@@ -70,6 +70,7 @@ export function Trigger({children, label}: TriggerProps) {
|
|||||||
onPressIn,
|
onPressIn,
|
||||||
onPressOut,
|
onPressOut,
|
||||||
accessibilityLabel: label,
|
accessibilityLabel: label,
|
||||||
|
accessibilityRole: role,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ const RadixTriggerPassThrough = React.forwardRef(
|
|||||||
)
|
)
|
||||||
RadixTriggerPassThrough.displayName = 'RadixTriggerPassThrough'
|
RadixTriggerPassThrough.displayName = 'RadixTriggerPassThrough'
|
||||||
|
|
||||||
export function Trigger({children, label}: TriggerProps) {
|
export function Trigger({children, label, role = 'button'}: TriggerProps) {
|
||||||
const {control} = React.useContext(Context)
|
const {control} = React.useContext(Context)
|
||||||
const {
|
const {
|
||||||
state: hovered,
|
state: hovered,
|
||||||
@@ -155,6 +155,7 @@ export function Trigger({children, label}: TriggerProps) {
|
|||||||
onMouseEnter,
|
onMouseEnter,
|
||||||
onMouseLeave,
|
onMouseLeave,
|
||||||
accessibilityLabel: label,
|
accessibilityLabel: label,
|
||||||
|
accessibilityRole: role,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {
|
import {
|
||||||
AccessibilityProps,
|
AccessibilityProps,
|
||||||
|
AccessibilityRole,
|
||||||
GestureResponderEvent,
|
GestureResponderEvent,
|
||||||
PressableProps,
|
PressableProps,
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
@@ -36,6 +37,7 @@ export type RadixPassThroughTriggerProps = {
|
|||||||
export type TriggerProps = {
|
export type TriggerProps = {
|
||||||
children(props: TriggerChildProps): React.ReactNode
|
children(props: TriggerChildProps): React.ReactNode
|
||||||
label: string
|
label: string
|
||||||
|
role?: AccessibilityRole
|
||||||
}
|
}
|
||||||
export type TriggerChildProps =
|
export type TriggerChildProps =
|
||||||
| {
|
| {
|
||||||
@@ -63,6 +65,7 @@ export type TriggerChildProps =
|
|||||||
onPressIn: () => void
|
onPressIn: () => void
|
||||||
onPressOut: () => void
|
onPressOut: () => void
|
||||||
accessibilityLabel: string
|
accessibilityLabel: string
|
||||||
|
accessibilityRole: AccessibilityRole
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
@@ -83,6 +86,7 @@ export type TriggerChildProps =
|
|||||||
onMouseEnter: () => void
|
onMouseEnter: () => void
|
||||||
onMouseLeave: () => void
|
onMouseLeave: () => void
|
||||||
accessibilityLabel: string
|
accessibilityLabel: string
|
||||||
|
accessibilityRole: AccessibilityRole
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -118,7 +118,10 @@ export function TabBar({
|
|||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View testID={testID} style={[pal.view, styles.outer]}>
|
<View
|
||||||
|
testID={testID}
|
||||||
|
style={[pal.view, styles.outer]}
|
||||||
|
accessibilityRole="tablist">
|
||||||
<DraggableScrollView
|
<DraggableScrollView
|
||||||
testID={`${testID}-selector`}
|
testID={`${testID}-selector`}
|
||||||
horizontal={true}
|
horizontal={true}
|
||||||
@@ -135,7 +138,8 @@ export function TabBar({
|
|||||||
onLayout={e => onItemLayout(e, i)}
|
onLayout={e => onItemLayout(e, i)}
|
||||||
style={styles.item}
|
style={styles.item}
|
||||||
hoverStyle={pal.viewLight}
|
hoverStyle={pal.viewLight}
|
||||||
onPress={() => onPressItem(i)}>
|
onPress={() => onPressItem(i)}
|
||||||
|
accessibilityRole="tab">
|
||||||
<View style={[styles.itemInner, selected && indicatorStyle]}>
|
<View style={[styles.itemInner, selected && indicatorStyle]}>
|
||||||
<Text
|
<Text
|
||||||
emoji
|
emoji
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import {useComposerControls} from '#/state/shell/composer'
|
|||||||
import {useMergedThreadgateHiddenReplies} from '#/state/threadgate-hidden-replies'
|
import {useMergedThreadgateHiddenReplies} from '#/state/threadgate-hidden-replies'
|
||||||
import {PostThreadFollowBtn} from '#/view/com/post-thread/PostThreadFollowBtn'
|
import {PostThreadFollowBtn} from '#/view/com/post-thread/PostThreadFollowBtn'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
|
import {InlineLinkText} from '#/components/Link'
|
||||||
import {AppModerationCause} from '#/components/Pills'
|
import {AppModerationCause} from '#/components/Pills'
|
||||||
import {RichText} from '#/components/RichText'
|
import {RichText} from '#/components/RichText'
|
||||||
import {SubtleWebHover} from '#/components/SubtleWebHover'
|
import {SubtleWebHover} from '#/components/SubtleWebHover'
|
||||||
@@ -744,12 +745,13 @@ function ExpandedPostDetails({
|
|||||||
·
|
·
|
||||||
</NewText>
|
</NewText>
|
||||||
|
|
||||||
<NewText
|
<InlineLinkText
|
||||||
|
to="#"
|
||||||
|
label={_(msg`Translate`)}
|
||||||
style={[a.text_sm, pal.link]}
|
style={[a.text_sm, pal.link]}
|
||||||
title={_(msg`Translate`)}
|
|
||||||
onPress={onTranslatePress}>
|
onPress={onTranslatePress}>
|
||||||
<Trans>Translate</Trans>
|
<Trans>Translate</Trans>
|
||||||
</NewText>
|
</InlineLinkText>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -256,6 +256,7 @@ let PostCtrls = ({
|
|||||||
requireAuth(() => onPressReply())
|
requireAuth(() => onPressReply())
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
accessibilityRole="button"
|
||||||
accessibilityLabel={plural(post.replyCount || 0, {
|
accessibilityLabel={plural(post.replyCount || 0, {
|
||||||
one: 'Reply (# reply)',
|
one: 'Reply (# reply)',
|
||||||
other: 'Reply (# replies)',
|
other: 'Reply (# replies)',
|
||||||
@@ -293,6 +294,7 @@ let PostCtrls = ({
|
|||||||
testID="likeBtn"
|
testID="likeBtn"
|
||||||
style={btnStyle}
|
style={btnStyle}
|
||||||
onPress={() => requireAuth(() => onPressToggleLike())}
|
onPress={() => requireAuth(() => onPressToggleLike())}
|
||||||
|
accessibilityRole="button"
|
||||||
accessibilityLabel={
|
accessibilityLabel={
|
||||||
post.viewer?.like
|
post.viewer?.like
|
||||||
? plural(post.likeCount || 0, {
|
? plural(post.likeCount || 0, {
|
||||||
@@ -332,6 +334,7 @@ let PostCtrls = ({
|
|||||||
onShare()
|
onShare()
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
accessibilityRole="button"
|
||||||
accessibilityLabel={_(msg`Share`)}
|
accessibilityLabel={_(msg`Share`)}
|
||||||
accessibilityHint=""
|
accessibilityHint=""
|
||||||
hitSlop={POST_CTRL_HITSLOP}>
|
hitSlop={POST_CTRL_HITSLOP}>
|
||||||
|
|||||||
Reference in New Issue
Block a user