Card Components
Container components for organizing content with headers, footers, and skeleton loading states.
Card Components
Card components provide structured containers for organizing content. They support headers, footers, descriptions, and loading skeleton states for a polished user experience.
Available Card Components
| Component | Purpose |
|---|---|
<x-card.card> |
Main content container with slots |
<x-card.card-skeleton> |
Loading placeholder for cards |
<x-dashboard-collapsible-card> |
Collapsible dashboard card |
<x-collapsible-section> |
Collapsible content section |
Card Component
The primary card component with flexible header, body, and footer sections.
Slots
| Slot | Description |
|---|---|
header |
Card header content |
headerRight |
Right-aligned header content |
headerDescription |
Descriptive text below header |
default |
Main card body content |
footer |
Card footer content |
Variables
| Variable | Type | Default | Description |
|---|---|---|---|
$class |
string | '' |
Additional CSS classes for container |
$skeleton |
boolean | false |
Show skeleton loading state |
$headerClass |
string | '' |
Additional classes for header |
$headerTitleClass |
string | '' |
Classes for header title area |
$headerRightClass |
string | '' |
Classes for right header area |
$headerDescriptionClass |
string | '' |
Classes for description |
$bodyClass |
string | '' |
Additional classes for body |
$footerClass |
string | '' |
Additional classes for footer |
Basic Usage
<x-card.card>
<p>Simple card content goes here.</p>
</x-card.card>
With Header
<x-card.card>
<x-slot name="header">Card Title</x-slot>
<p>Card content with a header.</p>
</x-card.card>
With Header and Footer
<x-card.card>
<x-slot name="header">User Settings</x-slot>
<div class="space-y-4">
<x-inputs.input label="Name" name="name" />
<x-inputs.input label="Email" name="email" type="email" />
</div>
<x-slot name="footer">
<x-buttons.button variant="secondary">Cancel</x-buttons.button>
<x-buttons.button variant="primary">Save Changes</x-buttons.button>
</x-slot>
</x-card.card>
With Header Right Content
<x-card.card>
<x-slot name="header">Recent Orders</x-slot>
<x-slot name="headerRight">
<x-buttons.button as="a" href="/orders" variant="secondary" icon="lucide:external-link">
View All
</x-buttons.button>
</x-slot>
{{-- Orders table --}}
<table class="w-full">
...
</table>
</x-card.card>
With Header Description
<x-card.card>
<x-slot name="header">API Settings</x-slot>
<x-slot name="headerDescription">
Configure your API keys and webhook endpoints.
</x-slot>
<div class="space-y-4">
<x-inputs.input
label="API Key"
name="api_key"
:value="$apiKey"
disabled
/>
</div>
</x-card.card>
With Loading Skeleton
{{-- Shows skeleton while loading --}}
<x-card.card :skeleton="$isLoading">
<x-slot name="header">User Profile</x-slot>
@if(!$isLoading)
<p>{{ $user->name }}</p>
<p>{{ $user->email }}</p>
@endif
</x-card.card>
Custom Classes
<x-card.card
class="bg-primary/5"
headerClass="bg-primary text-white"
bodyClass="p-8"
footerClass="justify-end"
>
<x-slot name="header">Custom Styled Card</x-slot>
<p>Content with custom styling.</p>
<x-slot name="footer">
<x-buttons.button variant="primary">Action</x-buttons.button>
</x-slot>
</x-card.card>
Real Examples from Codebase
{{-- Settings page card --}}
<x-card.card>
<x-slot name="header">{{ __('General Settings') }}</x-slot>
<x-slot name="headerDescription">
{{ __('Configure your application settings.') }}
</x-slot>
<form wire:submit="save">
<div class="space-y-4">
<x-inputs.input
label="{{ __('Site Name') }}"
name="site_name"
wire:model="site_name"
/>
<x-inputs.textarea
label="{{ __('Site Description') }}"
name="site_description"
wire:model="site_description"
/>
</div>
<x-slot name="footer">
<x-buttons.button type="submit" variant="primary" loadingTarget="save">
{{ __('Save Settings') }}
</x-buttons.button>
</x-slot>
</form>
</x-card.card>
{{-- User profile card --}}
<x-card.card>
<x-slot name="header">{{ __('Profile Information') }}</x-slot>
<x-slot name="headerRight">
<span class="text-sm text-gray-500">
{{ __('Last updated') }}: {{ $user->updated_at->diffForHumans() }}
</span>
</x-slot>
<div class="flex items-center gap-4">
<img src="{{ $user->avatar_url }}" class="w-16 h-16 rounded-full" />
<div>
<h3 class="font-medium">{{ $user->name }}</h3>
<p class="text-sm text-gray-500">{{ $user->email }}</p>
</div>
</div>
</x-card.card>
Card Skeleton Component
Loading placeholder that mimics card content while data loads.
Basic Usage
{{-- Standalone skeleton --}}
<x-card.card-skeleton />
In Card Context
The card component automatically shows the skeleton when skeleton is true:
<x-card.card :skeleton="!$dataLoaded">
{{-- Content appears after loading --}}
</x-card.card>
Custom Skeleton Layout
<div class="rounded-md border border-gray-200 dark:border-gray-800 p-4">
<div class="animate-pulse space-y-4">
{{-- Header skeleton --}}
<div class="h-4 bg-gray-200 dark:bg-gray-700 rounded w-1/3"></div>
{{-- Content lines --}}
<div class="space-y-2">
<div class="h-3 bg-gray-200 dark:bg-gray-700 rounded w-full"></div>
<div class="h-3 bg-gray-200 dark:bg-gray-700 rounded w-5/6"></div>
<div class="h-3 bg-gray-200 dark:bg-gray-700 rounded w-4/6"></div>
</div>
</div>
</div>
Dashboard Collapsible Card
Specialized card for dashboard widgets that can be collapsed/expanded.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
title |
string | required | Card title |
collapsed |
boolean | false |
Initial collapsed state |
icon |
string | null |
Header icon |
Basic Usage
<x-dashboard-collapsible-card title="Recent Activity">
<ul class="space-y-2">
@foreach($activities as $activity)
<li>{{ $activity->description }}</li>
@endforeach
</ul>
</x-dashboard-collapsible-card>
Initially Collapsed
<x-dashboard-collapsible-card
title="Advanced Options"
:collapsed="true"
icon="lucide:settings"
>
<p>Advanced configuration options...</p>
</x-dashboard-collapsible-card>
Collapsible Section
A general-purpose collapsible content section.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
title |
string | required | Section title |
open |
boolean | false |
Initial open state |
icon |
string | null |
Title icon |
Basic Usage
<x-collapsible-section title="Additional Information">
<p>This content can be collapsed and expanded.</p>
</x-collapsible-section>
Initially Open
<x-collapsible-section title="FAQ" :open="true">
<div class="space-y-4">
<div>
<h4 class="font-medium">Question 1?</h4>
<p class="text-gray-600">Answer 1.</p>
</div>
<div>
<h4 class="font-medium">Question 2?</h4>
<p class="text-gray-600">Answer 2.</p>
</div>
</div>
</x-collapsible-section>
Multiple Sections
<div class="space-y-4">
<x-collapsible-section title="Personal Information" :open="true">
<x-inputs.input label="Name" name="name" />
<x-inputs.input label="Email" name="email" />
</x-collapsible-section>
<x-collapsible-section title="Address">
<x-inputs.input label="Street" name="street" />
<x-inputs.input label="City" name="city" />
</x-collapsible-section>
<x-collapsible-section title="Preferences">
<x-inputs.checkbox label="Newsletter" name="newsletter" />
</x-collapsible-section>
</div>
Card Layouts
Grid of Cards
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<x-card.card>
<x-slot name="header">Card 1</x-slot>
<p>Content for card 1.</p>
</x-card.card>
<x-card.card>
<x-slot name="header">Card 2</x-slot>
<p>Content for card 2.</p>
</x-card.card>
<x-card.card>
<x-slot name="header">Card 3</x-slot>
<p>Content for card 3.</p>
</x-card.card>
</div>
Stacked Cards
<div class="space-y-6">
<x-card.card>
<x-slot name="header">Section 1</x-slot>
<p>First section content.</p>
</x-card.card>
<x-card.card>
<x-slot name="header">Section 2</x-slot>
<p>Second section content.</p>
</x-card.card>
</div>
Card with Stats
<x-card.card>
<x-slot name="header">Statistics</x-slot>
<div class="grid grid-cols-3 gap-4 text-center">
<div>
<p class="text-3xl font-bold text-primary">{{ $totalUsers }}</p>
<p class="text-sm text-gray-500">{{ __('Total Users') }}</p>
</div>
<div>
<p class="text-3xl font-bold text-success">{{ $activeUsers }}</p>
<p class="text-sm text-gray-500">{{ __('Active') }}</p>
</div>
<div>
<p class="text-3xl font-bold text-warning">{{ $pendingUsers }}</p>
<p class="text-sm text-gray-500">{{ __('Pending') }}</p>
</div>
</div>
</x-card.card>
Best Practices
- Use headers for context - Always include a header for non-trivial cards
- Group related actions in footer - Place buttons and actions in the footer slot
- Show loading states - Use skeleton when fetching data
- Keep cards focused - One card should serve one purpose
- Use consistent spacing - Apply
space-y-4or similar for internal content - Consider collapsible for long content - Use collapsible cards for optional/advanced sections