diff --git a/demo/src/screens/MenuStructure.js b/demo/src/screens/MenuStructure.js index 852f1c86c0..c664564ebb 100644 --- a/demo/src/screens/MenuStructure.js +++ b/demo/src/screens/MenuStructure.js @@ -83,6 +83,7 @@ export const navigationData = { {title: 'Dialog', tags: 'dialog modal popup alert', screen: 'unicorn.components.DialogScreen'}, {title: 'Feature Highlight', tags: 'native feature overlay', screen: 'unicorn.components.FeatureHighlightScreen'}, {title: 'Floating Button', tags: 'floating button', screen: 'unicorn.components.FloatingButtonScreen'}, + {title: 'Screen Footer', tags: 'screen footer sticky bottom', screen: 'unicorn.components.ScreenFooterScreen'}, {title: 'Hint', tags: 'hints tooltip', screen: 'unicorn.components.HintsScreen'}, {title: 'Toast', tags: 'toast top bottom snackbar', screen: 'unicorn.components.ToastsScreen'} ] diff --git a/demo/src/screens/componentScreens/ScreenFooterScreen.tsx b/demo/src/screens/componentScreens/ScreenFooterScreen.tsx new file mode 100644 index 0000000000..31cb99f77c --- /dev/null +++ b/demo/src/screens/componentScreens/ScreenFooterScreen.tsx @@ -0,0 +1,505 @@ +import React, {useState, useMemo} from 'react'; +import {StyleSheet, ScrollView, Image} from 'react-native'; +import { + View, + Text, + Button, + Colors, + SegmentedControl, + ScreenFooter, + ScreenFooterLayouts, + ScreenFooterBackgrounds, + KeyboardBehavior, + FooterAlignment, + HorizontalItemsDistribution, + ItemsFit, + Switch, + TextField, + Hooks, + Incubator +} from 'react-native-ui-lib'; + +// eslint-disable-next-line @typescript-eslint/no-var-requires +const basketIcon = require('../../assets/icons/collections.png'); + +enum ButtonType { + PRIMARY = 'Primary', + SECONDARY = 'Secondary', + LINK = 'Link' +} + +enum ItemSize { + SMALL = 'small', + MEDIUM = 'medium', + LARGE = 'large' +} + +const ITEMS_COUNT_OPTIONS = [ + {label: '1', value: 1}, + {label: '2', value: 2}, + {label: '3', value: 3} +]; + +const LAYOUT_OPTIONS = [ + {label: 'Horizontal', value: ScreenFooterLayouts.HORIZONTAL}, + {label: 'Vertical', value: ScreenFooterLayouts.VERTICAL} +]; + +const BACKGROUND_OPTIONS = [ + {label: 'Solid', value: ScreenFooterBackgrounds.SOLID}, + {label: 'Fading', value: ScreenFooterBackgrounds.FADING}, + {label: 'Transparent', value: ScreenFooterBackgrounds.TRANSPARENT} +]; + +const ALIGNMENT_OPTIONS = [ + {label: 'Start', value: FooterAlignment.START}, + {label: 'Center', value: FooterAlignment.CENTER}, + {label: 'End', value: FooterAlignment.END} +]; + +const DISTRIBUTION_OPTIONS = [ + {label: 'Stack', value: HorizontalItemsDistribution.STACK}, + {label: 'Spread', value: HorizontalItemsDistribution.SPREAD} +]; + +const ITEMS_FIT_OPTIONS = [ + {label: 'Fit', value: ItemsFit.FIT}, + {label: 'Stretch', value: ItemsFit.STRETCH}, + {label: 'Fixed', value: ItemsFit.FIXED} +]; + +const BUTTON_TYPE_OPTIONS = [ + {label: 'Primary', value: ButtonType.PRIMARY}, + {label: 'Secondary', value: ButtonType.SECONDARY}, + {label: 'Link', value: ButtonType.LINK} +]; + +const SIZE_OPTIONS = [ + {label: 'Small', value: ItemSize.SMALL}, + {label: 'Medium', value: ItemSize.MEDIUM}, + {label: 'Large', value: ItemSize.LARGE} +]; + +const KEYBOARD_BEHAVIOR_OPTIONS = [ + {label: 'Sticky', value: KeyboardBehavior.STICKY}, + {label: 'Hoisted', value: KeyboardBehavior.HOISTED} +]; + +const KEYBOARD_BEHAVIOR_OPTIONS_SPACED = [ + {label: 'Sticky', value: KeyboardBehavior.STICKY}, + {label: 'Hoisted', value: KeyboardBehavior.HOISTED}, + {label: '', value: 'dummy'} +]; + +const ScreenFooterScreen = () => { + const [itemsCount, setItemsCount] = useState(2); + const [layout, setLayout] = useState(ScreenFooterLayouts.HORIZONTAL); + const [background, setBackground] = useState(ScreenFooterBackgrounds.SOLID); + const [keyboardBehavior, setKeyboardBehavior] = useState(KeyboardBehavior.STICKY); + const [alignment, setAlignment] = useState(FooterAlignment.CENTER); + const [horizontalAlignment, setHorizontalAlignment] = useState(FooterAlignment.CENTER); + const [distribution, setDistribution] = useState(HorizontalItemsDistribution.STACK); + const [itemsFit, setItemsFit] = useState(ItemsFit.FIT); + + const [button1Type, setButton1Type] = useState(ButtonType.PRIMARY); + const [button2Type, setButton2Type] = useState(ButtonType.SECONDARY); + const [button3Type, setButton3Type] = useState(ButtonType.LINK); + const [buttonSize, setButtonSize] = useState(ItemSize.MEDIUM); + const [showExtraText, setShowExtraText] = useState(false); + const [showImage, setShowImage] = useState(false); + const [extraContentSize, setExtraContentSize] = useState(ItemSize.MEDIUM); + const [useLongButtonText, setUseLongButtonText] = useState(false); + const [itemWidth, setItemWidth] = useState(150); + const [shouldHideOnScroll, setShouldHideOnScroll] = useState(false); + const [useSafeArea, setUseSafeArea] = useState(true); + + const {onScroll, visible} = Hooks.useScrollToHide(); + + const isHorizontal = layout === ScreenFooterLayouts.HORIZONTAL; + + const getButtonSize = (size: ItemSize) => { + switch (size) { + case ItemSize.SMALL: + return Button.sizes.small; + case ItemSize.MEDIUM: + return Button.sizes.medium; + case ItemSize.LARGE: + return Button.sizes.large; + } + }; + + const getTextPreset = (size: ItemSize): {main: string; subtext: string} => { + switch (size) { + case ItemSize.SMALL: + return {main: 'text80', subtext: 'text100'}; + case ItemSize.MEDIUM: + return {main: 'text70', subtext: 'text90'}; + case ItemSize.LARGE: + return {main: 'text60', subtext: 'text80'}; + } + }; + + const getButtonProps = (type: ButtonType) => { + switch (type) { + case ButtonType.PRIMARY: + return { + backgroundColor: Colors.$backgroundPrimaryHeavy, + label: useLongButtonText ? 'Primary-longtxtlongtxtlongtxtlongtxtlongtxtlongtxt' : 'Checkout' + }; + case ButtonType.SECONDARY: + return { + backgroundColor: Colors.$backgroundDefault, + outline: true, + outlineColor: Colors.$backgroundPrimaryHeavy, + label: 'Secondary' + }; + case ButtonType.LINK: + return { + link: true, + backgroundColor: undefined, + label: 'Link', + color: Colors.$backgroundPrimaryHeavy + }; + } + }; + + const getImageSize = (size: ItemSize): number => { + switch (size) { + case ItemSize.SMALL: + return 24; + case ItemSize.MEDIUM: + return 32; + case ItemSize.LARGE: + return 40; + } + }; + + const renderFooterItems = useMemo(() => { + const items = []; + const textPreset = getTextPreset(extraContentSize); + const imageSize = getImageSize(extraContentSize); + + // Extra Text (Total price) + if (showExtraText) { + items.push( + + + Total:{' '} + + 257$ + + + + Including VAT. + + + ); + } + + // Image (Basket icon) + if (showExtraText && showImage) { + items.push( + + + + ); + } + + if (itemsCount >= 1) { + items.push(