@artsy/palette-mobile 17.6.0 → 17.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,5 +7,5 @@ export const BackButton = ({ color = "onBackgroundHigh", hitSlop = DEFAULT_HIT_S
7
7
  return (_jsx(TouchableOpacity, { onPress: onPress, hitSlop: hitSlop, accessibilityRole: "button", accessibilityLabel: showX ? "Close" : "Go back", accessibilityHint: showX ? "Dismiss this screen" : "Go back to the previous screen", style: style, children: showX ? (_jsx(CloseIcon, { fill: color, width: iconSize, height: iconSize })) : (_jsx(ChevronIcon, { direction: "left", fill: color, height: iconSize, width: iconSize })) }));
8
8
  };
9
9
  export const BackButtonWithBackground = ({ color = "onBackgroundHigh", hitSlop = DEFAULT_HIT_SLOP, onPress, showX = false, style, }) => {
10
- return (_jsx(TouchableOpacity, { onPress: onPress, hitSlop: hitSlop, children: _jsx(Flex, { backgroundColor: "background", width: 40, height: 40, borderRadius: 20, alignItems: "center", justifyContent: "center", accessibilityRole: "button", accessibilityLabel: showX ? "Close" : "Go back", accessibilityHint: showX ? "Dismiss this screen" : "Go back to the previous screen", style: style, children: showX ? (_jsx(CloseIcon, { fill: color, width: 26, height: 26 })) : (_jsx(ChevronIcon, { fill: color, direction: "left" })) }) }));
10
+ return (_jsx(TouchableOpacity, { accessibilityRole: "button", accessibilityLabel: showX ? "Close" : "Back", accessibilityHint: showX ? "Closes the modal" : "Navigates to the previous screen", onPress: onPress, hitSlop: hitSlop, children: _jsx(Flex, { backgroundColor: "background", width: 40, height: 40, borderRadius: 20, alignItems: "center", justifyContent: "center", accessibilityRole: "button", accessibilityLabel: showX ? "Close" : "Go back", accessibilityHint: showX ? "Dismiss this screen" : "Go back to the previous screen", style: style, children: showX ? (_jsx(CloseIcon, { fill: color, width: 26, height: 26 })) : (_jsx(ChevronIcon, { fill: color, direction: "left" })) }) }));
11
11
  };
@@ -19,7 +19,7 @@ export const Banner = ({ text, onClose, dismissable = false, variant = "defaultL
19
19
  });
20
20
  onClose?.();
21
21
  };
22
- return (_jsx(Animated.View, { style: {
22
+ return (_jsx(Animated.View, { accessibilityLabel: "Banner", style: {
23
23
  height: tempHeight,
24
24
  transform: [
25
25
  {
@@ -29,7 +29,7 @@ export const Banner = ({ text, onClose, dismissable = false, variant = "defaultL
29
29
  }),
30
30
  },
31
31
  ],
32
- }, children: _jsx(Flex, { backgroundColor: BANNER_VARIANTS[variant].backgroundColor, ...restProps, children: _jsxs(Flex, { px: 2, py: 1, flexDirection: "row", alignItems: "center", justifyContent: "space-between", children: [text ? (_jsx(Flex, { flex: 1, alignItems: "center", children: _jsx(Text, { textAlign: "center", variant: "xs", color: BANNER_VARIANTS[variant].color, children: text }) })) : (_jsx(Flex, { flex: 1, children: children })), !!dismissable && (_jsx(Flex, { children: _jsx(TouchableOpacity, { testID: "banner-close-button", onPress: handleClose, hitSlop: DEFAULT_HIT_SLOP, children: _jsx(CloseIcon, { fill: BANNER_VARIANTS[variant].color }) }) }))] }) }) }));
32
+ }, children: _jsx(Flex, { backgroundColor: BANNER_VARIANTS[variant].backgroundColor, ...restProps, children: _jsxs(Flex, { px: 2, py: 1, flexDirection: "row", alignItems: "center", justifyContent: "space-between", children: [text ? (_jsx(Flex, { flex: 1, alignItems: "center", children: _jsx(Text, { textAlign: "center", variant: "xs", color: BANNER_VARIANTS[variant].color, children: text }) })) : (_jsx(Flex, { flex: 1, children: children })), !!dismissable && (_jsx(Flex, { children: _jsx(TouchableOpacity, { accessibilityRole: "button", accessibilityLabel: "Close", accessibilityHint: "Dismiss banner", testID: "banner-close-button", onPress: handleClose, hitSlop: DEFAULT_HIT_SLOP, children: _jsx(CloseIcon, { fill: BANNER_VARIANTS[variant].color }) }) }))] }) }) }));
33
33
  };
