Skip to Content
TemplatesBlade Components

Blade Components

Components are reusable UI elements. All components from views/components/ are automatically available via the <x-name> syntax.

Button

Button Types

{{-- Basic types --}} <x-button type="accent">Accent (main)</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 variants --}} <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>

Sizes

<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">Go to Profile</x-button> <x-button href="/external" target="_blank">External Link</x-button>

States

{{-- Disabled --}} <x-button :disabled="true">Disabled</x-button> {{-- Form Submit --}} <x-button :submit="true" type="accent">Submit</x-button> {{-- With loading indicator --}} <x-button :withLoading="true">Loading...</x-button>

With Icon

<x-button type="accent"> <x-icon path="ph.regular.check" /> Save </x-button> <x-button type="error"> <x-icon path="ph.regular.trash" /> Delete </x-button> {{-- Icon only --}} <x-button type="outline-primary" size="small"> <x-icon path="ph.regular.gear" /> </x-button>

HTMX Integration

{{-- Button with HTMX navigation --}} <x-button href="/page" :swap="true" swapTarget="#main"> Load </x-button>

Additional Attributes

<x-button type="accent" class="my-custom-class" id="submit-btn" data-action="submit" onclick="handleClick()"> Button </x-button>

Card

Simple Card

<x-card> <p>Card content</p> </x-card>

With Title

<x-card title="Title"> <p>Content</p> </x-card> <x-card title="Title" subtitle="Subtitle"> <p>Content</p> </x-card>

With Custom Header (via slot)

<x-card> <x-slot:header> <div class="flex-between"> <h5>Users</h5> <x-button size="small" type="accent">Add</x-button> </div> </x-slot:header> <p>List of users...</p> </x-card>
<x-card title="Form"> <form> <input type="text" class="input" placeholder="Name"> </form> <x-slot:footer> <div class="flex-between"> <x-button type="outline-primary">Cancel</x-button> <x-button type="accent" :submit="true">Save</x-button> </div> </x-slot:footer> </x-card>

Modifiers

{{-- Without padding --}} <x-card :withoutPadding="true"> <img src="/image.jpg" style="width: 100%"> </x-card> {{-- Custom classes --}} <x-card headerClass="bg-accent-100" bodyClass="p-4" class="shadow-lg"> ... </x-card>

Alert

Types

<x-alert type="success">Operation completed successfully!</x-alert> <x-alert type="error">An error occurred</x-alert> <x-alert type="warning">Warning! Check data</x-alert> <x-alert type="info">Information message</x-alert>

Options

{{-- Without close button --}} <x-alert type="info" :withClose="false"> This message cannot be closed </x-alert> {{-- Borders only (no fill) --}} <x-alert type="success" :onlyBorders="true"> Alert with border </x-alert> {{-- Custom icon --}} <x-alert type="info" icon="ph.regular.bell"> Notification </x-alert>

Complex Content

<x-alert type="warning"> <strong>Important!</strong> <p>Your session will expire soon.</p> <x-button size="small" type="warning">Extend</x-button> </x-alert>

Basic Usage

{{-- Open button --}} <x-button data-modal-open="my-modal">Open Modal</x-button> {{-- Modal window --}} <x-modal id="my-modal" title="Title"> <p>Modal content</p> </x-modal>
<x-modal id="confirm-modal" title="Confirmation"> <p>Are you sure you want to delete?</p> <x-slot:footer> <x-button type="outline-primary" data-modal-close="confirm-modal"> Cancel </x-button> <x-button type="error"> Delete </x-button> </x-slot:footer> </x-modal>

Sizes

<x-modal id="small" title="Small" size="sm">...</x-modal> <x-modal id="default" title="Normal">...</x-modal> <x-modal id="large" title="Large" size="lg">...</x-modal> <x-modal id="xlarge" title="Extra Large" size="xl">...</x-modal>

Lazy Content Loading

<x-modal id="lazy-modal" title="Data" loadUrl="/api/modal-content" loadTarget="#modal-body"> <div id="modal-body"> <div class="skeleton" style="height: 200px;"></div> </div> </x-modal>

Closing via JavaScript

// Open openModal('my-modal'); // Close closeModal('my-modal');

Icons

Uses Phosphor Icons — https://phosphoricons.com/ 

Variants

{{-- Regular (default) --}} <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" />

With Parameters

<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" />

<x-link href="/page">Regular link</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>

Forms

Field (field wrapper)

<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">Name</x-forms.label> <x-forms.label for="email" :required="true">Email</x-forms.label>

Complete Form

<form method="POST" action="/submit"> @csrf <x-forms.field> <x-slot:label> <x-forms.label for="name" :required="true">Name</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">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">Send</x-button> </form>

Creating Your Own Component

1. Create a File

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. Add Styles

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. Use It

<x-stat-card title="Users" value="12,345" icon="ph.regular.users" change="+12%" changeType="positive" />

Overriding Standard Component

To change a standard component, create a file with the same name:

views/components/button.blade.php → replaces <x-button> views/components/card.blade.php → replaces <x-card> views/components/modal.blade.php → replaces <x-modal>

Working with Attributes

$attributes

{{-- Merge classes --}} <div {{ $attributes->merge(['class' => 'my-class']) }}> {{-- Exclude attributes --}} <div {{ $attributes->except(['class']) }}> {{-- Only specific attributes --}} <div {{ $attributes->only(['id', 'class']) }}> {{-- Check for existence --}} @if ($attributes->has('disabled')) ... @endif {{-- Get value --}} {{ $attributes->get('data-id', 'default') }}

@class directive

<div @class([ 'card', 'card--featured' => $featured, 'card--disabled' => $disabled, ])>

Slots

Named Slots

{{-- Component --}} @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>
{{-- Usage --}} <x-card> <x-slot:header> <h5>Title</h5> </x-slot:header> <p>Main content</p> <x-slot:footer> <x-button>Action</x-button> </x-slot:footer> </x-card>