diff --git a/src/CONST.js b/src/CONST.js
index 3326bfd69bb6..a36bf2459ee9 100755
--- a/src/CONST.js
+++ b/src/CONST.js
@@ -2280,6 +2280,11 @@ const CONST = {
'PLN', 'GBP', 'RUB', 'SGD', 'SEK', 'CHF', 'THB', 'USD',
],
CONCIERGE_TRAVEL_URL: 'https://community.expensify.com/discussion/7066/introducing-concierge-travel',
+ SCREEN_READER_STATES: {
+ ALL: 'all',
+ ACTIVE: 'active',
+ DISABLED: 'disabled',
+ },
};
export default CONST;
diff --git a/src/components/OpacityView.js b/src/components/OpacityView.js
index 9b9d24861323..2b0958ae7db5 100644
--- a/src/components/OpacityView.js
+++ b/src/components/OpacityView.js
@@ -1,71 +1,63 @@
import React from 'react';
-import {Animated} from 'react-native';
+import Animated, {useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated';
import PropTypes from 'prop-types';
+import * as StyleUtils from '../styles/StyleUtils';
+import variables from '../styles/variables';
const propTypes = {
- // Should we dim the view
+ /**
+ * Should we dim the view
+ */
shouldDim: PropTypes.bool.isRequired,
- // Content to render
+ /**
+ * Content to render
+ */
children: PropTypes.node.isRequired,
- // Array of style objects
+ /**
+ * Array of style objects
+ * @default []
+ */
// eslint-disable-next-line react/forbid-prop-types
style: PropTypes.arrayOf(PropTypes.object),
+
+ /**
+ * The value to use for the opacity when the view is dimmed
+ * @default 0.5
+ */
+ dimmingValue: PropTypes.number,
};
const defaultProps = {
style: [],
+ dimmingValue: variables.hoverDimValue,
};
-class OpacityView extends React.Component {
- constructor(props) {
- super(props);
- this.opacity = new Animated.Value(1);
- this.undim = this.undim.bind(this);
- }
-
- componentDidUpdate(prevProps) {
- if (!prevProps.shouldDim && this.props.shouldDim) {
- Animated.timing(this.opacity, {
- toValue: 0.5,
- duration: 50,
- useNativeDriver: true,
- }).start();
- }
-
- if (prevProps.shouldDim && !this.props.shouldDim) {
- this.undim();
+const OpacityView = (props) => {
+ const opacity = useSharedValue(1);
+ const opacityStyle = useAnimatedStyle(() => ({
+ opacity: opacity.value,
+ }));
+
+ React.useEffect(() => {
+ if (props.shouldDim) {
+ opacity.value = withTiming(props.dimmingValue, {duration: 50});
+ } else {
+ opacity.value = withTiming(1, {duration: 50});
}
- }
-
- undim() {
- Animated.timing(this.opacity, {
- toValue: 1,
- duration: 50,
- useNativeDriver: true,
- }).start(({finished}) => {
- // If animation doesn't finish because Animation.stop was called
- // (e.g. because it was interrupted by a gesture or another animation),
- // restart animation so we always make sure the component gets completely shown.
- if (finished) {
- return;
- }
- this.undim();
- });
- }
-
- render() {
- return (
-
- {this.props.children}
-
- );
- }
-}
+ }, [props.shouldDim, props.dimmingValue, opacity]);
+
+ return (
+
+ {props.children}
+
+ );
+};
+OpacityView.displayName = 'OpacityView';
OpacityView.propTypes = propTypes;
OpacityView.defaultProps = defaultProps;
export default OpacityView;
diff --git a/src/components/Pressable/GenericPressable/BaseGenericPressable.js b/src/components/Pressable/GenericPressable/BaseGenericPressable.js
new file mode 100644
index 000000000000..6caba1c39cd0
--- /dev/null
+++ b/src/components/Pressable/GenericPressable/BaseGenericPressable.js
@@ -0,0 +1,158 @@
+import React, {
+ useCallback,
+ useEffect,
+ useMemo,
+ forwardRef,
+} from 'react';
+import {Pressable} from 'react-native';
+import _ from 'underscore';
+import Accessibility from '../../../libs/Accessibility';
+import HapticFeedback from '../../../libs/HapticFeedback';
+import KeyboardShortcut from '../../../libs/KeyboardShortcut';
+import styles from '../../../styles/styles';
+import cursor from '../../../styles/utilities/cursor';
+import genericPressablePropTypes from './PropTypes';
+import CONST from '../../../CONST';
+import * as StyleUtils from '../../../styles/StyleUtils';
+
+/**
+ * Returns the cursor style based on the state of Pressable
+ * @param {Boolean} isDisabled
+ * @param {Boolean} isText
+ * @returns {Object}
+ */
+const getCursorStyle = (isDisabled, isText) => {
+ if (isDisabled) {
+ return cursor.cursorDisabled;
+ }
+
+ if (isText) {
+ return cursor.cursorText;
+ }
+
+ return cursor.cursorPointer;
+};
+
+const GenericPressable = forwardRef((props, ref) => {
+ const {
+ children,
+ onPress,
+ onLongPress,
+ onKeyPress,
+ disabled,
+ style,
+ accessibilityHint,
+ shouldUseHapticsOnLongPress,
+ shouldUseHapticsOnPress,
+ nextFocusRef,
+ keyboardShortcut,
+ shouldUseAutoHitSlop,
+ enableInScreenReaderStates,
+ onPressIn,
+ onPressOut,
+ ...rest
+ } = props;
+
+ const isScreenReaderActive = Accessibility.useScreenReaderStatus();
+ const [hitSlop, onLayout] = Accessibility.useAutoHitSlop();
+
+ const isDisabled = useMemo(() => {
+ let shouldBeDisabledByScreenReader = false;
+ if (enableInScreenReaderStates === CONST.SCREEN_READER_STATES.ACTIVE) {
+ shouldBeDisabledByScreenReader = !isScreenReaderActive;
+ }
+
+ if (enableInScreenReaderStates === CONST.SCREEN_READER_STATES.DISABLED) {
+ shouldBeDisabledByScreenReader = isScreenReaderActive;
+ }
+
+ return props.disabled || shouldBeDisabledByScreenReader;
+ }, [isScreenReaderActive, enableInScreenReaderStates, props.disabled]);
+
+ const onLongPressHandler = useCallback(() => {
+ if (!onLongPress) {
+ return;
+ }
+ if (shouldUseHapticsOnLongPress) {
+ HapticFeedback.longPress();
+ }
+ if (ref.current) {
+ ref.current.blur();
+ }
+ onLongPress();
+
+ Accessibility.moveAccessibilityFocus(nextFocusRef);
+ }, [shouldUseHapticsOnLongPress, onLongPress, nextFocusRef, ref]);
+
+ const onPressHandler = useCallback(() => {
+ if (shouldUseHapticsOnPress) {
+ HapticFeedback.press();
+ }
+ if (ref.current) {
+ ref.current.blur();
+ }
+ onPress();
+
+ Accessibility.moveAccessibilityFocus(nextFocusRef);
+ }, [shouldUseHapticsOnPress, onPress, nextFocusRef, ref]);
+
+ const onKeyPressHandler = useCallback((event) => {
+ if (event.key !== 'Enter') {
+ return;
+ }
+ onPressHandler();
+ }, [onPressHandler]);
+
+ useEffect(() => {
+ if (!keyboardShortcut) {
+ return () => {};
+ }
+ const {shortcutKey, descriptionKey, modifiers} = keyboardShortcut;
+ return KeyboardShortcut.subscribe(shortcutKey, onPressHandler, descriptionKey, modifiers, true, false, 0, false);
+ }, [keyboardShortcut, onPressHandler]);
+
+ return (
+ [
+ getCursorStyle(isDisabled, [props.accessibilityRole, props.role].includes('text')),
+ props.style,
+ isScreenReaderActive && StyleUtils.parseStyleFromFunction(props.screenReaderActiveStyle, state),
+ state.focused && StyleUtils.parseStyleFromFunction(props.focusStyle, state),
+ state.hovered && StyleUtils.parseStyleFromFunction(props.hoverStyle, state),
+ state.pressed && StyleUtils.parseStyleFromFunction(props.pressStyle, state),
+ isDisabled && [...StyleUtils.parseStyleFromFunction(props.disabledStyle, state), styles.noSelect],
+ ]}
+
+ // accessibility props
+ accessibilityState={{
+ disabled: isDisabled,
+ ...props.accessibilityState,
+ }}
+ aria-disabled={isDisabled}
+ aria-keyshortcuts={keyboardShortcut && `${keyboardShortcut.modifiers}+${keyboardShortcut.shortcutKey}`}
+
+ // ios-only form of inputs
+ onMagicTap={!isDisabled && onPressHandler}
+ onAccessibilityTap={!isDisabled && onPressHandler}
+
+ // eslint-disable-next-line react/jsx-props-no-spreading
+ {...rest}
+ >
+ {state => (_.isFunction(props.children) ? props.children({...state, isScreenReaderActive, isDisabled}) : props.children)}
+
+ );
+});
+
+GenericPressable.displayName = 'GenericPressable';
+GenericPressable.propTypes = genericPressablePropTypes.pressablePropTypes;
+GenericPressable.defaultProps = genericPressablePropTypes.defaultProps;
+
+export default GenericPressable;
diff --git a/src/components/Pressable/GenericPressable/PropTypes.js b/src/components/Pressable/GenericPressable/PropTypes.js
new file mode 100644
index 000000000000..a87f8d83c02a
--- /dev/null
+++ b/src/components/Pressable/GenericPressable/PropTypes.js
@@ -0,0 +1,130 @@
+import PropTypes from 'prop-types';
+import stylePropType from '../../../styles/stylePropTypes';
+import CONST from '../../../CONST';
+
+const stylePropTypeWithFunction = PropTypes.oneOfType([
+ stylePropType,
+ PropTypes.func,
+]);
+
+const pressablePropTypes = {
+ /**
+ * onPress callback
+ */
+ onPress: PropTypes.func.isRequired,
+
+ /**
+ * Specifies keyboard shortcut to trigger onPressHandler
+ * @example {shortcutKey: 'a', modifiers: ['ctrl', 'shift'], descriptionKey: 'keyboardShortcut.description'}
+ */
+ keyboardShortcut: PropTypes.shape({
+ descriptionKey: PropTypes.string.isRequired,
+ shortcutKey: PropTypes.string.isRequired,
+ modifiers: PropTypes.arrayOf(PropTypes.string),
+ }),
+
+ /**
+ * Specifies if haptic feedback should be used on press
+ * @default false
+ */
+ shouldUseHapticsOnPress: PropTypes.bool,
+
+ /**
+ * Specifies if haptic feedback should be used on long press
+ * @default false
+ */
+ shouldUseHapticsOnLongPress: PropTypes.bool,
+
+ /**
+ * style for when the component is disabled. Can be a function that receives the component's state (active, disabled, hover, focus, pressed, isScreenReaderActive)
+ * @default {}
+ * @example {backgroundColor: 'red'}
+ * @example state => ({backgroundColor: state.isDisabled ? 'red' : 'blue'})
+ */
+ disabledStyle: stylePropTypeWithFunction,
+
+ /**
+ * style for when the component is hovered. Can be a function that receives the component's state (active, disabled, hover, focus, pressed, isScreenReaderActive)
+ * @default {}
+ * @example {backgroundColor: 'red'}
+ * @example state => ({backgroundColor: state.hovered ? 'red' : 'blue'})
+ */
+ hoverStyle: stylePropTypeWithFunction,
+
+ /**
+ * style for when the component is focused. Can be a function that receives the component's state (active, disabled, hover, focus, pressed, isScreenReaderActive)
+ * @default {}
+ * @example {backgroundColor: 'red'}
+ * @example state => ({backgroundColor: state.focused ? 'red' : 'blue'})
+ */
+ focusStyle: stylePropTypeWithFunction,
+
+ /**
+ * style for when the component is pressed. Can be a function that receives the component's state (active, disabled, hover, focus, pressed, isScreenReaderActive)
+ * @default {}
+ * @example {backgroundColor: 'red'}
+ * @example state => ({backgroundColor: state.pressed ? 'red' : 'blue'})
+ */
+ pressStyle: stylePropTypeWithFunction,
+
+ /**
+ * style for when the component is active and the screen reader is on.
+ * Can be a function that receives the component's state (active, disabled, hover, focus, pressed, isScreenReaderActive)
+ * @default {}
+ * @example {backgroundColor: 'red'}
+ * @example state => ({backgroundColor: state.isScreenReaderActive ? 'red' : 'blue'})
+ */
+ screenReaderActiveStyle: stylePropTypeWithFunction,
+
+ /**
+ * Specifies if the component should be accessible when the screen reader is on
+ * @default 'all'
+ * @example 'all' - the component is accessible regardless of screen reader state
+ * @example 'active' - the component is accessible only when the screen reader is on
+ * @example 'disabled' - the component is not accessible when the screen reader is on
+ */
+ enableInScreenReaderStates: PropTypes.oneOf([CONST.SCREEN_READER_STATES.ALL, CONST.SCREEN_READER_STATES.ACTIVE, CONST.SCREEN_READER_STATES.DISABLED]),
+
+ /**
+ * Specifies which component should be focused after interacting with this component
+ */
+ nextFocusRef: PropTypes.func,
+
+ /**
+ * Specifies the accessibility label for the component
+ * @example 'Search'
+ * @example 'Close'
+ */
+ accessibilityLabel: PropTypes.string.isRequired,
+
+ /**
+ * Specifies the accessibility hint for the component
+ * @example 'Double tap to open'
+ */
+ accessibilityHint: PropTypes.string,
+
+ /**
+ * Specifies if the component should calculate its hitSlop automatically
+ * @default true
+ */
+ shouldUseAutoHitSlop: PropTypes.bool,
+};
+
+const defaultProps = {
+ keyboardShortcut: undefined,
+ shouldUseHapticsOnPress: false,
+ shouldUseHapticsOnLongPress: false,
+ disabledStyle: {},
+ hoverStyle: {},
+ focusStyle: {},
+ pressStyle: {},
+ screenReaderActiveStyle: {},
+ enableInScreenReaderStates: CONST.SCREEN_READER_STATES.ALL,
+ nextFocusRef: undefined,
+ shouldUseAutoHitSlop: true,
+};
+
+export default {
+ pressablePropTypes,
+ defaultProps,
+};
diff --git a/src/components/Pressable/GenericPressable/index.js b/src/components/Pressable/GenericPressable/index.js
new file mode 100644
index 000000000000..a5125653b949
--- /dev/null
+++ b/src/components/Pressable/GenericPressable/index.js
@@ -0,0 +1,24 @@
+import React, {forwardRef} from 'react';
+import GenericPressable from './BaseGenericPressable';
+import GenericPressablePropTypes from './PropTypes';
+
+const WebGenericPressable = forwardRef((props, ref) => (
+
+));
+
+WebGenericPressable.propTypes = GenericPressablePropTypes.pressablePropTypes;
+WebGenericPressable.defaultProps = GenericPressablePropTypes.defaultProps;
+
+export default WebGenericPressable;
diff --git a/src/components/Pressable/GenericPressable/index.native.js b/src/components/Pressable/GenericPressable/index.native.js
new file mode 100644
index 000000000000..02f06dad8a02
--- /dev/null
+++ b/src/components/Pressable/GenericPressable/index.native.js
@@ -0,0 +1,20 @@
+import React, {forwardRef} from 'react';
+import GenericPressable from './BaseGenericPressable';
+import GenericPressablePropTypes from './PropTypes';
+
+const NativeGenericPressable = forwardRef((props, ref) => (
+
+));
+
+NativeGenericPressable.propTypes = GenericPressablePropTypes.pressablePropTypes;
+NativeGenericPressable.defaultProps = GenericPressablePropTypes.defaultProps;
+
+export default NativeGenericPressable;
diff --git a/src/components/Pressable/PressableWithFeedback.js b/src/components/Pressable/PressableWithFeedback.js
new file mode 100644
index 000000000000..66401fc1d974
--- /dev/null
+++ b/src/components/Pressable/PressableWithFeedback.js
@@ -0,0 +1,52 @@
+import React, {forwardRef} from 'react';
+import _ from 'underscore';
+import propTypes from 'prop-types';
+import GenericPressable from './GenericPressable';
+import GenericPressablePropTypes from './GenericPressable/PropTypes';
+import OpacityView from '../OpacityView';
+import variables from '../../styles/variables';
+import * as StyleUtils from '../../styles/StyleUtils';
+
+const omittedProps = ['style', 'pressStyle', 'hoverStyle', 'focusStyle', 'wrapperStyle'];
+
+const PressableWithFeedbackPropTypes = {
+ ..._.omit(GenericPressablePropTypes.pressablePropTypes, omittedProps),
+ pressDimmingValue: propTypes.number,
+ hoverDimmingValue: propTypes.number,
+};
+
+const PressableWithFeedbackDefaultProps = {
+ ..._.omit(GenericPressablePropTypes.defaultProps, omittedProps),
+ pressDimmingValue: variables.pressDimValue,
+ hoverDimmingValue: variables.hoverDimValue,
+ wrapperStyle: [],
+};
+
+const PressableWithFeedback = forwardRef((props, ref) => {
+ const propsWithoutStyling = _.omit(props, omittedProps);
+ return (
+ // eslint-disable-next-line react/jsx-props-no-spreading
+
+ {state => (
+
+ {props.children}
+
+ )}
+
+ );
+});
+
+PressableWithFeedback.displayName = 'PressableWithFeedback';
+PressableWithFeedback.propTypes = PressableWithFeedbackPropTypes;
+PressableWithFeedback.defaultProps = PressableWithFeedbackDefaultProps;
+
+export default PressableWithFeedback;
diff --git a/src/components/Pressable/PressableWithoutFeedback.js b/src/components/Pressable/PressableWithoutFeedback.js
new file mode 100644
index 000000000000..a12862bcd0fd
--- /dev/null
+++ b/src/components/Pressable/PressableWithoutFeedback.js
@@ -0,0 +1,27 @@
+import React from 'react';
+import _ from 'underscore';
+import GenericPressable from './GenericPressable';
+import GenericPressableProps from './GenericPressable/PropTypes';
+
+const omittedProps = [
+ 'pressStyle',
+ 'hoverStyle',
+ 'focusStyle',
+ 'activeStyle',
+ 'disabledStyle',
+ 'screenReaderActiveStyle',
+ 'shouldUseHapticsOnPress',
+ 'shouldUseHapticsOnLongPress',
+];
+
+const PressableWithoutFeedback = (props) => {
+ const propsWithoutStyling = _.omit(props, omittedProps);
+ // eslint-disable-next-line react/jsx-props-no-spreading
+ return ;
+};
+
+PressableWithoutFeedback.displayName = 'PressableWithoutFeedback';
+PressableWithoutFeedback.propTypes = _.omit(GenericPressableProps.pressablePropTypes, omittedProps);
+PressableWithoutFeedback.defaultProps = _.omit(GenericPressableProps.defaultProps, omittedProps);
+
+export default PressableWithoutFeedback;
diff --git a/src/components/Pressable/index.js b/src/components/Pressable/index.js
new file mode 100644
index 000000000000..83f597b3de8d
--- /dev/null
+++ b/src/components/Pressable/index.js
@@ -0,0 +1,3 @@
+export {default as GenericPressable} from './GenericPressable';
+export {default as PressableWithFeedback} from './PressableWithFeedback';
+export {default as PressableWithoutFeedback} from './PressableWithoutFeedback';
diff --git a/src/libs/Accessibility/index.js b/src/libs/Accessibility/index.js
new file mode 100644
index 000000000000..607c01836405
--- /dev/null
+++ b/src/libs/Accessibility/index.js
@@ -0,0 +1,46 @@
+import {useEffect, useState, useCallback} from 'react';
+import {AccessibilityInfo} from 'react-native';
+import _ from 'underscore';
+import moveAccessibilityFocus from './moveAccessibilityFocus';
+
+const useScreenReaderStatus = () => {
+ const [isScreenReaderEnabled, setIsScreenReaderEnabled] = useState(false);
+ useEffect(() => {
+ const subscription = AccessibilityInfo.addEventListener('screenReaderChanged', setIsScreenReaderEnabled);
+
+ return subscription.remove;
+ }, []);
+
+ return isScreenReaderEnabled;
+};
+
+const getHitSlopForSize = ({x, y}) => {
+ /* according to https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/adaptivity-and-layout/
+ the minimum tappable area is 44x44 points */
+ const minimumSize = 44;
+ const hitSlopVertical = _.max([minimumSize - x, 0]);
+ const hitSlopHorizontal = _.max([minimumSize - y, 0]);
+ return {
+ top: hitSlopVertical,
+ bottom: hitSlopVertical,
+ left: hitSlopHorizontal,
+ right: hitSlopHorizontal,
+ };
+};
+
+const useAutoHitSlop = () => {
+ const [frameSize, setFrameSize] = useState({x: 0, y: 0});
+ const onLayout = useCallback((event) => {
+ const {layout} = event.nativeEvent;
+ if (layout.width !== frameSize.x && layout.height !== frameSize.y) {
+ setFrameSize({x: layout.width, y: layout.height});
+ }
+ }, [frameSize]);
+ return [getHitSlopForSize(frameSize), onLayout];
+};
+
+export default {
+ moveAccessibilityFocus,
+ useScreenReaderStatus,
+ useAutoHitSlop,
+};
diff --git a/src/libs/Accessibility/moveAccessibilityFocus/index.js b/src/libs/Accessibility/moveAccessibilityFocus/index.js
new file mode 100644
index 000000000000..c9130c7e34be
--- /dev/null
+++ b/src/libs/Accessibility/moveAccessibilityFocus/index.js
@@ -0,0 +1,8 @@
+const moveAccessibilityFocus = (ref) => {
+ if (!ref || !ref.current) {
+ return;
+ }
+ ref.current.focus();
+};
+
+export default moveAccessibilityFocus;
diff --git a/src/libs/Accessibility/moveAccessibilityFocus/index.native.js b/src/libs/Accessibility/moveAccessibilityFocus/index.native.js
new file mode 100644
index 000000000000..91605e06243d
--- /dev/null
+++ b/src/libs/Accessibility/moveAccessibilityFocus/index.native.js
@@ -0,0 +1,10 @@
+import {AccessibilityInfo} from 'react-native';
+
+const moveAccessibilityFocus = (ref) => {
+ if (!ref) {
+ return;
+ }
+ AccessibilityInfo.sendAccessibilityEvent(ref, 'focus');
+};
+
+export default moveAccessibilityFocus;
diff --git a/src/styles/StyleUtils.js b/src/styles/StyleUtils.js
index 1df9d5beccd7..67e1a9335f90 100644
--- a/src/styles/StyleUtils.js
+++ b/src/styles/StyleUtils.js
@@ -648,6 +648,17 @@ function parseStyleAsArray(styleParam) {
return _.isArray(styleParam) ? styleParam : [styleParam];
}
+/**
+ * Parse style function and return Styles object
+ * @param {Object|Object[]|Function} style
+ * @param {Object} state
+ * @returns {Object[]}
+ */
+function parseStyleFromFunction(style, state) {
+ const functionAppliedStyle = _.isFunction(style) ? style(state) : style;
+ return parseStyleAsArray(functionAppliedStyle);
+}
+
/**
* Receives any number of object or array style objects and returns them all as an array
* @param {Object|Object[]} allStyles
@@ -1033,6 +1044,7 @@ export {
getPaymentMethodMenuWidth,
getThemeBackgroundColor,
parseStyleAsArray,
+ parseStyleFromFunction,
combineStyles,
getPaddingLeft,
convertToLTR,
diff --git a/src/styles/styles.js b/src/styles/styles.js
index afde881c9445..ce468051d9ee 100644
--- a/src/styles/styles.js
+++ b/src/styles/styles.js
@@ -2505,6 +2505,14 @@ const styles = {
outline: 'none',
},
+ cursorPointer: {
+ cursor: 'pointer',
+ },
+
+ cursorText: {
+ cursor: 'text',
+ },
+
fullscreenCard: {
position: 'absolute',
left: 0,
diff --git a/src/styles/utilities/cursor/index.js b/src/styles/utilities/cursor/index.js
index 85aef855d2d9..00f7f9a7b1e3 100644
--- a/src/styles/utilities/cursor/index.js
+++ b/src/styles/utilities/cursor/index.js
@@ -29,4 +29,7 @@ export default {
cursorInitial: {
cursor: 'initial',
},
+ cursorText: {
+ cursor: 'text',
+ },
};
diff --git a/src/styles/utilities/cursor/index.native.js b/src/styles/utilities/cursor/index.native.js
index 99c7070fb477..95704e55b07a 100644
--- a/src/styles/utilities/cursor/index.native.js
+++ b/src/styles/utilities/cursor/index.native.js
@@ -9,4 +9,5 @@ export default {
cursorGrabbing: {},
cursorZoomOut: {},
cursorInitial: {},
+ cursorText: {},
};
diff --git a/src/styles/variables.js b/src/styles/variables.js
index c63bb6905e95..9b2882a5c4e5 100644
--- a/src/styles/variables.js
+++ b/src/styles/variables.js
@@ -132,4 +132,6 @@ export default {
// The height of the empty list is 14px (2px for borders and 12px for vertical padding)
// This is calculated based on the values specified in the 'getGoogleListViewStyle' function of the 'StyleUtils' utility
googleEmptyListViewHeight: 14,
+ hoverDimValue: 0.5,
+ pressDimValue: 0.2,
};