damus.io

damus.io website
git clone git://jb55.com/damus.io
Log | Files | Refs | README | LICENSE

TopMenu.tsx (7200B)


      1 import * as React from "react"
      2 import Link from "next/link"
      3 import { cn } from "@/lib/utils"
      4 import * as NavigationMenu from '@radix-ui/react-navigation-menu';
      5 import { Menu, X, Zap } from "lucide-react"
      6 import { Button } from "../ui/Button";
      7 import { DAMUS_APP_STORE_URL, DAMUS_MERCH_STORE_URL } from "@/lib/constants";
      8 import { useIntl } from "react-intl";
      9 import { AnimatePresence, motion, useScroll, useTransform } from "framer-motion";
     10 
     11 let regularNavItems: { nameIntlId: string, href: string, target?: string }[] = [
     12     { nameIntlId: "topbar.purple", href: "/purple" },
     13     { nameIntlId: "topbar.notedeck", href: "/notedeck" },
     14     { nameIntlId: "topbar.store", href: DAMUS_MERCH_STORE_URL, target: "_blank" },
     15     { nameIntlId: "topbar.events", href: "/#events" },
     16     { nameIntlId: "topbar.team", href: "/#team" },
     17     { nameIntlId: "topbar.contribute", href: "/#contribute" },
     18 ]
     19 
     20 const ENABLE_FULL_MENU = true
     21 
     22 export interface TopMenuProps {
     23     className?: string
     24     customCTA?: React.ReactNode
     25     hideLogoOnTop?: boolean
     26 }
     27 
     28 export function TopMenu({ className, customCTA, hideLogoOnTop: hideLogoOnTop = false }: TopMenuProps) {
     29     let navItemDefaultStyles = "hover:opacity-80 transition-opacity duration-200 ease-in-out"
     30     const [showMobileMenu, setShowMobileMenu] = React.useState<boolean>(false)
     31     const ref = React.useRef(null)
     32     const { scrollYProgress } = useScroll({
     33       target: ref,
     34       offset: ["start start", "end start"]
     35     })
     36     const logoOpacity = useTransform(scrollYProgress, [0.1, 0.5], [hideLogoOnTop ? 0.0 : 1.0, 1.0]);
     37     const menuBgColor = useTransform(scrollYProgress, [0.1, 0.5], ["rgba(0,0,0,0)", "rgba(0,0,0,0.5)"]);
     38     const intl = useIntl()
     39 
     40     // This is needed to allow intl commands to extract the strings
     41     const topbarItemNameIntl: Record<string, string> = {
     42         "topbar.purple": intl.formatMessage({ id: "topbar.purple", defaultMessage: "Purple" }),
     43         "topbar.notedeck": intl.formatMessage({ id: "topbar.notedeck", defaultMessage: "Notedeck" }),
     44         "topbar.store": intl.formatMessage({ id: "topbar.store", defaultMessage: "Store" }),
     45         "topbar.events": intl.formatMessage({ id: "topbar.events", defaultMessage: "Events" }),
     46         "topbar.team": intl.formatMessage({ id: "topbar.team", defaultMessage: "Our Team" }),
     47         "topbar.contribute": intl.formatMessage({ id: "topbar.contribute", defaultMessage: "Contribute" }),
     48     }
     49 
     50     return (<>
     51         <div ref={ref} className="absolute top-0 h-screen bg-transparent pointer-events-none w-4 left-0" />
     52         <motion.div
     53             style={{
     54               opacity: 0,
     55               backgroundColor: showMobileMenu ? "rgba(0,0,0,0.5)" : menuBgColor,
     56               borderColor: showMobileMenu ? "rgba(0,0,0,0.5)" : menuBgColor,
     57             }}
     58             animate={{ opacity: 1, transition: { delay: 1.5, duration: 1 } }}
     59             className="w-full border-b z-50 backdrop-blur-sm fixed"
     60         >
     61             <NavigationMenu.Root className={cn("flex flex-col items-center z-50", className)}>
     62               <div className="container justify-between items-center flex p-6">
     63                 <motion.div
     64                  style={{ opacity: logoOpacity }}
     65                 >
     66                     <NavigationMenu.Link className={cn(navItemDefaultStyles, "text-white")} href="/">
     67                         <img src="/logo_icon_2.png" className="h-12" alt={ intl.formatMessage({ id: "topbar.logo_alt_text", defaultMessage: "Damus logo" }) }/>
     68                     </NavigationMenu.Link>
     69                 </motion.div>
     70                 <div className="hidden lg:block">
     71                   <NavigationMenu.List className={cn("inline-flex space-x-6 items-center justify-self-center")}>
     72                       {ENABLE_FULL_MENU && (<>
     73                           {regularNavItems.map((item, index) => (
     74                               <NavigationMenu.Item key={index}>
     75                                   <NavigationMenu.Link className={cn(navItemDefaultStyles, "text-white")} href={item.href} target={item.target}>
     76                                       {topbarItemNameIntl[item.nameIntlId]}
     77                                   </NavigationMenu.Link>
     78                               </NavigationMenu.Item>
     79                           ))}
     80                           <NavigationMenu.Item>
     81                               <NavigationMenu.Link className={cn("text-yellow-500 flex items-center")} href="lightning:lnurl1dp68gurn8ghj7um9dej8xct5wvhxcmmv9uh8wetvdskkkmn0wahz7mrww4excup0v3sk6atnjmrn5a" target="_blank">
     82                                   <Zap className="h-4"/>
     83                                   { intl.formatMessage({ id: "topbar.zap_us", defaultMessage: "Zap Us" }) }
     84                               </NavigationMenu.Link>
     85                           </NavigationMenu.Item>
     86                       </>)}
     87                   </NavigationMenu.List>
     88                 </div>
     89                 <div className="hidden lg:block">
     90                   {customCTA ? customCTA : <>
     91                     <Link href={DAMUS_APP_STORE_URL} target="_blank" className="hidden lg:block">
     92                       <Button variant="accent">
     93                         {intl.formatMessage({ id: "topbar.download", defaultMessage: "Download" })}
     94                       </Button>
     95                     </Link>
     96                   </>}
     97                 </div>
     98                 <button className="lg:hidden" onClick={() => setShowMobileMenu(!showMobileMenu)}>
     99                   {showMobileMenu ? <X className="h-8 text-white"/> : <Menu className="h-8 text-white"/>}
    100                 </button>
    101               </div>
    102               <AnimatePresence>
    103                 {showMobileMenu && (
    104                   <motion.div className="lg:hidden container flex justify-end mb-6" key="mobile-menu">
    105                     <NavigationMenu.List className={cn("flex flex-col gap-6 justify-start items-end text-3xl font-bold p-6")}>
    106                         {ENABLE_FULL_MENU && (<>
    107                             {regularNavItems.map((item, index) => (
    108                                 <NavigationMenu.Item key={index}>
    109                                     <NavigationMenu.Link className={cn(navItemDefaultStyles, "text-white")} href={item.href} target={item.target}>
    110                                         {topbarItemNameIntl[item.nameIntlId]}
    111                                     </NavigationMenu.Link>
    112                                 </NavigationMenu.Item>
    113                             ))}
    114                             <NavigationMenu.Item>
    115                                 <NavigationMenu.Link className={cn("text-yellow-500 flex items-center")} href="lightning:lnurl1dp68gurn8ghj7um9dej8xct5wvhxcmmv9uh8wetvdskkkmn0wahz7mrww4excup0v3sk6atnjmrn5a" target="_blank">
    116                                     <Zap className="h-4"/>
    117                                     { intl.formatMessage({ id: "topbar.zap_us", defaultMessage: "Zap Us" }) }
    118                                 </NavigationMenu.Link>
    119                             </NavigationMenu.Item>
    120                         </>)}
    121                     </NavigationMenu.List>
    122                   </motion.div>
    123                 )}
    124               </AnimatePresence>
    125             </NavigationMenu.Root>
    126         </motion.div>
    127     </>)
    128 }