diff --git a/src/app/explorer/atoms.ts b/src/app/explorer/atoms.ts new file mode 100644 index 0000000000..9dd154ad85 --- /dev/null +++ b/src/app/explorer/atoms.ts @@ -0,0 +1,17 @@ +import { atom } from "jotai" +import { ActiveSection } from "./types" + +export const isNavStuckAtom = atom(false) +export const isSeachStuckAtom = atom(false) +export const activeSectionAtom = atom(ActiveSection.YourGuilds) + +// const { ref: navToggleRef, isStuck: isNavStuck } = useIsStuck() +// const { ref: searchRef, isStuck: isSearchStuck } = useIsStuck() +// const [activeSection, setActiveSection] = useState( +// ActiveSection.YourGuilds +// ) +// const spyActiveSection = useScrollspy(Object.values(ActiveSection), 100) +// useEffect(() => { +// if (!spyActiveSection) return +// setActiveSection(spyActiveSection as ActiveSection) +// }, [spyActiveSection]) diff --git a/src/app/explorer/page.tsx b/src/app/explorer/page.tsx index e0fc66dc35..9fc16d7974 100644 --- a/src/app/explorer/page.tsx +++ b/src/app/explorer/page.tsx @@ -4,109 +4,112 @@ import { ToggleGroup, ToggleGroupItem } from "@/components/ui/ToggleGroup" import { Button } from "@/components/ui/Button" import { Plus, SignIn } from "@phosphor-icons/react" import Robot from "/public/landing/robot.svg" -import { Header } from "@/components/Header" import { Separator } from "@/components/ui/Separator" -import useIsStuck from "hooks/useIsStuck" -import { PageBoundary } from "@/components/PageBoundary" import { Card } from "@/components/ui/Card" -import { useEffect, useState } from "react" +import useIsStuck from "hooks/useIsStuck" +import { useEffect } from "react" import useScrollspy from "hooks/useScrollSpy" import { GuildInfiniteScroll } from "@/components/GuildInfiniteScroll" import { GuildSearchBar } from "@/components/GuildSeachBar" import { ActiveSection } from "./types" import { Anchor } from "@/components/ui/Anchor" +import { Layout } from "@/components/Layout" +import { isNavStuckAtom, isSeachStuckAtom, activeSectionAtom } from "./atoms" +import { useAtom, useAtomValue, useSetAtom } from "jotai" -const Page = () => { - const isAuthenticated = false - const { ref: navToggleRef, isStuck: isNavStuck } = useIsStuck() - const { ref: searchRef, isStuck: isSearchStuck } = useIsStuck() - const [activeSection, setActiveSection] = useState( - ActiveSection.YourGuilds +const HeaderBackground = () => { + const isNavStuck = useAtomValue(isNavStuckAtom) + const isSearchStuck = useAtomValue(isSeachStuckAtom) + + return ( +
) +} + +const Nav = () => { + const isNavStuck = useAtomValue(isNavStuckAtom) + const isSearchStuck = useAtomValue(isSeachStuckAtom) + const [activeSection, setActiveSection] = useAtom(activeSectionAtom) const spyActiveSection = useScrollspy(Object.values(ActiveSection), 100) useEffect(() => { if (!spyActiveSection) return setActiveSection(spyActiveSection as ActiveSection) - }, [spyActiveSection]) + }, [spyActiveSection, setActiveSection]) return ( -
-
-
-
- -

- Guildhall -

-
-
-
-
-
-
-
-
-
- -
-
- - value && setActiveSection(value as ActiveSection) - } - value={activeSection} - > - - Your guilds - - - Explore guilds - - - {isAuthenticated && ( - - )} -
+ value && setActiveSection(value as ActiveSection)} + value={activeSection} + > + + Your guilds + + + Explore guilds + + + ) +} + +const Page = () => { + const isAuthenticated = false + const setIsNavStuck = useSetAtom(isNavStuckAtom) + const setIsSearchStuck = useSetAtom(isSeachStuckAtom) + const { ref: navToggleRef } = useIsStuck(setIsNavStuck) + const { ref: searchRef } = useIsStuck(setIsSearchStuck) + + return ( + <> + + + +
+ +
+ +
+ +
+
+
+
+ +
+ + Sign in to view your guilds / create new ones +
+ +
+ {isAuthenticated && } +
+

+ Explore verified guilds +

+
+
- -
- - Sign in to view your guilds / create new ones -
- -
- {isAuthenticated && } -
-

- Explore verified guilds -

-
- -
- -
- -
-
-
- + + + +

This website is{" "} { Guild SDK

-
-
-
+ + + ) } diff --git a/src/hooks/useIsStuck.ts b/src/hooks/useIsStuck.ts index 4aaac5e5c6..1b39eb4fd3 100644 --- a/src/hooks/useIsStuck.ts +++ b/src/hooks/useIsStuck.ts @@ -1,12 +1,22 @@ -import { useEffect, useRef, useState } from "react" +import { + Dispatch, + MutableRefObject, + SetStateAction, + useEffect, + useRef, + useState, +} from "react" /** * The IntersectionObserver triggers if the element is off the viewport, so we have * to set top="-1px" or bottom="-1px" on the sticky element instead of 0 */ -const useIsStuck = () => { +const useIsStuck = ( + setIsStuck?: Dispatch> +): { ref: MutableRefObject; isStuck?: boolean } => { const ref = useRef(null) - const [isStuck, setIsStuck] = useState(false) + const [isStuck, setIsStuckLocal] = useState(false) + const setIsStuckActive = setIsStuck ?? setIsStuckLocal useEffect(() => { if (!ref.current) return @@ -16,7 +26,7 @@ const useIsStuck = () => { const observer = new IntersectionObserver( ([e]) => { - setIsStuck( + setIsStuckActive( !e.isIntersecting && (e.boundingClientRect.top < topOffsetPx || e.boundingClientRect.bottom > bottomOffsetPx) @@ -31,7 +41,7 @@ const useIsStuck = () => { return () => observer.unobserve(cachedRef) }, [ref]) - return { ref, isStuck } + return { ref, isStuck: setIsStuck ? undefined : isStuck } } export default useIsStuck diff --git a/src/v2/components/GuildInfiniteScroll.tsx b/src/v2/components/GuildInfiniteScroll.tsx index e72c087b42..4da3ec3454 100644 --- a/src/v2/components/GuildInfiniteScroll.tsx +++ b/src/v2/components/GuildInfiniteScroll.tsx @@ -8,6 +8,7 @@ import { GuildBase } from "types" import { fetcherWithSign } from "utils/fetcher" import { useScrollBatchedRendering } from "hooks/useScrollBatchedRendering" import { Spinner } from "@phosphor-icons/react" +import { SWRConfiguration } from "swr" export const guildQueryAtom = atom("") const BATCH_SIZE = 24 @@ -26,10 +27,9 @@ const useExploreGuilds = ( guildsInitial: GuildBase[] ) => { const { isSuperAdmin } = useUser() - const options = { + const options: SWRConfiguration = { fallbackData: guildsInitial, dedupingInterval: 60000, // one minute - revalidateFirstPage: false, } // sending authed request for superAdmins, so they can see unverified & hideFromExplorer guilds too @@ -60,7 +60,6 @@ const useExploreGuilds = ( export const GuildInfiniteScroll = () => { const searchParams = new URLSearchParams(useAtomValue(guildQueryAtom)) const search = searchParams.get("search") - // const prevSearch = useRef(); const ref = useRef(null) const { data: filteredGuilds, @@ -70,12 +69,6 @@ export const GuildInfiniteScroll = () => { } = useExploreGuilds(searchParams, []) const renderedGuilds = filteredGuilds?.flat() - // useEffect(() => { - // if (prevSearch.current === search || prevSearch.current === undefined) return - // setSize(1) - // return () => { prevSearch.current = search } - // }, [search, setSize]) - useScrollBatchedRendering({ batchSize: 1, scrollTarget: ref, diff --git a/src/v2/components/GuildSeachBar.tsx b/src/v2/components/GuildSeachBar.tsx index 1a6268871f..6254f10289 100644 --- a/src/v2/components/GuildSeachBar.tsx +++ b/src/v2/components/GuildSeachBar.tsx @@ -32,11 +32,11 @@ export const GuildSearchBar = () => { ([_, value]) => value ) ) - history.replaceState( - null, - "", - `${pathName}${window.location.hash}?${newSearchParams.toString()}` - ) + // history.replaceState( + // null, + // "", + // `${pathName}${window.location.hash}?${newSearchParams.toString()}` + // ) setGuildQuery(newSearchParams.toString()) }, [debouncedSearch, order, setGuildQuery, pathName]) diff --git a/src/v2/components/Layout/Banner.tsx b/src/v2/components/Layout/Banner.tsx new file mode 100644 index 0000000000..d4b5018570 --- /dev/null +++ b/src/v2/components/Layout/Banner.tsx @@ -0,0 +1,7 @@ +export const Banner = () => ( +
+
+
+
+
+) diff --git a/src/v2/components/Layout/Footer.tsx b/src/v2/components/Layout/Footer.tsx new file mode 100644 index 0000000000..433a640320 --- /dev/null +++ b/src/v2/components/Layout/Footer.tsx @@ -0,0 +1,8 @@ +import { PropsWithChildren } from "react" +import { PageBoundary } from "../PageBoundary" + +export const Footer = ({ children }: PropsWithChildren) => ( +
+ {children} +
+) diff --git a/src/v2/components/Layout/Header.tsx b/src/v2/components/Layout/Header.tsx new file mode 100644 index 0000000000..d4e8326be6 --- /dev/null +++ b/src/v2/components/Layout/Header.tsx @@ -0,0 +1,9 @@ +import { PropsWithChildren } from "react" +import { Header as NavHeader } from "../Header" + +export const Header = ({ children }: PropsWithChildren) => ( +
+ + {children} +
+) diff --git a/src/v2/components/Layout/Headline.tsx b/src/v2/components/Layout/Headline.tsx new file mode 100644 index 0000000000..bc60297430 --- /dev/null +++ b/src/v2/components/Layout/Headline.tsx @@ -0,0 +1,14 @@ +import { ReactNode } from "react" +import { PageBoundary } from "../PageBoundary" + +interface HeadlineProps { + title: ReactNode +} + +export const Headline = ({ title }: HeadlineProps) => ( + +

+ {title} +

+
+) diff --git a/src/v2/components/Layout/Main.tsx b/src/v2/components/Layout/Main.tsx new file mode 100644 index 0000000000..6d5e2061a8 --- /dev/null +++ b/src/v2/components/Layout/Main.tsx @@ -0,0 +1,8 @@ +import { PropsWithChildren } from "react" +import { PageBoundary } from "../PageBoundary" + +export const Main = ({ children }: PropsWithChildren) => ( +
+ {children} +
+) diff --git a/src/v2/components/Layout/Root.tsx b/src/v2/components/Layout/Root.tsx new file mode 100644 index 0000000000..d98c9ff5d0 --- /dev/null +++ b/src/v2/components/Layout/Root.tsx @@ -0,0 +1,5 @@ +import { PropsWithChildren } from "react" + +export const Root = ({ children }: PropsWithChildren) => ( +
{children}
+) diff --git a/src/v2/components/Layout/index.ts b/src/v2/components/Layout/index.ts new file mode 100644 index 0000000000..c91a00c9e6 --- /dev/null +++ b/src/v2/components/Layout/index.ts @@ -0,0 +1,8 @@ +import { Banner } from "./Banner" +import { Footer } from "./Footer" +import { Header } from "./Header" +import { Headline } from "./Headline" +import { Main } from "./Main" +import { Root } from "./Root" + +export const Layout = { Root, Headline, Banner, Header, Footer, Main }