Components
InspireCMS offers a powerful component system based on Laravel's Blade components to help you build modular, reusable interface elements.
Component System Overview
Components in InspireCMS serve as the building blocks of your frontend templates. They:
- Encapsulate reusable interface elements
- Allow passing parameters and content
- Support theme-specific implementations
- Enable advanced template composition
- Improve code organization and maintainability
Component Types
InspireCMS supports several types of components:
1. Theme Components
Theme-specific components that define your site's visual elements:
- Layout components (header, footer, sidebar)
- Content display components (cards, tabs, modals)
- Navigation components (menus, breadcrumbs)
- Media display components (galleries, sliders)
2. Content Components
Components that render specific types of content:
- Blog post components
- Event listing components
- Product display components
- Team member components
3. Utility Components
Helper components for common UI patterns:
- Pagination components
- Alert/notification components
- Form input components
- Loading indicators
Component Directory Structure
InspireCMS organizes components in a hierarchical structure:
resources/views/components/
├── inspirecms/ # InspireCMS-specific components
│ ├── default/ # Default theme components
│ │ ├── layout.blade.php # Base layout component
│ │ ├── page.blade.php # Page template component
│ │ └── ... # Other default components
│ │
│ └── your-theme/ # Your custom theme components
│ ├── layout.blade.php # Theme-specific layout
│ ├── header.blade.php # Theme-specific header
│ └── ... # Other theme components
│
└── common/ # Theme-agnostic shared components
├── alert.blade.php
├── pagination.blade.php
└── ...
Using Components
Basic Component Usage
Using a component in your templates:
<x-cms-theme-component theme="my-theme" name="hero" :title="$heroTitle" :image="$heroImage">
<p>{{ $heroContent }}</p>
</x-cms-theme-component>
Using Components via Helper
The component helper makes it easier to use theme-aware components:
<x-dynamic-component :component="inspirecms_templates()->getComponentWithTheme('hero')" :title="$heroTitle" :image="$heroImage">
<p>{{ $heroContent }}</p>
</x-dynamic-component>
Component Slots
Use named slots to organize content within components:
<x-inspirecms-my-theme::card class="featured-card">
<x-slot:header>
<h3>{{ $title }}</h3>
</x-slot>
<p>{{ $content }}</p>
<x-slot:footer>
<a href="{{ $url }}" class="btn">Read more</a>
</x-slot>
</x-inspirecms-my-theme::card>
Creating Components
Basic Component Creation
Create a simple component:
<!-- resources/views/components/inspirecms/my-theme/alert.blade.php -->
<div class="alert alert-{{ $type ?? 'info' }}" role="alert">
@if(isset($dismissible) && $dismissible)
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
@endif
<div class="alert-content">
{{ $slot }}
</div>
</div>
Use your component:
<x-inspirecms-my-theme::alert type="warning" :dismissible="true">
This is a warning message that can be dismissed.
</x-inspirecms-my-theme::alert>
Component with Props
Create a component with defined props:
<!-- resources/views/components/inspirecms/my-theme/button.blade.php -->
@props([
'type' => 'primary',
'size' => 'md',
'url' => null,
'disabled' => false,
'icon' => null,
])
@php
$baseClass = 'btn';
$classes = [
$baseClass,
"btn-{$type}",
"btn-{$size}",
$disabled ? 'disabled' : '',
];
$attributes = $attributes->class(implode(' ', array_filter($classes)));
@endphp
@if($url && !$disabled)
<a href="{{ $url }}" {{ $attributes }}>
@if($icon)<span class="icon icon-{{ $icon }}"></span>@endif
{{ $slot }}
</a>
@else
<button {{ $attributes->merge(['type' => 'button', 'disabled' => $disabled]) }}>
@if($icon)<span class="icon icon-{{ $icon }}"></span>@endif
{{ $slot }}
</button>
@endif
Use this component:
<x-dynamic-component :component="inspirecms_templates()->getComponentWithTheme('button')"
type="success"
size="lg"
url="#"
icon="check"
class="my-4"
>
Submit Form
</x-dynamic-component>
Class-Based Components
For more complex components, create a class-based component:
namespace App\View\Components;
use Illuminate\View\Component;
class Gallery extends Component
{
public $images;
public $columns;
public $lightbox;
public function __construct($images = [], $columns = 3, $lightbox = true)
{
$this->images = $this->processImages($images);
$this->columns = max(1, min(12, (int) $columns));
$this->lightbox = $lightbox;
}
public function render()
{
return view('components.gallery');
}
private function processImages($images)
{
// Process and normalize image data
return collect($images)->map(function ($image) {
if (is_string($image) || is_numeric($image)) {
$media = inspirecms_asset()->findByKey($image);
if ($media) {
return [
'url' => $media->getUrl(),
'thumbnail' => $media->getUrl(['width' => 300, 'height' => 200, 'fit' => 'crop']),
'alt' => $media->alt_text ?? '',
'caption' => $media->caption ?? '',
'original' => $media,
];
}
return null;
}
return [
'url' => $image['url'] ?? '',
'thumbnail' => $image['thumbnail'] ?? $image['url'] ?? '',
'alt' => $image['alt'] ?? '',
'caption' => $image['caption'] ?? '',
'original' => $image['original'] ?? null,
];
})->filter();
}
public function columnClass()
{
return 'col-' . (12 / $this->columns);
}
}
Theme-Specific Components
Create components that adapt to the current theme:
Theme-Aware Components
Use the theme helper to get the appropriate component for the current theme:
@php
// This will check for 'header' component in the current theme,
// falling back to the default theme if not found
$headerComponent = inspirecms_templates()->getComponentWithTheme('header');
@endphp
<x-dynamic-component :component="$headerComponent" :title="$pageTitle" />
Component Overriding
Override default components by creating a component with the same name in your theme:
<!-- resources/views/components/inspirecms/default/navigation.blade.php -->
<nav class="default-navigation">
<!-- Default navigation implementation -->
</nav>
<!-- resources/views/components/inspirecms/my-theme/navigation.blade.php -->
<nav class="custom-navigation">
<!-- Custom navigation implementation -->
</nav>
Advanced Component Techniques
Component Composition
Build complex components by combining smaller ones:
<!-- resources/views/components/inspirecms/my-theme/content-block.blade.php -->
<section class="content-block {{ $type ?? 'default' }}">
<div class="container">
@if($title)
<x-inspirecms-my-theme::section-title :text="$title" :subtitle="$subtitle" />
@endif
<div class="content-block-body">
{{ $slot }}
</div>
@if(isset($footer))
<div class="content-block-footer">
{{ $footer }}
</div>
@endif
</div>
</section>
Component Variants
Create variants of components using attributes:
<!-- resources/views/components/inspirecms/my-theme/card.blade.php -->
@props([
'variant' => 'default',
'overlay' => false,
'aspectRatio' => null,
])
@php
$variants = [
'default' => 'card-default',
'feature' => 'card-feature bg-primary text-white',
'outline' => 'card-outline border-primary',
'simple' => 'card-simple shadow-sm',
];
$variantClass = $variants[$variant] ?? $variants['default'];
$classes = [
'card',
$variantClass,
$overlay ? 'card-overlay' : '',
$aspectRatio ? "ratio-{$aspectRatio}" : '',
];
@endphp
<div {{ $attributes->merge(['class' => implode(' ', array_filter($classes))]) }}>
<!-- Card content -->
</div>
Dynamic Components
Create components that render differently based on input:
<!-- resources/views/components/inspirecms/my-theme/content-display.blade.php -->
@props([
'content',
'mode' => 'full',
])
@php
$modes = [
'full' => 'components.content.full-display',
'summary' => 'components.content.summary-display',
'card' => 'components.content.card-display',
'minimal' => 'components.content.minimal-display',
];
$view = $modes[$mode] ?? $modes['full'];
@endphp
<x-dynamic-component :component="$view" :content="$content" />
Component Collections
Group related components together:
<!-- resources/views/components/inspirecms/my-theme/form/input.blade.php -->
@props(['name', 'label', 'type' => 'text'])
<div class="form-group">
<label for="{{ $name }}">{{ $label }}</label>
<input
type="{{ $type }}"
id="{{ $name }}"
name="{{ $name }}"
{{ $attributes->merge(['class' => 'form-control']) }}
>
@error($name)
<span class="error-message">{{ $message }}</span>
@enderror
</div>
Working with Content in Components
Content-Aware Components
Create components that intelligently display content:
<!-- resources/views/components/inspirecms/my-theme/content-renderer.blade.php -->
@props(['content', 'format' => 'full'])
@php
$documentTypeName = $content->documentType : 'default';
// Try to find a specialized component for this document type
$componentName = collect(["content.{$documentTypeName}-{$format}", "content.generic-{$format}"])
// Check if the specialized component exists
->where(fn ($name) => inspirecms_template()->hasComponent($name))
->map(fn ($name) => inspirecms_templates()->getComponentWithTheme($name))
// If even that doesn't exist, use a very basic fallback
->first() ?? inspirecms_template()->getComponentWithTheme("content.fallback");
@endphp
<x-dynamic-component :component="$componentName" :content="$content" />
Best Practices
- Keep Components Focused: Each component should have a single responsibility
- Document Components: Add docblocks and examples to component files
- Use Meaningful Props: Give props clear, descriptive names
- Set Default Values: Provide sensible defaults for component props
- Handle Edge Cases: Anticipate and handle empty or unexpected data
- Follow Naming Conventions: Use consistent naming for components and props
- Test Components: Write tests to verify component rendering
Note: For detailed examples of using components in templates, see the Templates documentation.
For integrating components into layouts, see the Layouts documentation.