Skip to content
Merged
114 changes: 81 additions & 33 deletions src/components/LandingHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { lightBinarLogo, darkBinarLogo } from '@baca/constants'
import { useColorScheme } from '@baca/contexts'
import { Box, Button, Icon, Pressable, Spacer } from '@baca/design-system'
import { useCallback, useTheme, useTranslation } from '@baca/hooks'
import { Box, Button, Icon, Pressable, Row, Spacer, Touchable } from '@baca/design-system'
import { useFullScreenModal } from '@baca/design-system/modals/useFullScreenModal'
import { useCallback, useMemo, useTheme, useTranslation } from '@baca/hooks'
import { useUniversalWidth } from '@baca/navigation/tabNavigator/hooks'
import { isSignedInAtom } from '@baca/store/auth'
import { useRouter } from 'expo-router'
import { useAtomValue } from 'jotai'
Expand All @@ -15,43 +17,92 @@ export function LandingHeader() {
const { t } = useTranslation()
const { push, canGoBack, back } = useRouter()

const height = 60 + top

const isDesktop = useUniversalWidth(768)

const isSignedIn = useAtomValue(isSignedInAtom)

const navigateToLogin = useCallback(() => push('/sign-in'), [push])
const navigateToSignUp = useCallback(() => push('/sign-up'), [push])

const height = 60 + top
const { closeFullScreenModal, modalComponentRenderFunction, presentFullScreenModal } =
useFullScreenModal()

return (
<View
style={[
{ borderBottomColor: colors.border.secondary, height, paddingTop: top },
jsStyles.appHeader,
Platform.select({ default: {}, web: { display: 'flex' } }),
]}
>
{canGoBack() ? (
<Pressable onPress={back}>
<Icon name="arrow-left-line" size={20} />
</Pressable>
) : (
<Image
resizeMethod="resize"
resizeMode="contain"
source={colorScheme === 'light' ? lightBinarLogo : darkBinarLogo}
style={jsStyles.logoWide}
/>
)}
{!isSignedIn ? (
<View style={jsStyles.rowContainer}>
const renderLeftMenu = useMemo(() => {
return canGoBack() ? (
<Pressable onPress={back}>
<Icon name="arrow-left-line" size={20} />
</Pressable>
) : (
<Image
resizeMethod="resize"
resizeMode="contain"
source={colorScheme === 'light' ? lightBinarLogo : darkBinarLogo}
style={jsStyles.logoWide}
/>
)
}, [back, canGoBack, colorScheme])

const fullScreenModal = modalComponentRenderFunction(
<Box flex={1}>
<View
style={[
{ borderBottomColor: colors.border.secondary, height, paddingTop: top },
jsStyles.appHeader,
Platform.select({ default: {}, web: { display: 'flex' } }),
]}
>
{renderLeftMenu}
<Touchable onPress={closeFullScreenModal}>
<Icon name="close-line" size={24} color="text.brand.primary" />
</Touchable>
</View>
<Box flex={1} />
<Box p={4} w="full">
<Button onPress={navigateToLogin}>{t('landing_screen.login_cta')}</Button>
<Spacer y="4" />
<Button onPress={navigateToSignUp}>{t('landing_screen.sign_up')}</Button>
</Box>
</Box>
)

const renderRightMenu = useMemo(() => {
if (isSignedIn) {
return <Box />
}

if (isDesktop) {
return (
<Row>
<Button onPress={navigateToLogin}>{t('landing_screen.login_cta')}</Button>
<Spacer x="4" />
<Button onPress={navigateToSignUp}>{t('landing_screen.sign_up')}</Button>
</View>
) : (
<Box />
)}
</View>
</Row>
)
}

return (
<Touchable onPress={presentFullScreenModal}>
<Icon name="menu-2-line" size={24} color="text.brand.primary" />
</Touchable>
)
}, [isDesktop, isSignedIn, navigateToLogin, navigateToSignUp, presentFullScreenModal, t])

return (
<>
<View
style={[
{ borderBottomColor: colors.border.secondary, height, paddingTop: top },
jsStyles.appHeader,
Platform.select({ default: {}, web: { display: 'flex' } }),
]}
>
{renderLeftMenu}
{renderRightMenu}
</View>
{fullScreenModal}
</>
)
}

Expand All @@ -66,7 +117,4 @@ const jsStyles = StyleSheet.create({
zIndex: 10,
},
logoWide: { height: 60, width: 150 },
rowContainer: {
flexDirection: 'row',
},
})
8 changes: 6 additions & 2 deletions src/components/Modal.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useTheme } from '@baca/hooks'
import { hex2rgba } from '@baca/utils'
import {
Modal as RNModal,
ModalProps,
Expand Down Expand Up @@ -48,7 +49,10 @@ export const Modal = ({
>
<ScrollableComponent
style={styles.scroll}
contentContainerStyle={[styles.scrollContent, { background: colors.bg.overlay }]}
contentContainerStyle={[
styles.scrollContent,
{ background: hex2rgba(colors.bg.overlay, 0.5) },
]}
showsVerticalScrollIndicator={false}
>
<TouchableWithoutFeedback>{children}</TouchableWithoutFeedback>
Expand All @@ -66,10 +70,10 @@ const styles = StyleSheet.create({
justifyContent: 'center',
},
scroll: {
paddingHorizontal: 32,
width: '100%',
},
scrollContent: {
justifyContent: 'center',
paddingHorizontal: 32,
},
})
1 change: 1 addition & 0 deletions src/design-system/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './bottomSheets'
export * from './components'
export * from './config'
export * from './modals'
export * from './utils'
37 changes: 37 additions & 0 deletions src/design-system/modals/FullScreenModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { useBoolean, useImperativeHandle } from '@baca/hooks'
import { RefObject } from 'react'
import { Modal, ModalProps } from 'react-native'

import { Box } from '../components'

export type ModalMethods = {
present: () => void
close: () => void
}

type Props = {
modalRef: RefObject<ModalMethods>
} & ModalProps

export const FullScreenModal = ({ children, modalRef, ...rest }: Props) => {
const [isOpen, setIsOpen] = useBoolean(false)

useImperativeHandle(modalRef, () => ({
present: setIsOpen.on,
close: setIsOpen.off,
}))

return (
<Modal
{...rest}
animationType="fade"
transparent
visible={isOpen}
onRequestClose={setIsOpen.off}
>
<Box bg="bg.primary" w="100%" height="100%">
{children}
</Box>
</Modal>
)
}
2 changes: 2 additions & 0 deletions src/design-system/modals/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './FullScreenModal'
export * from './useFullScreenModal'
25 changes: 25 additions & 0 deletions src/design-system/modals/useFullScreenModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useCallback, useRef } from 'react'

import { FullScreenModal, ModalMethods } from './FullScreenModal'

export const useFullScreenModal = () => {
const modalRef = useRef<ModalMethods>(null)

const modalComponentRenderFunction = (children: JSX.Element | JSX.Element[]) => {
return <FullScreenModal modalRef={modalRef}>{children}</FullScreenModal>
}

const presentFullScreenModal = useCallback(() => {
modalRef.current?.present?.()
}, [])

const closeFullScreenModal = useCallback(() => {
modalRef.current?.close?.()
}, [])

return {
modalComponentRenderFunction,
presentFullScreenModal,
closeFullScreenModal,
}
}
31 changes: 16 additions & 15 deletions src/navigation/tabNavigator/components/BottomBar.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Icon } from '@baca/design-system'
import { Column, Icon, Text } from '@baca/design-system'
import { useTheme } from '@baca/hooks'
import cssStyles from '@baca/styles'
import { Platform, StyleSheet, View } from 'react-native'
import { useSafeAreaInsets } from 'react-native-safe-area-context'

