Blade компоненты
Компоненты — переиспользуемые UI элементы. Все компоненты из views/components/ автоматически доступны через синтаксис <x-имя>.
Кнопка (button)
Типы кнопок
{{-- Основные типы --}}
<x-button type="accent">Accent (основная)</x-button>
<x-button type="primary">Primary</x-button>
<x-button type="success">Success</x-button>
<x-button type="error">Error / Danger</x-button>
<x-button type="warning">Warning</x-button>
{{-- Outline варианты --}}
<x-button type="outline-accent">Outline Accent</x-button>
<x-button type="outline-primary">Outline Primary</x-button>
<x-button type="outline-error">Outline Error</x-button>Размеры
<x-button size="tiny">Tiny</x-button>
<x-button size="small">Small</x-button>
<x-button size="medium">Medium (default)</x-button>
<x-button size="large">Large</x-button>Кнопка-ссылка
<x-button href="/profile">Перейти в профиль</x-button>
<x-button href="/external" target="_blank">Внешняя ссылка</x-button>Состояния
{{-- Disabled --}}
<x-button :disabled="true">Недоступна</x-button>
{{-- Submit формы --}}
<x-button :submit="true" type="accent">Отправить</x-button>
{{-- С индикатором загрузки --}}
<x-button :withLoading="true">Загрузка...</x-button>С иконкой
<x-button type="accent">
<x-icon path="ph.regular.check" />
Сохранить
</x-button>
<x-button type="error">
<x-icon path="ph.regular.trash" />
Удалить
</x-button>
{{-- Только иконка --}}
<x-button type="outline-primary" size="small">
<x-icon path="ph.regular.gear" />
</x-button>HTMX интеграция
{{-- Кнопка с HTMX навигацией --}}
<x-button href="/page" :swap="true" swapTarget="#main">
Загрузить
</x-button>Дополнительные атрибуты
<x-button
type="accent"
class="my-custom-class"
id="submit-btn"
data-action="submit"
onclick="handleClick()">
Кнопка
</x-button>Карточка (card)
Простая карточка
<x-card>
<p>Содержимое карточки</p>
</x-card>С заголовком
<x-card title="Заголовок">
<p>Содержимое</p>
</x-card>
<x-card title="Заголовок" subtitle="Подзаголовок">
<p>Содержимое</p>
</x-card>С кастомным header (через slot)
<x-card>
<x-slot:header>
<div class="flex-between">
<h5>Пользователи</h5>
<x-button size="small" type="accent">Добавить</x-button>
</div>
</x-slot:header>
<p>Список пользователей...</p>
</x-card>С footer
<x-card title="Форма">
<form>
<input type="text" class="input" placeholder="Имя">
</form>
<x-slot:footer>
<div class="flex-between">
<x-button type="outline-primary">Отмена</x-button>
<x-button type="accent" :submit="true">Сохранить</x-button>
</div>
</x-slot:footer>
</x-card>Модификаторы
{{-- Без padding --}}
<x-card :withoutPadding="true">
<img src="/image.jpg" style="width: 100%">
</x-card>
{{-- Кастомные классы --}}
<x-card
headerClass="bg-accent-100"
bodyClass="p-4"
class="shadow-lg">
...
</x-card>Алерт (alert)
Типы
<x-alert type="success">Операция выполнена успешно!</x-alert>
<x-alert type="error">Произошла ошибка</x-alert>
<x-alert type="warning">Внимание! Проверьте данные</x-alert>
<x-alert type="info">Информационное сообщение</x-alert>Опции
{{-- Без кнопки закрытия --}}
<x-alert type="info" :withClose="false">
Это сообщение нельзя закрыть
</x-alert>
{{-- Только бордер (без заливки) --}}
<x-alert type="success" :onlyBorders="true">
Алерт с бордером
</x-alert>
{{-- Кастомная иконка --}}
<x-alert type="info" icon="ph.regular.bell">
Уведомление
</x-alert>Сложный контент
<x-alert type="warning">
<strong>Важно!</strong>
<p>Ваша сессия скоро истечет.</p>
<x-button size="small" type="warning">Продлить</x-button>
</x-alert>Модальное окно (modal)
Базовое использование
{{-- Кнопка открытия --}}
<x-button data-modal-open="my-modal">Открыть модалку</x-button>
{{-- Модальное окно --}}
<x-modal id="my-modal" title="Заголовок">
<p>Содержимое модального окна</p>
</x-modal>С footer
<x-modal id="confirm-modal" title="Подтверждение">
<p>Вы уверены, что хотите удалить?</p>
<x-slot:footer>
<x-button type="outline-primary" data-modal-close="confirm-modal">
Отмена
</x-button>
<x-button type="error">
Удалить
</x-button>
</x-slot:footer>
</x-modal>Размеры
<x-modal id="small" title="Маленькая" size="sm">...</x-modal>
<x-modal id="default" title="Обычная">...</x-modal>
<x-modal id="large" title="Большая" size="lg">...</x-modal>
<x-modal id="xlarge" title="Очень большая" size="xl">...</x-modal>Ленивая загрузка контента
<x-modal
id="lazy-modal"
title="Данные"
loadUrl="/api/modal-content"
loadTarget="#modal-body">
<div id="modal-body">
<div class="skeleton" style="height: 200px;"></div>
</div>
</x-modal>Закрытие из JavaScript
// Открыть
openModal('my-modal');
// Закрыть
closeModal('my-modal');Иконки (icon)
Используются Phosphor Icons — https://phosphoricons.com/
Варианты
{{-- Regular (по умолчанию) --}}
<x-icon path="ph.regular.user" />
<x-icon path="ph.regular.gear" />
<x-icon path="ph.regular.bell" />
<x-icon path="ph.regular.check" />
<x-icon path="ph.regular.x" />
{{-- Bold --}}
<x-icon path="ph.bold.check-bold" />
<x-icon path="ph.bold.x-bold" />
{{-- Fill --}}
<x-icon path="ph.fill.star-fill" />
<x-icon path="ph.fill.heart-fill" />
{{-- Light --}}
<x-icon path="ph.light.user-light" />
{{-- Thin --}}
<x-icon path="ph.thin.house-thin" />
{{-- Duotone --}}
<x-icon path="ph.duotone.bell-duotone" />С параметрами
<x-icon
path="ph.regular.gear"
width="24"
height="24"
class="text-muted" />Font Awesome
<x-icon path="fa.solid.home" />
<x-icon path="fa.regular.envelope" />
<x-icon path="fa.brands.github" />Ссылка (link)
<x-link href="/page">Обычная ссылка</x-link>
<x-link href="/page" type="accent">Accent</x-link>
<x-link href="/page" type="primary">Primary</x-link>
<x-link href="/page" type="error">Error</x-link>
<x-link href="/page" type="success">Success</x-link>Формы
Field (обертка поля)
<x-forms.field>
<x-slot:label>
<x-forms.label for="email" :required="true">Email</x-forms.label>
</x-slot:label>
<input type="email" name="email" id="email" class="input">
</x-forms.field>Label
<x-forms.label for="name">Имя</x-forms.label>
<x-forms.label for="email" :required="true">Email</x-forms.label>Полная форма
<form method="POST" action="/submit">
@csrf
<x-forms.field>
<x-slot:label>
<x-forms.label for="name" :required="true">Имя</x-forms.label>
</x-slot:label>
<input type="text" name="name" id="name" class="input" required>
</x-forms.field>
<x-forms.field>
<x-slot:label>
<x-forms.label for="email" :required="true">Email</x-forms.label>
</x-slot:label>
<input type="email" name="email" id="email" class="input" required>
</x-forms.field>
<x-forms.field>
<x-slot:label>
<x-forms.label for="message">Сообщение</x-forms.label>
</x-slot:label>
<textarea name="message" id="message" class="input" rows="4"></textarea>
</x-forms.field>
<x-button type="accent" :submit="true">Отправить</x-button>
</form>Создание своего компонента
1. Создайте файл
views/components/stat-card.blade.php:
@props([
'title',
'value',
'icon' => null,
'change' => null,
'changeType' => 'neutral'
])
<div {{ $attributes->merge(['class' => 'stat-card']) }}>
@if ($icon)
<div class="stat-card__icon">
<x-icon :path="$icon" />
</div>
@endif
<div class="stat-card__content">
<span class="stat-card__title">{{ $title }}</span>
<span class="stat-card__value">{{ $value }}</span>
@if ($change)
<span class="stat-card__change stat-card__change--{{ $changeType }}">
{{ $change }}
</span>
@endif
</div>
</div>2. Добавьте стили
assets/sass/components/_stat-card.scss:
.stat-card {
display: flex;
gap: var(--space-md);
padding: var(--space-lg);
background: var(--secondary);
border-radius: var(--border1);
&__icon {
display: flex;
align-items: center;
justify-content: center;
width: 48px;
height: 48px;
background: var(--accent-100);
color: var(--accent);
border-radius: var(--border05);
}
&__title {
font-size: var(--small);
color: var(--text-muted);
}
&__value {
font-size: var(--h3);
font-weight: 700;
}
&__change {
font-size: var(--small);
&--positive { color: var(--success); }
&--negative { color: var(--error); }
&--neutral { color: var(--text-muted); }
}
}3. Используйте
<x-stat-card
title="Пользователи"
value="12,345"
icon="ph.regular.users"
change="+12%"
changeType="positive" />Переопределение стандартного компонента
Чтобы изменить стандартный компонент, создайте файл с тем же именем:
views/components/button.blade.php → заменит <x-button>
views/components/card.blade.php → заменит <x-card>
views/components/modal.blade.php → заменит <x-modal>Работа с атрибутами
$attributes
{{-- Слияние классов --}}
<div {{ $attributes->merge(['class' => 'my-class']) }}>
{{-- Исключение атрибутов --}}
<div {{ $attributes->except(['class']) }}>
{{-- Только определенные --}}
<div {{ $attributes->only(['id', 'class']) }}>
{{-- Проверка наличия --}}
@if ($attributes->has('disabled'))
...
@endif
{{-- Получение значения --}}
{{ $attributes->get('data-id', 'default') }}@class директива
<div @class([
'card',
'card--featured' => $featured,
'card--disabled' => $disabled,
])>Слоты
Именованные слоты
{{-- Компонент --}}
@props(['title'])
<div class="card">
@if (isset($header))
<div class="card-header">{{ $header }}</div>
@endif
<div class="card-body">{{ $slot }}</div>
@if (isset($footer))
<div class="card-footer">{{ $footer }}</div>
@endif
</div>{{-- Использование --}}
<x-card>
<x-slot:header>
<h5>Заголовок</h5>
</x-slot:header>
<p>Основной контент</p>
<x-slot:footer>
<x-button>Действие</x-button>
</x-slot:footer>
</x-card>