Fix headers on mobile with cool dropdown menu.

This commit is contained in:
jahooma 2021-12-18 00:37:05 -06:00
parent 86c2ff4605
commit 393a4962c9
4 changed files with 132 additions and 18 deletions

View File

@ -6,40 +6,83 @@ import { useUser } from '../hooks/use-user'
import { formatMoney } from '../lib/util/format'
import { Row } from './layout/row'
import { firebaseLogin, User } from '../lib/firebase/users'
import { MenuButton } from './menu'
const hoverClasses =
'hover:underline hover:decoration-indigo-400 hover:decoration-2'
const mobileNavigation = [
{
name: 'Home',
href: '/',
},
{
name: 'Account',
href: '/account',
},
{
name: 'Your bets',
href: '/bets',
},
{
name: 'Create a market',
href: '/create',
},
]
function ProfileSummary(props: { user: User }) {
const { user } = props
return (
<Row className="avatar items-center">
<div className="rounded-full w-10 h-10 mr-4">
<Image src={user.avatarUrl} width={40} height={40} />
</div>
<div className="truncate" style={{ maxWidth: 175 }}>
{user.name}
<div className="text-gray-700 text-sm">{formatMoney(user.balance)}</div>
</div>
</Row>
)
}
function SignedInHeaders(props: { user: User; themeClasses?: string }) {
const { user, themeClasses } = props
return (
<>
<Link href="/create">
<a className={clsx('text-base font-medium', themeClasses)}>
<a
className={clsx(
'text-base font-medium hidden md:block',
themeClasses
)}
>
Create a market
</a>
</Link>
<Link href="/bets">
<a className={clsx('text-base font-medium', themeClasses)}>Your bets</a>
<a
className={clsx(
'text-base font-medium hidden md:block',
themeClasses
)}
>
Your bets
</a>
</Link>
<Link href="/account">
<a className={clsx('text-base font-medium', themeClasses)}>
<Row className="avatar items-center">
<div className="rounded-full w-10 h-10 mr-4">
<Image src={user.avatarUrl} width={40} height={40} />
</div>
<div>
{user.name}
<div className="text-gray-700 text-sm">
{formatMoney(user.balance)}
</div>
</div>
</Row>
<a className={clsx('text-base font-medium hidden md:block')}>
<ProfileSummary user={user} />
</a>
</Link>
<MenuButton
className="md:hidden"
menuItems={mobileNavigation}
buttonContent={<ProfileSummary user={user} />}
/>
</>
)
}
@ -68,12 +111,12 @@ export function Header(props: { darkBackground?: boolean; children?: any }) {
return (
<nav
className="max-w-7xl w-full flex flex-row mx-auto pt-5 px-4 sm:px-6"
className="max-w-7xl w-full flex flex-row justify-between md:justify-start mx-auto pt-5 px-4 sm:px-6"
aria-label="Global"
>
<Link href="/">
<a className="flex flex-row gap-3">
<Image
<img
className="sm:h-10 sm:w-10 hover:rotate-12 transition-all"
src="/logo-icon.svg"
width={40}
@ -81,7 +124,7 @@ export function Header(props: { darkBackground?: boolean; children?: any }) {
/>
<div
className={clsx(
'font-major-mono lowercase mt-1 hidden sm:block sm:text-2xl',
'font-major-mono lowercase mt-1 sm:text-2xl',
darkBackground && 'text-white'
)}
>
@ -90,7 +133,7 @@ export function Header(props: { darkBackground?: boolean; children?: any }) {
</a>
</Link>
<Row className="gap-8 mt-1 md:ml-16 mr-8">
<Row className="gap-8 mt-1 md:ml-16">
{children}
{user ? (

51
web/components/menu.tsx Normal file
View File

@ -0,0 +1,51 @@
import { Fragment } from 'react'
import { Menu, Transition } from '@headlessui/react'
import clsx from 'clsx'
export function MenuButton(props: {
buttonContent: any
menuItems: { name: string; href: string }[]
className?: string
}) {
const { buttonContent, menuItems, className } = props
return (
<Menu
as="div"
className={clsx('flex-shrink-0 relative ml-4 z-10', className)}
>
<div>
<Menu.Button className="rounded-full flex">
<span className="sr-only">Open user menu</span>
{buttonContent}
</Menu.Button>
</div>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className="origin-top-right absolute right-0 mt-2 w-48 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 py-1 focus:outline-none">
{menuItems.map((item) => (
<Menu.Item key={item.name}>
{({ active }) => (
<a
href={item.href}
className={clsx(
active ? 'bg-gray-100' : '',
'block py-2 px-4 text-sm text-gray-700'
)}
>
{item.name}
</a>
)}
</Menu.Item>
))}
</Menu.Items>
</Transition>
</Menu>
)
}

19
web/package-lock.json generated
View File

@ -6,6 +6,7 @@
"": {
"name": "mantic",
"dependencies": {
"@headlessui/react": "^1.4.2",
"@heroicons/react": "^1.0.5",
"@nivo/core": "0.74.0",
"@nivo/line": "0.74.0",
@ -1586,6 +1587,18 @@
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz",
"integrity": "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw=="
},
"node_modules/@headlessui/react": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.4.2.tgz",
"integrity": "sha512-N8tv7kLhg9qGKBkVdtg572BvKvWhmiudmeEpOCyNwzOsZHCXBtl8AazGikIfUS+vBoub20Fse3BjawXDVPPdug==",
"engines": {
"node": ">=10"
},
"peerDependencies": {
"react": "^16 || ^17 || ^18",
"react-dom": "^16 || ^17 || ^18"
}
},
"node_modules/@heroicons/react": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@heroicons/react/-/react-1.0.5.tgz",
@ -9448,6 +9461,12 @@
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz",
"integrity": "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw=="
},
"@headlessui/react": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.4.2.tgz",
"integrity": "sha512-N8tv7kLhg9qGKBkVdtg572BvKvWhmiudmeEpOCyNwzOsZHCXBtl8AazGikIfUS+vBoub20Fse3BjawXDVPPdug==",
"requires": {}
},
"@heroicons/react": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@heroicons/react/-/react-1.0.5.tgz",

View File

@ -10,6 +10,7 @@
"prepare": "cd .. && husky install web/.husky"
},
"dependencies": {
"@headlessui/react": "^1.4.2",
"@heroicons/react": "^1.0.5",
"@nivo/core": "0.74.0",
"@nivo/line": "0.74.0",