Radix мертв, используйте это... (Base UI)

BBetter Stack
컴퓨터/소프트웨어AI/미래기술

Transcript

00:00:00Перестаньте использовать Radix и переходите на... на что? На Base UI. На самом деле, если вы фанат shadcn,
00:00:06то возможность переключиться есть уже сейчас. Если вы раньше не слышали о Base UI, то знайте — это проект
00:00:10от создателей Radix, Floating UI и Material UI. Это библиотека headless-компонентов,
00:00:15которая берет на себя функционал и доступность, оставляя дизайн полностью на ваше усмотрение.
00:00:20Это особенно важно сегодня, так как LLM всё еще плохо справляются со сложными кейсами и доступностью. Но всё,
00:00:24что я сейчас описал, в точности применимо и к Radix. Так зачем же нам новая библиотека?
00:00:30Давайте сразу перейдем к делу, и я покажу вам ключевые отличия. Начнем с документации Base UI,
00:00:35чтобы вы могли оценить выбор компонентов. В списке слева видно, что здесь есть практически всё,
00:00:44что может понадобиться вашей библиотеке компонентов, и даже продвинутые вещи вроде Combo Box,
00:00:48которого в Radix нет. Для каждого компонента есть отличные примеры того, как его использовать
00:00:52и стилизовать, например, с помощью CSS-модулей. При желании можно даже переключиться на примеры с Tailwind.
00:00:57Документация действительно на высоте, но мы здесь не ради неё. Давайте перейдем к первому
00:01:01важному отличию, о котором говорят чаще всего: Base UI активно развивается, а Radix пребывает
00:01:06в состоянии «зомби». Если взглянуть на графики активности на GitHub, видно, что Base UI растет,
00:01:10а в Radix изредка проскакивают случайные коммиты. Но еще нагляднее ситуация с закрытыми тикетами
00:01:15и пул-реквестами за последний месяц. Base UI закрыла 58 тикетов и приняла 154 PR, в то время как
00:01:20у Radix — по нулям. Если вкратце, компанию-создателя Radix купила WorkOS,
00:01:25но они не стали инвестировать в проект. В итоге команда Radix разбежалась, и мы имеем то, что имеем.
00:01:29Сооснователь Radix даже заявил, что использовал бы свое детище только как самый крайний вариант,
00:01:36и да — сейчас он работает над Base UI. Суть в том, чтобы ваши приложения зависели от библиотек,
00:01:42которые поддерживаются, иначе в будущем баг, который никто не собирается чинить, станет вашей головной болью.
00:01:47К счастью, Base UI намеренно сделана похожей на Radix, так что миграция не должна быть сложной.
00:01:53Однако это не помешало авторам внедрить несколько улучшений. Одно из моих любимых
00:01:58касается того, как реализован проп "asChild", знакомый многим по Radix. Если вы не в курсе,
00:02:02вот пример с Select из Radix: если я хочу использовать кастомный компонент в качестве триггера,
00:02:08просто обернув его в Select.Trigger, я получу лишнюю обертку над своей кнопкой «Подписаться»
00:02:13(на которую вам, кстати, стоит нажать). Но если я хочу, чтобы сама кнопка стала триггером,
00:02:17мне нужно добавить проп "asChild". Это говорит Radix объединить все свойства и функционал
00:02:22триггера с дочерним компонентом. Видно, как имя класса объединяется с кнопкой
00:02:27и в данном случае перезаписывает его. Если я удалю этот проп и сохраню, мы увидим обычную кнопку,
00:02:31которая функционально служит триггером для выбора. Это удобная фича, но на неё часто жаловались,
00:02:36потому что она не слишком очевидна. Признаюсь, порой при быстром просмотре кода
00:02:41я упускал этот проп из виду и не мог понять причину проблемы. Посмотрим, как это сделано в Base UI.
00:02:46Здесь тот же функционал: у меня есть кнопка-триггер, но обратите внимание на код —
00:02:50вместо "asChild" Base UI использует проп "render". Внутри него вы указываете компонент,
00:02:55который должен отрисоваться как ваш триггер. Изменение небольшое, но всё становится
00:03:00гораздо понятнее. Компонент буквально «рендерит» этот элемент, и вам не нужно выискивать
00:03:04тот самый проп "asChild" среди детей. На мой взгляд, это маленькое, но очень удачное улучшение.
00:03:09И это еще не всё. В проп "render" можно передать функцию. Это позволяет нам получить доступ
00:03:13к внутреннему состоянию компонента, который мы создаем. В данном примере с ползунком (Switch Thumb)
00:03:18мы можем сами решать, к какому компоненту применить пропсы, и добавлять кастомную логику рендеринга
00:03:24или стилизации в зависимости от состояния. У Switch Thumb есть такие состояния, как checked, dirty,
00:03:29disabled, filled и многие другие. Здесь мы просто проверяем, включен ли переключатель,
00:03:34и в зависимости от этого отрисовываем разные иконки. Есть даже хук, позволяющий внедрить
00:03:39эту логику рендер-пропа в ваши собственные компоненты. Это уже продвинутый уровень, но, думаю,
00:03:43вы видите: Base UI справится с любыми кастомными задачами. Вернемся к нашему Select.
00:03:48Следующее отличие — в Base UI компоненты могут управляться данными. Посмотрим на примере.
00:03:52Сначала код для Radix: у нас есть массив с подписями и значениями. Чтобы вывести их в список,
00:03:56мы просто проходимся методом map по массиву и отрисовываем элементы Select.Item. В Base UI
00:04:01всё выглядит почти так же: тот же массив, тот же map. Но есть один нюанс:
00:04:05мы также передаем этот массив в корневой компонент Select.Root. Это дает важный эффект —
00:04:10компонент «знает» о данных еще до начала рендеринга. Это немного повышает производительность,
00:04:14особенно при серверном рендеринге (SSR). Хотя, как по мне, тут еще есть что улучшить.
00:04:18Сейчас я передаю массив в проп "items" и тут же снова использую его в map ниже.
00:04:22Было бы круче сделать как в React Aria — другой headless-библиотеке. Там массив передается
00:04:27в родительский элемент, а в качестве детей используется функция, которая уже знает обо всех
00:04:31переданных данных. Так нам не приходится использовать массив в двух местах, а родитель
00:04:35служит провайдером данных. Но вернемся к нашему Select — у него есть еще одно отличие.
00:04:40Если рендер-пропы и подход с данными есть почти везде, то эта фишка уникальна для Select —
00:04:44поддержка мультивыбора (multi-select). Этого мучительно не хватало в Radix. В Base UI достаточно
00:04:49добавить проп "multiple" в корневой компонент, и ваш Select превращается в мульти-выбор. Всё просто.
00:04:54Более того, в Base UI есть компоненты, отсутствующие в Radix, например, Combo Box или Autocomplete.
00:04:59В этом и плюс активной разработки — команда быстро реагирует на запросы пользователей. Есть еще
00:05:03два отличия, которые я хочу показать. Перейдем к чекбоксу, а то Select уже немного поднадоел.
00:05:08Первое — это стилизация. Base UI предлагает классный альтернативный способ. Сейчас
00:05:13я использую Tailwind. Конечно, можно использовать обычный CSS, модули и всё прочее. Но в Tailwind
00:05:17для стилизации состояний обычно используют дата-атрибуты: например, "data-checked".
00:05:22В итоге получается очень длинная строка стилей, в которой легко запутаться. Base UI
00:05:26позволяет передать функцию в качестве имени класса. Она дает доступ к состоянию компонента.
00:05:32В случае с чекбоксом я применяю стили в зависимости от того, активен он или заблокирован.
00:05:36Это делается через простые условия. Мне кажется, так гораздо удобнее сразу видеть,
00:05:41откуда берутся те или иные стили, вместо того чтобы выискивать дата-атрибуты в одной длинной строке.
00:05:45Особенно это помогает, если вы используете Vanilla CSS или библиотеку Tailwind Variants.
00:05:50Посмотрите: я просто передаю состояние в функцию чекбокса, а выше прописаны базовые стили
00:05:55и варианты. Если "checked" — применить одно, если "disabled" — другое. На мой взгляд,
00:05:59это нагляднее, чем дата-атрибуты, но это дело вкуса. Здорово, что Base UI дает нам выбор.
00:06:03Кстати, возможность использовать функцию для классов я впервые полюбил в React Aria.
00:06:08У нас есть React Aria с её сложным порогом вхождения и простой Radix. Base UI оказалась
00:06:13где-то посередине, взяв лучшее от обеих. Для меня это идеальная headless-библиотека.
00:06:17Это основные отличия, но есть и много других: отличная поддержка React Hook Form и TanStack Form,
00:06:22удобная работа с анимациями, скраббинг инпутов, вложенные диалоги и меню при наведении.
00:06:27Уверен, на любые разумные просьбы на GitHub ответят быстро, так как проект активно живет.
00:06:33При этом я не призываю немедленно бросать всё и переносить свои проекты с Radix на Base UI —
00:06:38Radix всё еще работает. Но если я начинаю новый проект, я точно выберу Base UI.
00:06:41Или если мне позарез понадобится Combo Box, я тоже задумаюсь о переезде. А что вы думаете
00:06:45о Base UI? Пишите в комментариях, подписывайтесь и, как всегда, увидимся в следующем видео!
00:06:50i'm currently using tailwind you can use all of the traditional approaches like normal css css
00:06:55modules and loads more but if you are using something like tailwind one of the ways you
00:06:59typically style a component like this is by using data attributes for the state so we have data
00:07:04checked here and if it is checked we're going to use background primary you can see we just have a
00:07:08very long string for styling this in tailwind which can sometimes become a little bit of a problem so
00:07:13one of the options that base ui gives you that can help with this is you can actually use a function
00:07:17as your class name this gives you access to the state of the component so in the case of the check
00:07:22box here i'm applying styles based on whether the state is checked or disabled you can see i'm doing
00:07:26that with a simple conditional here and i sometimes think this is just a nicer way for a quick glance
00:07:31when you're looking over your code to see where exactly those checked and disabled styles are
00:07:35coming from instead of having to scan that single line and look for those data attributes i think
00:07:40it's especially even more helpful if you're using something like vanilla css it also works really
00:07:45well with another library that i really like called tailwind variants you can see here i'm simply
00:07:49passing through the state to my checkbox function and up in my tailwind variant checkbox we have our
00:07:53base styles but then we also have our variants and you can see here i'm simply saying if checked is
00:07:58true apply these styles if disabled is true apply these ones and i just think sometimes this is way
00:08:02clearer than using those data attributes but it's definitely up to your opinion and what you're
00:08:06comfortable with using it's just super nice that base ui gives us all of these choices i'll also
00:08:11add that using a function as a class name was something i first fell in love with from react
00:08:14area so it really seems to me like we have react area over here which does have a steeper learning
00:08:19curve and radix which is quite simple and base ui has sort of met in the middle and taken the
00:08:23features that i like about both of them and created me the ultimate headless library now that's all of
00:08:28the key differences that i wanted to go over in this video but there is still loads more like base ui has
00:08:33great support for react hook form and tan stack form it has animation support to make it a nice
00:08:38and easy process to actually animate your components and it even has features like input scrubbing
00:08:42nested dialogues and triggering menus on hover and i'm sure if you have a reasonable request they'd
00:08:47actually respond to it over on the github as it is actively maintained it is also worth saying though
00:08:52that i probably wouldn't jump to migrating my radix app over to base ui straight away as i don't think
00:08:57radix is completely broken if i'm starting a new project i definitely use base ui now and if i wanted
00:09:02a feature like a combo box or an autocomplete i'd also consider migrating my application let me know
00:09:07what you think of base ui in the comments though while you're down there subscribe and as always
00:09:11see you in the next one

