
❯ Вступление
Вряд ли в наше время еще нуждается в представлении Vue — фронтенд-фреймворк, который входит в тройку лидеров, наравне с React и Angular.
За годы своего существования Vue заматерел, прошёл через существенные изменения и оброс своей экосистемой. Например, к ней относится Nuxt — метафреймворк для SSR, созданный по аналогии с метафреймворком Next в экосистеме React.
Однако в этой экосистеме не хватало одной важной составляющей — UI-библиотеки, которая бы воспринималась всеми разработчиками, как надежное, современное и универсальное решение, которое сразу приходит на ум при фразе «UI-библиотека для Vue или Nuxt».
Да, есть вполне популярные и доказавшие свою профпригодность Quasar, Vuetify и PrimeVue. Но будто бы не хватало «своего» решения, которое бы получало поддержку со стороны экосистемы Vue и органично бы с ней интегрировалось.
Но кажется, теперь ожидание подошло к концу. Молодая UI-библиотека Nuxt UI от самих авторов Nuxt, которая постепенно вызревала и завоевывала доверие, наконец может претендовать на звание полноценного решения по умолчанию для всей экосистемы Vue.
Это стало возможно только после недавнего релиза новой версии — Nuxt UI 4. Давайте разберём, что из себя представляет Nuxt UI, что нового в четвертой версии и почему вам стоит обратить на неё внимание.
❯ 1. Технологии и совместимость
Nuxt и Vue
Изначально библиотека Nuxt UI создавалась только для работы с метафреймворком Nuxt. Но начиная с последней версии библиотеку можно использовать и просто вместе с Vue.
Получается, что Nuxt UI расширяет свою сферу применимости и теперь будет конкурировать и с устоявшимися UI-библиотеками для Vue.
Стоит сразу отметить, что в зависимости от того, используете ли вы Vue или Nuxt, какие-то аспекты работы с Nuxt UI отличаются. Поэтому в документации в верхнем правом углу есть переключатель Nuxt-Vue, чтобы выбрать, с каким фреймворком вы собираетесь работать.
TypeScript
TypeScript фактически стал стандартом во фронтенд-разработке. И Nuxt UI не отстаёт от современных реалий, поэтому библиотека написана на TS, что обеспечивает типобезопаснос��ь и автодополнение в редакторах кода.
Reka UI
Nuxt UI строится на основе UI-библиотеки Reka UI. Которая, в свою очередь, является портом под Vue известной библиотеки Radix UI для React.
Reka UI это нестилизованная UI-библиотека примитивных компонентов, созданная специально для того, чтобы разработчики создавали уже полноценные стилизованные UI-библиотеки на её основе, не тратя времени на многие рутинные, но важные задачи.
В том числе Reka UI решает и вопросы, связанные с доступностью (accessability) компонентов: соответствие требованиям WAI-ARIA, навигация с клавиатуры, управление фокусом и поддержка скрин-ридеров.
Благодаря этому и Nuxt UI поддерживает все перечисленные возможности.
Tailwind
Для стилизации Nuxt UI использует популярную CSS-библиотеку Tailwind CSS. Поэтому для того, чтобы полноценно использовать Nuxt UI, нужно уметь работать с Tailwind.
Причем в Nuxt UI используется Tailwind последней четвертой версии. Среди главных отличий четвёрки — теперь вся конфигурация идет в CSS, а не в tailwind.config.ts, как раньше. Есть и другие изменения, поэтому если вы раньше работали только с Tailwind 3, то сначала рекомендуем кратко ознакомиться с тем, что нового несет Tailwind 4.
Tailwind Variants
Tailwind Variants это библиотека, которая обеспечивает удобную систему для стилизации компонентов. Подробней о том, как это работает, мы поговорим далее в разделе Ст��лизация компонентов.
Подход к коду компонентов
В последнее время набирает популярность подход к UI-библиотекам, когда компоненты размещаются не в node_modules, а непосредственно в коде проекта. Такой подход популяризировала библиотека shadcn, которая изначально была написана под React, но сейчас уже портирована под все популярные фреймворки.
Так вот, к Nuxt UI это не относится. Это UI-библиотека в её классическом виде, где все компоненты находятся в node_modules и уже оттуда импортируются в код проекта.
Кстати, конечно же Nuxt UI поддерживает автоимпорт как в Nuxt, так и во Vue.
❯ 2. Теперь всё бесплатно
Экономическая модель профессиональных UI-библиотек обычно строится на том, что все элементарные компоненты (Button, Card, Input и т. д.) предоставляются бесплатно, однако более сложные компоненты, готовые блоки и шаблоны уже предлагаются за плату.
Ранее Nuxt UI следовала тому же подходу, но с новой 4-й версии все ранее платные продукты теперь доступны бесплатно. Если раньше бесплатно были доступны более 40 компонентов, то теперь доступно более 100.
Это стало возможным благодаря тому, что в июле 2025 крупная хостинг-компания Vercel приобрела NuxtLabs — компанию основных авторов Nuxt. Теперь они могут не переживать о монетизации и спокойно заниматься разработкой фреймворка и смежных продуктов, вроде Nuxt UI.
Хотя обратная сторона медали в том, что такое решение серьезно вредит конкуренции на рынке UI-библиотек для Nuxt и Vue. В новой реальности, где Nuxt UI предлагает pro-компоненты, шаблоны и UI-kit для Figma бесплатно, у веб-разработчиков будет меньше мотивации платить за продукты конкурентов, даже если те не будут уступать в качестве.
❯ 3. Готовые шаблоны
Бесплатными стали и стартовые шаблоны, которые команда Nuxt UI предлагает для быстрого старта разработки:
Starter — минимально рабочий проект, ничего лишнего.
Landing — лендинг для продукта, включает список возможностей, тарифные планы, отзывы.
SaaS — уже полноценный сайт, где помимо главной/лендинга есть блог, раздел с документацией, страница с тарифами и лента обновлений (changelog).
Docs — простая главная + раздел с документацией.
Dashboard — типовая внутренняя система с дашбордом, письмами, клиентами и сотрудниками.
Portfolio — портфолио с главной страницей, списком проектов и блогом.
Chat — заготовка для создания AI-чатов.
Changelog — лента обновлений продукта.
На момент выхода статьи большинство стартовых шаблонов доступны только в версии для Nuxt, а не для Vue.
Также, если хочется использовать Nuxt именно в качестве документации, то можно обратить внимание на проект Docus, тоже от авторов Nuxt UI. Это стартовый шаблон, который похож на Docs, но с небольшими отличиями. Например, в нём уже встроена поддержка мультиязычности (i18n).
❯ 4. Компоненты
Список всех компонентов можно наглядно посмотреть на специальной странице.

