ph/components

Link

Underlined inline link.

Code

Copy into src/components/ph/ .

link.css
.ph-link {
  color: inherit;
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-color: var(--link, var(--rule));
  padding-inline: 3px;
  margin-inline: -3px;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
  transition:
    color 150ms var(--ph-ease),
    background-color 150ms var(--ph-ease);
}

.ph-link:focus-visible,
.ph-link:hover {
  color: var(--foreground);
  background-color: var(--border);
}

/* Half ink keeps the tint's hue while clearing 4.5:1. */
@supports (color: color-mix(in oklab, red, red)) {
  .ph-link:focus-visible,
  .ph-link:hover {
    color: color-mix(in oklab, var(--link, var(--foreground)) 50%, var(--foreground));
    background-color: color-mix(in oklab, var(--link, var(--rule)) 15%, var(--background));
  }
}

@media (hover: none) {
  .ph-link:hover {
    background-color: transparent;
  }
}
Link.astro
---
import type { HTMLAttributes } from "astro/types";
import "./link.css";

type Props = HTMLAttributes<"a"> & {
  href: string;
  tint?: string;
};

const { href, tint, class: className, style, ...rest } = Astro.props;
const external = /^https?:\/\//.test(href);
---

<a
  href={href}
  target={external ? "_blank" : undefined}
  rel={external ? "noopener noreferrer" : undefined}
  data-tint={tint ? "" : undefined}
  class:list={["ph-link", className]}
  style={[tint && `--link: ${tint}`, style].filter(Boolean).join("; ") || undefined}
  {...rest}><slot /></a
>