active nav link style
This commit is contained in:
@@ -11,13 +11,13 @@ export function AppFooter() {
|
|||||||
</address>
|
</address>
|
||||||
<p>
|
<p>
|
||||||
Coded with <HeartIcon className="inline w-4 align-sub" /> using{" "}
|
Coded with <HeartIcon className="inline w-4 align-sub" /> using{" "}
|
||||||
<ExternalLink className={linkClass} href="https://remix.run">
|
<ExternalLink className={linkClass()} href="https://remix.run">
|
||||||
Remix
|
Remix
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Uses{" "}
|
Uses{" "}
|
||||||
<ExternalLink className={linkClass} href="https://umami.is/">
|
<ExternalLink className={linkClass()} href="https://umami.is/">
|
||||||
umami
|
umami
|
||||||
</ExternalLink>{" "}
|
</ExternalLink>{" "}
|
||||||
for simple, non-identifying analytics.
|
for simple, non-identifying analytics.
|
||||||
|
|||||||
14
packages/website/app/modules/navigation/active-link.tsx
Normal file
14
packages/website/app/modules/navigation/active-link.tsx
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import type { ReactNode } from "react"
|
||||||
|
import type { PathPattern } from "react-router"
|
||||||
|
import { useMatch } from "react-router"
|
||||||
|
|
||||||
|
export function ActiveLink({
|
||||||
|
to,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
to: string | PathPattern
|
||||||
|
children: (props: { active: boolean }) => ReactNode
|
||||||
|
}) {
|
||||||
|
const match = useMatch(to)
|
||||||
|
return <>{children({ active: match != undefined })}</>
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Menu, Transition } from "@headlessui/react"
|
import { Menu, Transition } from "@headlessui/react"
|
||||||
import { MenuAlt4Icon } from "@heroicons/react/outline"
|
import { MenuAlt4Icon } from "@heroicons/react/outline"
|
||||||
import clsx from "clsx"
|
import clsx from "clsx"
|
||||||
|
import { ActiveLink } from "~/modules/navigation/active-link"
|
||||||
import { useGuideLinksContext } from "~/modules/navigation/guide-links-context"
|
import { useGuideLinksContext } from "~/modules/navigation/guide-links-context"
|
||||||
import { Popper } from "~/modules/ui/popper"
|
import { Popper } from "~/modules/ui/popper"
|
||||||
import { AppLink } from "./app-link"
|
import { AppLink } from "./app-link"
|
||||||
@@ -39,8 +40,17 @@ export function MainNavigationMenu() {
|
|||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
{guideLinks.map(({ link }) => (
|
{guideLinks.map(({ link }) => (
|
||||||
<Menu.Item key={link.to}>
|
<Menu.Item key={link.to}>
|
||||||
{({ active }) => (
|
{(menuItem) => (
|
||||||
<AppLink {...link} className={menuItemClass({ active })} />
|
<ActiveLink to={link.to}>
|
||||||
|
{(activeLink) => (
|
||||||
|
<AppLink
|
||||||
|
{...link}
|
||||||
|
className={menuItemClass({
|
||||||
|
active: activeLink.active || menuItem.active,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</ActiveLink>
|
||||||
)}
|
)}
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export function MainNavigation() {
|
|||||||
</a>
|
</a>
|
||||||
<div className="hidden md:flex gap-4">
|
<div className="hidden md:flex gap-4">
|
||||||
{mainLinks.map((link) => (
|
{mainLinks.map((link) => (
|
||||||
<AppLink {...link} key={link.to} className={linkClass} />
|
<AppLink {...link} key={link.to} className={linkClass()} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className="md:hidden">
|
<div className="md:hidden">
|
||||||
|
|||||||
@@ -4,12 +4,16 @@ export const maxWidthContainer = clsx`mx-auto w-full max-w-screen-lg px-4`
|
|||||||
|
|
||||||
export const inlineIconClass = clsx`inline w-5 align-sub`
|
export const inlineIconClass = clsx`inline w-5 align-sub`
|
||||||
|
|
||||||
export const linkClass = clsx`
|
export const linkClass = ({ active = false } = {}) =>
|
||||||
font-medium inline-block relative
|
clsx(
|
||||||
opacity-60 hover:opacity-100 transition-opacity
|
clsx`font-medium inline-block relative`,
|
||||||
after:absolute after:block after:w-full after:h-px after:bg-white/50 after:translate-y-[3px] after:opacity-0 after:transition
|
clsx`opacity-60 hover:opacity-100 transition-opacity`,
|
||||||
hover:after:translate-y-[-1px] hover:after:opacity-100
|
clsx`after:absolute after:block after:w-full after:h-px after:bg-white/50 after:translate-y-[3px] after:opacity-0 after:transition`,
|
||||||
`
|
clsx`hover:after:translate-y-[-1px] hover:after:opacity-100`,
|
||||||
|
active
|
||||||
|
? clsx`text-emerald-500 after:bg-emerald-500`
|
||||||
|
: clsx`after:bg-white/50`,
|
||||||
|
)
|
||||||
|
|
||||||
export const docsProseClass = clsx`
|
export const docsProseClass = clsx`
|
||||||
prose prose-invert
|
prose prose-invert
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import clsx from "clsx"
|
import clsx from "clsx"
|
||||||
import { Outlet } from "remix"
|
import { Outlet } from "remix"
|
||||||
|
import { ActiveLink } from "~/modules/navigation/active-link"
|
||||||
import { AppLink } from "~/modules/navigation/app-link"
|
import { AppLink } from "~/modules/navigation/app-link"
|
||||||
import { useGuideLinksContext } from "~/modules/navigation/guide-links-context"
|
import { useGuideLinksContext } from "~/modules/navigation/guide-links-context"
|
||||||
import { MainNavigation } from "~/modules/navigation/main-navigation"
|
import { MainNavigation } from "~/modules/navigation/main-navigation"
|
||||||
@@ -24,7 +25,11 @@ export default function GuidePage() {
|
|||||||
<ul className="mt-3 flex flex-col gap-2 items-start">
|
<ul className="mt-3 flex flex-col gap-2 items-start">
|
||||||
{guideLinks.map(({ link }) => (
|
{guideLinks.map(({ link }) => (
|
||||||
<li key={link.to}>
|
<li key={link.to}>
|
||||||
<AppLink {...link} className={linkClass} />
|
<ActiveLink to={link.to}>
|
||||||
|
{({ active }) => (
|
||||||
|
<AppLink {...link} className={linkClass({ active })} />
|
||||||
|
)}
|
||||||
|
</ActiveLink>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -25,6 +25,8 @@
|
|||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-focus-on": "^3.5.4",
|
"react-focus-on": "^3.5.4",
|
||||||
|
"react-router": "^6.2.1",
|
||||||
|
"react-router-dom": "^6.2.1",
|
||||||
"remix": "^1.1.1"
|
"remix": "^1.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
4
pnpm-lock.yaml
generated
4
pnpm-lock.yaml
generated
@@ -117,6 +117,8 @@ importers:
|
|||||||
react: ^17.0.2
|
react: ^17.0.2
|
||||||
react-dom: ^17.0.2
|
react-dom: ^17.0.2
|
||||||
react-focus-on: ^3.5.4
|
react-focus-on: ^3.5.4
|
||||||
|
react-router: ^6.2.1
|
||||||
|
react-router-dom: ^6.2.1
|
||||||
rehype-prism-plus: ^1.3.1
|
rehype-prism-plus: ^1.3.1
|
||||||
remix: ^1.1.1
|
remix: ^1.1.1
|
||||||
tailwindcss: ^3.0.13
|
tailwindcss: ^3.0.13
|
||||||
@@ -137,6 +139,8 @@ importers:
|
|||||||
react: 17.0.2
|
react: 17.0.2
|
||||||
react-dom: 17.0.2_react@17.0.2
|
react-dom: 17.0.2_react@17.0.2
|
||||||
react-focus-on: 3.5.4_b08e3c15324cbe90a6ff8fcd416c932c
|
react-focus-on: 3.5.4_b08e3c15324cbe90a6ff8fcd416c932c
|
||||||
|
react-router: 6.2.1_react@17.0.2
|
||||||
|
react-router-dom: 6.2.1_react-dom@17.0.2+react@17.0.2
|
||||||
remix: 1.1.1
|
remix: 1.1.1
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@remix-run/dev': 1.1.1
|
'@remix-run/dev': 1.1.1
|
||||||
|
|||||||
Reference in New Issue
Block a user