Skip to content

Commit

Permalink
chore: remove disabled accessibility trait for AppbarContent and `C…
Browse files Browse the repository at this point in the history
…ard` (callstack#3794)
  • Loading branch information
DimitarNestorov committed Apr 3, 2023
1 parent caa308a commit ecf8ba4
Show file tree
Hide file tree
Showing 8 changed files with 195 additions and 122 deletions.
10 changes: 10 additions & 0 deletions example/src/Examples/AppbarExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
List,
Paragraph,
RadioButton,
Snackbar,
Switch,
Text,
} from 'react-native-paper';
Expand Down Expand Up @@ -36,6 +37,7 @@ const AppbarExample = ({ navigation }: Props) => {
const [appbarMode, setAppbarMode] = React.useState<AppbarModes>('small');
const [showCalendarIcon, setShowCalendarIcon] = React.useState(false);
const [showElevated, setShowElevated] = React.useState(false);
const [showSnackbar, setShowSnackbar] = React.useState(false);

const theme = useExampleTheme();
const { bottom, left, right } = useSafeAreaInsets();
Expand All @@ -60,6 +62,7 @@ const AppbarExample = ({ navigation }: Props) => {
<Appbar.Content
title="Title"
subtitle={showSubtitle ? 'Subtitle' : null}
onPress={() => setShowSnackbar(true)}
/>
{isCenterAlignedMode
? false
Expand Down Expand Up @@ -216,6 +219,13 @@ const AppbarExample = ({ navigation }: Props) => {
{theme.isV3 && renderFAB()}
</Appbar>
{!theme.isV3 && renderFAB()}
<Snackbar
visible={showSnackbar}
onDismiss={() => setShowSnackbar(false)}
duration={Snackbar.DURATION_SHORT}
>
Heading pressed
</Snackbar>
</>
);
};
Expand Down
127 changes: 79 additions & 48 deletions src/components/Appbar/AppbarContent.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from 'react';
import {
AccessibilityRole,
GestureResponderEvent,
Platform,
StyleProp,
Expand Down Expand Up @@ -54,6 +55,10 @@ export type Props = $RemoveChildren<typeof View> & {
* Function to execute on press.
*/
onPress?: (e: GestureResponderEvent) => void;
/**
* If true, disable all interactions for this component.
*/
disabled?: boolean;
/**
* Custom color for the text.
*/
Expand Down Expand Up @@ -99,6 +104,7 @@ const AppbarContent = ({
subtitle,
subtitleStyle,
onPress,
disabled,
style,
titleRef,
titleStyle,
Expand Down Expand Up @@ -128,56 +134,75 @@ const AppbarContent = ({

const variant = modeTextVariant[mode] as MD3TypescaleKey;

return (
<TouchableWithoutFeedback
accessibilityRole={onPress ? 'button' : 'text'}
onPress={onPress}
disabled={!onPress}
const content = (
<View
pointerEvents="box-none"
style={[styles.container, isV3 && modeContainerStyles[mode], style]}
testID={testID}
{...rest}
>
<View
pointerEvents="box-none"
style={[styles.container, isV3 && modeContainerStyles[mode], style]}
testID={testID}
{...rest}
>
{typeof title === 'string' ? (
<Text
{...(isV3 && { variant })}
ref={titleRef}
style={[
{
color: titleTextColor,
...(isV3
? theme.fonts[variant]
: Platform.OS === 'ios'
? theme.fonts.regular
: theme.fonts.medium),
},
!isV3 && styles.title,
titleStyle,
]}
numberOfLines={1}
accessible
// @ts-ignore Type '"heading"' is not assignable to type ...
accessibilityRole={Platform.OS === 'web' ? 'heading' : 'header'}
testID={`${testID}-title-text`}
>
{title}
</Text>
) : (
title
)}
{!isV3 && subtitle ? (
<Text
style={[styles.subtitle, { color: subtitleColor }, subtitleStyle]}
numberOfLines={1}
>
{subtitle}
</Text>
) : null}
</View>
</TouchableWithoutFeedback>
{typeof title === 'string' ? (
<Text
{...(isV3 && { variant })}
ref={titleRef}
style={[
{
color: titleTextColor,
...(isV3
? theme.fonts[variant]
: Platform.OS === 'ios'
? theme.fonts.regular
: theme.fonts.medium),
},
!isV3 && styles.title,
titleStyle,
]}
numberOfLines={1}
accessible
accessibilityRole={
onPress
? 'none'
: Platform.OS === 'web'
? ('heading' as 'header')
: 'header'
}
// @ts-expect-error We keep old a11y props for backwards compat with old RN versions
accessibilityTraits="header"
testID={`${testID}-title-text`}
>
{title}
</Text>
) : (
title
)}
{!isV3 && subtitle ? (
<Text
style={[styles.subtitle, { color: subtitleColor }, subtitleStyle]}
numberOfLines={1}
>
{subtitle}
</Text>
) : null}
</View>
);

if (onPress) {
return (
// eslint-disable-next-line react-native-a11y/has-accessibility-props
<TouchableWithoutFeedback
accessibilityRole={touchableRole}
// @ts-expect-error We keep old a11y props for backwards compat with old RN versions
accessibilityTraits={touchableRole}
accessibilityComponentType="button"
onPress={onPress}
disabled={disabled}
>
{content}
</TouchableWithoutFeedback>
);
}

return content;
};

AppbarContent.displayName = 'Appbar.Content';
Expand Down Expand Up @@ -209,6 +234,12 @@ const styles = StyleSheet.create({
},
});

const iosTouchableRole: readonly AccessibilityRole[] = ['button', 'header'];
const touchableRole: AccessibilityRole = Platform.select({
ios: iosTouchableRole as unknown as 'button',
default: iosTouchableRole[0],
});

export default AppbarContent;

// @component-docs ignore-next-line
Expand Down
72 changes: 45 additions & 27 deletions src/components/Card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import {
ViewStyle,
} from 'react-native';

import useLatestCallback from 'use-latest-callback';

import { useInternalTheme } from '../../core/theming';
import type { ThemeProp } from '../../types';
import Surface from '../Surface';
Expand Down Expand Up @@ -59,6 +61,10 @@ export type Props = React.ComponentProps<typeof Surface> & {
* Function to execute on press.
*/
onPress?: (e: GestureResponderEvent) => void;
/**
* If true, disable all interactions for this component.
*/
disabled?: boolean;
/**
* The number of milliseconds a user must touch the element before executing `onLongPress`.
*/
Expand Down Expand Up @@ -141,6 +147,7 @@ const Card = ({
theme: themeOverrides,
testID = 'card',
accessible,
disabled,
...rest
}: (OutlinedCardProps | ElevatedCardProps | ContainedCardProps) & Props) => {
const theme = useInternalTheme(themeOverrides);
Expand Down Expand Up @@ -208,13 +215,13 @@ const Card = ({
}
};

const handlePressIn = () => {
const handlePressIn = useLatestCallback(() => {
runElevationAnimation('in');
};
});

const handlePressOut = () => {
const handlePressOut = useLatestCallback(() => {
runElevationAnimation('out');
};
});

const total = React.Children.count(children);
const siblings = React.Children.map(children, (child) =>
Expand All @@ -235,6 +242,24 @@ const Card = ({
borderColor = themedBorderColor,
} = (StyleSheet.flatten(style) || {}) as ViewStyle;

const content = (
<View
style={[styles.innerContainer, contentStyle]}
testID={testID}
accessible={accessible}
>
{React.Children.map(children, (child, index) =>
React.isValidElement(child)
? React.cloneElement(child as React.ReactElement<any>, {
index,
total,
siblings,
})
: child
)}
</View>
);

return (
<Surface
style={[
Expand Down Expand Up @@ -269,29 +294,22 @@ const Card = ({
]}
/>
)}
<TouchableWithoutFeedback
delayPressIn={0}
disabled={!(onPress || onLongPress)}
delayLongPress={delayLongPress}
onLongPress={onLongPress}
onPress={onPress}
onPressIn={onPress || onLongPress ? handlePressIn : undefined}
onPressOut={onPress || onLongPress ? handlePressOut : undefined}
testID={testID}
accessible={accessible}
>
<View style={[styles.innerContainer, contentStyle]}>
{React.Children.map(children, (child, index) =>
React.isValidElement(child)
? React.cloneElement(child as React.ReactElement<any>, {
index,
total,
siblings,
})
: child
)}
</View>
</TouchableWithoutFeedback>

{onPress || onLongPress ? (
<TouchableWithoutFeedback
delayPressIn={0}
disabled={disabled}
delayLongPress={delayLongPress}
onLongPress={onLongPress}
onPress={onPress}
onPressIn={handlePressIn}
onPressOut={handlePressOut}
>
{content}
</TouchableWithoutFeedback>
) : (
content
)}
</Surface>
);
};
Expand Down
20 changes: 6 additions & 14 deletions src/components/Card/CardTitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,15 +146,9 @@ const CardTitle = ({
theme: themeOverrides,
}: Props) => {
const theme = useInternalTheme(themeOverrides);
const titleComponent = (props: any) =>
theme.isV3 ? <Text {...props} /> : <Title {...props} />;
const TitleComponent = theme.isV3 ? Text : Title;
const SubtitleComponent = theme.isV3 ? Text : Caption;

const subtitleComponent = (props: any) =>
theme.isV3 ? <Text {...props} /> : <Caption {...props} />;

const TextComponent = React.memo(({ component, ...rest }: any) =>
React.createElement(component, rest)
);
const minHeight = subtitle || left || right ? 72 : 50;
const marginBottom = subtitle ? 0 : 2;

Expand All @@ -170,24 +164,22 @@ const CardTitle = ({

<View style={[styles.titles]}>
{title && (
<TextComponent
component={titleComponent}
<TitleComponent
style={[styles.title, { marginBottom }, titleStyle]}
numberOfLines={titleNumberOfLines}
variant={titleVariant}
>
{title}
</TextComponent>
</TitleComponent>
)}
{subtitle && (
<TextComponent
component={subtitleComponent}
<SubtitleComponent
style={[styles.subtitle, subtitleStyle]}
numberOfLines={subtitleNumberOfLines}
variant={subtitleVariant}
>
{subtitle}
</TextComponent>
</SubtitleComponent>
)}
</View>
<View style={rightStyle}>{right ? right({ size: 24 }) : null}</View>
Expand Down
Loading

0 comments on commit ecf8ba4

Please sign in to comment.