diff --git a/README.md b/README.md
index 9d421dbe8db0..85cf05ac619e 100644
--- a/README.md
+++ b/README.md
@@ -45,6 +45,7 @@ You can use any IDE or code editing tool for developing on any platform. Use you
 For an M1 Mac, read this [SO](https://stackoverflow.com/c/expensify/questions/11580) for installing cocoapods.
 
 * To install the iOS dependencies, run: `npm install && cd ios/ && pod install && cd ..`
+* If you are an Expensify employee and want to point the emulator to your local VM, follow [this](https://stackoverflow.com/c/expensify/questions/7699)
 * To run a on a **Development Simulator**: `npm run ios`
 * Changes applied to Javascript will be applied automatically, any changes to native code will require a recompile
 
@@ -53,6 +54,7 @@ For an M1 Mac, read this [SO](https://stackoverflow.com/c/expensify/questions/11
 * To install the Android dependencies, run: `npm install`
 * Go through the instructions on [this SO post](https://stackoverflow.com/c/expensify/questions/13283/13284#13284) to start running the app on android.
 * For more information, go through the official React-Native instructions on [this page](https://reactnative.dev/docs/environment-setup#development-os) for "React Native CLI Quickstart" > Mac OS > Android
+* If you are an Expensify employee and want to point the emulator to your local VM, follow [this](https://stackoverflow.com/c/expensify/questions/7699)
 * To run a on a **Development Emulator**: `npm run android`
 * Changes applied to Javascript will be applied automatically, any changes to native code will require a recompile
 
diff --git a/assets/images/dot-indicator.svg b/assets/images/dot-indicator.svg
new file mode 100644
index 000000000000..49be497b35c1
--- /dev/null
+++ b/assets/images/dot-indicator.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 26.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 20 20" style="enable-background:new 0 0 20 20;" xml:space="preserve">
+<circle cx="10" cy="10" r="7.5"/>
+</svg>
diff --git a/src/components/Icon/Expensicons.js b/src/components/Icon/Expensicons.js
index 9c64691a2220..a78850c71505 100644
--- a/src/components/Icon/Expensicons.js
+++ b/src/components/Icon/Expensicons.js
@@ -19,6 +19,7 @@ import ClosedSign from '../../../assets/images/closed-sign.svg';
 import Collapse from '../../../assets/images/collapse.svg';
 import Concierge from '../../../assets/images/concierge.svg';
 import CreditCard from '../../../assets/images/creditcard.svg';
+import DotIndicator from '../../../assets/images/dot-indicator.svg';
 import DownArrow from '../../../assets/images/down.svg';
 import Download from '../../../assets/images/download.svg';
 import Emoji from '../../../assets/images/emoji.svg';
@@ -109,6 +110,7 @@ export {
     CreditCard,
     DeletedRoomAvatar,
     DomainRoomAvatar,
+    DotIndicator,
     DownArrow,
     Download,
     Emoji,
diff --git a/src/components/OfflineWithFeedback.js b/src/components/OfflineWithFeedback.js
new file mode 100644
index 000000000000..196a4da3d403
--- /dev/null
+++ b/src/components/OfflineWithFeedback.js
@@ -0,0 +1,131 @@
+import _ from 'underscore';
+import React from 'react';
+import {Pressable, View} from 'react-native';
+import PropTypes from 'prop-types';
+import compose from '../libs/compose';
+import withLocalize, {withLocalizePropTypes} from './withLocalize';
+import {withNetwork} from './OnyxProvider';
+import networkPropTypes from './networkPropTypes';
+import Text from './Text';
+import styles from '../styles/styles';
+import Tooltip from './Tooltip';
+import Icon from './Icon';
+import * as Expensicons from './Icon/Expensicons';
+import * as StyleUtils from '../styles/StyleUtils';
+import colors from '../styles/colors';
+import variables from '../styles/variables';
+
+/**
+ * This component should be used when we are using the offline pattern B (offline with feedback).
+ * You should enclose any element that should have feedback that the action was taken offline and it will take
+ * care of adding the appropriate styles for pending actions and displaying the dismissible error.
+ */
+
+const propTypes = {
+    /** The type of action that's pending  */
+    pendingAction: PropTypes.oneOf(['add', 'update', 'delete']),
+
+    /** The errors to display  */
+    // eslint-disable-next-line react/forbid-prop-types
+    errors: PropTypes.object,
+
+    /** A function to run when the X button next to the error is clicked */
+    onClose: PropTypes.func.isRequired,
+
+    /** The content that needs offline feedback */
+    children: PropTypes.node.isRequired,
+
+    /** Information about the network */
+    network: networkPropTypes.isRequired,
+
+    /** Additional styles to add after local styles. Applied to Pressable portion of button */
+    style: PropTypes.oneOfType([
+        PropTypes.arrayOf(PropTypes.object),
+        PropTypes.object,
+    ]),
+    ...withLocalizePropTypes,
+};
+
+const defaultProps = {
+    pendingAction: null,
+    errors: null,
+    style: [],
+};
+
+/**
+ * This method applies the strikethrough to all the children passed recursively
+ * @param {Array} children
+ * @return {Array}
+ */
+function applyStrikeThrough(children) {
+    return React.Children.map(children, (child) => {
+        if (!React.isValidElement(child)) {
+            return child;
+        }
+        const props = {style: StyleUtils.combineStyles(child.props.style, styles.offlineFeedback.deleted)};
+        if (child.props.children) {
+            props.children = applyStrikeThrough(child.props.children);
+        }
+        return React.cloneElement(child, props);
+    });
+}
+
+const OfflineWithFeedback = (props) => {
+    const hasErrors = !_.isEmpty(props.errors);
+    const isOfflinePendingAction = props.network.isOffline && props.pendingAction;
+    const isUpdateOrDeleteError = hasErrors && (props.pendingAction === 'delete' || props.pendingAction === 'update');
+    const isAddError = hasErrors && props.pendingAction === 'add';
+    const needsOpacity = (isOfflinePendingAction && !isUpdateOrDeleteError) || isAddError;
+    const needsStrikeThrough = props.network.isOffline && props.pendingAction === 'delete';
+    const hideChildren = !props.network.isOffline && props.pendingAction === 'delete' && !hasErrors;
+    let children = props.children;
+    const sortedErrors = _.chain(props.errors)
+        .keys()
+        .sortBy()
+        .map(key => props.errors[key])
+        .value();
+
+    // Apply strikethrough to children if needed, but skip it if we are not going to render them
+    if (needsStrikeThrough && !hideChildren) {
+        children = applyStrikeThrough(children);
+    }
+    return (
+        <View style={props.style}>
+            {!hideChildren && (
+                <View style={needsOpacity ? styles.offlineFeedback.pending : {}}>
+                    {children}
+                </View>
+            )}
+            {hasErrors && (
+                <View style={styles.offlineFeedback.error}>
+                    <View style={styles.offlineFeedback.errorDot}>
+                        <Icon src={Expensicons.DotIndicator} fill={colors.red} height={variables.iconSizeSmall} width={variables.iconSizeSmall} />
+                    </View>
+                    <View style={styles.offlineFeedback.textContainer}>
+                        {_.map(sortedErrors, (error, i) => (
+                            <Text key={i} style={styles.offlineFeedback.text}>{error}</Text>
+                        ))}
+                    </View>
+                    <Tooltip text={props.translate('common.close')}>
+                        <Pressable
+                            onPress={props.onClose}
+                            style={[styles.touchableButtonImage, styles.mr0]}
+                            accessibilityRole="button"
+                            accessibilityLabel={props.translate('common.close')}
+                        >
+                            <Icon src={Expensicons.Close} />
+                        </Pressable>
+                    </Tooltip>
+                </View>
+            )}
+        </View>
+    );
+};
+
+OfflineWithFeedback.propTypes = propTypes;
+OfflineWithFeedback.defaultProps = defaultProps;
+
+export default compose(
+    withLocalize,
+    withNetwork(),
+)(OfflineWithFeedback);
diff --git a/src/components/OptionRow.js b/src/components/OptionRow.js
index 61901bec3050..a6a75bceb48a 100644
--- a/src/components/OptionRow.js
+++ b/src/components/OptionRow.js
@@ -62,6 +62,8 @@ const propTypes = {
     /** Whether this option should be disabled */
     isDisabled: PropTypes.bool,
 
+    style: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]),
+
     ...withLocalizePropTypes,
 };
 
@@ -77,6 +79,7 @@ const defaultProps = {
     onSelectRow: () => {},
     isDisabled: false,
     optionIsFocused: false,
+    style: null,
 };
 
 const OptionRow = (props) => {
@@ -86,12 +89,12 @@ const OptionRow = (props) => {
         : styles.sidebarLinkText;
     const textUnreadStyle = (props.option.isUnread || props.forceTextUnreadStyle)
         ? [textStyle, styles.sidebarLinkTextUnread] : [textStyle];
-    const displayNameStyle = props.mode === CONST.OPTION_MODE.COMPACT
+    const displayNameStyle = StyleUtils.combineStyles(props.mode === CONST.OPTION_MODE.COMPACT
         ? [styles.optionDisplayName, ...textUnreadStyle, styles.optionDisplayNameCompact, styles.mr2]
-        : [styles.optionDisplayName, ...textUnreadStyle];
-    const alternateTextStyle = props.mode === CONST.OPTION_MODE.COMPACT
+        : [styles.optionDisplayName, ...textUnreadStyle], props.style);
+    const alternateTextStyle = StyleUtils.combineStyles(props.mode === CONST.OPTION_MODE.COMPACT
         ? [textStyle, styles.optionAlternateText, styles.textLabelSupporting, styles.optionAlternateTextCompact]
-        : [textStyle, styles.optionAlternateText, styles.textLabelSupporting];
+        : [textStyle, styles.optionAlternateText, styles.textLabelSupporting], props.style);
     const contentContainerStyles = props.mode === CONST.OPTION_MODE.COMPACT
         ? [styles.flex1, styles.flexRow, styles.overflowHidden, styles.alignItemsCenter]
         : [styles.flex1];
diff --git a/src/styles/StyleUtils.js b/src/styles/StyleUtils.js
index fe7113bb6314..7e280bf31429 100644
--- a/src/styles/StyleUtils.js
+++ b/src/styles/StyleUtils.js
@@ -437,6 +437,19 @@ function parseStyleAsArray(styleParam) {
     return _.isArray(styleParam) ? styleParam : [styleParam];
 }
 
+/**
+ * Receives any number of object or array style objects and returns them all as an array
+ * @param {Object|Object[]} allStyles
+ * @return {Object[]}
+ */
+function combineStyles(...allStyles) {
+    let finalStyles = [];
+    _.each(allStyles, (style) => {
+        finalStyles = finalStyles.concat(parseStyleAsArray(style));
+    });
+    return finalStyles;
+}
+
 /**
  * Get variable padding-left as style
  * @param {Number} paddingLeft
@@ -474,5 +487,6 @@ export {
     getMiniReportActionContextMenuWrapperStyle,
     getPaymentMethodMenuWidth,
     parseStyleAsArray,
+    combineStyles,
     getPaddingLeft,
 };
diff --git a/src/styles/styles.js b/src/styles/styles.js
index bcf73ffd6776..3a222ead81f8 100644
--- a/src/styles/styles.js
+++ b/src/styles/styles.js
@@ -2338,6 +2338,9 @@ const styles = {
         width: '100%',
         flexDirection: 'row',
         justifyContent: 'space-between',
+    },
+
+    peopleRowOfflineFeedback: {
         borderBottomWidth: 1,
         borderColor: themeColors.border,
         ...spacing.pv2,
@@ -2359,6 +2362,36 @@ const styles = {
         ...whiteSpace.noWrap,
     },
 
+    offlineFeedback: {
+        deleted: {
+            textDecorationLine: 'line-through',
+            textDecorationStyle: 'solid',
+        },
+        pending: {
+            opacity: 0.5,
+        },
+        error: {
+            flexDirection: 'row',
+            alignItems: 'center',
+        },
+        container: {
+            ...spacing.pv2,
+        },
+        textContainer: {
+            flexDirection: 'column',
+            flex: 1,
+        },
+        text: {
+            color: themeColors.textSupporting,
+            flex: 1,
+            textAlignVertical: 'center',
+            fontSize: variables.fontSizeLabel,
+        },
+        errorDot: {
+            marginRight: 12,
+        },
+    },
+
     sidebarPopover: {
         width: variables.sideBarWidth - 68,
     },
