UIButton — универсальная кнопка
Компонент UIButton реализует единый стиль кнопок проекта на базе Tailwind CSS и class-variance-authority (CVA). Он
поддерживает шесть вариантов оформления, шесть типоразмеров (включая квадратный icon-only), несколько степеней
скругления, состояния loading/disabled, а также может рендериться как <button> или как ссылка <a>.
- Файл: app/components/ui/button/UIButton.vue
- Варианты/классы: app/components/ui/button/button.ts (buttonVariants)
Быстрый старт
<script setup lang="ts">
import UIButton from 'components/ui/button/Button.vue'
</script>
<template>
<UIButton variant="primary" size="md">Отправить</UIButton>
</template>
API
Props
| Prop | Type | По умолчанию |
|---|---|---|
variant | 'primary' · 'secondary' · 'neutral' · 'outline' · 'ghost' · 'destructive' | 'primary' |
size | 'xs' · 'sm' · 'md' · 'lg' · 'xl' · 'icon' | 'md' |
rounded | 'md' · 'lg' · 'full' | 'md' |
iconPlacement | 'left' · 'right' · 'only' · undefined | undefined |
as | 'button' · 'a' | 'button' |
href? | string · undefined | undefined |
target? | string · undefined | undefined |
rel? | string · undefined | undefined |
ariaLabel? | string | undefined |
loading? | boolean | false |
disabled? | boolean | false |
class? | string | undefined |
Emits
| Prop | Type | По умолчанию |
|---|---|---|
click | (ev: MouseEvent) | не срабатывает в состояниях loading/disabled |
Slots
| Prop | По умолчанию |
|---|---|
default | — текст/контент кнопки |
icon | слот для иконки; располагать слева/справа/только иконка управляется prop iconPlacement |
Поведение и доступность
loading и disabled переводят кнопку в неинтерактивное состояние:
- Для
<button>проставляется атрибут disabled - Для
<a>добавляется aria-disabled="true" и отключаются pointer-events; обработчик клика предотвращается - Режим
icon-only(iconPlacement='only') скрывает текст; обязательно задавайтеariaLabel, чтобы описать действие кнопки для скринридеров - Кнопка управляет фокус-кольцом через utility-классы focus-visible и проектные токены (см. ниже)
Стили и токены
Основа оформлена через CVA (buttonVariants) и токены, определённые в Tailwind CSS переменных.
- Базовые классы:
inline-flex items-center justify-center gap-2 whitespace-nowrap select-none font-medium transition-colorsfocus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 ring-offset-background
- Варианты (variant):
- primary
bg: var(--btn-default-bg-primary)text: var(--btn-default-text-primary)hover bg: var(--btn-hover-bg-primary)active bg: var(--btn-active-bg-primary)disabled bg: var(--btn-default-bg-disable)disabled text: var(--btn-default-text-disable)
- secondary
bg: var(--btn-default-bg-secondary)text: var(--btn-default-text-secondary)hover bg: var(--btn-hover-bg-secondary)active bg: var(--btn-active-bg-secondary)disabled bg/text: как выше (disable)
- neutral
bg: var(--btn-default-bg-neutral)text: text-foregroundhover bg: var(--btn-hover-bg-neutral)active bg: var(--btn-active-bg-neutral)disabled bg/text: disable-токены
- outline
border: var(--input)фон: прозрачный, текст: text-foregroundhover/active bg: var(--accent), текст: var(--accent-foreground)
- ghost
фон: прозрачный, текст: text-foregroundhover/active bg: var(--accent), текст: var(--accent-foreground)
- destructive
bg-destructive, text-primary-foregroundhover:bg-destructive/90, active:bg-destructive/80disabled: disable-токены
- primary
- Размеры (size):
xs: h-7 px-2.5 + типографика btn-ssm: h-8 px-3 + btn-smd: h-9 px-4 + btn-mlg: h-10 px-5 + btn-mxl: h-11 px-6 + btn-licon: h-9 w-9 p-0 (квадратная)
- Скругление (rounded):
md: rounded-var(--elements-radius-m)lg: rounded-var(--elements-radius-l)full: rounded-full
- Фокус-кольцо:
- focus-visible:ring-ring
- focus-visible:ring-offset-2
- ring-offset-background
- Прочие состояния:
disabled: cursor-not-allowed opacity-50
Примечание: значения var(...) должны быть определены в app/assets/css/tailwind.css (ваши дизайн-токены). Токены вроде bg-destructive, text-foreground, accent/foreground предоставляются слоем Tailwind переменных и shadcn-настройками.
Примеры
Варианты (variant)
Размеры (size)
Скругление (rounded)
Иконка слева/справа/только иконка (iconPlacement)
Состояния loading/disabled
Ссылочный режим (as='a')
Кастомная ширина и utility-классы
Внутренние детали реализации
- Рендер через динамический тег (
<button>или<a>) управляется пропомas - При неинтерактивных состояниях клики предотвращаются внутри
onClick;для ссылок добавляетсяpointer-events-noneиaria-disabled - Спиннер загрузки —
<Icon name="lucide:loader-2" class="h-4 w-4 animate-spin" />; он позиционируется поверх контента благодаря relative-позиционированию корневого inline-flex (см. scoped-стили в компоненте) - Классы собираются через утилиту
cn(...)и CVA-функциюbuttonVariants
Советы по настройке темизации
- Меняйте значения
var(--btn-... )и системных токенов(--accent, --input, --elements-radius-*)в app/assets/css/tailwind.css - Для продвинутых кейсов можно расширить button.ts: добавить новые
variant/size/roundedв cva и экспортировать типы изButtonVariantProps - Если нужно переопределять спиннер или добавить иконку во время загрузки — можно расширить компонент слотом под
loaderили условным скрытием внутреннегоIcon