Часть компонентов элементарные — это разные кнопки, инпуты, бэджики, тултипы и т. д. Мы не будем на них останавливаться, потому что они уже есть в каждой UI-библиотеке, они почти везде идентичны и всем знакомы.
Гораздо интересней рассмотреть компоненты, которые ранее были только в платной версии Nuxt UI. В общей структуре библиотеки большинство таких pro-компонентов выделены в свои группы:
Page
К этой группе относятся сложные компоненты, из которых собираются лендинги, блоги, страницы с тарифами и другие маркетинговые и контентные страницы.
AuthForm — форма регистрации и авторизации
BlogPost, BlogPosts — для вывода карточек блога
ChangelogVersion, ChangelogVersions — для вывода ленты обновлений продукта (чейнжлога)
Page, PageBody, PageHeader, PageAside �� для разделения содержимого страниц на логические блоки (основная часть, хэдер и боковая панель)
PageAncors — список ссылок с иконками
PageCard — готовая карточка контента (заголовок, описание, изображение)
PageColumns — колоночная сетка для вывода карточек разной высоты (например, отзывы)
PageCTA — маркетинговый блок с призывом к действию
PageFeature — список фич продукта (часто используется внутри других блоков)
PageGrid — колоночная сетка для вывода карточек
PageHero — типовой hero-блок, обычно размещается наверху главной страницы
PageLinks — простой список ссылок
PageList — простой вертикальный список элементов
PageLogos — лента логотипов
PageSection — для удобного оформления контента с бэкграундом во всю ширину
PricingPlan, PricingPlans, PricingTable — для создания страниц с тарифами
Оценить, как можно использовать компоненты этой группы, можно на шаблонах Landing (демо, код) и SaaS (демо, код).
Dashboard
Группа компонентов, которые задают общий каркас для сайтов внутренних систем.
DashboardGroup — родительский компонент-оболочка
DashboardNavbar — панель навигации (заголовок текущей страницы, кнопки открытия/скрытия меню, переключатели и т. д.)
DashboardPanel — боковая панель небольшой ширины для вывода какого-то вспомогательного содержимого, например списка задач или писем
DathboardResizeHandle — дает возможность увеличения и уменьшения ширины панели или сайдбара
DashboardSearch — панель поиска (расширенная версия компонента CommandPalette)
DashboardSearchButton — кнопка, чтобы открыть панель поиска
DashboardSidebar — боковая панель
DashboardSidebarCollapse — кнопка для сворачивания/разворачивания сайдбара
DashboardSidebarToggle — кнопка разворачивания боковой панели, которая появляется в мобильной версии
DashboardToolbar — вспомогательная панель под панелью навигации (например, для вкладок и ссылок)
Посмотреть на примеры этой группы компонентов можно в шаблоне Dashboard. Ссылка на демо. Ссылка на код.

Chat
Группа компонентов, которые пригодятся для создания ИИ-чата.
ChatMessage — сообщение чата
ChatMessages — список сообщений чата
ChatPallete — родительский компонент-оболочка
ChatPrompt — многострочное поле для ввода сообщений
ChatPromptSubmit — кнопка отправки сообщения
Пример использования этих компонентов — в стартовом шаблоне Chat. Ссылка на демо. Ссылка на код.
Content
Группа вспомогательных компонентов, полезных для создания контентных разделов, например документации или блогов.
ContentNavigation — панель навигации со структурой разделов и страниц
ContentSearch — поисковая панель (расширенная версия компонента CommandPalette)
ContentSearchButton — кнопка для открытия поисковой панели
ContentSurround — показывает предыдущую и следующую страницы
ContentToc — навигация по текущей странице («Toc» означает Table of Content — т. е. содержимое страницы)
Компоненты этой группы доступны только если на проекте подключен модуль Nuxt Content для работы с контентом.
Наглядный пример использования этих компонентов — шаблон Docs. Ссылка на демо. Ссылка на код. Ну и конечно сама документация Nuxt UI.
Color Mode
Группы компонентов для удобной работы со светлой и темной темой.
ColorModeAvatar, ColorModeImage — чтобы показывать разные изображения в зависимости от того, включена ли светлая или темная тема. В частности, это пригодится, если вы размещаете на сайте скриншоты какого-то сайта, сервиса, программы и т. д.
ColorModeButton, ColorModeSelect, ColorModeSwitch — разные варианты переключателей между светлой и темной темой.
Оценить работу этих компонентов можно на любом из стартовых шаблонов.
Подробней о том, как в целом работает Color Mode в Nuxt UI, будет рассмотрено дальше.
❯ 5. Figma UI Kit
Nuxt UI предоставляет официальный дизайн кит для Figma, который тоже полностью бесплатен. Это при том, что обычно официальные UI Kit для Figma от разработчиков библиотек предоставляются только в платных тарифах.

