Смотрю на заявки за последние пару лет и вижу закономерность: заказчики всё чаще просят собрать именно antd dashboard - панель управления на связке React и Ant Design, а не самописный интерфейс с нуля. Причина простая: библиотека закрывает 80% типовых задач админки - таблицы, формы, графики, layout - и экономит недели на вёрстке. Ниже - как я собираю такие панели на практике: структура проекта, компоненты, роли доступа и грабли, на которые наступал сам.
Структура проекта: с чего начинается панель на Ant Design
Для новых проектов беру Vite, а не Create React App - сборка дашборда с десятками страниц на CRA после третьей минуты пересборки начинает раздражать даже терпеливого заказчика. Ставлю antd 5.x, TypeScript и React Router. Папки развожу по фичам, а не по типам файлов: features/orders, features/clients, features/analytics, каждая со своими компонентами, хуками и API-запросами внутри. Общий layout, тема antd и обёртки над Table и Form выношу в shared/ui.
Ant Design 5 переехал на CSS-in-JS вместо less-переменных, и это меняет подход к кастомизации темы. Токены задаются через ConfigProvider и объект theme, а не через файл со стилями:
import { ConfigProvider } from 'antd';
const theme = {
token: {
colorPrimary: '#1677ff',
borderRadius: 6,
},
components: {
Table: { headerBg: '#fafafa' },
},
};
function App() {
return (
<ConfigProvider theme={theme}>
<AppLayout />
</ConfigProvider>
);
}
Если дизайнер прислал макет с фирменными цветами клиента, это закрывает вопрос за 10 минут - без переопределения десятков CSS-классов через !important, как приходилось делать на antd 4.
Layout, Menu и Breadcrumb - каркас интерфейса
Базовый каркас почти всегда один и тот же: Sider с меню слева, шапка с профилем и уведомлениями, контентная область с хлебными крошками. Компонент Layout из коробки даёт нужную разметку, остаётся связать пункты меню с роутами:
import { Layout, Menu } from 'antd';
import { DashboardOutlined, TeamOutlined, BarChartOutlined } from '@ant-design/icons';
const { Sider, Content, Header } = Layout;
const menuItems = [
{ key: '/', icon: <DashboardOutlined />, label: 'Обзор' },
{ key: '/clients', icon: <TeamOutlined />, label: 'Клиенты' },
{ key: '/reports', icon: <BarChartOutlined />, label: 'Отчёты' },
];
function AppLayout({ children }) {
const navigate = useNavigate();
return (
<Layout style={{ minHeight: '100vh' }}>
<Sider breakpoint="lg" collapsedWidth="0">
<Menu
theme="dark"
mode="inline"
items={menuItems}
onClick={({ key }) => navigate(key)}
/>
</Sider>
<Layout>
<Header style={{ background: '#fff', padding: '0 24px' }} />
<Content style={{ margin: 24 }}>{children}</Content>
</Layout>
</Layout>
);
}
Пункт breakpoint="lg" сворачивает сайдбар на планшетах - без этого на iPad меню съедает половину экрана, и заказчики на приёмке почти всегда просят это поправить, если забыть сразу.
Бесплатный материал
🎁 Полезный скрипт в подарок
Подпишитесь на Telegram - пришлю готовый скрипт по этой теме.
Без спама. Отписка в 1 клик.
Таблицы и формы: связка Table и Form на практике
Основная часть любой админки - это таблицы с фильтрами и формы редактирования. На проекте для логистической компании таблица заказов росла до 40 тысяч строк, и клиентская пагинация antd легла бы на первом же фильтре. Пагинацию, сортировку и фильтры перевёл на сервер:
const columns = [
{ title: 'Клиент', dataIndex: 'name', key: 'name', sorter: true },
{
title: 'Статус',
dataIndex: 'status',
key: 'status',
filters: [
{ text: 'В пути', value: 'transit' },
{ text: 'Доставлен', value: 'done' },
],
},
];
function OrdersTable() {
const [params, setParams] = useState({ page: 1, pageSize: 20 });
const { data, isLoading } = useOrders(params);
return (
<Table
columns={columns}
dataSource={data?.items}
rowKey="id"
loading={isLoading}
pagination={{ current: params.page, pageSize: 20, total: data?.total }}
onChange={(pagination, filters, sorter) =>
setParams({ page: pagination.current, pageSize: 20, filters, sorter })
}
/>
);
}
Для форм связка Form.useForm плюс встроенные правила валидации закрывает 90% случаев без сторонних библиотек вроде Formik. Единственное место, где реально нужен React Query или SWR поверх - кэширование справочников (города СДЭК, статусы заказов, менеджеры), которые дёргаются на каждой форме заново, если не закешировать.
Графики для дашборда: что выбрать
Ant Design не тянет графики в основной пакет - их подключают отдельно. На практике сравнивал три варианта для панелей с аналитикой:
| Библиотека | Вес бандла | Кастомизация | Когда беру |
|---|---|---|---|
| @ant-design/charts | Средний | Готовые пресеты, стиль сразу под antd | Типовые графики без глубоких кастомных сценариев |
| Recharts | Небольшой | Гибкая композиция через React-компоненты | Когда нужен нестандартный вид виджета |
| ECharts (echarts-for-react) | Большой | Максимальная, включая карты и 3D | BI-дашборды с тепловыми картами и большим объёмом точек |
Для обычного дашборда продаж хватает @ant-design/charts - линии, столбцы и Pie собираются за час без танцев со стилями. Если нужен дашборд с географией доставок или тепловой картой активности, беру ECharts - он тяжелее, но по-другому карту с 5000 точек не отрисовать без лагов.
Роли доступа и защита роутов
Меню и роуты в панели почти всегда завязаны на роли: менеджер видит заказы, бухгалтер - отчёты и счета, админ - всё плюс настройки. Пункты меню фильтрую на фронте по массиву прав из токена, но саму защиту данных всегда дублирую на бэкенде - фронтовая проверка ролей это вопрос UX, а не безопасности.
function ProtectedRoute({ roles, children }) {
const { user } = useAuth();
if (!user) return <Navigate to="/login" />;
if (roles && !roles.some((r) => user.roles.includes(r))) {
return <Navigate to="/403" />;
}
return children;
}
Бэкенд под такие панели чаще собираю на Laravel - готовая система прав (Spatie Permission), очереди для экспорта отчётов и стабильный REST API под antd-таблицы связываются без лишних костылей. Если у вас уже есть API на другом стеке, отдельно смотрю на разработку API и бэкенда на Laravel под конкретно ваш дашборд - обычно нужен, когда старый бэкенд не тянет фильтры и агрегации, которые просит фронт.
Персональные данные клиентов - email, телефоны, адреса доставки - храню только на серверах в РФ, без завязки на иностранные облачные таблицы. Для дашборда с клиентской базой это не опция, а требование 152-ФЗ.
Производительность: на что смотрю в первую очередь
Ant Design - библиотека немаленькая, и без внимания к бандлу дашборд начинает грузиться по 4-5 секунд на слабом канале. Что реально экономит время:
- Импорт иконок точечно, а не пакетом
@ant-design/iconsцеликом - на одном проекте это срезало 300 КБ из бандла; - Ленивая загрузка страниц через
React.lazy- раздел «Настройки» открывают раз в неделю, незачем грузить его код на старте; - Мемоизация колонок
TableчерезuseMemo- без неё колонки пересоздаются на каждый рендер и таблица на 1000+ строк подтормаживает при вводе в фильтр; - Виртуализация длинных списков - начиная примерно с 500 строк на странице разница в отзывчивости заметна на глаз, даже с серверной пагинацией.
Отдельно слежу за тем, чтобы контекст авторизации не оборачивал весь layout - если AuthContext меняется на каждый тик (например, из-за таймера токена), перерисовывается вся страница целиком, включая тяжёлые графики. Разношу контексты по назначению вместо одного глобального.
Кастомный CRM/админ-интерфейс
Админка / CRM
от 100 000 ₽
Подробнее →Частые вопросы
Сколько стоит дашборд на Ant Design для React?
ЦРМ или админ-панель на React у меня стоит от 100 000 ₽ - цена зависит от количества разделов, сложности прав доступа и интеграций с внешними системами вроде эквайринга или СДЭК. Простая панель с 3-4 разделами и одной ролью укладывается в нижнюю границу, дашборд с аналитикой, ролями и экспортами - дороже.
Чем Ant Design лучше MUI для панели управления
Ant Design изначально заточен под enterprise-интерфейсы: у Table, Form и Tree больше готовых сценариев из коробки - серверная пагинация, вложенные фильтры, drag-and-drop колонок. MUI даёт больше свободы в дизайне и ближе к Material-гайдлайнам, но типовые вещи вроде сложной таблицы приходится собирать из более простых кубиков. Для внутренней CRM или бэк-офиса обычно беру antd - быстрее по срокам.
Можно ли адаптировать antd dashboard под мобильные устройства
Grid-система antd (Row/Col) и брейкпоинты у Sider и Menu адаптивны сами по себе, но Table на маленьком экране требует отдельной работы - либо горизонтальный скролл с зафиксированной первой колонкой, либо переключение на карточное представление ниже определённой ширины. Для панелей, которыми реально пользуются с телефона (например, курьеры или полевые менеджеры), карточный вид делаю отдельным компонентом, а не пытаюсь ужать таблицу.
Сколько времени занимает разработка админ-панели на antd
Панель на 5-7 разделов с таблицами, формами и одной-двумя ролями доступа обычно занимает от 3 до 5 недель вместе с интеграцией бэкенда. Дашборд с графиками, экспортом отчётов и несколькими ролями - от 6 недель. Сроки сильно зависят от готовности API: если бэкенд уже отдаёт данные в нужном формате, фронтовая часть на antd собирается заметно быстрее.