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

Aberta
#676 0 comentários 0 reações 0 responsáveis Ver no GitHub

Mantenedores costumam responder em até 1 dia

Ninguém assumiu esta issue ainda.

Avaliação

Dificuldade
4/5
Tempo estimado
3-5 dias
Facilidade para iniciantes
25/100
Tipo de issue
Funcionalidade
Clareza
Razoavelmente clara
Status de atividade
Ativa
Stack de tecnologia
react, typescript
Domínio
frontend

Direção de pesquisa

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.

Escrita pelo modelo de indexação a partir do texto da issue.

Descrição

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
Linguagem predominante
TypeScript
Estrelas
627
Forks
66
Merge médio
14h 56min
PRs com merge (30d)
170

Preparar o ambiente

Este projeto não oferece contêiner de desenvolvimento, Dockerfile nem guia de contribuição, então a configuração fica por sua conta: comece pelo README e veja nosso guia da primeira contribuição para os passos gerais.

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de voidzero-dev/void

Todas as issues de voidzero-dev/void

Issues semelhantes

Mais issues de TypeScript

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.