Navigation

LinkSection

Enlace a una sección de la misma página, con scroll-spy nativo

Preview

Introducción

Instalación

Uso

Haz scroll dentro del documento: el navegador marca solo la sección visible. Lo enciende scroll-target-group: auto en la lista, hoy solo en Chromium; active la marca a mano.

size
children
active

Code

import css from "./LinkSection.module.css";

type Size = "sm" | "md" | "lg";

interface ResponsiveSize {
  base: Size;
  mobile?: Size;
  tablet?: Size;
  desktop?: Size;
  wide?: Size;
}

interface LinkSectionProps {
  href: `#${string}`;
  size: Size | ResponsiveSize;
  active?: boolean;
  children: React.ReactNode;
}

function getSizeClasses(size: Size | ResponsiveSize): string {
  if (typeof size === "string") {
    return css[size];
  }

  const classes = [css[`${size.base}_base`]];

  if (size.mobile) classes.push(css[`${size.mobile}_mobile`]);
  if (size.tablet) classes.push(css[`${size.tablet}_tablet`]);
  if (size.desktop) classes.push(css[`${size.desktop}_desktop`]);
  if (size.wide) classes.push(css[`${size.wide}_wide`]);

  return classes.join(" ");
}

export default function LinkSection({
  href,
  size,
  active,
  children,
}: LinkSectionProps) {
  return (
    <a
      href={href}
      className={`
        ${css.link}
        ${getSizeClasses(size)}
        ${active ? css.active : ""}
      `}
      aria-current={active ? "location" : undefined}
    >
      {children}
    </a>
  );
}

Props

PropTypeRequiredDescription
href`#${string}`requiredAncla de una sección de la misma página. El tipo rechaza rutas como "/about" al compilar.
size"sm" | "md" | "lg" | ResponsiveSizerequiredTamaño del enlace (altura y tipografía). Fijo o responsive.
activeboolean—Marca el enlace como sección actual a mano (aria-current="location", fondo tintado). Con scroll-target-group: auto en la lista (hoy solo en Chromium), el navegador pinta solo la sección visible, sin aria-current.
childrenReact.ReactNoderequiredContenido del enlace.