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, })