Однако, на момент публикации материала с дизайн китом наблюдалась проблема, что он требует слишком много оперативной памяти, поэтому пользоваться им пока что может быть проблематично.
❯ 6. Установка
Процесс установки Nuxt UI отличается в зависимости от того, работаете ли вы с Nuxt, или с обычным Vue. Мы рассмотрим установку на Nuxt.
1. Установить пакет
Команда для установки через npm:
npm install @nuxt/ui
2. Подключить модуль
Нужно добавить Nuxt UI в список модулей в nuxt.config.ts.
export default defineNuxtConfig({
modules: ['@nuxt/ui']
})
3. Настроить CSS-файл
Прописать импорты в главном CSS-файле.
@import "tailwindcss";
@import "@nuxt/ui";
А сам CSS-файл должен быть подключен в nuxt.config.ts.
export default defineNuxtConfig({
modules: ['@nuxt/ui'],
css: ['~/assets/css/main.css']
})
4. Обернуть ваше приложение в UApp
Обычно «входной» файл проекта это app.vue. В этом файле нужно задать, чтобы все страницы были включены в компонент <UApp>.
<template>
<UApp>
<NuxtPage />
</UApp>
</template>
<UApp> обеспечивает нужные глобальные настройки и необходим для работы некоторых компонентов, вроде Toast, Tooltip, Modal и т. д.
5. Настроить расширение Tailwind для VSCode
Поскольку Nuxt UI строится вокруг Tailwind, то желательно ещё установить и настроить расширение Tailwind CSS IntelliSense для VSCode.
Документация Nuxt UI рекомендует следующие настройки для этого расширения:
{
"files.associations": {
"*.css": "tailwindcss"
},
"editor.quickSuggestions": {
"strings": "on"
},
"tailwindCSS.classAttributes": ["class", "ui"],
"tailwindCSS.experimental.classRegex": [
["ui:\\\\s*{([^)]*)\\\\s*}", "(?:'|\\"|`)([^']*)(?:'|\\"|`)"]
]
}
И на этом всё — можно начинать работу.
Установка из шаблонов
Напомним, что если вы начинаете новый проект, то можно не ставить всё с нуля, а использовать один из стартовых шаблонов, которые мы разбирали выше.
Их можно скопировать с Github или установить командой, например:
npm create nuxt@latest -- -t ui/landing
❯ 7. Дизайн-система NuxtUI
В Nuxt UI используется дизайн-система из Tailwind с небольшими дополнениями.
Тема Tailwind это набор CSS-переменных, которые задают разные CSS-значения: цвета, размеры, отступы и т. д.
Почитать подробней об этом можно в документации Tailwind. И там же в конце страницы можно посмотреть полный список CSS-переменных, которые составляют тему.
Редактирование темы
Вы можете переписать значения любых переменных темы через главный CSS-файл проекта. Для этого нужно использовать директиву @theme.
Там же вы можете добавить свои пользовательские переменные (например, дополнительные цвета или брейкпоинты), и после этого они будут доступны в виде соответствующих классов Tailwind.
Вот лишь несколько примеров редактирования темы:
1. Настройка шрифтов:
@theme {
--font-sans: 'Inter', system-ui, sans-serif;
--font-mono: 'Fira Code', monospace;
}
2. Перезаписывание конкретного цвета (в данном случае зеленого):
@theme static {
--color-green-50: oklch(97.53% 0.027 158.3);
--color-green-100: oklch(93.39% 0.046 160.6);
--color-green-200: oklch(86.71% 0.086 162.1);
--color-green-300: oklch(78.14% 0.128 156.9);
--color-green-400: oklch(73.68% 0.153 154.1);
--color-green-500: oklch(67.42% 0.142 152.9);
--color-green-600: oklch(60.45% 0.126 152.8);
--color-green-700: oklch(52.71% 0.109 152.3);
--color-green-800: oklch(46.43% 0.094 152.0);
--color-green-900: oklch(38.34% 0.078 153.4);
--color-green-950: oklch(27.82% 0.048 152.0);
}
3. Добавление нового цвета:
@theme static {
--color-brand-50: oklch(96.76% 0.010 17.0);
--color-brand-100: oklch(93.53% 0.021 17.3);
--color-brand-200: oklch(88.37% 0.041 17.3);
--color-brand-300: oklch(81.62% 0.070 17.3);
--color-brand-400: oklch(74.03% 0.108 17.3);
--color-brand-500: oklch(66.46% 0.147 17.4);
--color-brand-600: oklch(58.00% 0.174 19.6);
--color-brand-700: oklch(49.24% 0.154 21.2);
--color-brand-800: oklch(42.52% 0.134 21.4);
--color-brand-900: oklch(36.20% 0.114 22.1);
--color-brand-950: oklch(23.09% 0.071 24.0);
}
В примере новому цвету даётся название brand («бренд», т. е. «фирменный цвет»).
4. Добавление дополнительных брейкпоинтов:
@theme {
--breakpoint-3xl: 1920px;
--breakpoint-4xl: 2560px;
}
❯ 8. Семантические цвета
В работе с цветами у Nuxt UI есть важное отличие от Tailwind — возможность задавать цвета семантически. Т.е. указывать не конкретный цвет (red, blue и т. д.), а его роль.
Возможные семантические значения цветов по умолчанию: primary, secondary, success, info, warning, error и neutral. Соответственно, это: «основной», «второстепенный», «успех», «информация», «предупреждение», «ошибка», «нейтральный».
Каждому из этих семантических значений соответствует определенный конкретный цвет из темы проекта. Например, по умолчанию значению primary соответствует зеленый цвет green, а значению secondary — синий цвет blue.
В чём преимущества
Получается, что главное преимущество такого подхода в том, что можно просто поменять в конфиге значение primary c одного цвета на другой — и это поменяет основной цвет для всего проекта.
При этом, для светлой и для темной темы можно задавать разные значения CSS-переменных. Это второе важное преимущество семантического подхода — не нужно каждый раз прописывать по два класса цветов, чтобы учесть тёмную/светлую тему.
Как их использовать
Для указания цвета у компонентов обычно используется пропс «color». И значением этого пропса может быть только семантический цвет.
<template>
<UButton color="primary">Купить</UButton>
<UButton color="warning">Удалить</UButton>
<UButton color="neutral">Отправить</UButton>
</template>
А когда вам нужно задать цвет через класс, то также рекомендуется использовать семантические значения цветов без указания оттенков.
<template>
<span class="text-info">Информация</span>
<span class="text-warning">Предупреждение</span>
<span class="text-success">Успех</span>
</template>
Но при необходимости всё ещё можно использовать и обычный общепринятый в Tailwind способ, когда в классе указывается конкретный цвет и оттенок. Например, text-blue-400, bg-green-700 и т. д.
Как их настроить
Поменять соответствия цветов можно через рантайм-конфиг проекта — файл app.config.ts. Например:
export default defineAppConfig({
ui: {
colors: {
primary: 'blue',
secondary: 'violet',
neutral: 'slate'
}
}
})
При этом в качестве значений можно использовать только названия тех цветов, для которых уже есть CSS-переменные в теме проекта. Это может быть как цвет из набора Tailwind, так и добавленный вами цвет.
Обращаем внимание, что среди цветов из палитры Tailwind есть цвет с названием «neutral» (нейтральный). Его не стоит путать с одноимённым семантическим цветом «neutral» в Nuxt UI. Хотя при желании можно связать их, т. е. прописать в конфиге
neutral: 'neutral'.
Заметим, что в конфиге указывается только цвет в целом, но не указывается конкретный оттенок цвета (50, 100, 200, 300 и т. д.).
Если нужно поменять оттенок, то это нужно делать уже через главный CSS-файл. Например, вот так можно переназначить оттенки цвета для primary:
:root {
--ui-primary: var(--ui-color-primary-800);
}
.dark {
--ui-primary: var(--ui-color-primary-300);
}
Видно, что для семантических цветов задаются два значения: для светлой и для темной темы.
Как добавить свой вариант
Вы можете добавить свои значения для семантических цветов. Например, вам мало «primary» и «secondary» и вы хотите еще вариант «tertiary» («третий»). Это можно сделать в 3 шага:
1. Добавить новое семантическое значение в массив всех цветов в nuxt.config.ts:
export default defineNuxtConfig({
ui: {
theme: {
colors: [
'primary',
'secondary',
'tertiary',
'info',
'success',
'warning',
'error'
]
}
}
})
2. Назначить конкретный цвет в app.config.ts:
export default defineAppConfig({
ui: {
colors: {
primary: 'blue',
secondary: 'purple',
tertiary: 'indigo'
}
}
})
3. Назначить нужные вам оттенки в главном CSS-файле, отдельно для светлой и темной темы:
:root {
--ui-tertiary: var(--ui-color-tertiary-700);
}
.dark {
--ui-tertiary: var(--ui-color-tertiary-200);
}
Семантические оттенки серого текста, фона и границ
Для классов, которые задают цвет текста, фона и границ, дополнительно есть еще свои специальные семантические значения.
Для текста: Dimmed, Muted, Toned, Default, Highlighted, Inverted — т. е. «тусклый», «приглушенный», «осветленный», «по умолчанию», «выделенный», «инвертированный». Пример класса: text-muted.
Для бэкграунда: Default, Muted, Elevated, Accented, Inverted — т. е. «по умолчанию», «приглушенный», «приподнятый», «акцентированный», «инвертированный». Пример класса bg-elevated.
Для границ: Default, Muted, Accented, Inverted — т. е. «по умолчанию», «приглушенный», «акцентированный», «инвертированный». Пример класса: border-accented.
По умолчанию перечисленным семантическим значениям соответствуют разные градации серого цвета (neutral). Вот пример для класса text-muted.
:root {
--ui-text-muted: var(--ui-color-neutral-500);
}
.dark {
--ui-text-muted: var(--ui-color-neutral-400);
}
Подробней о том, как выглядят соответствующие цвета на практике и как их можно поменять, смотрите в документации.
❯ 9. Дополнения от Nuxt UI в стили проекта
В завершение вопроса про дизайн систему стоит отметить ряд небольших доп��лнений, которые Nuxt UI добавляет в стили проекта.
Переменные для контейнера и хэдера
Помимо прочего, в стили проекта добавляются три CSS-переменных:
--ui-container— задает максимальную ширину контейнера с контентом страниц.--ui-header-height— задает высоту хэдера сайта.--ui-radius— задает скругления границ (см. далее).
Перезаписанные радиусы
Nuxt UI прописывает свои собственные значения для Tailwind-классов, которые задают скругления границ: rounded-xs, rounded-sm и т. д.
Это сделано, чтобы в Nuxt UI значения скруглений зависели от общей проектной CSS-переменной --ui-radius.
Стили по умолчанию
По умолчанию к <body> страниц применяются несколько классов. В первую очередь, чтобы корректно работали светлая и темная темы.
body {
@apply antialiased text-default bg-default scheme-light dark:scheme-dark;
}
❯ 10. Стилизация компонентов
Стилизация компонентов в Nuxt UI построена на вариантном подходе. Для реализации этого подхода используется библиотека Tailwind Variants.
Суть этого подхода в том, что для каждого компонента есть специальные пропсы для его стилизации. Например, color (цвет), size (размер) и т. д. У этих пропсов могут быть только семантические значения, например для color — «primary», «secondary» и т. д., а для size — «xs», «sm» и т. д. Эти значения и называются вариантами — отсюда и название подхода.
<template>
<UButton color="secondary" variant="subtle" size="xl" icon="i-lucide-search">Искать</UButton>
</template>
И у каждого экземпляра компонента на основании этих выбранных вариантов определяется, какие классы Tailwind должны быть назначены на разные html-элементы в этом компоненте.
Чтобы понять, как именно это работает, нужно разобрать 2 вопроса: из чего состоит тема компонента и как можно менять эту тему.
Из чего состоит тема компонента
Тема компонента (component's theme) определяет, как его можно стилизовать. Она состоит из следующих частей:
Слоты темы (slots).
Варианты (variants).
Составные варианты (compound variants).
Варианты по умолчанию (default variants).
Рассмотрим каждую из этих частей подробней.
Слоты темы (slots)
Начнём с того, что со слотами есть терминологическая путаница.
В терминологии фреймворка Vue уже есть понятие слот (slot), которое означает место в компоненте для встраивания контента из родительского компонента.
А в терминологии Tailwind Variants у понятия слот (slot) совсем другое значение. Это просто ключ в конфигурации компонента. И в коде компонента можно привязать атрибуты HTML-элемента к значению этого ключа. Обычно закрепляется атрибут «class», и таким образом через этот слот передаются Tailwind классы, которые будут применяться к данному HTML-элементу.
Чтобы уменьшить путаницу, мы будем называть слоты Vue просто «слотами», а слоты Tailwind Variants термином «слоты темы». Только помните, что в документации Nuxt UI и те, и другие слоты называются одинаково — slots.
Например, у компонента Card (Карточка) есть следующие слоты темы:
root — основа, т. е. родительский элемент на самом верхнем уровне.
header — хэдер карточки.
body — тело карточки.
footer — футер карточки.
И если мы откроем страницу компонента Card и пролистаем до раздела Theme (конфиг темы компонента), то там в первую очередь перечисляются слоты темы этого компонента. И для каждого из слотов темы описываются классы, которые по умолчанию назначены на него. Вот пример всё для того же компонента Card:
export default defineAppConfig({
ui: {
card: {
slots: {
root: 'rounded-lg overflow-hidden',
header: 'p-4 sm:px-6',
body: 'p-4 sm:p-6',
footer: 'p-4 sm:px-6'
}
}
}
})
А вот так уже выглядит template-часть кода компонента Card в упрощенном виде:
<template>
<div :class="ui.root({ class: [props.ui?.root, props.class] })">
<div :class="ui.header({ class: props.ui?.header })">
<slot name="header" />
</div>
<div :class="ui.body({ class: props.ui?.body })">
<slot />
</div>
<div :class="ui.footer({ class: props.ui?.footer })">
<slot name="footer" />
</div>
</div>
</template>
Видно, что за атрибутом class нужных HMTL-элементов закреплены конкретные ключи из темы компонента.
Причём, в данном примере идёт почти полное пересечение слотов и слотов темы. Но это просто так совпало для данного конкретного компонента Card. На практике такое пересечение не обязательно.
Почему привязка атрибута class происходит именно как :class="ui.header({ class: props.ui?.header })", а не просто :class="ui.header", станет понятно чуть позже.
Варианты (variants)
С вариантами (variants) тоже есть терминологическая путаница.
Как мы уже говорили, в терминологии вариантного подхода варианты это возможные варианты значений специальных пропсов, относящихся к стилизации. Например, пропс «size» (размер) и его варианты «xs», «sm», «md», «xl» и т. д.
При этом у многих компонентов (Button, Card и т. д.) есть пропс, который в терминологии Nuxt UI тоже называется «вариант» (variant). Это просто один из пропсов, который отвечает за стилизацию, такой же как color, size, orientation и остальные. Обычно под variant подразумевается общий визуальный стиль элемента, например: solid (сплошная заливка), outline (контурная обводка), soft (приглушённая заливка) и т. д.
Поэтому обозначим, что когда речь идет о пропсе, мы будем называть это «вариант стиля». А когда речь про вариант в терминологии вариантного подхода, то это будет просто «вариант».
В итоге, система вариантов работает просто: если к компоненту применяется определенный вариант, то к его слотам темы будут дополнительно применяться классы, которые указаны в конфигурации его темы.
Например, если мы посмотрим на тему компонента кнопки (Button), то у видим там следующие пропсы и варианты к ним: (для краткости, мы убрали некоторые варианты для size)
export default defineAppConfig({
ui: {
button: {
variants: {
fieldGroup: {
horizontal: 'not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none focus-visible:z-[1]',
vertical: 'not-only:first:rounded-b-none not-only:last:rounded-t-none not-last:not-first:rounded-none focus-visible:z-[1]'
},
color: {
primary: '',
secondary: '',
success: '',
info: '',
warning: '',
error: '',
neutral: ''
},
variant: {
solid: '',
outline: '',
soft: '',
subtle: '',
ghost: '',
link: ''
},
size: {
xs: {
base: 'px-2 py-1 text-xs gap-1',
leadingIcon: 'size-4',
leadingAvatarSize: '3xs',
trailingIcon: 'size-4'
},
sm: {
base: 'px-2.5 py-1.5 text-xs gap-1.5',
leadingIcon: 'size-4',
leadingAvatarSize: '3xs',
trailingIcon: 'size-4'
}
},
block: {
true: {
base: 'w-full justify-center',
trailingIcon: 'ms-auto'
}
},
square: {
true: ''
},
leading: {
true: ''
},
trailing: {
true: ''
},
loading: {
true: ''
},
active: {
true: {
base: ''
},
false: {
base: ''
}
}
}
}
}
})
Рассмотрим подробней, что есть в этом конфиге:
Для пропса fieldGroup есть два варианта, и они задают список классов Tailwind. При этом не указывается, к каким слотам темы надо применять эти классы. Если слоты темы не указаны, то классы применяются к родительскому слоту темы (base или root).
Для пропсов color, variant, square, leading и т. д. перечислены доступные варианты, но эти варианты не задают никакие классы — это пустые строки. В данном случае это так, потому что классы тут будут заданы через составные варианты (compound variants), о которых мы будем говорить далее.
А вот для пропса size в имеющихся вариантах уже указываются классы для нескольких конкретных слотов темы.
Составные варианты (compound variants)
Составные варианты — это варианты, которые срабатывают, когда вместе выполняются определенные простые варианты.
Рассмотрим на примере всё той же кнопки: (опять же, сильно сократим число возможных вариантов)
export default defineAppConfig({
ui: {
button: {
compoundVariants: [
{
color: 'primary',
variant: 'solid',
class: 'text-inverted bg-primary hover:bg-primary/75 active:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary'
},
{
color: 'primary',
variant: 'outline',
class: 'ring ring-inset ring-primary/50 text-primary hover:bg-primary/10 active:bg-primary/10 disabled:bg-transparent aria-disabled:bg-transparent dark:disabled:bg-transparent dark:aria-disabled:bg-transparent focus:outline-none focus-visible:ring-2 focus-visible:ring-primary'
},
{
color: 'neutral',
variant: 'solid',
class: 'text-inverted bg-inverted hover:bg-inverted/90 active:bg-inverted/90 disabled:bg-inverted aria-disabled:bg-inverted focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-inverted'
},
{
color: 'neutral',
variant: 'outline',
class: 'ring ring-inset ring-accented text-default bg-default hover:bg-elevated active:bg-elevated disabled:bg-default aria-disabled:bg-default focus:outline-none focus-visible:ring-2 focus-visible:ring-inverted'
},
{
size: 'xs',
square: true,
class: 'p-1'
},
{
size: 'sm',
square: true,
class: 'p-1.5'
},
{
loading: true,
leading: true,
class: {
leadingIcon: 'animate-spin'
}
},
{
loading: true,
leading: false,
trailing: true,
class: {
trailingIcon: 'animate-spin'
}
}
]
}
}
})
Можно заметить разные группы составных вариантов:
сочетание значений пропсов color и variant задаёт классы для всей кнопки (мы оставили в примере всего 4 таких сочетания, но на самом деле их 6 * 7 = 42 сочетания)
пропс square в значении
trueозначает квадратную кнопку, поэтому в таком случае задаются одинаковые внутренние отступы (p-*) со всех сторон. При этом величина внутренних отступов будет разная для разных размеров кнопки (size).если пропс loading в значении
true, а также пропс leading или trailing в значенииtrue, то слот темы trailingIcon получает классanimate-spin, т. е. заставляет иконку постоянно крутиться.
Варианты по умолчанию (default variants)
У компонента могут быть указаны варианты по умолчанию. Вот пример для компонента Button:
export default defineAppConfig({
ui: {
button: {
defaultVariants: {
color: 'primary',
variant: 'solid',
size: 'md'
}
}
}
})
Как поменять тему у компонента
Теперь посмотрим, как можно менять тему компонента. Это можно сделать глобально или локально.
Глобальная настройка
Если нужно, чтобы изменения применились ко всем экземплярам данного компонента, то тогда стоит менять тему через рантайм-конфиг app.config.ts.
Можно прописать свои значения для slots, variants, compoundVariants и defaultVariants как в тех примерах, что мы приводили выше.
Локальная настройка конкретного экземпляра
Если нужно поменять тему у конкретного экземпляра компонента, то это можно сделать через специальный пропс ui, который доступен у всех компонентов. Например, мы хотим сделать меньше внутренние отступы (p-*) у карточки на странице.
<template>
<UCard
:ui="{
header: 'p-2 sm:px-4',
body: 'p-2 sm:p-4',
footer: 'p-2 sm:px-4'
}"
>
<p>Some text</p>
</UCard>
</template>
Также, если нужно поменять классы только для основного слота темы компонента (base или root), то можно просто передать нужные классы в атрибут class.
Решение конфликтов
В результате получается, что есть несколько слоёв стилизации:
классы, которые применяются к компоненту по умолчанию,
глобальная кастомизация — через
app.config.ts,локальная кастомизация — у конкретных экземпляров компонентов.
Чтобы все эти классы правильно объединились без конфликтов и по приоритету, используется встроенная вспомогательная библиотека tailwind-merge.
❯ 11. Интеграции
Nuxt UI хорошо интегрируется со многими модулями и библиотеками из экосистемы Nuxt. Часть из них уже включены в Nuxt UI, а другие требуют дополнительной установки. Рассмотрим некоторые самые важные.
Иконки (Icons)
Nuxt UI включает в себя модуль @nuxt/icon, сразу готовый к использованию. Он позволяет легко добавлять иконки через библиотеку Iconify, которая содержит иконки из множества популярных опенсорсных наборов.
Отдельную иконку можно добавить через компонент UIcon, указав название иконки через пропс «name». Для указания иконок используется синтаксис i-{название набора}-{название иконки}. Например:
<UIcon name="i-lucide-lightbulb" />
В этом примере мы используем иконку «lightbulb» (лампочка) из коллекции иконок «lucide».
Во многих компонентах есть специальные пропсы для вставки иконок. Например, в кнопке:
<UButton icon="i-lucide-sun">Button</UButton>
Отметим, что Nuxt рекомендует устанавливать в проект каждую коллекцию иконок, которую вы используете. Например, для коллекции lucide установка через npm будет через команду npm install @iconify-json/lucide. В результате иконки будут размещены локально, вместе с другими файлами проекта, что надежней и быстрее, чем загрузка их из внешнего источника.
В Nuxt UI есть своя тема иконок на проекте — это несколько десятков иконок, которые используются в компонентах. Посмотреть полный список можно в документации.
По умолчанию Nuxt UI использует иконки из коллекции Lucide.

