`Link`: mark the link to the current page (`aria-current`, `data-active`)

Ouverte
#676 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

Personne n'a encore pris cette issue.

Évaluation

Difficulté
4/5
Temps estimé
3-5 jours
Accessibilité débutants
25/100
Type d'issue
Fonctionnalité
Clarté
Plutôt claire
Activité
Active
Stack technique
react, typescript
Domaine
frontend

Piste de recherche

Start with the shared Link logic that #672 moves into void/pages-client, and read how useRouter() exposes the current path in the React adapter. The open questions are the prop name for prefix matching and whether to match by segment; settle those with maintainers before coding. Done when an exact match sets aria-current="page" and data-active, and activeMatch="prefix" matches whole segments while ignoring query and hash.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

Summary

Link renders a plain <a> with no sign that it points to the current page. Every navigation menu (a header, a sidebar, tabs) has to compare useRouter().path with each link's href by hand. Those hand-written checks usually style the active link but forget aria-current="page", so screen readers aren't told which link is the current page.

Example

What an app writes today:

import { Link, useRouter } from '@void/react';

// The section's home link only matches itself; the others also match their nested pages.
function isActive(path: string, href: string, home: string) {
  return path === href || (href !== home && path.startsWith(`${href}/`));
}

function Sidebar({ links, home }: { links: { href: string; label: string }[]; home: string }) {
  const { path } = useRouter();
  return links.map((link) => {
    const active = isActive(path, link.href, home);
    return (
      <Link
        key={link.href}
        href={link.href}
        data-active={active || undefined}
        aria-current={active ? 'page' : undefined}
      >
        {link.label}
      </Link>
    );
  });
}

What it could be:

<Link href="/admin">Overview</Link>
<Link href="/admin/users" activeMatch="prefix">Users</Link>
Proposal
  • aria-current="page" when the link's path is the current path. It's semantically "this is the current page", so exact match only.
  • data-active on the same link, for styling with [data-active] or Tailwind's data-active:. Unlike a class, it doesn't collide with the app's own className.
  • An opt-in for nested pages, for example activeMatch="prefix", so /admin/users stays highlighted on /admin/users/42. It matches whole path segments, so /admin/users doesn't match /admin/users-archive.
  • Ignore the query and hash when matching, so /inbox?page=2 still marks /inbox.

The names are only suggestions. The router already holds the current path in every adapter, so this should look the same in React, Vue, Svelte and Solid. #672, which moves the shared Link logic into void/pages-client, looks like the natural place for the matching.

Prior art
  • React Router: NavLink sets aria-current="page" and an active class, and takes end to choose between exact and nested matching.
  • TanStack Router: Link sets aria-current="page" and data-status="active", and takes activeOptions: { exact, includeSearch } and activeProps.
  • Vue Router: RouterLink adds router-link-active for nested matches, and router-link-exact-active plus aria-current="page" for exact ones.
  • Nuxt: NuxtLink takes activeClass and exactActiveClass.
Environment
  • void 1.5.0
  • @void/react 1.5.0
Langage dominant
TypeScript
Étoiles
627
Forks
66
Merge moyen
14 h 56 min
PR mergées (30 j)
170

Préparer son environnement

Ce projet ne fournit ni conteneur de développement, ni Dockerfile, ni guide de contribution : l'installation est à votre charge. Commencez par son README, et consultez notre guide de la première contribution pour les étapes générales.

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de voidzero-dev/void

Toutes les issues de voidzero-dev/void

Issues similaires

Plus d'issues TypeScript

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.