react-native-safe-area-context#useSafeArea TypeScript Examples
The following examples show how to use
react-native-safe-area-context#useSafeArea.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: calculator.tsx From protect-scotland with Apache License 2.0 | 6 votes |
CalculatorModal: FC<CalculatorModalProps> = () => {
const {t} = useTranslation();
const insets = useSafeArea();
const navigation = useNavigation<StackNavigationProp<any>>();
return (
<ScrollView
keyboardShouldPersistTaps="always"
style={styles.container}
contentContainerStyle={[
styles.contentContainer,
{paddingBottom: insets.bottom + SPACING_BOTTOM}
]}>
<ModalHeader
heading="calculator:heading"
color="amber"
onClosePress={() => navigation.goBack()}
/>
<View style={styles.top}>
<Illustration
source={CalculatorIllustration}
accessibilityIgnoresInvertColors={false}
accessibilityHint={t('calculator:illustrationAlt')}
accessibilityLabel={t('calculator:illustrationAlt')}
/>
<Markdown markdownStyles={markdownStyles}>
{t('calculator:body')}
</Markdown>
<Spacing s={18} />
<Text style={styles.highlight}>{t('calculator:highlight')}</Text>
<Spacing s={50} />
</View>
</ScrollView>
);
}
Example #2
Source File: test-result-modal.tsx From protect-scotland with Apache License 2.0 | 5 votes |
TestResultModal: React.FC = () => {
const {t} = useTranslation();
const navigation = useNavigation();
const insets = useSafeArea();
return (
<View
style={[
styles.modal,
{marginTop: insets.top + (Platform.OS === 'android' ? 25 : 5)}
]}>
<View style={styles.header}>
<ModalClose onPress={() => navigation.goBack()} />
</View>
<ScrollView contentContainerStyle={styles.contentContainerStyle}>
<Text
variant="h2"
color="darkerPurple"
accessible
style={styles.narrow}
align="center">
{t('onboarding:testResult:accessibility:howToAddResultLabel')}
</Text>
<Spacing s={20} />
<Illustration source={ModalIllustrationSource} />
<Spacing s={20} />
<Markdown markdownStyles={modalMarkdownStyles} style={styles.narrow}>
{t('onboarding:testResult:modal:content')}
</Markdown>
<Illustration
fullWidth
source={
Platform.OS === 'ios' ? IosMessageSource : AndroidMessageSource
}
accessible
accessibilityHint={t(
'onboarding:testResult:accessibility:messageIllustrationAlt'
)}
/>
<Spacing s={32} />
<Markdown markdownStyles={modalMarkdownStyles} style={styles.narrow}>
{t('onboarding:testResult:modal:content1')}
</Markdown>
<ArrowLink
containerStyle={styles.narrow}
externalLink={t('links:a')}
fullWidth
accessibilityHint={t('onboarding:testResult:modal:linkHint')}>
<Text variant="h4" color="primaryPurple">
{t('onboarding:testResult:modal:link')}
</Text>
</ArrowLink>
<Spacing s={50} />
</ScrollView>
</View>
);
}
Example #3
Source File: index.tsx From SQUID with MIT License | 5 votes |
MainApp = () => {
const inset = useSafeArea()
const { qrData, qrState, error, refreshQR } = useSelfQR()
const appVersion = DeviceInfo.getVersion();
const [location, setLocation] = useState('')
const getBeacon = async () => {
//TEST
// let lc = 'ห้าง Tesco lotus สาขาอโศก ตรงข้ามห้างดัง ตรงรถไฟฟ้ามหานครอมรรัตน'
// AsyncStorage.setItem('beacon-location', lc);
let beacon = await AsyncStorage.getItem('beacon-location');
if (beacon) {
setLocation(beacon)
}
}
useEffect(() => {
pushNotification.requestPermissions()
getBeacon()
}, [])
return (
<View
style={[styles.container, { paddingTop: inset.top, paddingBottom: 12 }]}
>
<StatusBar
barStyle={qrData?.getTagColor() ? 'light-content' : 'dark-content'}
backgroundColor={qrData?.getTagColor() ? COLORS.BLACK_1 : COLORS.PRIMARY_LIGHT}
/>
<QRBackground qr={qrData} />
<QRAvatar qr={qrData} qrState={qrState} />
<QRTagLabel qr={qrData} />
<Beancon location={location} />
<QRHeader qr={qrData} qrState={qrState} onRefreshQR={refreshQR} />
<QRSection qr={qrData} qrState={qrState} onRefreshQR={refreshQR} />
<QRFooter />
<Text
style={{
position: 'absolute',
bottom: 0,
right: 0,
paddingRight: 5,
fontFamily: FONT_FAMILY,
fontSize: FONT_SIZES[500] * 0.85,
textAlign: 'right',
color: '#0FA7DC'
}}
>
V {appVersion}
</Text>
</View>
)
}
Example #4
Source File: BottomSheet.tsx From mobile with Apache License 2.0 | 4 votes |
BottomSheet = ({content: ContentComponent, collapsed: CollapsedComponent, extraContent}: BottomSheetProps) => {
const bottomSheetPosition = useRef(new Animated.Value(1));
const bottomSheetRef: React.Ref<BottomSheetRaw> = useRef(null);
const [isExpanded, setIsExpanded] = useState(false);
const [i18n] = useI18n();
const toggleExpanded = useCallback(() => {
if (isExpanded) {
bottomSheetRef.current?.snapTo(1);
} else {
bottomSheetRef.current?.snapTo(0);
}
}, [isExpanded]);
const insets = useSafeArea();
const renderHeader = useCallback(() => <Box height={insets.top} />, [insets.top]);
const onOpenEnd = useCallback(() => setIsExpanded(true), []);
const onCloseEnd = useCallback(() => setIsExpanded(false), []);
const {width, height} = useWindowDimensions();
const snapPoints = [height, Math.max(width, height) * (extraContent ? 0.3 : 0.2)];
// Need to add snapPoints to set enough height when BottomSheet is collapsed
useEffect(() => {
bottomSheetRef.current?.snapTo(isExpanded ? 0 : 1);
}, [width, isExpanded, snapPoints]);
const expandedContentWrapper = useMemo(
() => (
<Animated.View style={{opacity: abs(sub(bottomSheetPosition.current, 1))}}>
<ContentComponent />
<TouchableOpacity
onPress={toggleExpanded}
style={styles.collapseButton}
accessibilityLabel={i18n.translate('BottomSheet.Collapse')}
accessibilityRole="button"
>
<Icon name="icon-chevron" />
</TouchableOpacity>
</Animated.View>
),
[i18n, toggleExpanded],
);
const collapsedContentWrapper = useMemo(
() => (
<Animated.View style={{...styles.collapseContent, opacity: pow(bottomSheetPosition.current, 2)}}>
<View style={styles.collapseContentHandleBar}>
<Icon name="sheet-handle-bar" />
</View>
{CollapsedComponent ? <CollapsedComponent /> : null}
</Animated.View>
),
[CollapsedComponent],
);
const renderContent = useCallback(() => {
return (
<SheetContentsContainer isExpanded={isExpanded} toggleExpanded={toggleExpanded}>
<>
{collapsedContentWrapper}
{expandedContentWrapper}
</>
</SheetContentsContainer>
);
}, [collapsedContentWrapper, expandedContentWrapper, isExpanded, toggleExpanded]);
return (
<>
<BottomSheetRaw
ref={bottomSheetRef}
borderRadius={32}
enabledContentGestureInteraction
renderContent={renderContent}
onOpenEnd={onOpenEnd}
onCloseEnd={onCloseEnd}
renderHeader={renderHeader}
snapPoints={snapPoints}
initialSnap={1}
callbackNode={bottomSheetPosition.current}
enabledInnerScrolling
/>
<Box height={snapPoints[1]} style={styles.spacer} />
</>
);
}
Example #5
Source File: sendNotice.tsx From protect-scotland with Apache License 2.0 | 4 votes |
SendNotice: FC<SendNoticeProps> = () => {
const {t} = useTranslation();
const insets = useSafeArea();
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(false);
const navigation = useNavigation();
const {contacts} = useExposure();
const {noticesWebPageURL, isolationDuration} = useSettings();
const handleOnSendNoticeRequest = useCallback(() => {
const createNoticeApi = async (selfIsolationDate: string) => {
try {
const key = await getKey(selfIsolationDate);
if (!key) {
return setError(true);
}
setError(false);
await SecureStore.setItemAsync(
'createNoticeCertKey',
JSON.stringify({key, selfIsolationDate})
);
const url = `${noticesWebPageURL}?key=${key}`;
await WebBrowser.openBrowserAsync(url, {
enableBarCollapsing: true,
showInRecents: true
});
navigation.navigate(ScreenNames.closeContact);
} catch (err) {
console.log(err);
setError(true);
}
};
const selfIsolationEndDate = getIsolationEndDate(
isolationDuration,
contacts,
'yyyy-MM-dd'
);
setIsLoading(true);
if (selfIsolationEndDate && noticesWebPageURL) {
createNoticeApi(selfIsolationEndDate.formatted);
}
if (!noticesWebPageURL) {
setError(true);
}
}, [contacts, noticesWebPageURL, isolationDuration, navigation]);
return (
<ScrollView
keyboardShouldPersistTaps="always"
style={styles.container}
contentContainerStyle={[
styles.contentContainer,
{paddingBottom: insets.bottom + SPACING_BOTTOM}
]}>
<ModalHeader
heading="sendNotice:heading"
onClosePress={navigation.goBack}
/>
<View style={styles.top}>
<Illustration
source={SendNoticeIllustration}
accessibilityIgnoresInvertColors={false}
/>
<Markdown markdownStyles={markdownStyles}>
{t('sendNotice:body')}
</Markdown>
<Spacing s={42} />
{error && (
<>
<View style={styles.errorBox}>
<Text style={styles.errorText}>
{t('common:tryAgain:description')}
</Text>
</View>
<Spacing s={20} />
</>
)}
<Button
variant="dark"
onPress={handleOnSendNoticeRequest}
label={t('sendNotice:continueLabel')}
hint={t('sendNotice:continueHint')}
disabled={isLoading}
textColor="white"
style={styles.button}>
{t('common:continue')}
</Button>
<Spacing s={50} />
</View>
</ScrollView>
);
}
Example #6
Source File: index.tsx From SQUID with MIT License | 4 votes |
MainApp = () => {
const inset = useSafeArea()
const { qrData, qrState, refreshQR } = useSelfQR()
const { beaconLocationName, enable, disable, isServiceEnabled } = useContactTracer()
const appVersion = DeviceInfo.getVersion();
const [location, setLocation] = useState('')
const popupRef = useRef<NotificationPopup | any>()
const smallDevice = Dimensions.get('window').height < 600
useEffect(() => {
setLocation(beaconLocationName.name)
if (location && popupRef && popupRef.current) {
popupRef.current.show({
slideOutTime: 20 * 1000
})
}
}, [beaconLocationName])
useEffect(() => {
pushNotification.requestPermissions()
}, [])
return (
<SafeAreaView style={{ flex: 1, backgroundColor: '#F9F9F9'}}>
<View
style={[styles.container, { paddingTop: inset.top, paddingBottom: inset.bottom }]}
>
<StatusBar
barStyle={qrData?.getTagColor() ? 'light-content' : 'dark-content'}
backgroundColor={qrData?.getTagColor() ? COLORS.BLACK_1 : COLORS.PRIMARY_LIGHT}
/>
<View style={styles.containerTop}>
<View style={styles.containerHeader}>
<TouchableOpacity style={styles.circularButton} onPress={refreshQR}>
<FontAwesome name="refresh" color={COLORS.GRAY_4} size={24} style={{ marginLeft: 10 }} />
</TouchableOpacity>
<Text style={styles.textHeader}>
{qrData && (`${qrData.getCreatedDate().format(I18n.t('fully_date'))}`)}
</Text>
<TouchableOpacity onPress={() => {
isServiceEnabled ? disable() : enable()
}}>
<FontAwesome
name="bluetooth-b"
color={COLORS.GRAY_4}
size={24}
style={{ marginRight: 10 }}
/>
{isServiceEnabled ? (
<View style={{
width: 10,
height: 10,
backgroundColor: COLORS.GREEN,
position: 'absolute',
borderRadius: 50,
borderTopWidth: Math.floor((4 / 100) * 24),
right: Math.floor((8 / 100) * 50)
}} />
) : void 0}
</TouchableOpacity>
</View>
<View style={styles.containerCard}>
<View style={styles.card}>
<View style={styles.cardHeader}>
<View style={{ flex: 1, padding: 10 }}>
<AvatarProfile qr={qrData} qrState={qrState} />
</View>
<View style={{ flex: 2, alignContent: 'flex-start' }}>
<RiskLabel qr={qrData} qrState={qrState} onRefreshQR={refreshQR} />
</View>
</View>
<View style={{ flex: 3 }}>
<QRImage qr={qrData} qrState={qrState} onRefreshQR={refreshQR} />
</View>
<View style={styles.cardFooter}>
<Image
source={require('./logo-pin-morchana.png')}
style={{
height: smallDevice ? 20 : 30,
width: (smallDevice ? 20 : 30) * (260 / 140),
}}
resizeMode="contain"
/>
<Text style={styles.textVersion}>
แอปพลิเคชันหมอชนะ <Text style={{ color: '#0FA7DC', fontSize: FONT_SIZES[600] * 0.85, fontFamily: FONT_FAMILY }}>V{appVersion}</Text>
</Text>
</View>
</View>
</View>
</View>
<NotificationPopup
ref={popupRef}
renderPopupContent={props => (
<BeaconFoundPopupContent {...props} result={location} />
)}
/>
</View>
</SafeAreaView>
)
}
Example #7
Source File: QuestionaireForm.tsx From SQUID with MIT License | 4 votes |
QuestionaireForm = ({ navigation }) => {
const { showSpinner, hide } = useHUD()
const [formValue, setFormValue] = useState({})
const inset = useSafeArea()
const [index, setIndex] = useState(0)
const isFocused = useIsFocused()
const dataInputTable = useMemo(() => getDataInputTable(), [])
const di = dataInputTable[index]
const value = formValue[di.id]
const setValue = (value) => {
setFormValue({ ...formValue, [di.id]: value })
}
const onBack = useCallback(() => {
if (index === 0) {
navigation.pop()
} else {
setIndex(index - 1)
}
}, [index])
const footer = (
<Footer style={{ paddingBottom: inset.bottom }}>
<PrimaryButton
title={I18n.t('next')}
style={{
width: '100%',
}}
containerStyle={{
width: '100%',
}}
disabled={typeof value === 'undefined' || value?.length === 0}
onPress={async () => {
if (dataInputTable[index + 1]) {
setIndex(index + 1)
} else {
showSpinner()
await updateUserData({ questionaire: formValue })
applicationState.setData('filledQuestionaireV2', true)
navigation.navigate('QuestionaireSummary')
hide()
}
}}
/>
</Footer>
)
const fixedFooter = Dimensions.get('window').height > 700
return (
<Container>
{isFocused ? <FormBackHandler onBack={onBack} /> : null}
<StatusBar
backgroundColor={COLORS.WHITE}
barStyle="dark-content"
/>
<FormHeader
style={{ backgroundColor: 'white', paddingTop: inset.top }}
onBack={onBack}
>
<View style={styles.header}>
<Text style={styles.title}>{di.title}</Text>
{di.subtitle ? (
<Text style={styles.subtitle}>{di.subtitle}</Text>
) : (
void 0
)}
<View
style={{
flexDirection: 'row',
alignItems: 'center',
marginTop: 16,
}}
>
<Text
style={{ fontFamily: FONT_BOLD, color:'#C4CCD4', marginRight: 12, fontSize: FONT_SIZES[500] }}
>
{index + 1} / {dataInputTable.length}
</Text>
<Progress
height={8}
style={{ flex: 1 }}
progress={(index + 1) / dataInputTable.length}
/>
</View>
</View>
</FormHeader>
<ScrollView
style={{
flex: 1,
borderTopColor: '#E3F4FF',
borderTopWidth: 1,
}}
contentContainerStyle={{ justifyContent: 'center' }}
>
{di ? (
<FormDataInput
key={di.id}
di={di}
setValue={setValue}
value={value}
/>
) : null}
{fixedFooter? null: footer}
</ScrollView>
{fixedFooter? footer: null}
</Container>
)
}
Example #8
Source File: BottomSheet.tsx From mobile with Apache License 2.0 | 4 votes |
BottomSheetInternal = (
{expandedComponent: ExpandedComponent, collapsedComponent: CollapsedComponent}: BottomSheetProps,
ref: React.Ref<BottomSheetBehavior>,
) => {
const bottomSheetPosition = useRef(new Animated.Value(1));
const bottomSheetRef: React.Ref<BottomSheetRaw> = useRef(null);
const [isExpanded, setIsExpanded] = useState(false);
const [extraContent, setExtraContent] = useState(false);
const [onStateChange, setOnStateChange] = useState<(isExpanded: boolean) => void>();
const behavior = useMemo<BottomSheetBehavior>(
() => ({
expand: () => {
setIsExpanded(true);
},
collapse: () => {
setIsExpanded(false);
},
refreshSnapPoints: setExtraContent,
callbackNode: bottomSheetPosition.current,
setOnStateChange: callback => setOnStateChange(() => callback),
isExpanded,
}),
[isExpanded],
);
useImperativeHandle(ref, () => behavior, [behavior]);
useEffect(() => onStateChange?.(isExpanded), [isExpanded, onStateChange]);
const {orientation} = useOrientation();
const bottomPadding = orientation === 'landscape' ? 120 : 140;
const insets = useSafeArea();
const renderHeader = useCallback(() => <Box height={insets.top} />, [insets.top]);
const onOpenEnd = useCallback(() => setIsExpanded(true), []);
const onCloseEnd = useCallback(() => setIsExpanded(false), []);
const {width, height} = useWindowDimensions();
const snapPoints = [height, extraContent ? 200 + insets.bottom : bottomPadding + insets.bottom];
// Need to add snapPoints to set enough height when BottomSheet is collapsed
useEffect(() => {
bottomSheetRef.current?.snapTo(isExpanded ? 0 : 1);
}, [width, isExpanded, snapPoints]);
const expandedComponentWrapper = useMemo(() => <ExpandedComponent {...behavior} />, [behavior]);
const collapsedComponentWrapper = useMemo(() => <CollapsedComponent {...behavior} />, [behavior]);
const renderContent = useCallback(() => {
return (
<SheetContentsContainer>
<>
<View
style={styles.collapseContent}
accessibilityElementsHidden={isExpanded}
importantForAccessibility={isExpanded ? 'no-hide-descendants' : undefined}
pointerEvents={isExpanded ? 'none' : undefined}
>
{collapsedComponentWrapper}
</View>
<View
pointerEvents={isExpanded ? undefined : 'none'}
accessibilityElementsHidden={!isExpanded}
importantForAccessibility={isExpanded ? undefined : 'no-hide-descendants'}
>
{expandedComponentWrapper}
</View>
</>
</SheetContentsContainer>
);
}, [collapsedComponentWrapper, expandedComponentWrapper, isExpanded]);
return (
<>
<BottomSheetRaw
ref={bottomSheetRef}
borderRadius={32}
enabledContentGestureInteraction
renderContent={renderContent}
onOpenEnd={onOpenEnd}
onCloseEnd={onCloseEnd}
renderHeader={renderHeader}
snapPoints={snapPoints}
initialSnap={1}
callbackNode={bottomSheetPosition.current}
enabledInnerScrolling
/>
<Box height={snapPoints[1]} />
</>
);
}
Example #9
Source File: BottomTabBar.tsx From nlw2-proffy with MIT License | 4 votes |
export default function BottomTabBar({
state,
navigation,
descriptors,
activeBackgroundColor,
activeTintColor,
adaptive = true,
allowFontScaling,
inactiveBackgroundColor,
inactiveTintColor,
keyboardHidesTabBar = false,
labelPosition,
labelStyle,
iconStyle,
safeAreaInsets,
showLabel,
style,
tabStyle,
}: Props) {
const { colors } = useTheme();
const buildLink = useLinkBuilder();
const focusedRoute = state.routes[state.index];
const focusedDescriptor = descriptors[focusedRoute.key];
const focusedOptions = focusedDescriptor.options;
const dimensions = useWindowDimensions();
const isKeyboardShown = useIsKeyboardShown();
const shouldShowTabBar =
focusedOptions.tabBarVisible !== false &&
!(keyboardHidesTabBar && isKeyboardShown);
const visibilityAnimationConfigRef = React.useRef(
focusedOptions.tabBarVisibilityAnimationConfig
);
React.useEffect(() => {
visibilityAnimationConfigRef.current =
focusedOptions.tabBarVisibilityAnimationConfig;
});
const [isTabBarHidden, setIsTabBarHidden] = React.useState(!shouldShowTabBar);
const [visible] = React.useState(
() => new Animated.Value(shouldShowTabBar ? 1 : 0)
);
React.useEffect(() => {
const visibilityAnimationConfig = visibilityAnimationConfigRef.current;
if (shouldShowTabBar) {
const animation =
visibilityAnimationConfig?.show?.animation === 'spring'
? Animated.spring
: Animated.timing;
animation(visible, {
toValue: 1,
useNativeDriver,
duration: 250,
...visibilityAnimationConfig?.show?.config,
}).start(({ finished }) => {
if (finished) {
setIsTabBarHidden(false);
}
});
} else {
setIsTabBarHidden(true);
const animation =
visibilityAnimationConfig?.hide?.animation === 'spring'
? Animated.spring
: Animated.timing;
animation(visible, {
toValue: 0,
useNativeDriver,
duration: 200,
...visibilityAnimationConfig?.hide?.config,
}).start();
}
}, [visible, shouldShowTabBar]);
const [layout, setLayout] = React.useState({
height: 0,
width: dimensions.width,
});
const handleLayout = (e: LayoutChangeEvent) => {
const { height, width } = e.nativeEvent.layout;
setLayout((layout) => {
if (height === layout.height && width === layout.width) {
return layout;
} else {
return {
height,
width,
};
}
});
};
const { routes } = state;
const shouldUseHorizontalLabels = () => {
if (labelPosition) {
return labelPosition === 'beside-icon';
}
if (!adaptive) {
return false;
}
if (layout.width >= 768) {
// Screen size matches a tablet
let maxTabItemWidth = DEFAULT_MAX_TAB_ITEM_WIDTH;
const flattenedStyle = StyleSheet.flatten(tabStyle);
if (flattenedStyle) {
if (typeof flattenedStyle.width === 'number') {
maxTabItemWidth = flattenedStyle.width;
} else if (typeof flattenedStyle.maxWidth === 'number') {
maxTabItemWidth = flattenedStyle.maxWidth;
}
}
return routes.length * maxTabItemWidth <= layout.width;
} else {
const isLandscape = dimensions.width > dimensions.height;
return isLandscape;
}
};
const defaultInsets = useSafeArea();
const insets = {
top: safeAreaInsets?.top ?? defaultInsets.top,
right: safeAreaInsets?.right ?? defaultInsets.right,
bottom: safeAreaInsets?.bottom ?? defaultInsets.bottom,
left: safeAreaInsets?.left ?? defaultInsets.left,
};
const paddingBottom = Math.max(
insets.bottom - Platform.select({ ios: 4, default: 0 }),
0
);
return (
<Animated.View
style={[
styles.tabBar,
{
backgroundColor: colors.card,
borderTopColor: colors.border,
},
{
transform: [
{
translateY: visible.interpolate({
inputRange: [0, 1],
outputRange: [layout.height + paddingBottom, 0],
}),
},
],
// Absolutely position the tab bar so that the content is below it
// This is needed to avoid gap at bottom when the tab bar is hidden
position: isTabBarHidden ? 'absolute' : (null as any),
},
{
height: DEFAULT_TABBAR_HEIGHT + paddingBottom,
paddingBottom,
paddingHorizontal: Math.max(insets.left, insets.right),
},
style,
]}
pointerEvents={isTabBarHidden ? 'none' : 'auto'}
>
<View style={styles.content} onLayout={handleLayout}>
{routes.map((route, index) => {
const focused = index === state.index;
const { options } = descriptors[route.key];
const onPress = () => {
const event = navigation.emit({
type: 'tabPress',
target: route.key,
canPreventDefault: true,
});
if (!focused && !event.defaultPrevented) {
navigation.dispatch({
...CommonActions.navigate(route.name),
target: state.key,
});
}
};
const onLongPress = () => {
navigation.emit({
type: 'tabLongPress',
target: route.key,
});
};
const label =
options.tabBarLabel !== undefined
? options.tabBarLabel
: options.title !== undefined
? options.title
: route.name;
const accessibilityLabel =
options.tabBarAccessibilityLabel !== undefined
? options.tabBarAccessibilityLabel
: typeof label === 'string'
? `${label}, tab, ${index + 1} of ${routes.length}`
: undefined;
return (
<NavigationContext.Provider
key={route.key}
value={descriptors[route.key].navigation}
>
<NavigationRouteContext.Provider value={route}>
<BottomTabItem
route={route}
focused={focused}
horizontal={shouldUseHorizontalLabels()}
onPress={onPress}
onLongPress={onLongPress}
accessibilityLabel={accessibilityLabel}
to={buildLink(route.name, route.params)}
testID={options.tabBarTestID}
allowFontScaling={allowFontScaling}
activeTintColor={activeTintColor}
inactiveTintColor={inactiveTintColor}
activeBackgroundColor={activeBackgroundColor}
inactiveBackgroundColor={inactiveBackgroundColor}
button={options.tabBarButton}
icon={options.tabBarIcon}
badge={options.tabBarBadge}
label={label}
showLabel={showLabel}
labelStyle={labelStyle}
iconStyle={iconStyle}
style={tabStyle}
/>
</NavigationRouteContext.Provider>
</NavigationContext.Provider>
);
})}
</View>
</Animated.View>
);
}
Example #10
Source File: Snackbar.tsx From react-native-template with MIT License | 4 votes |
Snackbar = ({
visible,
message,
onDismiss,
btnTitle,
onPress,
unsafeView,
}: SnackbarProps) => {
const timeoutRef = useRef(-1)
const insets = useSafeArea()
const safeArea = !unsafeView
? insets
: { top: 0, bottom: 0, left: 0, right: 0 }
const snackbarHeight =
SNACKBAR_HEIGHT + safeArea.bottom + safeArea.bottom / 2 + 10
const translateY = useValue(snackbarHeight)
const opacity = useMemo(
() =>
timing({
to: 1,
from: 0.2,
duration: 200,
}),
// eslint-disable-next-line
[message]
)
useCode(
() => [
cond(
bin(visible),
set(
translateY,
timing({
from: translateY,
to: 0,
duration: 250,
})
),
cond(
neq(translateY, snackbarHeight),
set(
translateY,
timing({
from: translateY,
to: snackbarHeight,
duration: 150,
})
)
)
),
],
[visible, snackbarHeight, translateY]
)
useEffect(() => {
if (visible) {
timeoutRef.current = setTimeout(() => {
onDismiss()
}, 3000)
}
return clearTimeoutRef
}, [onDismiss, visible])
const clearTimeoutRef = () => clearTimeout(timeoutRef.current)
const handleOnPress = () => {
onDismiss()
clearTimeout(timeoutRef.current)
setTimeout(() => {
onPress!()
}, 150)
}
return (
<View style={styles.container}>
<Animated.View
style={[
styles.snackbar,
{
transform: [{ translateY }],
height: snackbarHeight,
backgroundColor: "#1D2226",
},
]}
>
<Animated.Text
style={[
styles.text,
{
marginBottom: safeArea.bottom,
opacity,
},
]}
>
{message}
</Animated.Text>
{onPress && (
<TouchableOpacity
onPress={handleOnPress}
style={styles.touchable}
activeOpacity={0.6}
>
<Text
style={[
styles.dismissText,
{
marginBottom: safeArea.bottom,
color: "#15AAE1",
},
]}
>
{btnTitle}
</Text>
</TouchableOpacity>
)}
<TouchableOpacity
onPress={onDismiss}
style={styles.touchable}
activeOpacity={0.6}
>
<Text
style={[
styles.dismissText,
{
marginBottom: safeArea.bottom,
color: "#2E97C8",
},
]}
>
Dismiss
</Text>
</TouchableOpacity>
</Animated.View>
</View>
)
}