Nav link
Navbar link. Use tone="dark" on dark backgrounds.
Code
Copy into src/components/ph/ .
nav-link.css
.ph-nav-link,
.ph-nav-link[data-tone="light"] {
--nav-fg: var(--ph-black);
--nav-hover-bg: var(--ph-black);
--nav-hover-fg: var(--ph-yellow);
}
.dark .ph-nav-link:not([data-tone="light"]),
[data-tone="dark"] .ph-nav-link:not([data-tone="light"]),
.ph-nav-link[data-tone="dark"] {
--nav-fg: var(--ph-cream);
--nav-hover-bg: var(--ph-cream);
--nav-hover-fg: var(--ph-purple);
}
.ph-nav-link {
padding: 0.25rem 0.5rem;
color: var(--nav-fg);
font-family: var(--ph-font-mono);
font-size: 1rem;
font-weight: 600;
letter-spacing: 0.025em;
text-transform: uppercase;
text-decoration: none;
transition:
color 300ms ease,
background-color 300ms ease;
}
.ph-nav-link:hover,
.ph-nav-link:focus-visible,
.ph-nav-link[aria-current="page"] {
background: var(--nav-hover-bg);
color: var(--nav-hover-fg);
}
@media (prefers-reduced-motion: reduce) {
.ph-nav-link {
transition: none;
}
}
NavLink.astro
---
import type { HTMLAttributes } from "astro/types";
import "./nav-link.css";
type Props = HTMLAttributes<"a"> & {
href: string;
tone?: "light" | "dark";
};
const { href, tone, class: className, ...rest } = Astro.props;
const external = /^https?:\/\//.test(href);
---
<a
href={href}
target={external ? "_blank" : undefined}
rel={external ? "noopener noreferrer" : undefined}
data-tone={tone}
class:list={["ph-nav-link", className]}
{...rest}><slot /></a
>
Copy into components/ph/ (or src/components/ph/).
nav-link.css
.ph-nav-link,
.ph-nav-link[data-tone="light"] {
--nav-fg: var(--ph-black);
--nav-hover-bg: var(--ph-black);
--nav-hover-fg: var(--ph-yellow);
}
.dark .ph-nav-link:not([data-tone="light"]),
[data-tone="dark"] .ph-nav-link:not([data-tone="light"]),
.ph-nav-link[data-tone="dark"] {
--nav-fg: var(--ph-cream);
--nav-hover-bg: var(--ph-cream);
--nav-hover-fg: var(--ph-purple);
}
.ph-nav-link {
padding: 0.25rem 0.5rem;
color: var(--nav-fg);
font-family: var(--ph-font-mono);
font-size: 1rem;
font-weight: 600;
letter-spacing: 0.025em;
text-transform: uppercase;
text-decoration: none;
transition:
color 300ms ease,
background-color 300ms ease;
}
.ph-nav-link:hover,
.ph-nav-link:focus-visible,
.ph-nav-link[aria-current="page"] {
background: var(--nav-hover-bg);
color: var(--nav-hover-fg);
}
@media (prefers-reduced-motion: reduce) {
.ph-nav-link {
transition: none;
}
}
nav-link.tsx
import type { AnchorHTMLAttributes } from "react";
import { cn } from "./cn";
import "./nav-link.css";
type NavLinkProps = AnchorHTMLAttributes<HTMLAnchorElement> & {
href: string;
tone?: "light" | "dark";
};
export function NavLink({ href, tone, className, ...rest }: NavLinkProps) {
const external = /^https?:\/\//.test(href);
return (
<a
href={href}
target={external ? "_blank" : undefined}
rel={external ? "noopener noreferrer" : undefined}
data-tone={tone}
className={cn("ph-nav-link", className)}
{...rest}
/>
);
}
cn.ts
export const cn = (...parts: (string | false | null | undefined)[]) => parts.filter(Boolean).join(" ");