mobile responsiveness

This commit is contained in:
MapleLeaf
2021-12-30 22:49:36 -06:00
parent a14120a2f8
commit 93cb788394
10 changed files with 409 additions and 35 deletions

View File

@@ -0,0 +1,34 @@
import { Link } from "remix"
import { ExternalLink } from "~/components/external-link"
export type AppLinkProps = {
type: "router" | "internal" | "external"
label: React.ReactNode
to: string
className?: string
}
export function AppLink(props: AppLinkProps) {
switch (props.type) {
case "router":
return (
<Link className={props.className} to={props.to}>
{props.label}
</Link>
)
case "internal":
return (
<a className={props.className} href={props.to}>
{props.label}
</a>
)
case "external":
return (
<ExternalLink className={props.className} href={props.to}>
{props.label}
</ExternalLink>
)
}
}

View File

@@ -1,29 +1,102 @@
import { CodeIcon } from "@heroicons/react/outline"
import { DocumentTextIcon, ExternalLinkIcon } from "@heroicons/react/solid"
import { MenuAlt4Icon } from "@heroicons/react/outline"
import { useRect } from "@reach/rect"
import clsx from "clsx"
import { useRef, useState } from "react"
import { FocusOn } from "react-focus-on"
import { Link } from "remix"
import { ExternalLink } from "~/components/external-link"
import { mainLinks } from "~/app-links"
import { AppLink } from "~/components/app-link"
import type { ContentIndexEntry } from "~/helpers/create-index.server"
import { linkClass } from "~/styles"
export function MainNavigation() {
const menuItemClass = clsx`
px-3 py-2 transition text-left font-medium block
opacity-50 hover:opacity-100 hover:bg-black/30
`
export function MainNavigation({
guideRoutes,
}: {
guideRoutes: ContentIndexEntry[]
}) {
return (
<nav className="flex justify-between items-center h-16">
<Link to="/">
<h1 className="text-3xl font-light">reacord</h1>
</Link>
<div className="flex gap-4">
<Link className={linkClass} to="/docs/guides/getting-started">
<DocumentTextIcon className="inline align-sub w-5" /> Guides
</Link>
<a className={linkClass} href="/docs/api">
<CodeIcon className="inline align-sub w-5" /> API Reference
</a>
<ExternalLink
className={linkClass}
href="https://github.com/itsMapleLeaf/reacord"
>
<ExternalLinkIcon className="inline align-sub w-5" /> GitHub
</ExternalLink>
<div className="hidden md:flex gap-4">
{mainLinks.map((link) => (
<AppLink key={link.to} className={linkClass} {...link} />
))}
</div>
<div className="md:hidden">
<PopoverMenu>
{mainLinks.map((link) => (
<AppLink key={link.to} className={menuItemClass} {...link} />
))}
<hr className="border-0 h-[2px] bg-black/50" />
{guideRoutes.map((route) => (
<Link key={route.route} to={route.route} className={menuItemClass}>
{route.title}
</Link>
))}
</PopoverMenu>
</div>
</nav>
)
}
function PopoverMenu({ children }: { children: React.ReactNode }) {
const [visible, setVisible] = useState(false)
const buttonRef = useRef<HTMLButtonElement>(null)
const buttonRect = useRect(buttonRef)
const panelRef = useRef<HTMLDivElement>(null)
const panelRect = useRect(panelRef)
/* eslint-disable jsx-a11y/no-static-element-interactions */
/* eslint-disable jsx-a11y/click-events-have-key-events */
return (
<>
<button
title="Menu"
className={linkClass}
onClick={() => setVisible(!visible)}
ref={buttonRef}
>
<MenuAlt4Icon className="w-6" />
</button>
<FocusOn
enabled={visible}
onClickOutside={() => setVisible(false)}
onEscapeKey={() => setVisible(false)}
>
<div
className="fixed"
style={{
left: (buttonRect?.right ?? 0) - (panelRect?.width ?? 0),
top: (buttonRect?.bottom ?? 0) + 8,
}}
onClick={() => setVisible(false)}
>
<div
className={clsx(
"transition-all",
visible
? "opacity-100 visible"
: "translate-y-2 opacity-0 invisible",
)}
>
<div ref={panelRef}>
<div className="w-48 bg-slate-800 rounded-lg shadow overflow-hidden max-h-[calc(100vh-4rem)] overflow-y-auto">
{children}
</div>
</div>
</div>
</div>
</FocusOn>
</>
)
}