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

Aperta
#676 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
25/100
Tipo di issue
Funzionalità
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
react, typescript
Ambito
frontend

Direzione di ricerca

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.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

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
Lingua principale
TypeScript
Stelle
627
Fork
66
Merge medio
14h 56m
PR unite (30g)
170

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di voidzero-dev/void

Tutte le issue di voidzero-dev/void

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.