Overview
Lyger’s component system provides a flexible foundation for building reusable, reactive UI components. Components can be used standalone or integrated with Livewire for enhanced reactivity.
The component system in Lyger\Components is designed to work alongside Livewire components, providing additional UI building blocks and patterns.
Basic Components
Creating a Component
Extend the Lyger\Components\Component base class:
<? php
namespace App\Components ;
use Lyger\Components\ Component ;
class Card extends Component
{
protected string $title = '' ;
protected string $content = '' ;
protected function mount () : void
{
$this -> title = $this -> title ?: 'Default Title' ;
}
protected function renderInline () : string
{
return <<< HTML
< div class = "card bg-white shadow-lg rounded-lg p-6" >
< h3 class = "text-xl font-bold mb-4" > { $this -> title } </ h3 >
< div class = "content" > { $this -> content } </ div >
</ div >
HTML ;
}
}
Component Registration
Register components with the ComponentManager:
use Lyger\Components\ ComponentManager ;
use App\Components\ Card ;
ComponentManager :: register ( 'card' , Card :: class );
// Create instance
$card = ComponentManager :: make ( 'card' );
$card -> title = 'Welcome' ;
$card -> content = 'Hello, World!' ;
echo $card -> render ();
Component Lifecycle
Construction
Component is instantiated with new or ComponentManager::make().
Mount
The mount() method is called to initialize component state.
Before Render
The beforeRender() method is called before rendering (optional).
Render
The component is rendered using render() which calls renderView() or renderInline().
Lifecycle Methods
class LifecycleExample extends Component
{
protected function mount () : void
{
// Called once when component is created
$this -> properties [ 'initialized' ] = true ;
}
protected function beforeRender () : void
{
// Called before each render
$this -> properties [ 'timestamp' ] = time ();
}
public function render () : string
{
// Automatically calls beforeRender() then renderView()
return parent :: render ();
}
}
Views and Templates
Using External Views
class UserCard extends Component
{
protected string $view = 'components.user-card' ;
protected function mount () : void
{
$this -> properties = [
'name' => 'John Doe' ,
'email' => 'john@example.com' ,
'avatar' => '/images/avatar.jpg' ,
];
}
}
Create the view file at resources/views/components/user-card.php:
< div class = "user-card" >
< img src = "<?= $avatar ?>" alt = "<?= $name ?>" >
< h3 ><?= $name ?></ h3 >
< p ><?= $email ?></ p >
</ div >
Inline Rendering
Override renderInline() for simple components:
class Badge extends Component
{
protected string $text = '' ;
protected string $color = 'blue' ;
protected function renderInline () : string
{
return "<span class= \" badge bg-{ $this -> color }-500 text-white px-3 py-1 rounded-full \" >{ $this -> text }</span>" ;
}
}
Properties and Data
Setting Properties
class DataComponent extends Component
{
protected array $properties = [];
public function setData ( array $data ) : self
{
foreach ( $data as $key => $value ) {
$this -> setProperty ( $key , $value );
}
return $this ;
}
public function getData () : array
{
return $this -> properties ;
}
}
// Usage
$component = new DataComponent ();
$component -> setData ([
'title' => 'Product' ,
'price' => 29.99 ,
'stock' => 100 ,
]);
Magic Methods
Components support magic getters and setters:
$component = new Card ();
$component -> title = 'My Title' ; // Uses __set()
$component -> description = 'Text content' ;
echo $component -> title ; // Uses __get()
if ( isset ( $component -> title )) { // Uses __isset()
// Property exists
}
Method Calling
Components can expose methods that can be called dynamically:
class Calculator extends Component
{
public function add ( int $a , int $b ) : int
{
return $a + $b ;
}
public function multiply ( int $a , int $b ) : int
{
return $a * $b ;
}
}
$calc = new Calculator ();
$result = $calc -> call ( 'add' , [ 5 , 10 ]);
// Returns:
// [
// 'success' => true,
// 'data' => 15,
// 'updates' => []
// ]
Error Handling
$result = $calc -> call ( 'nonExistentMethod' , []);
// Returns:
// [
// 'error' => 'Method nonExistentMethod not found'
// ]
Built-in Components
Create forms with validation and error handling:
Modal Component
Display modal dialogs:
use Lyger\Components\ Modal ;
$modal = new Modal ();
$modal -> title = 'Confirm Action' ;
$modal -> size = 'md' ; // sm, md, lg, xl, full
$modal -> isOpen = true ;
echo $modal -> render ();
// Control modal state
$modal -> open ();
$modal -> close ();
$modal -> toggle ();
Modal component includes built-in backdrop and animation support. The size property controls the modal width.
Table Component
Create sortable data tables:
use Lyger\Components\ Table ;
class UserTable extends Table
{
protected function defineColumns () : array
{
return [
'id' => [
'label' => 'ID' ,
'sortable' => true ,
],
'name' => [
'label' => 'Name' ,
'sortable' => true ,
],
'email' => [
'label' => 'Email' ,
'sortable' => false ,
],
'created_at' => [
'label' => 'Created' ,
'sortable' => true ,
'format' => fn ( $value ) => date ( 'Y-m-d' , strtotime ( $value )),
],
];
}
protected function getData () : array
{
return User :: all ();
}
}
$table = new UserTable ();
echo $table -> render ();
Table Actions
Add action buttons to table rows:
class UserTable extends Table
{
protected function mount () : void
{
parent :: mount ();
$this -> actions = [
[
'label' => 'Edit' ,
'url' => fn ( $row ) => "/users/{ $row ['id']}/edit" ,
'class' => 'text-blue-600 hover:text-blue-900' ,
],
[
'label' => 'Delete' ,
'url' => fn ( $row ) => "/users/{ $row ['id']}/delete" ,
'class' => 'text-red-600 hover:text-red-900' ,
],
];
}
}
Sorting
// Sort by column
$table -> sort ( 'name' ); // First click: ascending
$table -> sort ( 'name' ); // Second click: descending
Alert Component
Display notifications and messages:
Success Alert
Error Alert
Warning Alert
Info Alert
use Lyger\Components\ Alert ;
$alert = new Alert ();
$alert -> type = 'success' ;
$alert -> message = 'Your changes have been saved!' ;
$alert -> dismissible = true ;
echo $alert -> render ();
Events and Communication
Emitting Events
class EventEmitter extends Component
{
public function triggerAction ()
{
$result = $this -> emit ( 'actionTriggered' , [
'timestamp' => time (),
'user' => 'John' ,
]);
return $result ;
}
}
Event Data Structure
[
'event' => 'actionTriggered' ,
'data' => [
'timestamp' => 1234567890 ,
'user' => 'John' ,
],
]
Validation
Components support data validation:
class ValidatedComponent extends Component
{
protected array $properties = [
'email' => '' ,
'age' => 0 ,
];
public function save ()
{
try {
$validated = $this -> validate ([
'email' => [ 'required' , 'email' ],
'age' => [ 'required' , 'integer' , 'min:18' ],
], [
'email.required' => 'Email is required' ,
'age.min' => 'You must be at least 18 years old' ,
]);
// Use validated data
return [ 'success' => true , 'data' => $validated ];
} catch ( ValidationException $e ) {
return [ 'success' => false , 'errors' => $e -> getErrors ()];
}
}
}
AJAX Handler
Components can handle AJAX requests:
use Lyger\Components\ LiveHandler ;
// Handle incoming request
$request = [
'component' => 'user-card' ,
'method' => 'updateProfile' ,
'params' => [ 'John Doe' , 'john@example.com' ],
'properties' => [
'userId' => 123 ,
],
];
$response = LiveHandler :: handle ( $request );
// Response format:
// [
// 'success' => true,
// 'data' => [...],
// 'updates' => [...]
// ]
Slots
Components support slot-based content injection:
use Lyger\Components\ Slot ;
class LayoutComponent extends Component
{
protected function renderInline () : string
{
return <<< HTML
< div class = "layout" >
< header > {{ $header }} </ header >
< main > {{ $slot }} </ main >
< footer > {{ $footer }} </ footer >
</ div >
HTML ;
}
}
// Usage
$layout = new LayoutComponent ();
$layout -> header = new Slot ( '<h1>Site Title</h1>' );
$layout -> slot = new Slot ( '<p>Main content</p>' );
$layout -> footer = new Slot ( '<p>© 2026</p>' );
Best Practices
Component Composition
Build complex UIs by composing smaller, focused components rather than creating monolithic ones.
Separate Concerns
Keep presentation logic in components and business logic in services or models.
Reusability
Design components to be reusable across different contexts by using properties and configuration.
Type Safety
Use PHP type declarations for component properties and method parameters.
Documentation
Document component properties, methods, and usage examples for your team.
API Reference
Component Methods
Method Description mount()Called when component is created beforeRender()Called before rendering render()Renders the component renderView()Renders from external view file renderInline()Renders inline template toArray()Returns component as array call($method, $params)Calls component method emit($event, $data)Emits event validate($rules, $messages)Validates properties setProperty($key, $value)Sets property getProperty($key)Gets property refresh()Refreshes component
ComponentManager Methods
Method Description register($name, $class)Registers component make($name)Creates component instance getRegistered()Gets all registered components
Method Description defineFields()Defines form fields submit()Submits form value($name)Gets field value setValue($name, $value)Sets field value error($name)Gets field error hasError($name)Checks if field has error renderFields()Renders all fields renderField($name, $field)Renders single field
Table Methods
Method Description defineColumns()Defines table columns getData()Gets table data sort($column)Sorts by column
Modal Methods
Method Description open()Opens modal close()Closes modal toggle()Toggles modal state