Link и активные состояния

Link в Radix UI — это компонент для создания навигационных элементов, который сочетает в себе семантику HTML-ссылки и расширяемость для управления состояниями, такими как активное состояние, фокус и наведение. Он построен с учетом accessibility (доступности), что делает его предпочтительным инструментом для интерфейсов, где важна корректная поддержка клавиатурной навигации и экранных читалок.

Компонент Link обычно импортируется из пакета Radix UI и используется аналогично стандартному тегу <a>, но с дополнительными свойствами для управления состояниями:

import * as Link from '@radix-ui/react-link';

<Link.Root href="/home">
  Домой
</Link.Root>

Здесь Link.Root является основным контейнером компонента. Атрибут href задаёт адрес ссылки. Radix UI сохраняет семантику HTML-ссылки, позволяя при этом расширять поведение через стили и состояния.

Стилизация активного состояния

Активное состояние (active state) — это визуальное обозначение текущей страницы или выбранного элемента в меню. В Radix UI активное состояние часто реализуется через сочетание CSS и состояния компонента.

Пример с использованием CSS-псевдокласса :active и классов состояния:

<Link.Root
  href="/about"
  className="link"
>
  О нас
</Link.Root>
.link {
  text-decoration: none;
  color: #333;
  font-weight: 500;
  transition: color 0.2s ease-in-out;
}

.link:hover {
  color: #0070f3;
}

.link:active {
  color: #0050a3;
}

Radix UI позволяет управлять активным состоянием программно через пропсы, если необходимо синхронизировать его с состоянием маршрутизатора, например, в React Router:

import { useLocation } from 'react-router-dom';

const NavLink = ({ to, children }) => {
  const location = useLocation();
  const isActive = location.pathname === to;

  return (
    <Link.Root
      href={to}
      className={`link ${isActive ? 'active' : ''}`}
    >
      {children}
    </Link.Root>
  );
};
.link.active {
  color: #ff0000;
  font-weight: 700;
}

Поддержка фокуса и клавиатурной навигации

Radix UI обеспечивает корректное управление фокусом через встроенные механизмы focus-visible. Это особенно важно для доступности и визуальной идентификации элементов при навигации с клавиатуры:

.link:focus-visible {
  outline: 2px solid #0070f3;
  outline-offset: 2px;
}

Использование :focus-visible вместо простого :focus позволяет показывать контур только при взаимодействии через клавиатуру, не мешая визуальному восприятию при кликах мышью.

Интеграция с анимацией и стилями

Активное состояние может сопровождаться анимацией, чтобы улучшить пользовательский опыт. Например, плавное изменение цвета или подчеркивания при наведении и выборе:

.link {
  position: relative;
  padding-bottom: 2px;
}

.link::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  width: 0;
  height: 2px;
  background-color: #0070f3;
  transition: width 0.3s ease;
}

.link:hover::after,
.link.active::after {
  width: 100%;
}

Такой подход позволяет визуально различать текущий активный пункт меню и обеспечивать плавный переход при смене состояния.

Комбинация с другими компонентами Radix UI

Link часто используется совместно с компонентами Tabs, NavigationMenu и Breadcrumbs, создавая единый стиль навигации. Radix UI предлагает универсальные хуки и пропсы для управления состояниями, что позволяет синхронизировать активный пункт с маршрутизацией и другими интерактивными элементами интерфейса.

Пример с использованием Tabs и Link:

import * as Tabs from '@radix-ui/react-tabs';

<Tabs.Root defaultValue="home">
  <Tabs.List>
    <Tabs.Trigger value="home">
      <Link.Root href="/home">Домой</Link.Root>
    </Tabs.Trigger>
    <Tabs.Trigger value="about">
      <Link.Root href="/about">О нас</Link.Root>
    </Tabs.Trigger>
  </Tabs.List>
</Tabs.Root>

В этом случае визуальное и функциональное активное состояние синхронизировано между вкладками и ссылками.

Поддержка SSR и навигационных библиотек

Link полностью совместим с серверным рендерингом (Next.js, Remix) и библиотеками маршрутизации (React Router, Wouter). Это достигается через возможность оборачивать компонент в любую обертку или прокидывать ref, сохраняя при этом доступность и состояния:

<Link.Root asChild>
  <NextLink href="/contact">
    <a className="link">Контакты</a>
  </NextLink>
</Link.Root>

Использование asChild позволяет интегрировать Radix UI с внешними компонентами без потери функционала активных состояний и фокусных стилей.

Важные рекомендации

  • Активное состояние следует явно синхронизировать с маршрутизатором, чтобы пользователи понимали текущую позицию в приложении.
  • Использовать focus-visible для доступности, избегая визуального шума при клике мышью.
  • Для сложных анимаций можно комбинировать CSS-переходы и Radix UI состояния через классы или динамическое управление стилями.
  • Интеграция с asChild позволяет использовать любые кастомные компоненты вместо стандартного <a>, сохраняя семантику и состояния.

Эта комбинация гибкости, доступности и интеграции с экосистемой React делает Link в Radix UI мощным инструментом для построения современного навигационного интерфейса.