Livewire UI Components - v1.0-beta2
Calendar Component
The Calendar component provides a flexible and customizable calendar display for your application. It features a responsive design with support for different views (day, week, month, year), color schemes, event display, and localization.
Basic Usage
<x-calendar />
Examples
Basic Calendar
<x-calendar />
Calendar with Primary Color Scheme
<x-calendar color-scheme="primary" />
Calendar with Secondary Color Scheme
<x-calendar color-scheme="secondary" />
Calendar with Accent Color Scheme
<x-calendar color-scheme="accent" />
Calendar with Custom Color
<x-calendar color-scheme="custom" custom-color="#8A2BE2" />
Different Calendar Views
<!-- Day View -->
<x-calendar view="day" />
<!-- Week View -->
<x-calendar view="week" />
<!-- Month View (default) -->
<x-calendar view="month" />
<!-- Year View -->
<x-calendar view="year" />
Multiple Month Calendar
<x-calendar :months="3" />
Calendar with Weekend Highlighting
<x-calendar :weekendHighlight="true" />
Calendar with Sunday as First Day of Week
<x-calendar :sundayStart="true" />
Calendar with Custom Locale
<x-calendar locale="fr-FR" />
Calendar with Events
@php
$events = [
[
'id' => 'meeting-1',
'date' => '2025-07-20',
'label' => 'Team Meeting',
'title' => 'Quarterly planning session',
'description' => 'Discuss Q3 goals and initiatives',
'start_time' => '10:00',
'end_time' => '11:30',
'colorScheme' => 'primary',
],
[
'id' => 'conference-1',
'range' => ['2025-07-25', '2025-07-27'],
'label' => 'Conference',
'title' => 'Annual industry conference',
'description' => 'Networking and learning opportunities',
'start_time' => '09:00',
'end_time' => '17:00',
'colorScheme' => 'accent',
],
[
'id' => 'custom-event',
'date' => '2025-07-15',
'label' => 'Custom Event',
'title' => 'Event with custom color',
'description' => 'This event uses a custom color',
'colorScheme' => 'custom',
'customColor' => '#FF5733',
]
];
@endphp
<x-calendar :events="$events" />
Calendar with Custom Event Modal
<x-calendar :events="$events">
<x-slot:eventModalContent>
{{--
You have access to the $selectedEvent variable here.
You can use it to display any event data.
--}}
<div>
<h3 class="text-2xl font-bold text-dark dark:text-white">{{ $selectedEvent['title'] }}</h3>
@if(!empty($selectedEvent['description']))
<p class="mt-4 mb-4 text-base-content">{{ $selectedEvent['description'] }}</p>
@endif
{{-- Custom fields and layout --}}
<div class="bg-gray-100 dark:bg-base-300 p-4 rounded-lg mt-4">
<p class="text-sm text-base-content">
<span class="font-semibold">Location:</span>
{{ $selectedEvent['location'] ?? 'No location specified' }}
</p>
<p class="text-sm text-base-content mt-2">
<span class="font-semibold">Organizer:</span>
{{ $selectedEvent['organizer'] ?? 'No organizer specified' }}
</p>
</div>
{{-- You can even add forms or buttons for event actions --}}
<div class="mt-6 flex space-x-3">
<button class="btn btn-primary">Edit Event</button>
<button class="btn btn-outline btn-error">Delete Event</button>
</div>
</div>
</x-slot:eventModalContent>
</x-calendar>
Calendar with Custom Configuration
@php
$config = [
'settings' => [
'selected' => [
'dates' => ['2025-07-10']
],
'visibility' => [
'theme' => 'light'
]
]
];
@endphp
<x-calendar :config="$config" />
Props
| Prop | Type | Default | Description |
|---|---|---|---|
id |
string|null | null |
Optional ID for the calendar element |
months |
int|null | 1 |
Number of months to display |
locale |
string|null | 'en-EN' |
Locale for the calendar |
weekendHighlight |
boolean|null | false |
Whether to highlight weekends |
sundayStart |
boolean|null | false |
Whether the week starts on Sunday |
colorScheme |
string|null | 'primary' |
Color scheme for the calendar (primary, secondary, accent, custom) |
customColor |
string|null | null |
Hex color code for custom color scheme |
view |
string|null | 'month' |
Calendar view (day, week, month, year) |
config |
array|null | [] |
Additional configuration options |
events |
array|null | [] |
Array of events to display on the calendar |
Event Format
Events can be specified in two formats:
Single Date Event
[
'id' => 'event-1', // Unique identifier for the event
'date' => '2025-07-15', // Date in Y-m-d format
'label' => 'Meeting', // Event label (displayed on calendar)
'title' => 'Team planning meeting', // Event title (displayed in popup)
'description' => 'Meeting details', // Event description (displayed in popup)
'start_time' => '14:00', // Optional start time
'end_time' => '15:30', // Optional end time
'colorScheme' => 'primary', // Color scheme (primary, secondary, accent, custom)
'customColor' => '#FF5733', // Custom color (when colorScheme is 'custom')
'css' => 'custom-class' // Optional additional CSS classes
]
Date Range Event
[
'id' => 'event-2', // Unique identifier for the event
'range' => ['2025-07-20', '2025-07-25'], // Start and end dates
'label' => 'Conference', // Event label (displayed on calendar)
'title' => 'Annual conference', // Event title (displayed in popup)
'description' => 'Conference details', // Event description (displayed in popup)
'start_time' => '09:00', // Optional start time
'end_time' => '17:00', // Optional end time
'colorScheme' => 'accent', // Color scheme (primary, secondary, accent, custom)
'customColor' => null, // Custom color (when colorScheme is 'custom')
'css' => 'custom-class' // Optional additional CSS classes
]
Customizing the Event Modal
The Calendar component provides two ways to customize the event modal that appears when a user clicks on an event:
- Using the
eventModalContentslot for simple customizations - Creating a custom Livewire component for more complex customizations
Method 1: Using the Event Modal Slot
For simple customizations, you can use the eventModalContent slot:
<x-calendar :events="$events">
<x-slot:eventModalContent>
{{-- Your custom modal content here --}}
</x-slot:eventModalContent>
</x-calendar>
Within the eventModalContent slot, you have access to the $selectedEvent variable, which contains all the data for the currently selected event:
<x-slot:eventModalContent>
<div>
<h3 class="text-2xl font-bold">{{ $selectedEvent['title'] }}</h3>
<p class="mt-4">{{ $selectedEvent['description'] }}</p>
{{-- Access any custom fields you've added to your events --}}
@if(isset($selectedEvent['location']))
<p class="mt-2"><strong>Location:</strong> {{ $selectedEvent['location'] }}</p>
@endif
</div>
</x-slot:eventModalContent>
Method 2: Creating a Custom Livewire Component
For more complex customizations, you can create a custom Livewire component that replaces the default EventModalContent component. This approach gives you more flexibility and allows you to add custom logic, methods, and properties.
Step 1: Create a Custom Livewire Component
Create a new Livewire component that will handle the event modal content:
<?php
namespace App\Livewire;
use Livewire\Component;
use Livewire\Attributes\On;
use Illuminate\View\View;
class CustomEventModal extends Component
{
public ?array $event = null;
// You can add additional properties here
public bool $isEditing = false;
public array $editableEvent = [];
#[On('loadEventModal')]
public function loadEvent(array $selectedEvent): void
{
$this->event = $selectedEvent;
$this->resetState();
}
// You can add additional methods here
public function resetState(): void
{
$this->isEditing = false;
$this->editableEvent = [];
}
public function startEditing(): void
{
$this->isEditing = true;
$this->editableEvent = $this->event;
}
public function saveChanges(): void
{
// Handle saving changes to the event
$this->isEditing = false;
// Emit an event to update the calendar
$this->dispatch('eventUpdated', event: $this->editableEvent);
}
public function render(): View
{
return view('livewire.custom-event-modal');
}
}
Step 2: Create a Blade Template for Your Component
Create a corresponding Blade template for your custom component:
{{-- resources/views/livewire/custom-event-modal.blade.php --}}
<div>
@if ($event)
<div>
@if ($isEditing)
{{-- Edit Mode --}}
<form wire:submit.prevent="saveChanges">
<div class="mb-4">
<label class="block text-sm font-medium mb-1">Title</label>
<input type="text" wire:model="editableEvent.title" class="w-full rounded-md border-gray-300 dark:border-gray-700 dark:bg-gray-800">
</div>
<div class="mb-4">
<label class="block text-sm font-medium mb-1">Description</label>
<textarea wire:model="editableEvent.description" class="w-full rounded-md border-gray-300 dark:border-gray-700 dark:bg-gray-800" rows="3"></textarea>
</div>
<div class="mb-4">
<label class="block text-sm font-medium mb-1">Location</label>
<input type="text" wire:model="editableEvent.location" class="w-full rounded-md border-gray-300 dark:border-gray-700 dark:bg-gray-800">
</div>
<div class="flex space-x-3 mt-6">
<button type="submit" class="btn btn-primary">Save Changes</button>
<button type="button" wire:click="resetState" class="btn btn-outline">Cancel</button>
</div>
</form>
@else
{{-- View Mode --}}
<h3 class="text-2xl font-bold text-dark dark:text-white">{{ $event['title'] ?? $event['label'] }}</h3>
@if (!empty($event['description']))
<p class="mt-4 mb-4 text-base-content">{{ $event['description'] }}</p>
@endif
<div class="bg-gray-100 dark:bg-base-300 p-4 rounded-lg mt-4">
<div class="flex items-center space-x-2 text-base-content mb-2">
<span class="font-semibold">Date:</span>
@if (isset($event['range']))
<span>{{ $event['start_date'] }} - {{ $event['end_date'] }}</span>
@else
<span>{{ date('j M Y', strtotime($event['date'])) }}</span>
@endif
</div>
<div class="flex items-center space-x-2 text-base-content mb-2">
<span class="font-semibold">Time:</span>
@if (!empty($event['start_time']))
<span>{{ $event['start_time'] }}@if (!empty($event['end_time'])) - {{ $event['end_time'] }}@endif</span>
@else
<span>All day</span>
@endif
</div>
<div class="flex items-center space-x-2 text-base-content">
<span class="font-semibold">Location:</span>
<span>{{ $event['location'] ?? 'No location specified' }}</span>
</div>
</div>
<div class="mt-6 flex space-x-3">
<button wire:click="startEditing" class="btn btn-primary">Edit Event</button>
<button class="btn btn-outline btn-error">Delete Event</button>
</div>
@endif
</div>
@endif
</div>
Step 3: Use Your Custom Component with the Calendar
Pass your custom component's name to the Calendar component using the eventView parameter:
<x-calendar
:events="$events"
eventView="custom-event-modal"
/>
Example: Custom Event Modal with Tabs
Here's an example of a more complex custom event modal with tabs:
<x-calendar :events="$events">
<x-slot:eventModalContent>
<div x-data="{ activeTab: 'details' }">
{{-- Tabs --}}
<div class="border-b border-gray-200 dark:border-gray-700">
<nav class="flex space-x-8" aria-label="Tabs">
<button
@click="activeTab = 'details'"
:class="{ 'border-primary text-primary': activeTab === 'details', 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300': activeTab !== 'details' }"
class="py-4 px-1 border-b-2 font-medium text-sm"
>
Details
</button>
<button
@click="activeTab = 'attendees'"
:class="{ 'border-primary text-primary': activeTab === 'attendees', 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300': activeTab !== 'attendees' }"
class="py-4 px-1 border-b-2 font-medium text-sm"
>
Attendees
</button>
<button
@click="activeTab = 'actions'"
:class="{ 'border-primary text-primary': activeTab === 'actions', 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300': activeTab !== 'actions' }"
class="py-4 px-1 border-b-2 font-medium text-sm"
>
Actions
</button>
</nav>
</div>
{{-- Tab Content --}}
<div class="mt-4">
{{-- Details Tab --}}
<div x-show="activeTab === 'details'">
<h3 class="text-2xl font-bold">{{ $selectedEvent['title'] }}</h3>
<p class="mt-4">{{ $selectedEvent['description'] }}</p>
<div class="mt-4 grid grid-cols-2 gap-4">
<div>
<h4 class="font-semibold">Date & Time</h4>
<p>{{ $selectedEvent['start_date'] ?? date('j M', strtotime($selectedEvent['date'])) }}</p>
<p>{{ $selectedEvent['start_time'] ?? 'All day' }}</p>
</div>
<div>
<h4 class="font-semibold">Location</h4>
<p>{{ $selectedEvent['location'] ?? 'No location specified' }}</p>
</div>
</div>
</div>
{{-- Attendees Tab --}}
<div x-show="activeTab === 'attendees'">
<h3 class="text-xl font-semibold mb-4">Attendees</h3>
@if(isset($selectedEvent['attendees']) && count($selectedEvent['attendees']) > 0)
<ul class="divide-y divide-gray-200 dark:divide-gray-700">
@foreach($selectedEvent['attendees'] as $attendee)
<li class="py-3 flex items-center">
<div class="w-8 h-8 rounded-full bg-primary text-white flex items-center justify-center mr-3">
{{ substr($attendee['name'], 0, 1) }}
</div>
<div>
<p class="font-medium">{{ $attendee['name'] }}</p>
<p class="text-sm text-gray-500">{{ $attendee['email'] }}</p>
</div>
</li>
@endforeach
</ul>
@else
<p class="text-gray-500">No attendees for this event</p>
@endif
</div>
{{-- Actions Tab --}}
<div x-show="activeTab === 'actions'">
<h3 class="text-xl font-semibold mb-4">Event Actions</h3>
<div class="space-y-3">
<button class="btn btn-primary w-full">Edit Event</button>
<button class="btn btn-outline w-full">Duplicate Event</button>
<button class="btn btn-outline btn-error w-full">Delete Event</button>
</div>
</div>
</div>
</div>
</x-slot:eventModalContent>
</x-calendar>
Understanding the EventModalContent Component
The default EventModalContent component is a Livewire component that displays event details in the calendar modal. It:
- Listens for the
loadEventModalevent dispatched by the Calendar component - Receives the selected event data and stores it in the
$eventproperty - Renders a view that displays the event details
When you create a custom component, you need to ensure it:
- Has a public
$eventproperty to store the event data - Listens for the
loadEventModalevent using the#[On('loadEventModal')]attribute - Has a
loadEvent()method that accepts the selected event data - Renders a view that displays the event data
Color Schemes
The Calendar component supports four color schemes:
- Primary (
color-scheme="primary") - Uses your application's primary color - Secondary (
color-scheme="secondary") - Uses your application's secondary color - Accent (
color-scheme="accent") - Uses your application's accent color - Custom (
color-scheme="custom" custom-color="#HEX") - Uses a custom color specified by thecustom-colorprop
Each event can also have its own color scheme by specifying the colorScheme property in the event data.
Calendar Views
The Calendar component supports four different views:
- Day (
view="day") - Shows a detailed view of a single day - Week (
view="week") - Shows a week view with days as columns - Month (
view="month") - Shows a traditional month calendar (default) - Year (
view="year") - Shows a year overview with months
Users can switch between views using the view selector in the calendar header.
Event Interactions
Events on the calendar are interactive:
- Hovering over an event shows a subtle scale animation
- Clicking on an event displays a modal with detailed information
- Events with the same color scheme are visually grouped
Responsive Behavior
The calendar adapts to different screen sizes:
- Large screens: Full day names, more detailed event information
- Medium screens: Short day names (e.g., "Mon" instead of "Monday")
- Small screens: Minimal day names (e.g., "M" instead of "Monday"), compact layout
Styling
The Calendar component uses Tailwind CSS for styling. You can customize the appearance by:
- Using the provided props (
colorScheme,customColor, etc.) - Adding custom CSS classes via the
cssproperty in events - Providing custom configuration via the
configprop
Default Classes
- Calendar container:
mx-auto px-4 lg:container - Calendar header:
flex justify-between items-center p-4 border-b border-stroke dark:border-dark-3 - Weekdays:
grid grid-cols-7 text-center py-2 border-b border-stroke dark:border-dark-3 - Month grid:
grid grid-cols-7 gap-px - Day cell:
p-1 h-24 sm:h-28 md:h-32 border border-stroke dark:border-dark-3 - Event:
rounded-md p-1 text-xs mb-1 truncate shadow-sm
Methods
The Calendar component includes several helper methods:
| Method | Description |
|---|---|
getContrastColor(string $hexColor) |
Determines appropriate text color (black or white) based on background color |
addCss(string $config) |
Adds Tailwind CSS classes to the calendar configuration |
popups() |
Generates HTML for event popups |
customColorScript() |
Generates JavaScript for handling custom colors |
setup() |
Sets up the calendar configuration |
Accessibility
The Calendar component follows accessibility best practices:
- Uses semantic HTML for calendar structure
- Provides proper labeling for dates and events
- Supports keyboard navigation
- Includes appropriate ARIA attributes
- Ensures sufficient color contrast for all color schemes
Related Components
- DatePicker - Date selection input
- DateTime - Date and time selection input