Enforce a11y props on buttons

This commit is contained in:
Eric Bailey
2024-01-10 15:02:07 -06:00
parent 9bd19a6762
commit 22f0c16cf1
3 changed files with 67 additions and 15 deletions
+12 -3
View File
@@ -5,6 +5,7 @@ import {
PressableProps, PressableProps,
TextProps, TextProps,
ViewStyle, ViewStyle,
AccessibilityProps,
} from 'react-native' } from 'react-native'
import {useTheme, atoms, tokens, web, native} from '#/alf' import {useTheme, atoms, tokens, web, native} from '#/alf'
@@ -22,7 +23,10 @@ export type VariantProps = {
size?: ButtonSize size?: ButtonSize
} }
export type ButtonProps = Omit<PressableProps, 'children'> & export type ButtonProps = Omit<
PressableProps,
'children' | 'style' | 'accessibilityLabel' | 'accessibilityHint'
> &
VariantProps & { VariantProps & {
children: children:
| ((props: { | ((props: {
@@ -37,14 +41,17 @@ export type ButtonProps = Omit<PressableProps, 'children'> &
}) => React.ReactNode) }) => React.ReactNode)
| React.ReactNode | React.ReactNode
| string | string
accessibilityLabel: Required<AccessibilityProps>['accessibilityLabel']
accessibilityHint: Required<AccessibilityProps>['accessibilityHint']
} }
export type ButtonTextProps = TextProps & VariantProps & {disabled?: boolean} export type ButtonTextProps = TextProps & VariantProps & {disabled?: boolean}
export function Button({ export function Button({
children, children,
style,
type, type,
size, size,
accessibilityLabel,
accessibilityHint,
disabled = false, disabled = false,
...rest ...rest
}: ButtonProps) { }: ButtonProps) {
@@ -179,6 +186,9 @@ export function Button({
<Pressable <Pressable
role="button" role="button"
{...rest} {...rest}
aria-label={accessibilityLabel}
accessibilityLabel={accessibilityLabel}
accessibilityHint={accessibilityHint}
disabled={disabled || false} disabled={disabled || false}
accessibilityState={{ accessibilityState={{
disabled: disabled || false, disabled: disabled || false,
@@ -188,7 +198,6 @@ export function Button({
atoms.align_center, atoms.align_center,
...baseStyles, ...baseStyles,
...(state.hovered ? hoverStyles : []), ...(state.hovered ? hoverStyles : []),
typeof style === 'function' ? style(state) : style,
]} ]}
onPressIn={onPressIn} onPressIn={onPressIn}
onPressOut={onPressOut} onPressOut={onPressOut}
+3 -3
View File
@@ -59,7 +59,7 @@ export function Link({
}: LinkProps) { }: LinkProps) {
const t = useTheme() const t = useTheme()
const navigation = useNavigation<NavigationProp>() const navigation = useNavigation<NavigationProp>()
const {href, accessibilityRole} = useLinkProps<AllNavigatorParams>({ const {href} = useLinkProps<AllNavigatorParams>({
to: to:
typeof to === 'string' ? convertBskyAppUrlIfNeeded(sanitizeUrl(to)) : to, typeof to === 'string' ? convertBskyAppUrlIfNeeded(sanitizeUrl(to)) : to,
}) })
@@ -139,9 +139,9 @@ export function Link({
return ( return (
<Button <Button
role="link"
accessibilityRole={accessibilityRole}
{...rest} {...rest}
role="link"
accessibilityRole="link"
href={href} href={href}
onPress={onPress} onPress={onPress}
{...web({ {...web({
+52 -9
View File
@@ -151,9 +151,15 @@ export function Buttons() {
return ( return (
<View style={[a.gap_md, a.align_start]}> <View style={[a.gap_md, a.align_start]}>
<Button>Unstyled button</Button> <Button
accessibilityLabel="Click here"
accessibilityHint="Opens something">
Unstyled button
</Button>
<Button> <Button
accessibilityLabel="Click here"
accessibilityHint="Opens something">
{({state}) => ( {({state}) => (
<View style={[a.p_md, a.rounded_full, t.atoms.bg_contrast_300]}> <View style={[a.p_md, a.rounded_full, t.atoms.bg_contrast_300]}>
<Text>Entirely custom button, state: {JSON.stringify(state)}</Text> <Text>Entirely custom button, state: {JSON.stringify(state)}</Text>
@@ -161,15 +167,28 @@ export function Buttons() {
)} )}
</Button> </Button>
<Button type="primary" size="large"> <Button
accessibilityLabel="Click here"
accessibilityHint="Opens something"
type="primary"
size="large">
Default button Default button
</Button> </Button>
<Button type="primary" size="large" disabled> <Button
accessibilityLabel="Click here"
accessibilityHint="Opens something"
type="primary"
size="large"
disabled>
Default button (disabled) Default button (disabled)
</Button> </Button>
<Button type="primary" size="large"> <Button
accessibilityLabel="Click here"
accessibilityHint="Opens something"
type="primary"
size="large">
{({props}) => ( {({props}) => (
<> <>
<FontAwesomeIcon icon={['fas', 'plus']} size={12} /> <FontAwesomeIcon icon={['fas', 'plus']} size={12} />
@@ -178,37 +197,61 @@ export function Buttons() {
)} )}
</Button> </Button>
<Button type="secondary" size="small"> <Button
accessibilityLabel="Click here"
accessibilityHint="Opens something"
type="secondary"
size="small">
Small button Small button
</Button> </Button>
<Button type="secondary" size="small" disabled> <Button
accessibilityLabel="Click here"
accessibilityHint="Opens something"
type="secondary"
size="small"
disabled>
Small button (disabled) Small button (disabled)
</Button> </Button>
<Link <Link
accessibilityLabel="Click here"
accessibilityHint="Opens something"
to="https://blueskyweb.xyz" to="https://blueskyweb.xyz"
warnOnMismatchingTextChild warnOnMismatchingTextChild
style={[a.text_md]}> style={[a.text_md]}>
External External
</Link> </Link>
<Link to="https://blueskyweb.xyz" style={[a.text_md]}> <Link
accessibilityLabel="Click here"
accessibilityHint="Opens something"
to="https://blueskyweb.xyz"
style={[a.text_md]}>
<H3>External with custom children</H3> <H3>External with custom children</H3>
</Link> </Link>
<Link <Link
accessibilityLabel="Click here"
accessibilityHint="Opens something"
to="https://blueskyweb.xyz" to="https://blueskyweb.xyz"
warnOnMismatchingTextChild warnOnMismatchingTextChild
style={[a.text_md]}> style={[a.text_md]}>
https://blueskyweb.xyz https://blueskyweb.xyz
</Link> </Link>
<Link <Link
accessibilityLabel="Click here"
accessibilityHint="Opens something"
to="https://bsky.app/profile/bsky.app" to="https://bsky.app/profile/bsky.app"
warnOnMismatchingTextChild warnOnMismatchingTextChild
style={[a.text_md]}> style={[a.text_md]}>
Internal Internal
</Link> </Link>
<Link type="primary" size="large" to="https://bsky.app/profile/bsky.app"> <Link
accessibilityLabel="Click here"
accessibilityHint="Opens something"
type="primary"
size="large"
to="https://bsky.app/profile/bsky.app">
{({props}) => <ButtonText {...props}>Link as a button</ButtonText>} {({props}) => <ButtonText {...props}>Link as a button</ButtonText>}
</Link> </Link>
</View> </View>