Урок 16. Старый vs Новый: библиотека и реестр, Radix и Base UI
⚡ Кратко
Классическая библиотека даёт компонент как чёрный ящик, shadcn/ui —
как исходник. Кроме того, сам shadcn/ui изменился: современные версии
строятся на Base UI, а не на Radix, и используют render
вместо asChild.
Кастомизация кнопки
❌ Библиотека: переопределяем чужие стили
// каждая библиотека предлагает свой способ, и все они разные
<Button sx={{ borderRadius: 12, textTransform: "none" }}>Кнопка</Button>
// либо тема на весь проект
createTheme({ components: { MuiButton: { styleOverrides: { root: { … } } } } })
Работает, пока задача укладывается в предусмотренный API. Дальше начинается борьба со специфичностью и «!important».
✅ Реестр: правим свой файл
// src/components/ui/button.tsx
const buttonVariants = cva("inline-flex items-center rounded-lg …", {
variants: { variant: { default: "bg-primary …" } },
})
Нет «API кастомизации» — есть код. Это одновременно самая сильная и самая ответственная сторона подхода.
Внутри самого shadcn/ui: Radix → Base UI
| Что | Старые версии (Radix) | Актуальные (Base UI) |
|---|---|---|
| Пакет примитивов | @radix-ui/react-* | @base-ui/react |
| Полиморфизм | asChild + Slot | проп render |
| Стиль по умолчанию | default / new-york | base-nova |
| Части оверлея | Overlay, Content | Backdrop, Popup |
| Состояния в атрибутах | data-[state=open] | data-open, data-closed |
// старый способ подменить тег кнопки-триггера
<DialogTrigger asChild>
<Button>Открыть</Button>
</DialogTrigger>
// современный
<DialogTrigger render={<Button>Открыть</Button>} />
Это главная причина расхождений между курсом и статьями
в интернете. Увидели
asChild и @radix-ui/* — перед
вами материал под старую версию. Он не «неправильный», но API другое;
при желании ту же базу можно поставить флагом --base radix.Что не изменилось
- Идея реестра: код копируется в проект.
- Связка
cva+cn()для вариантов. - Семантические токены темы и тёмный режим по классу.
- Композиция из мелких подкомпонентов вместо пропсов-флагов.