Write on the margins of the internet. Powered by the AT Protocol. margin.at
extension web atproto comments
at main 85 lines 2.4 kB view raw
1import { useStore as useNanoStore, useStore } from "@nanostores/react"; 2import { useState } from "react"; 3import { $user } from "../../store/auth"; 4import { $feedLayout } from "../../store/feedLayout"; 5import { Tabs } from "../ui"; 6import LayoutToggle from "../ui/LayoutToggle"; 7import FeedItems from "./FeedItems"; 8 9interface MasonryFeedProps { 10 motivation?: string; 11 emptyMessage?: string; 12 showTabs?: boolean; 13 title?: string; 14} 15 16export default function MasonryFeed({ 17 motivation, 18 emptyMessage = "No items found.", 19 showTabs = false, 20 title, 21}: MasonryFeedProps) { 22 const user = useStore($user); 23 const layout = useNanoStore($feedLayout); 24 const [activeTab, setActiveTab] = useState(user ? "my" : "global"); 25 26 const handleTabChange = (id: string) => { 27 if (id === activeTab) return; 28 setActiveTab(id); 29 window.scrollTo({ top: 0, behavior: "smooth" }); 30 }; 31 32 const tabs = user 33 ? [ 34 { id: "my", label: "My" }, 35 { id: "global", label: "Global" }, 36 ] 37 : [{ id: "global", label: "Global" }]; 38 39 const creator = activeTab === "my" ? user?.did : undefined; 40 const type = activeTab === "my" ? "my-feed" : "all"; 41 42 return ( 43 <div className="mx-auto max-w-2xl xl:max-w-none"> 44 {title && ( 45 <h1 className="text-3xl font-display font-bold text-surface-900 dark:text-white mb-6 text-center lg:text-left"> 46 {title} 47 </h1> 48 )} 49 50 {showTabs && ( 51 <div className="sticky top-0 z-10 bg-white/95 dark:bg-surface-800/95 backdrop-blur-sm pb-4 mb-2 -mx-1 px-1 pt-1"> 52 <div className="flex items-center gap-3"> 53 <div className="flex-1"> 54 <Tabs 55 tabs={tabs} 56 activeTab={activeTab} 57 onChange={handleTabChange} 58 /> 59 </div> 60 <LayoutToggle className="hidden sm:inline-flex" /> 61 </div> 62 </div> 63 )} 64 65 {!showTabs && ( 66 <div className="flex justify-end mb-4"> 67 <LayoutToggle className="hidden sm:inline-flex" /> 68 </div> 69 )} 70 71 <FeedItems 72 key={activeTab} 73 type={type} 74 motivation={motivation} 75 emptyMessage={ 76 activeTab === "my" 77 ? emptyMessage 78 : `No ${motivation === "bookmarking" ? "bookmarks" : "highlights"} from the community yet.` 79 } 80 creator={creator} 81 layout={layout} 82 /> 83 </div> 84 ); 85}