Перенастроить тему иконок можно в рантайм-конфиге app.config.ts, например:
export default defineAppConfig({
ui: {
icons: {
search: 'i-lucide-search',
stop: 'i-lucide-square',
success: 'i-lucide-circle-check',
warning: 'i-lucide-triangle-alert'
}
}
})
Шрифты (Fonts)
В Nuxt UI сразу включает в себя модуль @nuxt/fonts для легкого подключения шрифтов от популярных провайдеров (Google Fonts и т. д.).
Шрифты в Tailwind настраиваются в главном CSS-файле через директиву @theme и специальные переменные:
@theme {
--font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}
В примере выше используются значения по умолчанию — они взяты из документации Tailwind.
Дополнительно ничего делать не нужно: модуль @nuxt/fonts увидит данные шрифты и загрузит их при необходимости.
Цветовая тема (Color Mode)
В Nuxt UI также интегрирован модуль @nuxtjs/color-mode для удобной работы со светлой и темной темами на сайте.

Он обеспечивает автоматическое определение нужной цветовой темы, а также работу специальных компонентов:
ColorModeSwitch и ColorModeSelect чтобы переключаться между светлой и темной темой.
ColorModeAvatar и ColorModeImage, чтобы показывать разные изображения в зависимости от того, светлая или темная тема сейчас активна. В частности, это пригодится, если вы размещаете на сайте скриншоты какого-то сайта, сервиса, программы и т. д.
И напомним, что все семантические цвета в Nuxt UI сразу настроены так, что для светлой и для темной темы указываются свои CSS-переменные. Поэтому в зависимости от темы могут отличаться оттенки цветов или даже сами цвета.
А если необходимо явно указать, что конкретный класс должен применяться только в темной теме, используется приставка dark: — это стандартная возможность Tailwind. Подробней о том, как работает тёмная тема в Tailwind — в документации.
Мультиязычность (i18n)
Компоненты Nuxt UI сразу поддерживают более 50 языков, а также смену направления текста (LTR/RTL, т.е. слева-направо и справа-налево).
Вот так можно поменять язык компонентов на русский:
<script setup lang="ts">
import { ru } from '@nuxt/ui/locale'
</script>
<template>
<UApp :locale="ru">
<NuxtPage />
</UApp>
</template>
Посмотреть перевод на русский и другие языки можно в репозитории.
О том, как добавить свои переводы или настроит�� существующие, смотрите в документации.
Если же необходимо пойти дальше и сделать динамическое переключение между языками на сайте, то нужно подключить модуль Nuxt i18n. В обычных стартовых шаблонах Nuxt UI нет примеров проекта с подключенным i18n, но есть специальный шаблон для блогов Docus, в котором уже есть i18n.
Nuxt Content
Nuxt Content это модуль для Nuxt, созданный чтобы легко выводить на сайте контент, который хранится в форматах markdown, yml или json. Nuxt Content полезен, когда вы хотите добавить на сайте блог или раздел с документацией.

