diff --git a/src/view/com/profile/FollowButton.tsx b/src/view/com/profile/FollowButton.tsx
index 7a194cee9a..5204f5a40c 100644
--- a/src/view/com/profile/FollowButton.tsx
+++ b/src/view/com/profile/FollowButton.tsx
@@ -1,16 +1,18 @@
import React from 'react'
import {observer} from 'mobx-react-lite'
-import {Button} from '../util/forms/Button'
+import {Button, ButtonType} from '../util/forms/Button'
import {useStores} from 'state/index'
import * as apilib from 'lib/api/index'
import * as Toast from '../util/Toast'
const FollowButton = observer(
({
+ type = 'inverted',
did,
declarationCid,
onToggleFollow,
}: {
+ type?: ButtonType
did: string
declarationCid: string
onToggleFollow?: (v: boolean) => void
@@ -42,7 +44,7 @@ const FollowButton = observer(
return (
diff --git a/src/view/com/util/Pager.tsx b/src/view/com/util/Pager.tsx
index 9ce5006cd1..89ba59e853 100644
--- a/src/view/com/util/Pager.tsx
+++ b/src/view/com/util/Pager.tsx
@@ -15,11 +15,13 @@ export interface TabBarProps {
}
interface Props {
+ tabBarPosition?: 'top' | 'bottom'
renderTabBar: (props: TabBarProps) => JSX.Element
onPageSelected?: (e: PageSelectedEvent) => void
}
export const Pager = ({
children,
+ tabBarPosition = 'top',
renderTabBar,
onPageSelected,
}: React.PropsWithChildren) => {
@@ -45,7 +47,13 @@ export const Pager = ({
return (
- {renderTabBar({selectedPage, position, offset, onSelect: onTabBarSelect})}
+ {tabBarPosition === 'top' &&
+ renderTabBar({
+ selectedPage,
+ position,
+ offset,
+ onSelect: onTabBarSelect,
+ })}
{children}
+ {tabBarPosition === 'bottom' &&
+ renderTabBar({
+ selectedPage,
+ position,
+ offset,
+ onSelect: onTabBarSelect,
+ })}
)
}
diff --git a/src/view/com/util/PostMeta.tsx b/src/view/com/util/PostMeta.tsx
index 1a36a72e82..c53de5c1f1 100644
--- a/src/view/com/util/PostMeta.tsx
+++ b/src/view/com/util/PostMeta.tsx
@@ -77,6 +77,7 @@ export const PostMeta = observer(function (opts: PostMetaOpts) {
void
}) {
const pal = usePalette('default')
@@ -36,8 +40,10 @@ export function TabBar({
)
const panX = Animated.add(position, offset)
- const underlineStyle = {
- backgroundColor: pal.colors.link,
+ const indicatorStyle = {
+ backgroundColor: indicatorColor || pal.colors.link,
+ bottom: indicatorPosition === 'bottom' ? -1 : undefined,
+ top: indicatorPosition === 'top' ? -1 : undefined,
left: panX.interpolate({
inputRange: items.map((_item, i) => i),
outputRange: itemLayouts.map(l => l.x),
@@ -72,12 +78,16 @@ export function TabBar({
return (
-
+
{items.map((item, i) => {
const selected = i === selectedPage
return (
onPressItem(i)}>
-
+
{item}
@@ -94,15 +104,19 @@ const styles = StyleSheet.create({
flexDirection: 'row',
paddingHorizontal: 14,
},
- item: {
+ itemTop: {
+ paddingTop: 10,
+ paddingBottom: 10,
+ marginRight: 24,
+ },
+ itemBottom: {
paddingTop: 8,
paddingBottom: 12,
marginRight: 24,
},
- underline: {
+ indicator: {
position: 'absolute',
height: 3,
- bottom: -1,
borderRadius: 4,
},
})
diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx
index b38e1cc367..390746eb34 100644
--- a/src/view/screens/Home.tsx
+++ b/src/view/screens/Home.tsx
@@ -1,8 +1,8 @@
import React from 'react'
import {
+ Animated,
FlatList,
StyleSheet,
- TouchableOpacity,
View,
useWindowDimensions,
} from 'react-native'
@@ -15,7 +15,6 @@ import {withAuthRequired} from 'view/com/auth/withAuthRequired'
import {Feed} from '../com/posts/Feed'
import {LoadLatestBtn} from '../com/util/LoadLatestBtn'
import {WelcomeBanner} from '../com/util/WelcomeBanner'
-import {UserAvatar} from 'view/com/util/UserAvatar'
import {TabBar} from 'view/com/util/TabBar'
import {Pager, PageSelectedEvent, TabBarProps} from 'view/com/util/Pager'
import {FAB} from '../com/util/FAB'
@@ -23,15 +22,18 @@ import {useStores} from 'state/index'
import {usePalette} from 'lib/hooks/usePalette'
import {s} from 'lib/styles'
import {useOnMainScroll} from 'lib/hooks/useOnMainScroll'
+import {useSafeAreaInsets} from 'react-native-safe-area-context'
+import {useAnimatedValue} from 'lib/hooks/useAnimatedValue'
import {useAnalytics} from 'lib/analytics'
import {ComposeIcon2} from 'lib/icons'
+import {clamp} from 'lodash'
const TAB_BAR_HEIGHT = 82
+const BOTTOM_BAR_HEIGHT = 48
type Props = NativeStackScreenProps
export const HomeScreen = withAuthRequired((_opts: Props) => {
const store = useStores()
- const pal = usePalette('default')
const [selectedPage, setSelectedPage] = React.useState(0)
useFocusEffect(
@@ -51,26 +53,15 @@ export const HomeScreen = withAuthRequired((_opts: Props) => {
[store],
)
- const onPressAvi = React.useCallback(() => {
- store.shell.openDrawer()
- }, [store])
-
- const renderTabBar = React.useCallback(
- (props: TabBarProps) => {
- return (
-
-
-
-
-
-
- )
- },
- [store.me.avatar, pal, onPressAvi],
- )
+ const renderTabBar = React.useCallback((props: TabBarProps) => {
+ return
+ }, [])
return (
-
+
@@ -79,6 +70,46 @@ export const HomeScreen = withAuthRequired((_opts: Props) => {
)
})
+const FloatingTabBar = observer((props: TabBarProps) => {
+ const store = useStores()
+ const safeAreaInsets = useSafeAreaInsets()
+ const pal = usePalette('default')
+ const interp = useAnimatedValue(0)
+
+ const pad = React.useMemo(
+ () => ({
+ paddingBottom: clamp(safeAreaInsets.bottom, 15, 20),
+ }),
+ [safeAreaInsets],
+ )
+
+ React.useEffect(() => {
+ Animated.timing(interp, {
+ toValue: store.shell.minimalShellMode ? 0 : 1,
+ duration: 100,
+ useNativeDriver: true,
+ isInteraction: false,
+ }).start()
+ }, [interp, store.shell.minimalShellMode])
+ const transform = {
+ transform: [
+ {translateY: Animated.multiply(interp, -1 * BOTTOM_BAR_HEIGHT)},
+ ],
+ }
+
+ return (
+
+
+
+ )
+})
+
const AlgoView = observer(() => {
const store = useStores()
const onMainScroll = useOnMainScroll(store)
@@ -270,13 +301,19 @@ const FollowingView = observer(() => {
const styles = StyleSheet.create({
tabBar: {
+ position: 'absolute',
+ left: 0,
+ right: 0,
+ bottom: 0,
flexDirection: 'row',
alignItems: 'center',
- paddingHorizontal: 18,
- borderBottomWidth: 1,
+ paddingHorizontal: 8,
+ borderTopWidth: 1,
+ paddingTop: 0,
+ paddingBottom: 30,
+ // height: 100,
},
tabBarAvi: {
- marginRight: 16,
- paddingBottom: 2,
+ marginRight: 4,
},
})
diff --git a/src/view/shell/BottomBar.tsx b/src/view/shell/BottomBar.tsx
index c59d8c6758..1cbf2de868 100644
--- a/src/view/shell/BottomBar.tsx
+++ b/src/view/shell/BottomBar.tsx
@@ -34,16 +34,24 @@ export const BottomBar = observer(({navigation}: BottomTabBarProps) => {
const minimalShellInterp = useAnimatedValue(0)
const safeAreaInsets = useSafeAreaInsets()
const {track} = useAnalytics()
- const {isAtHome, isAtSearch, isAtNotifications} = useNavigationState(
- state => {
- return {
+ const {isAtHome, isAtSearch, isAtNotifications, noBorder} =
+ useNavigationState(state => {
+ const res = {
isAtHome: getTabState(state, 'Home') !== TabState.Outside,
isAtSearch: getTabState(state, 'Search') !== TabState.Outside,
isAtNotifications:
getTabState(state, 'Notifications') !== TabState.Outside,
+ noBorder: getTabState(state, 'Home') === TabState.InsideAtRoot,
}
- },
- )
+ if (!res.isAtHome && !res.isAtNotifications && !res.isAtSearch) {
+ // HACK for some reason useNavigationState will give us pre-hydration results
+ // and not update after, so we force isAtHome if all came back false
+ // -prf
+ res.isAtHome = true
+ res.noBorder = true
+ }
+ return res
+ })
React.useEffect(() => {
if (store.shell.minimalShellMode) {
@@ -99,6 +107,7 @@ export const BottomBar = observer(({navigation}: BottomTabBarProps) => {