diff --git a/src/components/NoteList/index.tsx b/src/components/NoteList/index.tsx index a258dafa..71c369b8 100644 --- a/src/components/NoteList/index.tsx +++ b/src/components/NoteList/index.tsx @@ -18,7 +18,7 @@ import { useTranslation } from 'react-i18next' import PullToRefresh from 'react-simple-pull-to-refresh' import NoteCard, { NoteCardLoadingSkeleton } from '../NoteCard' import { PictureNoteCardMasonry } from '../PictureNoteCardMasonry' -import TabSwitcher from '../TabSwitch' +import Tabs from '../Tabs' const LIMIT = 100 const ALGO_LIMIT = 500 @@ -291,7 +291,7 @@ export default function NoteList({ return (
- { return (
- void -} - -export default function TabSwitcher({ - tabs, - value, - className, - onTabChange, - threshold = 800 -}: { - tabs: TabDefinition[] - value: string - className?: string - onTabChange?: (tab: string) => void - threshold?: number -}) { - const { t } = useTranslation() - const { deepBrowsing, lastScrollTop } = useDeepBrowsing() - const activeIndex = tabs.findIndex((tab) => tab.value === value) - - return ( -
threshold ? '-translate-y-[calc(100%+12rem)]' : '', - className - )} - > -
- {tabs.map((tab) => ( -
{ - tab.onClick?.() - onTabChange?.(tab.value) - }} - > - {t(tab.label)} -
- ))} -
-
-
= 0 ? activeIndex * (100 / tabs.length) : 0}%` - }} - > -
-
-
-
- ) -} diff --git a/src/components/Tabs/index.tsx b/src/components/Tabs/index.tsx new file mode 100644 index 00000000..84b8c6fb --- /dev/null +++ b/src/components/Tabs/index.tsx @@ -0,0 +1,76 @@ +import { cn } from '@/lib/utils' +import { useDeepBrowsing } from '@/providers/DeepBrowsingProvider' +import { useEffect, useRef, useState } from 'react' +import { useTranslation } from 'react-i18next' + +type TabDefinition = { + value: string + label: string +} + +export default function Tabs({ + tabs, + value, + onTabChange, + threshold = 800 +}: { + tabs: TabDefinition[] + value: string + onTabChange?: (tab: string) => void + threshold?: number +}) { + const { t } = useTranslation() + const { deepBrowsing, lastScrollTop } = useDeepBrowsing() + const activeIndex = tabs.findIndex((tab) => tab.value === value) + const tabRefs = useRef<(HTMLDivElement | null)[]>([]) + const [indicatorStyle, setIndicatorStyle] = useState({ width: 0, left: 0 }) + + useEffect(() => { + const handleResize = () => { + if (activeIndex >= 0 && tabRefs.current[activeIndex]) { + const activeTab = tabRefs.current[activeIndex] + const { offsetWidth, offsetLeft } = activeTab + const padding = 32 // 16px padding on each side + setIndicatorStyle({ + width: offsetWidth - padding, + left: offsetLeft + padding / 2 + }) + } + } + window.addEventListener('resize', handleResize) + handleResize() // Initial call to set the indicator style + return () => { + window.removeEventListener('resize', handleResize) + } + }, [activeIndex]) + + return ( +
threshold ? '-translate-y-[calc(100%+12rem)]' : '' + )} + > + {tabs.map((tab, index) => ( +
(tabRefs.current[index] = el)} + className={cn( + `text-center w-full py-2 font-semibold clickable cursor-pointer rounded-lg`, + value === tab.value ? '' : 'text-muted-foreground' + )} + onClick={() => onTabChange?.(tab.value)} + > + {t(tab.label)} +
+ ))} +
+
+ ) +} diff --git a/src/pages/primary/ExplorePage/index.tsx b/src/pages/primary/ExplorePage/index.tsx index 530ebc6a..1d3616ad 100644 --- a/src/pages/primary/ExplorePage/index.tsx +++ b/src/pages/primary/ExplorePage/index.tsx @@ -1,6 +1,6 @@ import FollowingFavoriteRelayList from '@/components/FollowingFavoriteRelayList' import RelayList from '@/components/RelayList' -import TabSwitcher from '@/components/TabSwitch' +import Tabs from '@/components/Tabs' import PrimaryPageLayout from '@/layouts/PrimaryPageLayout' import { Compass } from 'lucide-react' import { forwardRef, useState } from 'react' @@ -18,7 +18,7 @@ const ExplorePage = forwardRef((_, ref) => { titlebar={} displayScrollToTopButton > -