diff --git a/core/components/Screen/index.tsx b/core/components/Screen/index.tsx index 09eb20563e0d2240dd48874e1db5e1c221a62c22..fa60a5ec991a68e8cf6681f293a2744b5489846e 100644 --- a/core/components/Screen/index.tsx +++ b/core/components/Screen/index.tsx @@ -17,6 +17,7 @@ import { useScreenComponentInternal } from '@holi/core/components/Screen/useScre import Animated, { useAnimatedStyle, useDerivedValue } from 'react-native-reanimated' import { dimensions } from '@holi/ui/styles/globalVars' import { KeyboardAwareScrollViewRefreshable } from '@holi/core/helpers/withRefreshControl' +import { useScreenOptions } from '@holi/core/navigation/hooks/useScreenOptions' const isIos = Platform.OS === 'ios' @@ -85,9 +86,22 @@ function ScreenWithScrolling(props: ScreenProps) { ) } -function ScreenWithoutScrolling({ children, contentPadding }: FixedScreenProps) { +function ScreenWithoutScrolling({ children, contentPadding, preset, style, contentContainerStyle }: FixedScreenProps) { const { styles } = useStyles(stylesheet) - return <View style={[styles.screenContentContainer, styles.flex1, styles.padding(contentPadding)]}>{children}</View> + return ( + <View style={[style, styles.container]}> + <View + style={[ + contentContainerStyle, + preset === 'fixed' && styles.flexEnd, + styles.padding(contentPadding), + styles.screenContentContainer, + ]} + > + {children} + </View> + </View> + ) } type BottomComponentWrapperProps = { @@ -120,12 +134,13 @@ export const Screen = (props: ScreenProps) => { keyboardVerticalOffset = 100, statusBarProps, keyboardAvoidingViewProps, - backgroundColor, + backgroundColor = 'page', safeAreaEdges = [], StickyBottomComponent, headerOptions, StickyTopComponent, - padding = { left: 'xs', right: 'xs' }, + padding, + contentContainerPadding = { left: 'xs', right: 'xs' }, testID, ...otherProps } = props @@ -135,17 +150,18 @@ export const Screen = (props: ScreenProps) => { const { stickyBottomLayout, stickyBottomOffset, stickyTopLayout, stickyTopOffset } = useScreenComponentInternal({ headerOptions, }) - + const safeAreaInsets = useSafeAreaInsets() + const navigationOptions = useScreenOptions() return ( <SafeAreaView edges={safeAreaEdges} mode="padding" testID={testID} style={[ - styles.padding(padding), styles.container, styles.relative, - { backgroundColor: backgroundColor || theme.colors.bg.page }, + styles.padding(padding), + { backgroundColor: theme.colors.bg[backgroundColor] }, ]} > <StatusBar {...statusBarProps} barStyle={themeName === 'dark' ? 'light-content' : 'dark-content'} /> @@ -155,13 +171,12 @@ export const Screen = (props: ScreenProps) => { keyboardVerticalOffset={keyboardVerticalOffset} {...keyboardAvoidingViewProps} style={[ + keyboardAvoidingViewProps?.style, styles.flex1, styles.relative, - isNonScrolling(preset) && styles.fixedScreenContainer, + styles.contentContainerPadding(navigationOptions.headerShown, safeAreaInsets.top, contentContainerPadding), StickyBottomComponent ? styles.stickyBottomOffset(stickyBottomOffset) : null, StickyTopComponent ? styles.stickyTopOffset(stickyTopOffset) : null, - // TODO: move back up when fixedScreenContainer is fixed - keyboardAvoidingViewProps?.style, ]} > {StickyTopComponent && ( diff --git a/core/components/Screen/index.web.tsx b/core/components/Screen/index.web.tsx index 8a46399659059f79f2d045cd862f1cb878be4d4b..cd5a92ae7a9257e7985099ddda0f828272510e9b 100644 --- a/core/components/Screen/index.web.tsx +++ b/core/components/Screen/index.web.tsx @@ -10,10 +10,11 @@ import { ScrollViewRefreshable } from '@holi/core/helpers/withRefreshControl' export const Screen = (props: ScreenProps) => { const { keyboardAvoidingViewProps, - backgroundColor, + backgroundColor = 'page', StickyBottomComponent, StickyTopComponent, padding, + contentContainerPadding = { left: 'xs', right: 'xs' }, headerOptions, testID, children, @@ -28,7 +29,7 @@ export const Screen = (props: ScreenProps) => { return ( <View testID={testID} - style={[styles.padding(padding), styles.container, { backgroundColor: backgroundColor || theme.colors.bg.page }]} + style={[styles.padding(padding), styles.container, { backgroundColor: theme.colors.bg[backgroundColor] }]} > <HoliContainer flex={1} noPadding> <View @@ -48,7 +49,7 @@ export const Screen = (props: ScreenProps) => { <ScrollViewRefreshable {...scrollViewProps} - style={[scrollViewProps?.style, style]} + style={[scrollViewProps?.style, style, styles.contentContainerPadding(0, 0, contentContainerPadding)]} contentContainerStyle={[scrollViewProps?.contentContainerStyle, contentContainerStyle]} > {children} diff --git a/core/components/Screen/styles.ts b/core/components/Screen/styles.ts index 68c7f74522f932e9a2301ca73688afb417f4fd5e..dddbafdf6d9511974eae0386ec97176f14974569 100644 --- a/core/components/Screen/styles.ts +++ b/core/components/Screen/styles.ts @@ -2,7 +2,13 @@ import type { ScreenPadding } from '@holi/core/components/Screen/types' import { dimensions } from '@holi/ui/styles/globalVars' import { Spacing } from 'holi-bricks/tokens' import { createStyleSheet } from 'holi-bricks/utils' -import { Dimensions } from 'react-native' + +const makePadding = (padding?: ScreenPadding) => ({ + paddingTop: padding?.top ? Spacing[padding?.top] : 0, + paddingBottom: padding?.bottom ? Spacing[padding?.bottom] : 0, + paddingLeft: padding?.left ? Spacing[padding?.left] : 0, + paddingRight: padding?.right ? Spacing[padding?.right] : 0, +}) export const stylesheet = createStyleSheet(() => { return { @@ -22,11 +28,14 @@ export const stylesheet = createStyleSheet(() => { alignItems: 'stretch', }, padding: (padding?: ScreenPadding) => { + const parsedPadding = makePadding(padding) + return parsedPadding + }, + contentContainerPadding: (headerShown = true, topInset: number, padding?: ScreenPadding) => { + const parsePadding = makePadding(padding) return { - paddingTop: padding?.top ? Spacing[padding?.top] : 0, - paddingBottom: padding?.bottom ? Spacing[padding?.bottom] : 0, - paddingLeft: padding?.left ? Spacing[padding?.left] : 0, - paddingRight: padding?.right ? Spacing[padding?.right] : 0, + ...parsePadding, + paddingTop: headerShown ? parsePadding.paddingTop : topInset + parsePadding.paddingTop, } }, stickyBottomOffset: (offset: number) => { @@ -71,15 +80,14 @@ export const stylesheet = createStyleSheet(() => { right: 0, zIndex: 10, }, - fixedScreenContainer: { - flex: 1, - maxHeight: Dimensions.get('screen').height - dimensions.bottomBarHeight - dimensions.topBarHeight, - }, relative: { position: 'relative', }, flex1: { flex: 1, }, + flexEnd: { + justifyContent: 'flex-end', + }, } }) diff --git a/core/components/Screen/types.ts b/core/components/Screen/types.ts index f4cfe3abda01b014dba92600dfdc9a3eccafc384..299e301de9a817697c8579b3e18fe6347e822389 100644 --- a/core/components/Screen/types.ts +++ b/core/components/Screen/types.ts @@ -1,6 +1,7 @@ import type { ScrollToggleHeightThreshold } from '@holi/core/components/Screen/useAutoPreset' import type { NavigationCustomOptions } from '@holi/core/navigation/hooks/useScreenOptions/types' import type { SpacingSize } from 'holi-bricks/tokens' +import type { lightTheme } from 'holi-bricks/themes/light' import type { ReactNode } from 'react' import type { ScrollViewProps, KeyboardAvoidingViewProps, ViewStyle, StyleProp, StatusBarProps } from 'react-native' import type { Edges } from 'react-native-safe-area-context' @@ -18,7 +19,7 @@ export interface BaseScreenProps { /** * Background of the screen */ - backgroundColor?: string + backgroundColor?: keyof (typeof lightTheme)['colors']['bg'] /** * The distance between keyboard and focused `TextInput` when keyboard is shown. Default is `0`. */ @@ -44,10 +45,14 @@ export interface BaseScreenProps { contentContainerStyle?: StyleProp<ViewStyle> style?: StyleProp<ViewStyle> /** - * Padding object { top, bottom, left, right } needed to add + * Padding of the external wrapper object { top, bottom, left, right } needed to add * padding to the screen outer container. It uses padding. */ padding?: ScreenPadding + /** + * Pads the wrapper of the inner content + */ + contentContainerPadding?: ScreenPadding children: ReactNode | ReactNode[] testID?: string } diff --git a/core/screens/search/typesense/Search.tsx b/core/screens/search/typesense/Search.tsx index 2862a433672e099d58ee3be594bede2cc6cabcdb..2320528e4d1cbc75405e63a1398d8d12a24e5733 100644 --- a/core/screens/search/typesense/Search.tsx +++ b/core/screens/search/typesense/Search.tsx @@ -17,7 +17,7 @@ import { createStyleSheet } from 'holi-bricks/utils' import React, { useMemo } from 'react' import { useTranslation } from 'react-i18next' import { InstantSearch } from 'react-instantsearch-core' -import { Dimensions, Platform, View } from 'react-native' +import { View } from 'react-native' import TypesenseInstantSearchAdapter from 'typesense-instantsearch-adapter' import ErrorBoundary from '@holi/core/errors/components/ErrorBoundary' @@ -32,8 +32,6 @@ const searchFields = ['title_de', 'title_en', 'description_de', 'description_en' const embeddingFields = ['embedding'] -const TOP_COMPONENT_HEIGHT = 144 - const createTypesenseInstantSearchAdapter = () => { return new TypesenseInstantSearchAdapter({ server: { @@ -65,7 +63,10 @@ export const Search = () => { return ( <InstantSearch searchClient={typesenseInstantSearchAdapter.searchClient} indexName={typesenseCollection}> <Screen + backgroundColor="page" preset="fixed" + contentContainerPadding={{}} + contentContainerStyle={{ flex: 1 }} // this is needed because flash list has no initial size, it calculates it while rendering. headerOptions={{ title: t('search.title'), headerTitleAlign: 'center', @@ -73,8 +74,6 @@ export const Search = () => { footerShown: false, }, }} - style={styles.screen} - contentContainerStyle={styles.container} StickyTopComponent={ <View style={styles.filterContainer}> <HoliBox padding={[0, dimensions.spacingS]}> @@ -83,11 +82,6 @@ export const Search = () => { <SearchFacetsChips initialFacet={initialFacet} onFacetChange={(facet) => updateParams({ facet })} /> </View> } - padding={{}} - keyboardAvoidingViewProps={{ - style: styles.wrapper, - }} - keyboardVerticalOffset={0} > <ErrorBoundary> <SearchHitInfiniteList /> @@ -98,26 +92,6 @@ export const Search = () => { } const stylesheet = createStyleSheet((theme) => ({ - screen: { - ...Platform.select({ - native: { - maxHeight: Dimensions.get('screen').height - dimensions.topBarHeight - TOP_COMPONENT_HEIGHT, - }, - web: { - maxHeight: Dimensions.get('window').height - dimensions.topBarHeight - TOP_COMPONENT_HEIGHT, - }, - }), - }, - wrapper: { - ...Platform.select({ - native: { - maxHeight: Dimensions.get('screen').height - dimensions.topBarHeight, - }, - }), - }, - container: { - flex: 1, - }, filterContainer: { paddingTop: dimensions.spacingS, gap: dimensions.spacingS, diff --git a/core/screens/search/typesense/SearchHitInfiniteList.tsx b/core/screens/search/typesense/SearchHitInfiniteList.tsx index 6b565075f3c7976483d53595a3ac080a24694b21..c8ab5e7fcf80f7c15adeb461121395292b339ccd 100644 --- a/core/screens/search/typesense/SearchHitInfiniteList.tsx +++ b/core/screens/search/typesense/SearchHitInfiniteList.tsx @@ -16,9 +16,9 @@ import type { SearchResults } from 'algoliasearch-helper' import type { Hit } from 'instantsearch.js' import HoliLoader from '@holi/ui/components/molecules/HoliLoader' import { useDebounce } from '@holi/ui/helper' -import { dimensions } from '@holi/ui/styles/globalVars' import { useOnRefresh } from '@holi/core/refreshing/hooks/useOnRefresh' import ErrorBoundary from '@holi/core/errors/components/ErrorBoundary' +import { Spacing } from 'holi-bricks/tokens' const isWeb = Platform.OS === 'web' @@ -64,7 +64,7 @@ export function SearchHitInfiniteList() { <FlashList contentContainerStyle={styles.list} testID={'search-results-list'} - estimatedItemSize={HIT_HEIGHT + dimensions.spacingS} + estimatedItemSize={HIT_HEIGHT + Spacing['xs']} data={items} keyExtractor={(item) => item.id} ItemSeparatorComponent={() => <HoliGap size={'s'} />} @@ -108,11 +108,11 @@ export function SearchHitInfiniteList() { const stylesheet = createStyleSheet({ loader: { - padding: dimensions.spacingSM, + padding: Spacing['xxs'], position: 'relative', }, list: { - paddingHorizontal: dimensions.spacingS, - paddingVertical: dimensions.spacingS, + paddingVertical: Spacing['xs'], + paddingHorizontal: Spacing['xs'], }, })