Nuxt UI тесно интегрируется с библиотекой Nuxt Content:
1. Компоненты для Nuxt Content
Выше в разделе про компоненты мы уже рассказывали, что Nuxt UI предоставляет специальные удобные компоненты для создания блога или документации: ContentNavigation, ContentSearch, ContentSearchButton, ContentSurround и ContentToc.
2. Типографика
Nuxt Content преобразует контент в markdown-разметке в специальные компоненты типографики. Например, обычные параграфы — в <ProseP>, заголовки — в <ProseH1> и т. д.
И Nuxt UI в свою очередь предоставляет стилизацию для этих компонентов типографики — с ними можно работать, как и с обычными компонентами Nuxt UI.
Подробней о том, как работать с компонентами типографики, мы рассмотрим в следующем разделе.
3. Утилита mapContentNavigation
Nuxt UI также добавляет утилиту mapContentNavigation, которая пригодится, чтобы создать правильный массив объектов навигации, например для компонента UBreadcrumb.
Настройка
Отметим, что для того, чтобы Nuxt UI корректно работал с Nuxt Content, важно явно указать для Tailwind путь до файлов с контентом. Это необходимо, чтобы Tailwind увидела все нужные ей классы в этих файлах.
Для этого нужно в главном CSS-файле через директиву @source указать путь до папки /content, например:
@source "../../../content/**/*";
❯ 12. Компоненты типографики
Фреймворк Nuxt предоставляет инструменты, чтобы создавать текстовый контент на сайтах, используя формат markdown.
Для этого есть специальный модуль Nuxt MDC. Но еще удобней использовать модуль Nuxt Content, который под капотом использует Nuxt MDC, но предоставляет дополнительные возможности. Мы не будем останавливаться подробно на том, как работают эти модули — вы можете это изучить по ссылкам выше.
В обоих случаях исходный markdown-контент будет преобразован в специальные компоненты типографики (prose components) — это обычные vue-компоненты, но предназначенные для вывода markdown-контента.
При этом есть как простые компоненты типографики, так и более сложные — MDC-компоненты. И для тех, и для других Nuxt UI предлагает инструменты для стилизации.
Рассмотрим, в чем особенности этих компонентов и как их использовать с Nuxt UI.
Простые компоненты типографики
Простые компоненты типографики предназначены для вывода обычного markdown-контента. Это текст, заголовки, списки, таблицы, изображения, iframe и код.
Каждому типу markdown-контента соответствует свой компонент, который начинается со слова Prose. И каждый такой компонент соответствует своему HTML-тэгу:
Абзац текста →
<ProseP>→<p># Heading→<ProseH1>→<h1>*bold**→<ProseStrong>→<strong>т.д.
Полный список можно посмотреть в документации модуля Nuxt MDC.
Преимущество использования таких промежуточных компонентов по сравнению с рендерингом сразу в html-тэги в том, что это позволяет добавлять дополнительные возможности в вывод контента. Например, заголовкам можно автоматически добавлять якорные ссылки, а блокам с кодом — кнопку для копирования.
Nuxt UI же добавляет стилизацию для этих компонентов типографики. Это значит, что они по умолчанию будут выдержаны в едином дизайне со всем сайтом, а их стили можно удобно настраивать из общей конфигурации в app.config.ts.
То, как можно стилизовать компоненты типографики, описывается в специальном разделе Typography документации. Это работает так же, как стилизация обычных компонентов Nuxt UI, которые мы рассматривали до этого.
Вот так например выглядит тема для компонента заголовка ProseH1:
export default defineAppConfig({
ui: {
prose: {
h1: {
slots: {
base: 'text-4xl text-highlighted font-bold mb-8 scroll-mt-[calc(45px+var(--ui-header-height))] lg:scroll-mt-(--ui-header-height)',
link: 'inline-flex items-center gap-2'
}
}
}
}
})
Обратите внимание, что конфигурация этих компонентов имеет дополнительный уровень вложенности prose.
Также можно использовать эти простые prose-компоненты напрямую на ваших обычных страницах, чтобы поддерживать единую стилистику для параграфов текста, заголовков, списков и остального типового контента.
MDC-компоненты типографики
Nuxt MDC также предоставляет собственный MDC-синтаксис, чтобы добавлять vue-компоненты прямо в markdown. В том числе можно использовать пропсы, атрибуты и слоты.
При этом просто использовать обычные компоненты библиотеки Nuxt UI для этого не получится — для вставки компонентов в markdown нужны их специальные MDC-версии. И библиотека Nuxt UI предоставляет несколько таких MDC-версии компонентов, например: Accordion, Badge, Callout, CardGroup, Tabs и т. д.
Например, вот так будет выглядеть MDC-версия компонента Card в markdown-файле:
::card{title="Startup" icon="i-lucide-users" color="primary" to="<https://nuxt.lemonsqueezy.com>" target="_blank"}
Best suited for small teams, startups and agencies with up to 5 developers.
::
Как и все остальные компоненты Nuxt UI, их можно стилизовать через app.config.ts. При этом, как и в случае с простыми компонентами типографики, они будут в категории prose.

