Управление scroll

Radix UI предоставляет высокоуровневые компоненты для создания интерфейсов с богатой интерактивностью, и управление прокруткой (scroll) является одной из ключевых задач при работе с динамическими списками, модальными окнами и всплывающими элементами. В основе подхода Radix UI лежит контроль состояния и возможность кастомизации поведения scroll через встроенные хуки и свойства компонентов.


ScrollArea: базовая концепция

ScrollArea — основной компонент для организации прокручиваемого контента. Он инкапсулирует стили и обработку событий, позволяя создавать как вертикальные, так и горизонтальные области прокрутки с кастомными скроллбарами.

Пример базовой структуры:

import * as ScrollArea from '@radix-ui/react-scroll-area';

<ScrollArea.Root style={{ width: 300, height: 200 }}>
  <ScrollArea.Viewport>
    <div style={{ height: 600, padding: 10 }}>
      Длинный контент, который требует прокрутки.
    </div>
  </ScrollArea.Viewport>
  <ScrollArea.Scrollbar orientation="vertical">
    <ScrollArea.Thumb />
  </ScrollArea.Scrollbar>
</ScrollArea.Root>
  • Root — корневой контейнер scroll-области, управляет состоянием прокрутки.
  • Viewport — область, в которой отображается контент; все, что выходит за её пределы, скрыто.
  • Scrollbar — кастомный скроллбар, может быть вертикальным или горизонтальным.
  • Thumb — «ползунок» скроллбара, положение которого синхронизировано с прокруткой Viewport.

Управление видимостью скроллбаров

Radix UI позволяет легко управлять видимостью скроллбаров через свойство forceMount и CSS-анимации. Это полезно для плавного появления/исчезновения скроллбаров при наведении или прокрутке.

<ScrollArea.Scrollbar orientation="vertical" forceMount>
  <ScrollArea.Thumb />
</ScrollArea.Scrollbar>
  • forceMount гарантирует, что скроллбар всегда присутствует в DOM, даже если он не виден.
  • Для динамических эффектов можно использовать CSS-селекторы [data-state='visible'] и [data-state='hidden'] для плавного появления.

Автоскролл к элементу

Radix UI не предоставляет встроенный метод для автоматической прокрутки к элементу, но можно использовать API ref и стандартные методы DOM:

const itemRef = useRef(null);

const scrollToItem = () => {
  itemRef.current?.scrollIntoView({ beh * avior: 'smooth', block: 'start' });
};

<div ref={itemRef}>Целевой элемент</div>
  • scrollIntoView интегрируется с любыми ScrollArea, так как они используют стандартный DOM для Viewport.
  • Свойство beh * avior: 'smooth' обеспечивает плавный переход, что особенно важно в сложных интерфейсах.

Горизонтальная прокрутка

ScrollArea поддерживает горизонтальную прокрутку через orientation="horizontal":

<ScrollArea.Scrollbar orientation="horizontal">
  <ScrollArea.Thumb />
</ScrollArea.Scrollbar>
  • Горизонтальная прокрутка часто используется для каруселей и таблиц с большим количеством колонок.
  • Стилизация Thumb и Scrollbar может быть отдельной для вертикальной и горизонтальной оси.

События прокрутки и состояние

Компонент ScrollArea.Root предоставляет событие onScroll, которое позволяет отслеживать положение прокрутки:

<ScrollArea.Root onScr oll={(event) => {
  console.log(event.currentTarget.scrollTop);
}}>
  <ScrollArea.Viewport>
    ...
  </ScrollArea.Viewport>
</ScrollArea.Root>
  • scrollTop и scrollLeft дают точное положение по вертикали и горизонтали.
  • Можно использовать эти данные для реализации «липких» заголовков, анимаций или lazy-loading контента.

Кастомизация скроллбаров

Radix UI предоставляет полную свободу в стилизации Scrollbar и Thumb с помощью CSS:

.scrollbar {
  background-color: rgba(0,0,0,0.1);
  border-radius: 4px;
}

.thumb {
  background-color: rgba(0,0,0,0.5);
  border-radius: 4px;
}
  • Можно менять размеры, форму и анимацию Thumb при наведении.
  • С помощью data-orientation можно создавать отдельные стили для вертикального и горизонтального скроллбаров.

Оптимизация производительности

При больших списках рекомендуется использовать overflow: hidden для контейнера ScrollArea и отложенную отрисовку элементов, чтобы уменьшить количество DOM-операций при прокрутке. В сочетании с хуками React (useMemo, useCallback) это позволяет снизить нагрузку на рендеринг и избежать «тормозов» интерфейса.


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

ScrollArea хорошо сочетается с компонентами Dialog, Popover и Tabs:

  • В Dialog ScrollArea позволяет делать прокручиваемый контент внутри модального окна без влияния на глобальную прокрутку страницы.
  • В Tabs горизонтальная ScrollArea поддерживает навигацию между вкладками с большим количеством элементов.
  • В Popover можно ограничить область прокрутки, чтобы всплывающее меню не выходило за пределы видимой зоны.

Управление scroll в Radix UI сочетает гибкость кастомизации с предсказуемым поведением компонентов. Использование ScrollArea, правильное подключение событий прокрутки, работа с ref и CSS-анимациями позволяет создавать сложные интерфейсы с плавной прокруткой и контролем пользовательского опыта.