diff --git a/demo/src/screens/MenuStructure.js b/demo/src/screens/MenuStructure.js
index c63e9edf65..4340052b38 100644
--- a/demo/src/screens/MenuStructure.js
+++ b/demo/src/screens/MenuStructure.js
@@ -85,6 +85,11 @@ export const navigationData = {
title: 'Overlays',
screens: [
{title: 'Action Sheet', tags: 'action sheet cross-platform', screen: 'unicorn.components.ActionSheetScreen'},
+ {
+ title: 'Action Sheet (Incubator)',
+ tags: 'action sheet',
+ screen: 'unicorn.components.IncubatorActionSheetScreen'
+ },
{title: 'Dialog', tags: 'dialog modal popup alert', screen: 'unicorn.components.DialogScreen'},
{title: 'Feature Highlight', tags: 'feature overlay', screen: 'unicorn.components.FeatureHighlightScreen'},
{title: 'Floating Button', tags: 'floating button', screen: 'unicorn.components.FloatingButtonScreen'},
diff --git a/demo/src/screens/incubatorScreens/ActionSheetItems.tsx b/demo/src/screens/incubatorScreens/ActionSheetItems.tsx
new file mode 100644
index 0000000000..c0260a0aa1
--- /dev/null
+++ b/demo/src/screens/incubatorScreens/ActionSheetItems.tsx
@@ -0,0 +1,210 @@
+import React from 'react';
+import {Alert, StyleSheet} from 'react-native';
+import {Assets, BorderRadiuses, Colors, Image, ImageProps, Spacings, View} from 'react-native-ui-lib';
+
+export enum TEXT_LENGTH {
+ NO_TEXT = 'No text',
+ SHORT = 'Short',
+ LONG = 'Long'
+}
+
+export enum CUSTOM_TITLE_COMPONENT {
+ NONE = 'None',
+ AVATAR = 'Avatar',
+ ICON = 'Icon',
+ THUMBNAIL = 'Thumbnail'
+}
+
+export enum OPTIONS_TYPE {
+ NONE = 'None',
+ REGULAR = 'Regular',
+ WITH_ICONS = 'With icons',
+ SECTION_HEADERS = 'Section headers',
+ GRID_VIEW = 'Grid view',
+ GRID_VIEW_LONG = 'Grid view long'
+}
+
+export type State = {
+ titleLength: TEXT_LENGTH;
+ titleIsProminent: boolean;
+ titleIsClickable: boolean;
+ subtitleLength: TEXT_LENGTH;
+ showFooter: boolean;
+ optionsType: OPTIONS_TYPE;
+ visible: boolean;
+};
+
+export const ICONS = [
+ Assets.icons.demo.settings,
+ Assets.icons.demo.refresh,
+ Assets.icons.check,
+ Assets.icons.x,
+ Assets.icons.plusSmall,
+ Assets.icons.demo.camera
+];
+
+const GRID_ITEM_CIRCLE_SIZE = 52;
+
+const pickOption = (option: string) => {
+ Alert.alert(`picked: ${option}`);
+};
+
+const renderCustomItem = (imageProps: ImageProps) => {
+ return (
+
+
+
+
+
+ );
+};
+
+export const listItems = [
+ {title: 'Open Settings', onPress: () => pickOption('Open Settings')},
+ {title: 'View Notifications', onPress: () => pickOption('View Notifications')},
+ {title: 'Update Profile', onPress: () => pickOption('Update Profile')},
+ {title: 'Log Out', onPress: () => pickOption('Log Out')},
+ {title: 'Share Post', onPress: () => pickOption('Share Post')},
+ {title: 'Send Message', onPress: () => pickOption('Send Message')},
+ {title: 'Take Photo', onPress: () => pickOption('Take Photo')},
+ {title: 'Record Video', onPress: () => pickOption('Record Video')},
+ {title: 'Add to Favorites', onPress: () => pickOption('Add to Favorites')},
+ {title: 'Search', onPress: () => pickOption('Search')},
+ {title: 'Refresh Feed', onPress: () => pickOption('Refresh Feed')},
+ {title: 'Edit Post', onPress: () => pickOption('Edit Post')},
+ {title: 'Report Issue', onPress: () => pickOption('Report Issue')},
+ {title: 'Contact Support', onPress: () => pickOption('Contact Support')},
+ {title: 'View Profile', onPress: () => pickOption('View Profile')},
+ {title: 'Cancel', onPress: () => pickOption('Cancel')}
+];
+
+export const gridItems = [
+ {
+ title: 'Open Settings',
+ renderCustomItem: () => renderCustomItem({source: Assets.icons.demo.settings}),
+ onPress: () => pickOption('Open Settings')
+ },
+ {
+ title: 'View Notifications',
+ renderCustomItem: () => renderCustomItem({source: Assets.icons.demo.refresh}),
+ onPress: () => pickOption('View Notifications')
+ },
+ {
+ title: 'Update Profile',
+ renderCustomItem: () => renderCustomItem({source: Assets.icons.check}),
+ onPress: () => pickOption('Update Profile'),
+ avoidDismiss: true
+ },
+ {
+ title: 'Log Out',
+ renderCustomItem: () => renderCustomItem({source: Assets.icons.x}),
+ onPress: () => pickOption('Log Out')
+ },
+ {
+ title: 'Share Post',
+ renderCustomItem: () => renderCustomItem({source: Assets.icons.plusSmall}),
+ onPress: () => pickOption('Share Post')
+ },
+ {
+ title: 'Take Photo',
+ renderCustomItem: () => renderCustomItem({source: Assets.icons.demo.camera}),
+ onPress: () => pickOption('Take Photo')
+ },
+ {
+ title: 'Record Video',
+ renderCustomItem: () => renderCustomItem({source: Assets.icons.demo.camera}),
+ onPress: () => pickOption('Record Video')
+ },
+ {
+ title: 'Send Message',
+ renderCustomItem: () => renderCustomItem({source: Assets.icons.demo.settings}),
+ onPress: () => pickOption('Send Message')
+ },
+ {
+ title: 'Create Event',
+ renderCustomItem: () => renderCustomItem({source: Assets.icons.x}),
+ onPress: () => pickOption('Create Event')
+ },
+ {
+ title: 'Browse Contacts',
+ renderCustomItem: () => renderCustomItem({source: Assets.icons.check}),
+ onPress: () => pickOption('Browse Contacts')
+ },
+ {
+ title: 'Check Updates',
+ renderCustomItem: () => renderCustomItem({source: Assets.icons.plusSmall}),
+ onPress: () => pickOption('Check Updates')
+ },
+ {
+ title: 'Provide Feedback',
+ renderCustomItem: () => renderCustomItem({source: Assets.icons.demo.refresh}),
+ onPress: () => pickOption('Provide Feedback')
+ },
+ {
+ title: 'View Gallery',
+ renderCustomItem: () => renderCustomItem({source: Assets.icons.demo.camera}),
+ onPress: () => pickOption('View Gallery')
+ },
+ {
+ title: 'Access Help',
+ renderCustomItem: () => renderCustomItem({source: Assets.icons.check}),
+ onPress: () => pickOption('Access Help')
+ },
+ {
+ title: 'Explore Settings',
+ renderCustomItem: () => renderCustomItem({source: Assets.icons.x}),
+ onPress: () => pickOption('Explore Settings')
+ },
+ {
+ title: 'Manage Subscriptions',
+ renderCustomItem: () => renderCustomItem({source: Assets.icons.plusSmall}),
+ onPress: () => pickOption('Manage Subscriptions')
+ },
+ {
+ title: 'Change Password',
+ renderCustomItem: () => renderCustomItem({source: Assets.icons.demo.settings}),
+ onPress: () => pickOption('Change Password')
+ },
+ {
+ title: 'View Terms of Service',
+ renderCustomItem: () => renderCustomItem({source: Assets.icons.demo.refresh}),
+ onPress: () => pickOption('View Terms of Service')
+ },
+ {
+ title: 'Contact Support',
+ renderCustomItem: () => renderCustomItem({source: Assets.icons.x}),
+ onPress: () => pickOption('Contact Support')
+ },
+ {
+ title: 'Manage Privacy Settings',
+ renderCustomItem: () => renderCustomItem({source: Assets.icons.check}),
+ onPress: () => pickOption('Manage Privacy Settings')
+ },
+ {
+ title: 'Send Feedback',
+ renderCustomItem: () => renderCustomItem({source: Assets.icons.plusSmall}),
+ onPress: () => pickOption('Send Feedback')
+ },
+ {
+ title: 'View FAQ',
+ renderCustomItem: () => renderCustomItem({source: Assets.icons.demo.camera}),
+ onPress: () => pickOption('View FAQ')
+ },
+ {
+ title: 'Reset App Preferences',
+ renderCustomItem: () => renderCustomItem({source: Assets.icons.demo.refresh}),
+ onPress: () => pickOption('Reset App Preferences')
+ }
+];
+
+const styles = StyleSheet.create({
+ gridItemCircle: {
+ width: GRID_ITEM_CIRCLE_SIZE,
+ height: GRID_ITEM_CIRCLE_SIZE,
+ borderWidth: 1,
+ borderRadius: BorderRadiuses.br100,
+ borderColor: Colors.$outlineDisabled
+ },
+
+ containerStyle: {marginBottom: Spacings.s2, marginHorizontal: Spacings.s2, alignContent: 'center'}
+});
diff --git a/demo/src/screens/incubatorScreens/IncubatorActionSheetScreen.tsx b/demo/src/screens/incubatorScreens/IncubatorActionSheetScreen.tsx
new file mode 100644
index 0000000000..3ca557d88d
--- /dev/null
+++ b/demo/src/screens/incubatorScreens/IncubatorActionSheetScreen.tsx
@@ -0,0 +1,259 @@
+import _ from 'lodash';
+import React, {useState} from 'react';
+import {Alert, ScrollView, StyleSheet} from 'react-native';
+import {View, Button, Incubator, Text, Switch, RadioButton, RadioGroup, Typography, Colors} from 'react-native-ui-lib';
+import {listItems, gridItems, TEXT_LENGTH, OPTIONS_TYPE, State, ICONS} from './ActionSheetItems';
+
+function IncubatorActionSheetScreen() {
+ const [actionSheetOptions, setActionSheetOptions] = useState({
+ titleLength: TEXT_LENGTH.SHORT,
+ titleIsProminent: false,
+ titleIsClickable: false,
+ subtitleLength: TEXT_LENGTH.SHORT,
+ showFooter: false,
+ optionsType: OPTIONS_TYPE.REGULAR,
+ visible: false
+ });
+
+ const updateState = (newValues: Partial) => {
+ setActionSheetOptions(prevOptions => ({
+ ...prevOptions,
+ ...newValues
+ }));
+ };
+
+ const setTitleLength = (titleLength: TEXT_LENGTH) => {
+ if (titleLength !== actionSheetOptions.titleLength) {
+ updateState({titleLength});
+ }
+ };
+
+ const toggleProminent = () => {
+ updateState({titleIsProminent: !actionSheetOptions.titleIsProminent});
+ };
+
+ const toggleClickable = () => {
+ updateState({titleIsClickable: !actionSheetOptions.titleIsClickable});
+ };
+
+ const setSubtitleLength = (subtitleLength: TEXT_LENGTH) => {
+ if (subtitleLength !== actionSheetOptions.subtitleLength) {
+ updateState({subtitleLength});
+ }
+ };
+
+ const toggleFooter = () => {
+ updateState({showFooter: !actionSheetOptions.showFooter});
+ };
+
+ const setOptionsType = (optionsType: OPTIONS_TYPE) => {
+ if (optionsType !== actionSheetOptions.optionsType) {
+ updateState({optionsType});
+ }
+ };
+
+ const showActionSheet = () => {
+ updateState({visible: true});
+ };
+
+ const setVisible = (visible: boolean) => {
+ updateState({visible});
+ };
+
+ const getTitle = () => {
+ const {titleLength} = actionSheetOptions;
+ switch (titleLength) {
+ case TEXT_LENGTH.NO_TEXT:
+ return undefined;
+ case TEXT_LENGTH.SHORT:
+ default:
+ return 'Title';
+ case TEXT_LENGTH.LONG:
+ return 'This is a very long title, perhaps too long';
+ }
+ };
+
+ const clicked = (text: string) => {
+ Alert.alert(text);
+ };
+
+ const getSubtitle = () => {
+ const {subtitleLength} = actionSheetOptions;
+ switch (subtitleLength) {
+ case TEXT_LENGTH.NO_TEXT:
+ default:
+ return undefined;
+ case TEXT_LENGTH.SHORT:
+ return 'Subtitle';
+ case TEXT_LENGTH.LONG:
+ return 'This is a very long subtitle that hopefully tests two lines';
+ }
+ };
+
+ const getHeaderProps = () => {
+ const {titleIsProminent, titleIsClickable} = actionSheetOptions;
+ const onPress = titleIsClickable ? () => clicked('Header clicked') : undefined;
+ const titleStyle = titleIsProminent ? {...Typography.text70BO} : undefined;
+
+ return {
+ title: getTitle(),
+ titleProps: {accessibilityLabel: 'Custom accessibility label for ActionSheet header'},
+ subtitle: getSubtitle(),
+ titleStyle,
+ onPress
+ };
+ };
+
+ const getGridOptions = () => {
+ const {optionsType} = actionSheetOptions;
+ if (optionsType === OPTIONS_TYPE.GRID_VIEW || optionsType === OPTIONS_TYPE.GRID_VIEW_LONG) {
+ return {
+ numColumns: 3
+ };
+ }
+ };
+
+ const getList = () => {
+ const {optionsType} = actionSheetOptions;
+ switch (optionsType) {
+ case 'None':
+ return [];
+ case 'Regular':
+ return listItems;
+ case 'With icons':
+ return listItems.map((item, index) => ({
+ ...item,
+ icon: {
+ source: ICONS[index % ICONS.length],
+ tintColor: index % ICONS.length === 2 && 'red',
+ style: {marginRight: 10}
+ }
+ }));
+ case 'Grid view':
+ return gridItems.slice(0, 6).map(item => ({
+ ...item,
+ containerStyle: styles.gridItemsContainer
+ }));
+ case 'Grid view long':
+ return gridItems.map(item => ({
+ ...item,
+ containerStyle: styles.gridItemsContainer
+ }));
+ case 'Section headers':
+ return listItems.map((item, index) => ({
+ ...item,
+ isSectionHeader: index % 3 === 0,
+ titleStyle: index % 3 === 0 && {...Typography.text65},
+ sectionHeaderStyle: styles.sectionHeaders
+ }));
+ default:
+ return [];
+ }
+ };
+
+ const renderRadioButton = (key: string, value: string, hasLeftMargin: boolean) => {
+ return ;
+ };
+
+ const renderRadioGroup = (title: string,
+ data: {[s: number]: string},
+ initialValue?: string,
+ onValueChange?: (data: any) => void) => {
+ const radioButtons: React.ReactElement[] = [];
+ Object.entries(data).forEach(([key, value], index) => {
+ radioButtons.push(renderRadioButton(`${title}_${key}`, value, index !== _.size(data) - 1));
+ });
+
+ return (
+
+ {title}:
+
+ {radioButtons}
+
+
+ );
+ };
+
+ const renderTitleSwitches = () => {
+ const {titleIsProminent, titleIsClickable} = actionSheetOptions;
+
+ return (
+
+ Prominent style:
+
+ Clickable:
+
+
+ );
+ };
+
+ const renderActionSheet = () => {
+ const {visible, showFooter} = actionSheetOptions;
+ const list = getList();
+ const headerProps = getHeaderProps();
+ const gridOptions = getGridOptions();
+ const footerCustomElement = showFooter ? (
+
+
+ Footer
+
+
+ ) : undefined;
+
+ return (
+ {
+ console.log(`props onDismiss called!`);
+ setVisible(false);
+ }}
+ dialogProps={{
+ bottom: true,
+ centerH: true,
+ width: '95%',
+ height: _.isEmpty(list) && !gridOptions ? 150 : undefined,
+ headerProps
+ }}
+ gridOptions={gridOptions}
+ footerCustomElement={footerCustomElement}
+ />
+ );
+ };
+
+ return (
+
+
+ Action Sheet
+
+
+
+ {renderRadioGroup('Title', TEXT_LENGTH, actionSheetOptions.titleLength, setTitleLength)}
+ {renderTitleSwitches()}
+ {renderRadioGroup('Subtitle', TEXT_LENGTH, actionSheetOptions.subtitleLength, setSubtitleLength)}
+ {renderRadioGroup('Options', OPTIONS_TYPE, actionSheetOptions.optionsType, setOptionsType)}
+
+ Add footer:
+
+
+
+