Key Takeaway

Base UI является идеологическим и техническим преемником Radix, предлагая лучшую поддержку, расширенный набор компонентов и более современный API для разработки сложных интерфейсов.

Highlights

Radix UI фактически перешел в режим поддержки ("зомби-состояние") после покупки WorkOS и ухода ключевых разработчиков.

Base UI — это новый амбициозный проект от создателей Radix

Timeline

Введение в Base UI и закат Radix

Автор представляет Base UI как новую альтернативу популярной библиотеке Radix для фанатов shadcn. Это headless-библиотека, которая берет на себя вопросы доступности, позволяя разработчикам полностью контролировать дизайн. Проект создается экспертами из команд Radix, Floating UI и Material UI. Спикер отмечает, что в эпоху LLM использование проверенных библиотек с высокой доступностью становится критически важным. Основной вопрос раздела заключается в том, почему индустрии нужна замена уже существующим решениям.

Сравнение активности и проблемы поддержки

В этом сегменте наглядно демонстрируется разница в жизненном цикле двух библиотек через статистику GitHub. Base UI показывает бурный рост и активную работу над тикетами, в то время как Radix практически не обновляется. Автор объясняет это покупкой создателей Radix компанией WorkOS, которая не заинтересована в развитии open-source проекта. Даже сооснователь Radix признался, что сейчас предпочитает работать над Base UI. Это важный контекст для разработчиков, которые хотят строить долговечные приложения на поддерживаемом стеке.