❯ 13. Композаблы
Nuxt UI предоставляет несколько композиционных функций:
defineShortcuts — чтобы определять горячие клавиши сайта,
useOverlay — чтобы вручную контролировать оверлей (в компонентах Modal и Slideover),
useToast — чтобы показывать уведомления (компонент Toast).
❯ 14. ИИ-возможности
MCP (Model Context Protocol) это стандартный протокол, который позволяет AI-ассистентам (Claude Code, Cursor и т. д.) обращаться к внешним источникам информации и инструментам.
Nuxt UI предоставляет собственный MCP-сервер, который дает информацию о компонентах, исходном коде, примерах и другой полезной информации о Nuxt UI. Подробней — в документации.
Кроме этого, Nuxt UI предоставляет LLMs.txt — специальный файл со всей документацией в структурированном формате специально для LLM (больших языковых моделей).
Также напомним, что у самого фреймворка Nuxt тоже есть свой MCP-сервер и LLMs.txt.
❯ 15. Витрина проектов
Примеры некоторых реальных проектов, которые используют Nuxt UI, можно посмотреть в разделе Showcase (Витрина).

❯ Заключение
По итогу этого разбора давайте просуммируем плюсы Nuxt UI, о которых мы узнали:
Создана самими разработчиками Nuxt.
Написана на TypeScript.
Поддерживает как Nuxt, так и Vue.
Отвечает всем современным требованиям по доступности благодаря Reka UI.
Основана на сверхпопулярной CSS-библиотеке Tailwind.
Удобная конфигурация стилей через Tailwind Variants.
Наборы семантически заданных цветов.
Больше число продвинутых бесплатных компонентов.
Компоненты типографики.
Интеграция с модулями из экосистемы Nuxt: Content, MDC, i18n, Icons, Fonts, Color Mode.
Бесплатный Figma Kit (хоть и пока с проблемами).
Разнообразные бесплатные стартовые шаблоны.
Подробная документация.
Инструменты для разработки с помощью ИИ: MCP-сервер и LLMs.txt.
Финансовая поддержка от мирового хостинг-гиганта Vercel.
Справедливости ради, стоит выделить и причины, почему вам может не подойти Nuxt UI:
Nuxt UI не подойдет, если вам не нравится Tailwind.
Это библиотека в ее классическом понимании. Поэтому она не подойдет, если вам нужен copy-paste подход в духе shadcn.
Библиотека пока ещё не набрала популярность, особенно в среде обычных Vue-проектов, и поэтому её не так часто можно встретить на практике.
По сумме аргументов кажется, что у Nuxt UI в любом случае хорошие перспективы в своей нише. А как оно будет на самом деле, покажет время.
Надеемся, что наша статья пробудила у вас интерес к Nuxt UI и помогла разобраться, как начать работать с этой библиотекой.
Чтобы не пропустить следующую статью: https://t.me/nickneustroev_blog
Поделитесь своим опытом в комментариях и расскажите, какую UI-библиотеку вы используете при работе с Vue и Nuxt?
Новости, обзоры продуктов и конкурсы от команды Timeweb.Cloud — в нашем Telegram-канале ↩
Перед оплатой в разделе «Бонусы и промокоды» в панели управления активируйте промокод и получите кэшбэк на баланс.