import React from 'react'
import type { ViewProps, TabLayout, TabsTabProps } from 'tamagui'
import {
AnimatePresence,
Button,
H5,
SizableText,
Tabs,
XStack,
YStack,
styled,
} from 'tamagui'
const demos = ['background', 'underline'] as const
const demosTitle: Record<(typeof demos)[number], string> = {
background: 'Background Indicator',
underline: 'Underline Indicator',
}
export const TabsAdvancedDemo = () => {
const [demoIndex, setDemoIndex] = React.useState(0)
const demo = demos[demoIndex]
return (
<>
{demo === 'underline' ? : }
>
)
}
const TabsAdvancedBackground = () => {
const [tabState, setTabState] = React.useState<{
currentTab: string
/**
* Layout of the Tab user might intend to select (hovering / focusing)
*/
intentAt: TabLayout | null
/**
* Layout of the Tab user selected
*/
activeAt: TabLayout | null
/**
* Used to get the direction of activation for animating the active indicator
*/
prevActiveAt: TabLayout | null
}>({
activeAt: null,
currentTab: 'tab1',
intentAt: null,
prevActiveAt: null,
})
const setCurrentTab = (currentTab: string) => setTabState({ ...tabState, currentTab })
const setIntentIndicator = (intentAt) => setTabState({ ...tabState, intentAt })
const setActiveIndicator = (activeAt) =>
setTabState({ ...tabState, prevActiveAt: tabState.activeAt, activeAt })
const { activeAt, intentAt, prevActiveAt, currentTab } = tabState
// 1 = right, 0 = nowhere, -1 = left
const direction = (() => {
if (!activeAt || !prevActiveAt || activeAt.x === prevActiveAt.x) {
return 0
}
return activeAt.x > prevActiveAt.x ? -1 : 1
})()
const handleOnInteraction: TabsTabProps['onInteraction'] = (type, layout) => {
if (type === 'select') {
setActiveIndicator(layout)
} else {
setIntentIndicator(layout)
}
}
return (
{intentAt && (
)}
{activeAt && (
)}
Profile
Connections
Notifications
{currentTab}
)
}
const TabsAdvancedUnderline = () => {
const [tabState, setTabState] = React.useState<{
currentTab: string
/**
* Layout of the Tab user might intend to select (hovering / focusing)
*/
intentAt: TabLayout | null
/**
* Layout of the Tab user selected
*/
activeAt: TabLayout | null
/**
* Used to get the direction of activation for animating the active indicator
*/
prevActiveAt: TabLayout | null
}>({
activeAt: null,
currentTab: 'tab1',
intentAt: null,
prevActiveAt: null,
})
const setCurrentTab = (currentTab: string) => setTabState({ ...tabState, currentTab })
const setIntentIndicator = (intentAt) => setTabState({ ...tabState, intentAt })
const setActiveIndicator = (activeAt) =>
setTabState({ ...tabState, prevActiveAt: tabState.activeAt, activeAt })
const { activeAt, intentAt, prevActiveAt, currentTab } = tabState
// 1 = right, 0 = nowhere, -1 = left
const direction = (() => {
if (!activeAt || !prevActiveAt || activeAt.x === prevActiveAt.x) {
return 0
}
return activeAt.x > prevActiveAt.x ? -1 : 1
})()
const handleOnInteraction: TabsTabProps['onInteraction'] = (type, layout) => {
if (type === 'select') {
setActiveIndicator(layout)
} else {
setIntentIndicator(layout)
}
}
return (
{intentAt && (
)}
{activeAt && (
)}
Profile
Connections
Notifications
{currentTab}
)
}
const TabsRovingIndicator = ({ active, ...props }: { active?: boolean } & ViewProps) => {
return (
)
}
const AnimatedYStack = styled(YStack, {
flex: 1,
x: 0,
opacity: 1,
transition: '100ms',
variants: {
// 1 = right, 0 = nowhere, -1 = left
direction: {
':number': (direction) => ({
enterStyle: {
x: direction > 0 ? -25 : 25,
opacity: 0,
},
exitStyle: {
zIndex: 0,
x: direction < 0 ? -25 : 25,
opacity: 0,
},
}),
},
} as const,
})