34
34
  const BANNER_VARIANTS = {
35
35
  defaultLight: {
@@ -69,7 +69,9 @@ export const Button = ({ children, disabled, haptic, icon, iconPosition = "left"
69
69
  };
70
70
  const containerSize = getSize();
71
71
  const to = useStyleForVariantAndState(variant, testOnly_state ?? displayState);
72
- return (_jsx(Spring, { native: true, to: to, config: config.stiff, children: (springProps) => (_jsx(Pressable, { hitSlop: hitSlop, testOnly_pressed: testOnly_state === DisplayState.Pressed, disabled: testOnly_state === DisplayState.Disabled || disabled, onPressIn: () => {
72
+ return (_jsx(Spring, { native: true, to: to, config: config.stiff, children: (springProps) => (_jsx(Pressable, { accessibilityLabel: rest.accessibilityLabel, accessibilityRole: "button", accessibilityState: {
73
+ disabled,
74
+ }, hitSlop: hitSlop, testOnly_pressed: testOnly_state === DisplayState.Pressed, disabled: testOnly_state === DisplayState.Disabled || disabled, onPressIn: () => {
73
75
  if (displayState === DisplayState.Loading) {
74
76
  return;
75
77
  }
@@ -1,4 +1,4 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Text } from "../Text";
3
3
  import { Touchable } from "../Touchable";
4
- export const LinkButton = (props) => (_jsx(Touchable, { onPress: props.onPress, children: _jsx(Text, { underline: true, ...props }) }));
4
+ export const LinkButton = (props) => (_jsx(Touchable, { accessibilityRole: "link", onPress: props.onPress, children: _jsx(Text, { underline: true, ...props }) }));
@@ -73,7 +73,9 @@ export const Button = ({ children, disabled: disabledProp, haptic, icon, iconPos
73
73
  textDecorationLine: pressAnimationProgress.get() > 0 ? "underline" : "none",
74
74
  };
75
75
  });
76
- return (_jsx(Pressable, { disabled: disabled, onPressIn: () => {
76
+ return (_jsx(Pressable, { accessibilityLabel: restProps.accessibilityLabel, accessibilityRole: "button", accessibilityState: {
77
+ disabled,
78
+ }, disabled: disabled, onPressIn: () => {
77
79
  if (loading) {
78
80
  return;
79
81
  }
@@ -1,4 +1,4 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Text } from "../Text";
3
3
  import { Touchable } from "../Touchable";
4
- export const LinkButton = (props) => (_jsx(Touchable, { onPress: props.onPress, children: _jsx(Text, { underline: true, ...props }) }));
4
+ export const LinkButton = (props) => (_jsx(Touchable, { accessibilityRole: "link", onPress: props.onPress, children: _jsx(Text, { underline: true, ...props }) }));
@@ -43,7 +43,9 @@ export const Checkbox = ({ checked: checkedProp, disabled, error, onPress, text,
43
43
  : checkboxStyles[error ? "error" : "default"][isChecked ? "checked" : "unchecked"];
44
44
  const textColor = error ? color("red100") : disabled ? color("mono30") : color("mono100");
45
45
  const subtitleColor = error ? color("red100") : disabled ? color("mono30") : color("mono60");
46
- return (_jsx(TouchableWithoutFeedback, { onPress: (event) => {
46
+ // TODO: migrate away from using this checkbox implementation and
47
+ // use the one from the community solutions - reasoning - this is an inaccessible component
48
+ return (_jsx(TouchableWithoutFeedback, { accessibilityRole: "checkbox", onPress: (event) => {
47
49
  if (disabled) {
48
50
  return;
49
51
  }
@@ -18,7 +18,7 @@ export const Chip = ({ image, title, subtitle, onPress }) => {
18
18
  const handleOnPressOut = () => {
19
19
  animatedState.transitionTo("to");
20
20
  };
21
- return (_jsx(Touchable, { onPress: onPress, onPressIn: handleOnPressIn, onPressOut: handleOnPressOut, noFeedback: true, children: _jsxs(Flex, { flexDirection: "row", minWidth: 200, height: 70, overflow: "hidden", borderRadius: 5, children: [!!image && _jsx(Image, { src: image, width: 70, height: 70 }), _jsxs(View, { state: animatedState, style: {
21
+ return (_jsx(Touchable, { accessibilityRole: "button", accessibilityLabel: title, onPress: onPress, onPressIn: handleOnPressIn, onPressOut: handleOnPressOut, noFeedback: true, children: _jsxs(Flex, { flexDirection: "row", minWidth: 200, height: 70, overflow: "hidden", borderRadius: 5, children: [!!image && _jsx(Image, { src: image, width: 70, height: 70 }), _jsxs(View, { state: animatedState, style: {
22
22
  flex: 1,
23
23
  padding: space(1),
24
24
  justifyContent: "center",
@@ -36,7 +36,7 @@ export const CollapsibleMenuItem = forwardRef(({ children, overtitle, title, isE
36
36
  });
37
37
  },
38
38
  }), [isOpen]);
39
- return (_jsxs(Flex, { ref: componentRef, collapsable: false, children: [_jsxs(Touchable, { onPress: () => {
39
+ return (_jsxs(Flex, { ref: componentRef, collapsable: false, children: [_jsxs(Touchable, { accessibilityRole: "button", accessibilityLabel: "Collapsible Element", accessibilityState: { disabled }, accessibilityHint: "Tap to " + (isOpen ? "collapse" : "expand"), onPress: () => {
40
40
  setIsOpen(!isOpen);
41
41
  isOpen ? onCollapse?.() : onExpand?.();
42
42
  }, disabled: disabled, children: [!!overtitle && (_jsx(Text, { variant: "sm", color: disabled ? "mono30" : "mono100", children: overtitle })), _jsxs(Flex, { flexDirection: "row", justifyContent: "space-between", alignItems: "center", children: [_jsx(Text, { variant: "lg", color: disabled ? "mono30" : "mono100", style: { maxWidth: "90%" }, children: title }), _jsxs(Flex, { flexDirection: "row", alignItems: "center", children: [!!isCompleted && (_jsx(CheckCircleIcon, { fill: "green100", height: 24, width: 24, style: { marginRight: 5 } })), _jsx(ChevronIcon, { direction: isOpen ? "up" : "down", fill: disabled ? "mono30" : "mono60" })] })] })] }), _jsx(Collapse, { opened: isOpen, children: children })] }));
@@ -44,7 +44,7 @@ export const Dialog = (props) => {
44
44
  StyleSheet.absoluteFillObject,
45
45
  { opacity: value, backgroundColor: "rgba(194,194,194,0.5)" },
46
46
  ] }));
47
- return (_jsxs(Modal, { ...other, visible: visible, statusBarTranslucent: true, transparent: true, animationType: "none", children: [!!onBackgroundPress ? (_jsx(TouchableWithoutFeedback, { testID: "dialog-backdrop", onPress: onBackgroundPress, children: backdrop })) : (backdrop), _jsx(SafeAreaView, { pointerEvents: "box-none", style: {
47
+ return (_jsxs(Modal, { ...other, visible: visible, statusBarTranslucent: true, transparent: true, animationType: "none", children: [!!onBackgroundPress ? (_jsx(TouchableWithoutFeedback, { accessibilityRole: "button", accessibilityLabel: "Dismiss", accessibilityHint: "Dismisses the dialog", testID: "dialog-backdrop", onPress: onBackgroundPress, children: backdrop })) : (backdrop), _jsx(SafeAreaView, { pointerEvents: "box-none", style: {
48
48
  flex: 1,
49
49
  justifyContent: "center",
50
50
  alignItems: "center",
@@ -206,7 +206,7 @@ export const Input = forwardRef(({ addClearListener = false, defaultValue, disab
206
206
  }, children: [unit && (_jsx(Text, { color: disabled ? "mono30" : "mono60", variant: "sm-display", children: unit })), icon] }));
207
207
  }
208
208
  if (onSelectTap) {
209
- return (_jsx(TouchableOpacity, { onPress: onSelectTap, style: [
209
+ return (_jsx(TouchableOpacity, { accessibilityRole: "button", onPress: onSelectTap, style: [
210
210
  leftComponentSharedStyles,
211
211
  {
212
212
  width: selectComponentWidth,
@@ -248,7 +248,7 @@ export const Input = forwardRef(({ addClearListener = false, defaultValue, disab
248
248
  } }) }));
249
249
  }
250
250
  if (enableClearButton && value) {
251
- return (_jsx(Flex, { justifyContent: "center", position: "absolute", right: `${HORIZONTAL_PADDING}px`, top: hasTitle ? LABEL_HEIGHT : 0, height: INPUT_MIN_HEIGHT, zIndex: 100, ref: rightComponentRef, children: _jsx(Touchable, { haptic: "impactMedium", onPress: handleClear, hitSlop: { bottom: 40, right: 40, left: 0, top: 40 }, accessibilityLabel: "Clear input button", testID: "clear-input-button", children: _jsx(XCircleIcon, { fill: "mono30" }) }) }));
251
+ return (_jsx(Flex, { justifyContent: "center", position: "absolute", right: `${HORIZONTAL_PADDING}px`, top: hasTitle ? LABEL_HEIGHT : 0, height: INPUT_MIN_HEIGHT, zIndex: 100, ref: rightComponentRef, children: _jsx(Touchable, { haptic: "impactMedium", onPress: handleClear, hitSlop: { bottom: 40, right: 40, left: 0, top: 40 }, accessibilityRole: "button", accessibilityHint: "Clears the input", accessibilityLabel: "Clear", testID: "clear-input-button", children: _jsx(XCircleIcon, { fill: "mono30" }) }) }));
252
252
  }
253
253
  if (secureTextEntry) {
254
254
  return (_jsx(Flex, { justifyContent: "center", position: "absolute", right: `${HORIZONTAL_PADDING}px`, top: hasTitle ? LABEL_HEIGHT : 0, height: INPUT_MIN_HEIGHT, zIndex: 100, ref: rightComponentRef, children: _jsx(Touchable, { haptic: true, onPress: () => {
@@ -257,7 +257,7 @@ export const Input = forwardRef(({ addClearListener = false, defaultValue, disab
257
257
  duration: 200,
258
258
  });
259
259
  setShowPassword(!showPassword);
260
- }, accessibilityLabel: showPassword ? "hide password button" : "show password button", hitSlop: { bottom: 40, right: 40, left: 0, top: 40 }, children: !showPassword ? _jsx(EyeClosedIcon, { fill: "mono30" }) : _jsx(EyeOpenedIcon, { fill: "mono60" }) }) }));
260
+ }, accessibilityRole: "button", accessibilityLabel: showPassword ? "hide password icon" : "show password icon", accessibilityHint: showPassword ? "Hides the password" : "Shows the password", hitSlop: { bottom: 40, right: 40, left: 0, top: 40 }, children: !showPassword ? _jsx(EyeClosedIcon, { fill: "mono30" }) : _jsx(EyeOpenedIcon, { fill: "mono60" }) }) }));
261
261
  }
262
262
  return null;
263
263
  }, [
@@ -287,7 +287,7 @@ export const Input = forwardRef(({ addClearListener = false, defaultValue, disab
287
287
  return (_jsx(Flex, { style: {
288
288
  alignItems: "flex-end",
289
289
  top: space(2),
290
- }, children: _jsx(Touchable, { onPress: props.onHintPress, haptic: "impactLight", hitSlop: {
290
+ }, children: _jsx(Touchable, { accessibilityRole: "button", accessibilityHint: "hint", onPress: props.onHintPress, haptic: "impactLight", hitSlop: {
291
291
  top: 5,
292
292
  right: 10,
293
293
  bottom: 5,
@@ -332,7 +332,7 @@ export const Input = forwardRef(({ addClearListener = false, defaultValue, disab
332
332
  if (!props.title) {
333
333
  return null;
334
334
  }
335
- return (_jsx(Flex, { flexDirection: "row", zIndex: 100, pointerEvents: "none", height: LABEL_HEIGHT, children: _jsxs(AnimatedText, { style: [labelStyles, labelAnimatedStyles], numberOfLines: 1, children: [" ", props.title, " "] }) }));
335
+ return (_jsx(Flex, { flexDirection: "row", zIndex: 100, pointerEvents: "none", height: LABEL_HEIGHT, children: _jsxs(AnimatedText, { style: [labelStyles, labelAnimatedStyles], numberOfLines: 1, accessibilityLabel: "input label", children: [" ", props.title, " "] }) }));
336
336
  }, [labelStyles, labelAnimatedStyles, props.title]);
337
337
  const renderAndroidPlaceholderMeasuringHack = useCallback(() => {
338
338
  if (Platform.OS === "ios" || !isArray(placeholder)) {
@@ -24,21 +24,21 @@ describe("Input", () => {
24
24
  it("should render the clear button when input is not empty and pressing it should clear the input", async () => {
25
25
  renderWithWrappers(_jsx(Input, { testID: testID, placeholder: "USD", enableClearButton: true }));
26
26
  fireEvent(screen.getByTestId(testID), "onChangeText", "Banksy");
27
- await screen.findByLabelText("Clear input button");
28
- fireEvent.press(screen.getByLabelText("Clear input button"));
27
+ await screen.findByLabelText("Clear");
28
+ fireEvent.press(screen.getByLabelText("Clear"));
29
29
  expect(screen.queryByDisplayValue("Banksy")).toBeFalsy();
30
30
  });
31
31
  it("should show the correct show/hide password icon", () => {
32
32
  renderWithWrappers(_jsx(Input, { placeholder: "password", secureTextEntry: true }));
33
33
  screen.getByPlaceholderText("password");
34
- screen.getByLabelText("show password button");
34
+ screen.getByLabelText("show password icon");
35
35
  fireEvent(screen.getByPlaceholderText("password"), "onChangeText", "123456");
36
- fireEvent.press(screen.getByLabelText("show password button"));
37
- expect(screen.queryByLabelText("show password button")).toBeFalsy();
38
- screen.getByLabelText("hide password button");
39
- fireEvent.press(screen.getByLabelText("hide password button"));
40
- expect(screen.queryByLabelText("hide password button")).toBeFalsy();
41
- screen.getByLabelText("show password button");
36
+ fireEvent.press(screen.getByLabelText("show password icon"));
37
+ expect(screen.queryByLabelText("show password icon")).toBeFalsy();
38
+ screen.getByLabelText("hide password icon");
39
+ fireEvent.press(screen.getByLabelText("hide password icon"));
40
+ expect(screen.queryByLabelText("hide password icon")).toBeFalsy();
41
+ screen.getByLabelText("show password icon");
42
42
  });
43
43
  it("enables scrolling when multiline is true", () => {
44
44
  renderWithWrappers(_jsx(Input, { testID: testID, multiline: true }));
@@ -46,7 +46,7 @@ const NAVBAR_HEIGHT = 44;
46
46
  export const Header = ({ onBack, title, onSkip }) => {
47
47
  useUpdateScreenContext({ header: "regular" });
48
48
  const insets = useSafeAreaInsets();
49
- return (_jsxs(Flex, { mt: `${insets.top}px`, height: NAVBAR_HEIGHT, flexDirection: "row", alignItems: "center", justifyContent: "space-between", px: SCREEN_HORIZONTAL_PADDING, children: [_jsx(Flex, { children: !!onBack && (_jsx(BackButton, { onPress: onBack, style: { flex: 1, justifyContent: "center" }, hitSlop: { left: 20, right: 20 } })) }), !!title && _jsx(Text, { children: title }), !!onSkip && (_jsx(Touchable, { haptic: "impactLight", onPress: onSkip, children: _jsx(Flex, { height: "100%", justifyContent: "center", children: _jsx(Text, { textAlign: "right", variant: "xs", children: "Skip" }) }) }))] }));
49
+ return (_jsxs(Flex, { mt: `${insets.top}px`, height: NAVBAR_HEIGHT, flexDirection: "row", alignItems: "center", justifyContent: "space-between", px: SCREEN_HORIZONTAL_PADDING, children: [_jsx(Flex, { children: !!onBack && (_jsx(BackButton, { onPress: onBack, style: { flex: 1, justifyContent: "center" }, hitSlop: { left: 20, right: 20 } })) }), !!title && _jsx(Text, { children: title }), !!onSkip && (_jsx(Touchable, { accessibilityRole: "button", haptic: "impactLight", onPress: onSkip, children: _jsx(Flex, { height: "100%", justifyContent: "center", children: _jsx(Text, { textAlign: "right", variant: "xs", children: "Skip" }) }) }))] }));
50
50
  };
51
51
  /**
52
52
  * @deprecated Use `Screen.Header` instead.
@@ -20,7 +20,7 @@ export const StepTabs = ({ onTabPress, activeTab, tabs }) => {
20
20
  onTabPress(label, index);
21
21
  };
22
22
  return (_jsx(TabBarContainer, { scrollEnabled: false, activeTabIndex: activeTab, tabLayouts: tabLayouts, children: tabs.map(({ label, completed }, index) => {
23
- return (_jsx(TouchableOpacity, { onPress: () => onTabSelect(label, index), children: _jsxs(Box, { width: tabWidth, justifyContent: "space-between", flexDirection: "row", alignItems: "center", onLayout: (e) => {
23
+ return (_jsx(TouchableOpacity, { accessibilityRole: "button", onPress: () => onTabSelect(label, index), children: _jsxs(Box, { width: tabWidth, justifyContent: "space-between", flexDirection: "row", alignItems: "center", onLayout: (e) => {
24
24
  const layout = e.nativeEvent.layout;
25
25
  setTabLayouts((layouts) => {
26
26
  const result = layouts.slice(0);
@@ -4,7 +4,7 @@ import { useColor } from "../../utils/hooks";
4
4
  import { Text } from "../Text";
5
5
  export const TabV3 = ({ label, superscript, active, onLayout, onPress, style }) => {
6
6
  const color = useColor();
7
- return (_jsx(Pressable, { onPress: onPress, children: ({ pressed }) => (_jsxs(View, { onLayout: onLayout, style: {
7
+ return (_jsx(Pressable, { accessibilityRole: "button", onPress: onPress, children: ({ pressed }) => (_jsxs(View, { onLayout: onLayout, style: {
8
8
  alignItems: "center",
9
9
  justifyContent: "center",
10
10
  paddingHorizontal: 15,
@@ -6,5 +6,5 @@ import { Text } from "../Text";
6
6
  import { Touchable } from "../Touchable";
7
7
  export const MenuItem = ({ title, text, value, onPress, disabled = false, chevron = _jsx(ChevronIcon, { direction: "right", fill: "mono60" }), }) => {
8
8
  const color = useColor();
9
- return (_jsx(Touchable, { onPress: onPress, underlayColor: color("mono5"), disabled: disabled, children: _jsxs(Flex, { flexDirection: "row", alignItems: "center", justifyContent: "space-between", py: 2, px: 2, pr: "15px", children: [_jsx(Flex, { flexDirection: "row", mr: 2, children: _jsx(Text, { variant: "md", color: "onBackgroundHigh", children: title }) }), !!value && (_jsx(Flex, { flex: 1, children: _jsx(Text, { variant: "md", color: "mono60", numberOfLines: 1, textAlign: "right", children: value }) })), !!(onPress && chevron) && _jsx(Flex, { ml: 1, children: chevron }), !!text && (_jsx(Text, { variant: "md", color: color("mono60"), children: text }))] }) }));
9
+ return (_jsx(Touchable, { accessibilityRole: "button", accessibilityState: { disabled }, accessibilityLabel: "Menu item ${title}", onPress: onPress, underlayColor: color("mono5"), disabled: disabled, children: _jsxs(Flex, { flexDirection: "row", alignItems: "center", justifyContent: "space-between", py: 2, px: 2, pr: "15px", children: [_jsx(Flex, { flexDirection: "row", mr: 2, children: _jsx(Text, { variant: "md", color: "onBackgroundHigh", children: title }) }), !!value && (_jsx(Flex, { flex: 1, children: _jsx(Text, { variant: "md", color: "mono60", numberOfLines: 1, textAlign: "right", children: value }) })), !!(onPress && chevron) && _jsx(Flex, { ml: 1, children: chevron }), !!text && (_jsx(Text, { variant: "md", color: color("mono60"), children: text }))] }) }));
10
10
  };
@@ -30,7 +30,7 @@ export const Message = ({ bodyTextStyle, children, containerStyle, IconComponent
30
30
  }),
31
31
  },
32
32
  ],
33
- }, children: _jsxs(Flex, { px: 2, backgroundColor: color(colors[variant].background), ...containerStyle, children: [_jsxs(Flex, { py: 1, flexDirection: "row", justifyContent: "space-between", children: [_jsxs(Flex, { flex: 1, children: [_jsxs(Flex, { flexDirection: "row", children: [!!IconComponent && iconPosition === "left" && (_jsx(Flex, { mr: 1, testID: "icon-component-left", children: _jsx(IconComponent, {}) })), !!title && (_jsx(Text, { pr: 2, variant: "xs", color: color(colors[variant].title), ...titleStyle, children: title }))] }), !!text && (_jsx(Text, { variant: "xs", color: color(colors[variant].text), ...bodyTextStyle, children: text })), children] }), !!IconComponent && iconPosition === "right" && (_jsx(Flex, { mr: showCloseButton ? 1 : 0, justifyContent: "center", testID: "icon-component-right", children: _jsx(IconComponent, {}) })), !!showCloseButton && (_jsx(Flex, { style: { marginTop: 2 }, children: _jsx(TouchableOpacity, { testID: "Message-close-button", onPress: handleClose, hitSlop: { bottom: 10, right: 10, left: 10, top: 10 }, children: _jsx(CloseIcon, { fill: colors[variant].icon }) }) }))] }), !!IconComponent && iconPosition === "bottom" && (_jsx(Flex, { mb: 1, justifyContent: "center", testID: "icon-component-bottom", children: _jsx(IconComponent, {}) }))] }) }));
33
+ }, children: _jsxs(Flex, { px: 2, backgroundColor: color(colors[variant].background), ...containerStyle, children: [_jsxs(Flex, { py: 1, flexDirection: "row", justifyContent: "space-between", children: [_jsxs(Flex, { flex: 1, children: [_jsxs(Flex, { flexDirection: "row", children: [!!IconComponent && iconPosition === "left" && (_jsx(Flex, { mr: 1, testID: "icon-component-left", children: _jsx(IconComponent, {}) })), !!title && (_jsx(Text, { pr: 2, variant: "xs", color: color(colors[variant].title), ...titleStyle, children: title }))] }), !!text && (_jsx(Text, { variant: "xs", color: color(colors[variant].text), ...bodyTextStyle, children: text })), children] }), !!IconComponent && iconPosition === "right" && (_jsx(Flex, { mr: showCloseButton ? 1 : 0, justifyContent: "center", testID: "icon-component-right", children: _jsx(IconComponent, {}) })), !!showCloseButton && (_jsx(Flex, { style: { marginTop: 2 }, children: _jsx(TouchableOpacity, { accessibilityRole: "button", accessibilityHint: "Dismiss message", testID: "Message-close-button", onPress: handleClose, hitSlop: { bottom: 10, right: 10, left: 10, top: 10 }, children: _jsx(CloseIcon, { fill: colors[variant].icon }) }) }))] }), !!IconComponent && iconPosition === "bottom" && (_jsx(Flex, { mb: 1, justifyContent: "center", testID: "icon-component-bottom", children: _jsx(IconComponent, {}) }))] }) }));
34
34
  };
35
35
  const colors = {
36
36
  default: {
@@ -45,7 +45,7 @@ export const RadioButton = ({ accessibilityState, block, disabled, error, onPres
45
45
  radioButtonStyle,
46
46
  ], animate: ["borderColor"], duration: DURATION, children: !!selected &&
47
47
  (!!disabled ? (_jsx(DisabledDot, { size: radioButtonSize })) : (_jsx(RadioDot, { size: radioButtonSize }))) }) }));
48
- return (_jsx(TouchableWithoutFeedback, { accessibilityState: accessibilityState, onPress: (event) => {
48
+ return (_jsx(TouchableWithoutFeedback, { accessibilityRole: "radio", accessibilityState: accessibilityState, onPress: (event) => {
49
49
  if (disabled) {
50
50
  return;
51
51
  }
@@ -47,5 +47,5 @@ const Center = ({ animated, hideTitle, title }) => {
47
47
  const Left = ({ hideLeftElements, leftElements, onBack }) => {
48
48
  if (hideLeftElements)
49
49
  return null;
50
- return (_jsx(_Fragment, { children: leftElements || (_jsx(Touchable, { onPress: onBack, underlayColor: "transparent", hitSlop: DEFAULT_HIT_SLOP, children: _jsx(ArrowLeftIcon, { fill: "onBackgroundHigh" }) })) }));
50
+ return (_jsx(_Fragment, { children: leftElements || (_jsx(Touchable, { accessibilityRole: "button", accessibilityLabel: "Back", accessibilityHint: "Navigates to the previous screen", onPress: onBack, underlayColor: "transparent", hitSlop: DEFAULT_HIT_SLOP, children: _jsx(ArrowLeftIcon, { fill: "onBackgroundHigh" }) })) }));
51
51
  };
@@ -84,7 +84,7 @@ export const RoundSearchInput = ({ value, placeholder, onLeftIconPress, ...rest
84
84
  rest.onFocus?.(e);
85
85
  }, enterKeyHint: "search", returnKeyType: "search" }), _jsx(Flex, { position: "absolute", height: SEARCH_INPUT_CONTAINER_HEIGHT, justifyContent: "center", alignItems: "center", style: {
86
86
  paddingHorizontal: CONTAINER_HORIZONTAL_PADDING,
87
- }, children: _jsx(Touchable, { onPress: () => {
87
+ }, children: _jsx(Touchable, { accessibilityRole: "button", accessibilityLabel: `${isFocused ? "Back" : "Search"}`, onPress: () => {
88
88
  ref.current?.blur();
89
89
  setIsFocused(false);
90
90
  onLeftIconPress?.();
@@ -14,7 +14,7 @@ const TAB_BAR_HEIGHT = 50;
14
14
  const PillTabItem = ({ focusedTab: focusedTabProp, ...props }) => {
15
15
  const [focusedTab, setFocusedTab] = useState(focusedTabProp.value);
16
16
  // We want to debounce the focusedTab value to avoid showing two pills at once
17
- const debouncedFocusedTab = debounce(setFocusedTab, 30);
17
+ const debouncedFocusedTab = debounce(setFocusedTab, 50);
18
18
  useAnimatedReaction(() => focusedTabProp.value, (value) => {
19
19
  runOnJS(debouncedFocusedTab)(value);
20
20
  });
@@ -40,7 +40,7 @@ export const ToolTipFlyout = ({ containerStyle, tapToDismiss, height, width, onC
40
40
  handleClose();
41
41
  }
42
42
  };
43
- return (_jsx(TouchableWithoutFeedback, { onPress: onPress, testID: testID, children: _jsx(Animated.View, { style: [
43
+ return (_jsx(TouchableWithoutFeedback, { accessibilityLabel: "Tooltip", accessibilityHint: "Tap to dismiss", onPress: onPress, testID: testID, children: _jsx(Animated.View, { style: [
44
44
  {
45
45
  backgroundColor: color("mono100"),
46
46
  position: "absolute",
@@ -8,4 +8,4 @@ export default {
8
8
  title: "Touchable",
9
9
  component: Touchable,
10
10
  };
11
- export const Examples = () => (_jsxs(List, { children: [_jsx(Touchable, { children: _jsx(Text, { children: "This is a text wrapped in a `Touchable`." }) }), _jsx(Touchable, { children: _jsxs(Flex, { width: 200, alignItems: "center", borderColor: "red", borderWidth: 1, children: [_jsx(TrashIcon, {}), _jsx(Text, { children: "This is a cell with an icon and a text, wrapped in a `Touchable`." })] }) })] }));
11
+ export const Examples = () => (_jsxs(List, { children: [_jsx(Touchable, { accessibilityRole: "button", children: _jsx(Text, { children: "This is a text wrapped in a `Touchable`." }) }), _jsx(Touchable, { accessibilityRole: "button", children: _jsxs(Flex, { width: 200, alignItems: "center", borderColor: "red", borderWidth: 1, children: [_jsx(TrashIcon, {}), _jsx(Text, { children: "This is a cell with an icon and a text, wrapped in a `Touchable`." })] }) })] }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@artsy/palette-mobile",
3
- "version": "17.6.0",
3
+ "version": "17.8.0",
4
4
  "description": "Artsy's design system for React Native",
5
5
  "scripts": {
6
6
  "android": "RCT_METRO_PORT=8082 react-native run-android --port 8082 --terminal terminal",
@@ -107,6 +107,7 @@
107
107
  "eslint-plugin-prettier": "4.2.1",
108
108
  "eslint-plugin-react": "7.32.2",
109
109
  "eslint-plugin-react-hooks": "^4.6.0",
110
+ "eslint-plugin-react-native-a11y": "^3.5.1",
110
111
  "eslint-plugin-storybook": "0.6.10",
111
112
  "eslint-plugin-testing-library": "6.4.0",
112
113
  "husky": "^8.0.3",