import { Add, CheckRounded, Home, KeyboardDoubleArrowLeft, KeyboardDoubleArrowRight, Search, } from '@mui/icons-material' import { isMobile } from '@walletconnect/browser-utils' import clsx from 'clsx' import { useRouter } from 'next/router' import { useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import { DappNavigationProps } from '@dao-dao/types' import { SITE_TITLE, getSupportedChains } from '@dao-dao/utils' import { usePlatform } from '../../hooks' import { ChainLogo } from '../chain/ChainLogo' import { DaoDropdown } from '../dao' import { IconButton, ThemeToggle } from '../icon_buttons' import { Logo } from '../logo/Logo' import { Tooltip } from '../tooltip/Tooltip' import { useAppContext } from './AppContext' import { Footer } from './Footer' import { PageHeader } from './PageHeader' import { Row } from './Row' // Width of `lg` tailwind selector. Don't change this without changing the // compact button media query class that shows the compact toggle at the very // bottom, so the user can toggle between compact and not compact mode when it // is not forced. const FORCE_COMPACT_NAVIGATION_AT_WIDTH = 1024 // Width of `md` tailwind selector. Don't change this without changing all of // the `md:` tailwind class media queries since they are set based on when it is // in responsive mobile mode. const FORCE_MOBILE_NAVIGATION_AT_WIDTH = 768 // Force off when in responsive mobile mode since it displays full width when // open and we can show all details. Force on when larger than mobile but still // not very wide since it takes up a lot of space. const getForceCompact = () => window.innerWidth < FORCE_MOBILE_NAVIGATION_AT_WIDTH ? false : window.innerWidth < FORCE_COMPACT_NAVIGATION_AT_WIDTH ? true : undefined export const DappNavigation = ({ setCommandModalVisible, followingDaos, walletConnected, compact, setCompact, mountedInBrowser, LinkWrapper, }: DappNavigationProps) => { const { t } = useTranslation() const { isMac } = usePlatform() const { responsiveNavigation: { enabled: responsiveEnabled, toggle: toggleResponsive, }, } = useAppContext() const { pathname, query } = useRouter() const isHome = pathname === '/[[...tab]]' const homeTabPath = isHome && query?.tab && Array.isArray(query?.tab) ? query.tab[0] : undefined const homeSelectedChainId = homeTabPath ? getSupportedChains().find(({ name }) => name === homeTabPath)?.chainId : undefined // Use screen resize to determine when compact should be forced on or off. const [forceCompact, setForceCompact] = useState( // Initialize not compact to prevent hydration errors (since it takes at // least 1 render to update this). false ) useEffect(() => { // Only run in browser. if (typeof window === 'undefined' || !mountedInBrowser) { return } const updateForceCompact = () => setForceCompact(getForceCompact()) // Update on initialization. updateForceCompact() window.addEventListener('resize', updateForceCompact) // Clean up on umount return () => window.removeEventListener('resize', updateForceCompact) }, [mountedInBrowser]) // If forceCompact is set to a boolean, override compact. if (forceCompact !== undefined) { compact = forceCompact } const [showFollowingTopBorder, setShowFollowingTopBorder] = useState(false) const [showFollowingBottomBorder, setShowFollowingBottomBorder] = useState(false) const scrollableFollowingContainerRef = useRef(null) useEffect(() => { const ref = scrollableFollowingContainerRef.current if (!ref) { return } const updateBorders = () => { const { scrollTop, scrollHeight, clientHeight } = ref // 0.5rem (~8px) padding before the top of the first sub DAO image, and a // couple extra pixels so the first element actually looks covered. const contentHiddenOnTop = scrollTop > 11 setShowFollowingTopBorder(contentHiddenOnTop) // 1rem (~16px) padding before the bottom of the last sub DAO image, and // a couple extra pixels so the last element actually looks covered. const contentHiddenOnBottom = scrollTop < scrollHeight - clientHeight - 19 setShowFollowingBottomBorder(contentHiddenOnBottom) } updateBorders() // Add listener on mount, remove on cleanup. ref.addEventListener('scroll', updateBorders) return () => ref.removeEventListener('scroll', updateBorders) // Update when compact is changed since positioning is different. }, [scrollableFollowingContainerRef, compact]) return ( <> {/* Layer underneath that allows closing the responsive navigation by tapping on visible parts of the page. */} {responsiveEnabled && (
responsiveEnabled && toggleResponsive()} >
)} ) }