import { TabBarItemWrapper } from './TabBarItemWrapper'
import { bottomTabs } from '../navigation-config'
import { bottomTabs, getTabColor } from '../navigation-config'
import { cns } from '../utils'

export function BottomBar({ visible }: { visible: boolean }) {
Expand All @@ -28,21 +28,27 @@ export function BottomBar({ visible }: { visible: boolean }) {
{bottomTabs.map((tab, i) => (
<TabBarItemWrapper key={i} name={tab.name} id={tab.id} params={tab.params}>
{({ focused, pressed, hovered }) => (
<Icon
name={focused ? tab.iconFocused : tab.icon}
size={40}
color="nav.item.button.icon.fg"
<Column
px={2}
alignItems="center"
style={[
jsStyles.tabIcon,
pressed && jsStyles.tabIconPressed,
Platform.select({
web: {
transitionDuration: '200ms',
transform: hovered ? [{ scale: 1.2 }] : [{ scale: 1 }],
transform: [{ scale: hovered ? 1.1 : pressed ? 0.9 : 1 }],
},
}),
]}
/>
gap={2}
>
<Icon
name={focused ? tab.iconFocused : tab.icon}
size={24}
color={getTabColor(focused)}
/>
<Text.XsMedium color={getTabColor(focused)}>{tab.displayedName}</Text.XsMedium>
</Column>
)}
</TabBarItemWrapper>
))}
Expand All @@ -56,16 +62,11 @@ const jsStyles = StyleSheet.create({
alignItems: 'center',
borderTopWidth: 1,
flexDirection: 'row',
height: 49,
height: 56,
justifyContent: 'space-around',
paddingHorizontal: 16,
},

tabIcon: {
paddingHorizontal: 8,
},
tabIconPressed: {
opacity: 0.8,
transform: [{ scale: 0.9 }],
},
})
14 changes: 4 additions & 10 deletions src/navigation/tabNavigator/components/HeaderLogo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import { Pressable } from '@bacons/react-views'
import { Link } from 'expo-router'
import { Platform, StyleSheet, View } from 'react-native'

import { useWidth } from '../hooks'
import { useUniversalWidth } from '../hooks'
import { cns } from '../utils'

export function HeaderLogo() {
const { colors } = useTheme()
const isLargeHorizontal = useWidth(1264)
const isLargeHorizontal = useUniversalWidth(1264)

return (
<View
Expand All @@ -19,14 +19,7 @@ export function HeaderLogo() {
web: cns(cssStyles.headerContainer),
})}
>
<Link
style={Platform.select({
default: jsStyles.headerLink,
web: cns(cssStyles.headerLink),
})}
href="/"
asChild
>
<Link style={jsStyles.headerLink} href="/" asChild>
<Pressable>
{({ hovered }) => (
<View
Expand Down Expand Up @@ -69,6 +62,7 @@ const jsStyles = StyleSheet.create({
},
headerLink: {
alignItems: 'center',
paddingBottom: 24,
},
headerLogo: {
alignItems: 'center',
Expand Down
9 changes: 5 additions & 4 deletions src/navigation/tabNavigator/components/SideBar.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import { useTheme } from '@baca/hooks'
import { useSafeAreaInsets, useTheme } from '@baca/hooks'
import { signOut } from '@baca/store/auth'
import cssStyles from '@baca/styles'
import { Platform, StyleSheet, View } from 'react-native'

import { HeaderLogo } from './HeaderLogo'
import { SideBarTabItem } from './SideBarTabItem'
import { useWidth } from '../hooks'
import { useUniversalWidth } from '../hooks'
import { upperSideTabs } from '../navigation-config'
import { cns } from '../utils'

const NAV_MEDIUM_WIDTH = 244

export function SideBar({ visible }: { visible: boolean }) {
const { colors } = useTheme()
const isLarge = useWidth(1264)
const { top } = useSafeAreaInsets()
const isLarge = useUniversalWidth(1264)

return (
<View
Expand All @@ -38,6 +39,7 @@ export function SideBar({ visible }: { visible: boolean }) {
<View
style={[
jsStyles.sidebarInner,
{ paddingTop: top + 8 },
{ borderRightColor: colors.border.secondary },
...Platform.select({
default: [
Expand Down Expand Up @@ -106,7 +108,6 @@ const jsStyles = StyleSheet.create({
minWidth: 72,
paddingBottom: 20,
paddingHorizontal: 12,
paddingTop: 8,
position: 'absolute',
width: 72,
},
Expand Down
Loading