Enforce a11y props on buttons
This commit is contained in:
+12
-3
@@ -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}
|
||||||
|
|||||||
@@ -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({
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user