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