Улучшения в API: от asChild к render

Спикер подробно разбирает техническое улучшение механизма рендеринга дочерних элементов. В Radix часто критиковали проп "asChild" за неочевидность и сложность при отладке кода. Base UI заменяет его на проп "render", который может принимать как компонент, так и функцию. Использование функции позволяет напрямую обращаться к внутренним состояниям, таким как "checked" или "disabled", для условного отображения иконок или стилей. Это делает компоненты чрезвычайно гибкими и упрощает создание кастомной логики внутри UI-элементов.

Управление данными и мульти-выбор

Раздел посвящен работе с данными и новым функциональным возможностям компонента Select. В отличие от Radix, Base UI позволяет передавать массив данных напрямую в корневой компонент через проп "items". Это улучшает производительность при серверном рендеринге, так как компонент заранее знает о структуре данных. Самым ожидаемым нововведением стала встроенная поддержка мульти-выбора с помощью простого пропа "multiple". Также упоминается наличие сложных компонентов вроде Combo Box, которые отсутствуют в стандартном наборе Radix.

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

Автор демонстрирует преимущество использования функций для управления классами CSS вместо длинных строк с дата-атрибутами. Такой подход делает код чище, особенно при использовании Tailwind или библиотеки Tailwind Variants. Base UI позиционируется как золотая середина между простотой Radix и мощью React Aria. Помимо прочего, библиотека предлагает отличную интеграцию с формами и поддержку анимаций. В финале автор советует выбирать Base UI для новых проектов, но не торопиться с немедленной миграцией старых систем, если текущий функционал их устраивает.

Community Posts

View all posts