Write on the margins of the internet. Powered by the AT Protocol.
margin.at
extension
web
atproto
comments
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}