PHPackages                             codenzia/project-essentials - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. codenzia/project-essentials

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

codenzia/project-essentials
===========================

Essential project utilities and helpers for Laravel applications.

v0.1.2(1w ago)071[1 PRs](https://github.com/Codenzia/project-essentials/pulls)MITPHPPHP ^8.3CI passing

Since May 30Pushed 2w agoCompare

[ Source](https://github.com/Codenzia/project-essentials)[ Packagist](https://packagist.org/packages/codenzia/project-essentials)[ Docs](https://github.com/codenzia/project-essentials)[ GitHub Sponsors](https://github.com/:vendor_name)[ RSS](/packages/codenzia-project-essentials/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (22)Versions (8)Used By (0)

Project Essentials — UI components, form fields, table columns &amp; helpers for Filament
=========================================================================================

[](#project-essentials--ui-components-form-fields-table-columns--helpers-for-filament)

[![Latest Version](https://camo.githubusercontent.com/fab1de031ff31b59a9ddc0ff38252dc83c4eabc5b644238a4531f430f474343c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f636f64656e7a69612f70726f6a6563742d657373656e7469616c732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/codenzia/project-essentials)[![PHP Version](https://camo.githubusercontent.com/2d66a259e1d62d990c6e2d50eacfcf3450e861df8fb0540bbedb0a408882c8ea/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f636f64656e7a69612f70726f6a6563742d657373656e7469616c732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/codenzia/project-essentials)[![Filament](https://camo.githubusercontent.com/a4590ecd31837ed0b59c24f0e88d92d9da4b077f18d050fe8aa87d3d95154a57/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f46696c616d656e742d763425323025374325323076352d6635396530623f7374796c653d666c61742d737175617265)](https://filamentphp.com)[![License](https://camo.githubusercontent.com/9c004fc6d096ddf34bc835bfd17379da638cd9eed1977d29c716bc02535736ec/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f636f64656e7a69612f70726f6a6563742d657373656e7469616c732e7376673f7374796c653d666c61742d737175617265)](LICENSE.md)

**Essential UI components, form fields, table columns, infolist entries, traits, and helpers for [Laravel](https://laravel.com) and [Filament v4 / v5](https://filamentphp.com) projects.** A curated component library distilled from every Codenzia Filament app — the bits we reach for in every project that aren't worth re-implementing each time.

> **Why this exists.** Every Filament CRUD project eventually needs a progress column, a coloured-pill list, an icon picker, an RTL-aware paginator, a tag column with overflow handling, a percentage slider form field. Building these one project at a time is wasted hours; bundling them into a versioned package keeps the API consistent across every app you ship.

> **Try it live:** A working integration is included in the [Codenzia plugins demo](https://github.com/Codenzia/plugins-demo) at `/admin/demo/project-essentials`.

---

Requirements
------------

[](#requirements)

DependencyVersionPHP`^8.3`Filament`^4.0 || ^5.0`---

Features
--------

[](#features)

**UI Components**

- **Progress** — Circular SVG progress indicator with gradient colors
- **Pagination** — Custom Laravel pagination view with RTL and dark mode support
- **IconPicker** — Filament form select with 45+ categorized Heroicons
- **DropdownCheckList** — Multi-select dropdown with search, avatars, and enum support
- **DropdownLink** — Styled dropdown link item
- **SplitButtonDropdown** — Split button with main action + dropdown menu
- **PercentageSlider** — Interactive 0-100% slider form field
- **CounterInput** — Increment/decrement number input field
- **ProgressBarColumn / ProgressBarEntry** — Progress bar for tables and infolists
- **ColoredEnumColumn / ColoredEnumEntry** — Enum-aware colored columns and entries
- **HtmlColumn** — Render raw HTML content in table columns
- **UserAvatarColumn / UserAvatarEntry** — User avatar display with fallback
- **TagColumn / TagEntry** — Tag display with color randomization and context limits
- **ColoredPillsColumn / ColoredPillsEntry** — Generic colored pill badges with per-item colors, sizes, enum support, and hover card overflow
- **PriorityColumn / PriorityEntry** — Priority display with icon, color, and label from enums
- **CircularProgressBar** — SVG circular progress bar with gradient
- **CreatedUpdatedColumn / CreatedUpdatedEntry** — Created/updated timestamps with user avatars
- **StateSwitcher** — Toggle column with configurable on/off enum states and labels
- **ResponsiveTabs** — Responsive tabs with overflow "More" dropdown
- **LoadingSpinner** — Advanced loading spinner with 4 variants (minimal, elegant, orbital, pulse)
- **Banner** — Top-of-page notification banner with success/danger/warning styles
- **GridLayoutSwitcher** — Session-persistent grid size slider
- **ColumnToggle** — Custom column visibility toggling with session persistence
- **LocaleSwitcher** — Self-contained language switcher dropdown (works in Filament panels AND public Blade pages; no flag-icons or host-Tailwind dependency)

**Form Components**

- **IconColoredEnumSelect** — Rich select with colored icons for enums
- **DatePickerWithHint** — DatePicker with auto format hint from config
- **DateTimePickerWithHint** — DateTimePicker with auto format hint from config
- **CounterInput** — Stepper number input with +/- buttons
- **DateRangePicker** — Date range picker with from/to inputs, clear button, and locale-aware display
- **CardRepeater** — Card-based repeater with inline/card modes, relationship support, and CRUD actions

**Table Filters**

- **DateRangeFilter** — Table filter using DateRangePicker with automatic query scoping and indicators

**Helpers**

- **DateHelper** — Date formatting, duration, and human-readable format hints
- **DateRangeHelper** — Parse and format date ranges
- **FileHelper** — File type detection by extension
- **TailwindHelper** — Tailwind v4 safe dynamic color class resolver
- **FormatHelper** — Text truncation, hex-to-rgba, formatted IDs
- **FilamentTableHelper** — Reusable timestamp/userstamp columns and search filters

**Traits**

- **IconColoredEnum** — Labels, icons, and colors for PHP enums
- **Userstamps** — Auto-track created\_by / updated\_by on models
- **CanToggleColumns** — Session-persistent table column toggling
- **CanFixFilamentActionCancel** — Fix for Filament modal cancel bug
- **CanLogsActivity** — Automatic activity logging with elegant diffing
- **HasGridLayoutSwitcher** — Grid layout size with session persistence
- **HasDashboardDateFilter** — Dashboard widget date filtering
- **HasHeaderFormActions** — Mirror form footer actions to page header
- **HasPageSettings** — Database-backed per-user page settings with presets, grouping, reordering, live preview, and admin bulk-apply
- **HasColoredEnumViewComponent** — Enum coloring for columns/entries
- **HasProgressBarViewComponent** — Configurable progress bar rendering
- **HasUserAvatarViewComponent** — Size configuration for avatar columns/entries
- **HasCreatedUpdatedViewComponent** — Username limit configuration for created/updated columns/entries

Requirements
------------

[](#requirements-1)

- PHP 8.3+
- Laravel 12+
- Filament 4.x

Installation
------------

[](#installation)

```
composer require codenzia/project-essentials
```

Publish the config (optional):

```
php artisan vendor:publish --tag="project-essentials-config"
```

Publish and run migrations (required for HasPageSettings):

```
php artisan vendor:publish --tag="project-essentials-migrations"
php artisan migrate
```

Publish views for customization (optional):

```
php artisan vendor:publish --tag="project-essentials-views"
```

Plugin Registration
-------------------

[](#plugin-registration)

Register the plugin in your Filament panel provider:

```
use Codenzia\ProjectEssentials\ProjectEssentialsPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        ->plugins([
            ProjectEssentialsPlugin::make(),
        ]);
}
```

---

Traits
------

[](#traits)

### IconColoredEnum

[](#iconcoloredenum)

Gives PHP backed enums labels, icons, and Tailwind-compatible colors.

```
use Codenzia\ProjectEssentials\Traits\IconColoredEnum;

enum StatusEnum: string
{
    use IconColoredEnum;

    case ACTIVE = 'active';
    case INACTIVE = 'inactive';

    public static function getLabels(): array
    {
        return [
            self::ACTIVE->value => 'Active',
            self::INACTIVE->value => 'Inactive',
        ];
    }

    public static function getIcons(): array
    {
        return [
            self::ACTIVE->value => 'heroicon-o-check-circle',
            self::INACTIVE->value => 'heroicon-o-x-circle',
        ];
    }

    public static function getColors(): array
    {
        return [
            self::ACTIVE->value => 'success',
            self::INACTIVE->value => 'danger',
        ];
    }

}

// Usage
$status = StatusEnum::ACTIVE;
$status->getLabel();           // "Active"
$status->getIcon();            // "heroicon-o-check-circle"
$status->getColor();           // "success"
$status->tailwindColorClass(); // "text-success-500"

StatusEnum::labels();          // ['active' => 'Active', 'inactive' => 'Inactive']
StatusEnum::options();         // [['value' => 'active', 'label' => 'Active'], ...]
StatusEnum::casesExcept([StatusEnum::INACTIVE]); // [StatusEnum::ACTIVE]
```

### Userstamps

[](#userstamps)

Automatically tracks `created_by_user_id` and `updated_by_user_id` on Eloquent models.

```
use Codenzia\ProjectEssentials\Traits\Userstamps;

class Invoice extends Model
{
    use Userstamps;
}

// Requires migration columns:
// $table->foreignId('created_by_user_id')->nullable();
// $table->foreignId('updated_by_user_id')->nullable();

$invoice->createdByUser; // User who created
$invoice->updatedByUser; // User who last updated
```

Configure the User model in `config/project-essentials.php`:

```
'user_model' => 'App\\Models\\User',
```

### CanToggleColumns

[](#cantogglecolumns)

Session-persistent column visibility toggling for Filament tables. Replaces Filament's built-in toggle with a custom dropdown.

```
use Codenzia\ProjectEssentials\Traits\CanToggleColumns;

class ListUsers extends ListRecords
{
    use CanToggleColumns;

    public function table(Table $table): Table
    {
        $columns = [
            TextColumn::make('name'),
            TextColumn::make('email')->toggleable(),
            TextColumn::make('phone')->toggleable(isToggledHiddenByDefault: true),
        ];

        return $table->columns(
            $this->makeColumnsForToggle($columns)
        );
    }
}
```

### CanFixFilamentActionCancel

[](#canfixfilamentactioncancel)

Fixes a bug in Filament where `modalCancelAction` callbacks execute on modal render instead of button click.

```
use Codenzia\ProjectEssentials\Traits\CanFixFilamentActionCancel;

class ViewUser extends ViewRecord
{
    use CanFixFilamentActionCancel;
}
```

### HasGridLayoutSwitcher

[](#hasgridlayoutswitcher)

Provides session-persistent grid layout size switching for Filament pages with card/grid views.

```
use Codenzia\ProjectEssentials\Traits\HasGridLayoutSwitcher;

class ListProjects extends ListRecords
{
    use HasGridLayoutSwitcher;

    protected function getHeaderActions(): array
    {
        return [
            $this->makeGridLayoutSwitcherAction(),
        ];
    }
}
```

### HasDashboardDateFilter

[](#hasdashboarddatefilter)

Adds date range filtering to Filament dashboard widgets.

```
use Codenzia\ProjectEssentials\Traits\HasDashboardDateFilter;

class RevenueChart extends ChartWidget
{
    use HasDashboardDateFilter;

    protected function getData(): array
    {
        $startDate = $this->getFilterStartDate();
        // Filter your query with $startDate...
    }
}
```

### HasHeaderFormActions

[](#hasheaderformactions)

Mirrors form footer actions (Save, Cancel, etc.) to the page header automatically.

```
use Codenzia\ProjectEssentials\Traits\HasHeaderFormActions;

class EditUser extends EditRecord
{
    use HasHeaderFormActions;
    // Header will now show the same actions as the footer
}
```

### HasPageSettings

[](#haspagesettings)

Database-backed per-user settings modal for any Filament page or widget. Supports section grouping, admin presets, live preview, reset to defaults, scoped settings, and bulk-apply to roles/teams.

**Requires migration** — run `php artisan vendor:publish --tag="project-essentials-migrations" && php artisan migrate`

#### Basic Usage (raw Filament components)

[](#basic-usage-raw-filament-components)

```
use Codenzia\ProjectEssentials\Traits\HasPageSettings;

class ListInvoices extends ListRecords
{
    use HasPageSettings;

    protected function getHeaderActions(): array
    {
        return [
            $this->settings([
                Toggle::make('show_archived')->label('Show Archived'),
                Select::make('default_view')->options(['table' => 'Table', 'grid' => 'Grid']),
            ]),
        ];
    }

    // Read a setting value anywhere in the page
    public function getEloquentQuery(): Builder
    {
        $query = parent::getEloquentQuery();

        if ($this->getPageSetting('show_archived', false)) {
            $query->withArchived();
        }

        return $query;
    }
}
```

#### Fluent Definitions with PageSettingDefinition

[](#fluent-definitions-with-pagesettingdefinition)

Use the fluent builder for grouped settings with labels, descriptions, and defaults:

```
use Codenzia\ProjectEssentials\Models\PageSettingDefinition;
use Codenzia\ProjectEssentials\Traits\HasPageSettings;

class Dashboard extends Page
{
    use HasPageSettings;

    protected function getHeaderActions(): array
    {
        return [
            $this->settings([
                // KPI Cards group
                PageSettingDefinition::checkbox('show_revenue')
                    ->label('Revenue')
                    ->description('Monthly revenue breakdown and trends')
                    ->group('KPI Cards')
                    ->default(true),

                PageSettingDefinition::checkbox('show_tasks')
                    ->label('Active Tasks')
                    ->group('KPI Cards')
                    ->default(true),

                // Display group
                PageSettingDefinition::select('default_view')
                    ->label('Default View')
                    ->options(['table' => 'Table', 'grid' => 'Grid'])
                    ->group('Display')
                    ->default('table'),

                PageSettingDefinition::toggle('compact_mode')
                    ->label('Compact Mode')
                    ->description('Reduce spacing between elements')
                    ->group('Display')
                    ->default(false),
            ]),
        ];
    }
}
```

#### Live Preview

[](#live-preview)

Enable reactive updates that apply instantly as the user toggles settings (before submitting):

```
class Dashboard extends Page
{
    use HasPageSettings;

    protected function pageSettingsLivePreview(): bool
    {
        return true;
    }

    protected function onPageSettingPreviewUpdated(string $key, mixed $value): void
    {
        // Reactively update your page state
        if (str_starts_with($key, 'smartStatsVisibility.')) {
            $this->calculateMetrics();
        }
    }
}
```

#### Scoped Settings

[](#scoped-settings)

Store different settings per context (e.g., per project):

```
class ProjectBoard extends Page
{
    use HasPageSettings;

    public Project $project;

    protected function getPageSettingsScope(): ?string
    {
        return (string) $this->project->id;
    }
}
```

#### Admin Presets

[](#admin-presets)

Save and load named configurations:

```
// Save current settings as a preset
$this->saveAsPageSettingsPreset('Manager View', isDefault: true);

// Apply a preset by ID
$this->applyPageSettingsPreset($presetId);

// Delete a preset
$this->deletePageSettingsPreset($presetId);
```

When presets exist for a page, a "Load Preset" dropdown automatically appears at the top of the settings modal.

#### Bulk Apply (Admin)

[](#bulk-apply-admin)

Push settings to all users with a specific role or in a department:

```
// Apply to all users with the "manager" role
$this->applyPageSettingsToRole('manager');

// Apply to all users in a department
$this->applyPageSettingsToTeam(teamId: $departmentId, teamRelation: 'department_id');
```

#### Reset to Defaults

[](#reset-to-defaults)

A "Reset to Defaults" button is automatically added to the settings modal footer. You can also call it programmatically:

```
$this->resetPageSettingsToDefaults();
```

#### Default Values

[](#default-values)

Define sensible defaults that apply before the user ever opens the modal:

```
protected function getPageSettingsDefaults(): array
{
    return [
        'show_archived' => false,
        'default_view' => 'table',
        'compact_mode' => false,
    ];
}
```

When using `PageSettingDefinition`, defaults are automatically extracted from each definition's `->default()` value.

#### Available Methods

[](#available-methods)

MethodDescription`settings(array $inputs)`Create settings header action (shortcut)`getPageSettingsAction(?array $schema)`Create settings action with optional schema override`getPageSetting(string $key, mixed $default)`Read a single setting value`getPageSettingsData()`Get all settings (merged with defaults)`savePageSettings(array $data)`Persist settings to database`getPageSettingsOrder()`Get saved item order (for sortable)`resetPageSettingsToDefaults()`Delete stored settings, revert to defaults`saveAsPageSettingsPreset(string $name, bool $isDefault)`Save current config as a preset`applyPageSettingsPreset(int $presetId)`Apply a preset`deletePageSettingsPreset(int $presetId)`Delete a preset`applyPageSettingsToRole(string $role)`Bulk-apply to role`applyPageSettingsToTeam(int $teamId, string $teamRelation)`Bulk-apply to team#### Overridable Methods

[](#overridable-methods)

MethodDefaultDescription`getPageSettingsFormSchema()``[]`Define settings form fields`getPageSettingsDefaults()`Auto from definitionsDefault values`getPageSettingsScope()``null`Scope key for per-context settings`pageSettingsLivePreview()``false`Enable reactive live preview`onPageSettingPreviewUpdated($key, $value)`no-opHandle live preview changes`onPageSettingsUpdated(array $data)`no-opHook after save### CanLogsActivity

[](#canlogsactivity)

Automatic activity logging for Eloquent models. Tracks creates, updates, and deletes with human-readable descriptions.

```
use Codenzia\ProjectEssentials\Traits\CanLogsActivity;

class Invoice extends Model
{
    use CanLogsActivity;

    // Optional: custom field-to-relation mappings
    public function getActivityLogFieldMappings(): array
    {
        return ['client_user_id' => 'client'];
    }

    // Optional: custom friendly names
    public function getActivityLogFriendlyNames(): array
    {
        return ['client_user_id' => 'Client'];
    }
}
```

Requires an `activity_logs` table with columns: `user_id`, `model_id`, `model`, `current_data`, `new_data`, `description`, `created_at`, `updated_at`.

### HasCreatedUpdatedViewComponent

[](#hascreatedupdatedviewcomponent)

Mixin trait for `CreatedUpdatedColumn` and `CreatedUpdatedEntry`. Provides a `limit()` method to truncate displayed usernames.

```
use Codenzia\ProjectEssentials\Traits\HasCreatedUpdatedViewComponent;

class MyColumn extends Column
{
    use HasCreatedUpdatedViewComponent;
}

// Usage
MyColumn::make('timestamps')->limit(15);
```

### HasColoredEnumViewComponent

[](#hascoloredenumviewcomponent)

Mixin trait for Filament columns/entries to support enum-based coloring. Used internally by `ColoredEnumColumn` and `ColoredEnumEntry`.

### HasProgressBarViewComponent

[](#hasprogressbarviewcomponent)

Configurable progress bar rendering with label, alignment, font sizes, and value visibility. Used internally by `ProgressBarColumn` and `ProgressBarEntry`.

### HasUserAvatarViewComponent

[](#hasuseravatarviewcomponent)

Size configuration mixin for avatar columns/entries. Used internally by `UserAvatarColumn` and `UserAvatarEntry`.

---

Form Components
---------------

[](#form-components)

### IconColoredEnumSelect

[](#iconcoloredenumselect)

A rich Filament Select with colored icons for PHP enums using `IconColoredEnum`. Supports two visual modes: **icon + colored text** (default) and **badge** (colored background pills with icon).

```
use Codenzia\ProjectEssentials\Forms\Components\IconColoredEnumSelect;

// Default mode: icon + colored text in dropdown
IconColoredEnumSelect::make('status')
    ->enumClass(StatusEnum::class)
    ->label('Status')

// Badge mode: colored background pills with icon
IconColoredEnumSelect::make('proficiency')
    ->enumClass(ProficiencyLevelEnum::class)
    ->badge()
```

MethodDescription`enumClass(string)`The enum class (must use `IconColoredEnum` trait)`badge(bool)`Enable badge mode — renders options as colored background pills with icon (default: `false`)### DatePickerWithHint

[](#datepickerwithhint)

DatePicker that auto-applies `config('app.date_format')` with a human-readable format hint icon.

```
use Codenzia\ProjectEssentials\Forms\Components\DatePickerWithHint;

// Default: hint icon next to the label (top)
DatePickerWithHint::make('start_date')
    ->label('Start Date')

// Prefix icon inside the input — avoids extra label-row height in table repeaters
DatePickerWithHint::make('due_date')
    ->hintPosition('left')

// Suffix icon inside the input
DatePickerWithHint::make('due_date')
    ->hintPosition('right')
```

MethodValuesDescription`hintPosition(string)``'top'` (default), `'left'`, `'right'``top` — hint icon with tooltip next to label; `left` — prefix icon inside input; `right` — suffix icon inside input### PercentageSlider

[](#percentageslider)

Interactive slider for 0-100% values with +/- buttons and drag support.

```
use Codenzia\ProjectEssentials\Forms\Components\PercentageSlider;

PercentageSlider::make('progress')
    ->label('Completion')
```

### CounterInput

[](#counterinput)

Stepper number input with increment/decrement buttons.

```
use Codenzia\ProjectEssentials\Forms\Components\CounterInput;

CounterInput::make('quantity')
    ->label('Quantity')
```

### DateTimePickerWithHint

[](#datetimepickerwithhint)

DateTimePicker that auto-applies `config('app.datetime_format')` with a human-readable format hint.

```
use Codenzia\ProjectEssentials\Forms\Components\DateTimePickerWithHint;

DateTimePickerWithHint::make('start_at')
    ->label('Start At')
```

### DateRangePicker

[](#daterangepicker)

A date range picker field with From/To inputs, locale-aware display formatting, and a clear button. Matches Filament's native DatePicker styling.

```
use Codenzia\ProjectEssentials\Forms\Components\DateRangePicker;

DateRangePicker::make('date_range')
    ->label('Date Range')

// With custom date format and placeholder
DateRangePicker::make('period')
    ->dateFormat('Y-m-d')
    ->placeholder('Select period')
```

State structure: `['from' => '2024-01-01', 'to' => '2024-12-31']`

MethodDescription`dateFormat(string)`PHP date format string (default: `config('app.date_format', 'd M, Y')`)`placeholder(string)`Placeholder text when no dates selected### CardRepeater

[](#cardrepeater)

A card-based repeater field that displays items as read-only cards with inline editing. Supports two modes: **card mode** (read-only cards with edit-on-click) and **inline mode** (form fields always visible). Full relationship support for HasMany and BelongsToMany.

```
use Codenzia\ProjectEssentials\Forms\Components\CardRepeater;

// Card mode with relationship
CardRepeater::make('milestones')
    ->relationship()
    ->gridColumns(1)
    ->cardSchema(fn (Schema $schema) => $schema->schema([
        View::make('milestone-card'),
    ]))
    ->formSchema([
        TextInput::make('title')->required(),
        DatePicker::make('due_date'),
    ])
    ->addActionLabel('Add milestone')
    ->addActionIcon('heroicon-o-plus')
    ->deletable()

// Inline mode (no cardSchema — fields always visible)
CardRepeater::make('items')
    ->formSchema([
        TextInput::make('name')->required(),
        TextInput::make('quantity')->numeric(),
    ])
    ->gridColumns(1)
    ->deletable()

// BelongsToMany with grid layout
CardRepeater::make('members')
    ->relationship()
    ->gridColumns(3)
    ->cardSchema(fn (Schema $schema) => $schema->schema([
        View::make('member-card'),
    ]))
    ->formSchema([
        Select::make('user_id')->relationship('user', 'name'),
    ])
    ->disableOptionsWhenSelectedInSiblingItems('user_id')

// BelongsToMany with custom save logic (pivot data)
CardRepeater::make('members')
    ->relationship('members', function ($relationship, $state) {
        $relationship->sync(collect($state)->mapWithKeys(fn ($item) => [
            $item['id'] => ['role' => $item['role']],
        ]));
    })

// Table-style layout with a shared header row above all cards
CardRepeater::make('goals')
    ->relationship()
    ->gridColumns(1)
    ->tableHeader('forms.components.goal-card-header')
    ->cardSchema(fn (Schema $schema) => $schema->schema([
        View::make('forms.components.goal-card'),
    ]))
```

**Note on `tableHeader()` vs inline `@if($isFirst)` headers.** It's tempting to put a column header inside the first card's view using `@if($isFirst)`, but that makes the first card taller than the rest and breaks any absolute positioning the wrapper does (notably the hover-only delete button alignment). Use `tableHeader()` instead — the header renders once above the grid and every card wrapper stays the same height.

MethodDescription`formSchema(array|Closure)`Form fields for add/edit mode`cardSchema(Closure)`Read-only card display (enables card mode)`cardActions(array|Closure)`Custom actions on each card`showCardActionsOnHover(bool)`Show card actions only on hover (default: `true`)`relationship(?string, ?Closure)`Enable relationship mode with optional custom save`gridColumns(int|Closure)`Number of grid columns (default: `1`)`tableHeader(string|Closure)`Blade view rendered once above the card grid (e.g. a table-style column header row). Keeps all card wrappers uniform in height so positioned controls (like the hover delete button) align consistently`emptyMessage(string|Closure)`Message when no items (default: `'No items yet'`)`addActionLabel(string|Closure)`Label for the add button (default: `'Add item'`)`addActionIcon(string|Closure)`Icon for the add button`addActionAlignment(string|Closure)`Alignment: `'left'`, `'center'`, `'right'` (default: `'left'`)`deletable(bool|Closure)`Allow deleting items (default: `true`)`editable(bool|Closure)`Allow editing items (default: `true`)`disableOptionsWhenSelectedInSiblingItems(string)`Disable selected options in sibling Select fields---

Table Filters
-------------

[](#table-filters)

### DateRangeFilter

[](#daterangefilter)

A table filter that uses DateRangePicker for date range filtering. Automatically builds the query, formats indicators, and supports custom column targeting.

```
use Codenzia\ProjectEssentials\Tables\Filters\DateRangeFilter;

// Basic — filters by the column matching the filter name
DateRangeFilter::make('created_at')

// With custom column and placeholder
DateRangeFilter::make('date_filter')
    ->column('published_at')
    ->placeholder('Published date')
```

MethodDescription`column(string)`Database column to filter (default: filter name)`placeholder(string)`Placeholder text in the picker---

Table Columns
-------------

[](#table-columns)

### ColoredEnumColumn

[](#coloredenumcolumn)

TextColumn with automatic enum-based coloring and icons.

```
use Codenzia\ProjectEssentials\Tables\Columns\ColoredEnumColumn;

ColoredEnumColumn::make('status')
    ->enum(StatusEnum::class)
    ->label('Status')
```

### ProgressBarColumn

[](#progressbarcolumn)

Visual progress bar column for tables.

```
use Codenzia\ProjectEssentials\Tables\Columns\ProgressBarColumn;

ProgressBarColumn::make('progress')
    ->progressLabel('Completion')
    ->alignValue('right')
    ->labelFontSize('sm')
    ->valueFontSize('xs')
```

MethodDescription`progressLabel(string)`Label text above the bar`alignValue(string)``'left'`, `'center'`, `'right'`, `'before'`, `'after'``hideValue(bool)`Hide percentage text`labelFontSize(string)`Font size: `'xs'`, `'sm'`, `'md'`, `'lg'`, `'xl'``valueFontSize(string)`Font size for the value### HtmlColumn

[](#htmlcolumn)

Renders raw HTML content in a table column.

```
use Codenzia\ProjectEssentials\Tables\Columns\HtmlColumn;

HtmlColumn::make('custom')
    ->html(fn ($record) => '' . e($record->name) . '')
```

### UserAvatarColumn

[](#useravatarcolumn)

Displays user avatars with automatic fallback. Resolves user from relationships automatically.

```
use Codenzia\ProjectEssentials\Tables\Columns\UserAvatarColumn;

UserAvatarColumn::make('assignee.avatar')
    ->size('size-10')
    ->label('Assignee')
```

### TagColumn

[](#tagcolumn)

Displays tags as colored badges with configurable context limits. Supports random or gradient colors.

```
use Codenzia\ProjectEssentials\Tables\Columns\TagColumn;

TagColumn::make('tags')
    ->label('Tags')
```

### ColoredPillsColumn / ColoredPillsEntry

[](#coloredpillscolumn--coloredpillsentry)

Generic colored pill badge component for tables and infolists. Each item can have its own color, size, and tooltip. Overflow items are shown in a polished hover card (teleported to body to escape table overflow). Both components share a single blade view.

Supports two modes:

- **Manual** — provide `itemColor()`, `itemTooltip()`, `itemSubtitle()` closures for full control
- **Enum** — pass an `IconColoredEnum`-based enum via `enum()` to auto-resolve colors, tooltips, and subtitles

```
use Codenzia\ProjectEssentials\Tables\Columns\ColoredPillsColumn;
use Codenzia\ProjectEssentials\Infolists\Components\ColoredPillsEntry;

// Enum mode — colors, tooltips, and subtitles auto-resolved from ProficiencyLevelEnum
ColoredPillsColumn::make('skills')
    ->label('Skills')
    ->visibleLimit(3)
    ->itemLabel(fn ($item) => $item->name)
    ->enum(ProficiencyLevelEnum::class, 'pivot.proficiency')
    ->emptyLabel('No Skills')
    ->hoverLabel(':count more skill|:count more skills')

// Same API for infolists
ColoredPillsEntry::make('skills')
    ->label('Skills')
    ->visibleLimit(3)
    ->itemLabel(fn ($item) => $item->name)
    ->enum(ProficiencyLevelEnum::class, 'pivot.proficiency')
    ->emptyLabel('No Skills')
    ->hoverLabel(':count more skill|:count more skills')

// Manual mode — full control with closures
ColoredPillsColumn::make('categories')
    ->visibleLimit(2)
    ->itemColor(fn ($item) => 'bg-blue-100 border-blue-300 text-blue-700 dark:bg-blue-500/15 dark:border-blue-400/50 dark:text-blue-400')
    ->emptyLabel('No Categories')

// Custom item resolver
ColoredPillsColumn::make('permissions')
    ->items(fn ($record) => $record->roles->flatMap->permissions->unique('id'))
    ->itemLabel(fn ($item) => $item->display_name)
```

MethodDescription`visibleLimit(int)`Max items shown before `+N` overflow badge (default: 3)`items(Closure)`Custom resolver `fn($record) => Collection` (default: `$record->{columnName}`)`itemLabel(string|Closure)`Label accessor — attribute name or `fn($item) => string` (default: `'name'`)`enum(string, string)`Auto-resolve colors/tooltips/subtitles from an `IconColoredEnum`. Args: enum class, dot-notation attribute path (e.g. `'pivot.proficiency'`)`itemColor(Closure)`CSS classes per item `fn($item) => string` — overrides enum colors if both set`itemSize(Closure)`Size class per item `fn($item) => string` (default: `'text-xs'`)`itemTooltip(Closure)`Tooltip per item `fn($item) => ?string` — overrides enum tooltips if both set`itemSubtitle(Closure)`Subtitle shown next to label in hover card `fn($item) => ?string` — overrides enum subtitles`emptyLabel(string)`Text when collection is empty (default: `'No Items'`)`hoverLabel(string)`Singular|plural for hover card header (default: `':count more item|:count more items'`)`tailwindColorToBadgeClasses(string)`Static helper: converts a Tailwind color name (e.g. `'danger'`, `'blue'`) to full light/dark badge CSS classes### PriorityColumn

[](#prioritycolumn)

Displays priority with icon and color from your enum. Works with any enum implementing `HasLabel`, `HasColor`, and `HasIcon` contracts, or with static `color()`/`icon()` methods.

```
use Codenzia\ProjectEssentials\Tables\Columns\PriorityColumn;

PriorityColumn::make('priority')
    ->label('Priority')
    ->textColor('#FF5733') // Optional: override the enum color
```

### CircularProgressBar

[](#circularprogressbar)

SVG circular progress bar with gradient colors. Reads `real_progress` from the record.

```
use Codenzia\ProjectEssentials\Tables\Columns\CircularProgressBar;

CircularProgressBar::make('progress')
    ->label('Progress')
```

### CreatedUpdatedColumn

[](#createdupdatedcolumn)

Shows created/updated timestamps with user avatars. Requires `created_at`, `updated_at` timestamps and optionally `createdByUser`/`updatedByUser` relationships on the model.

```
use Codenzia\ProjectEssentials\Tables\Columns\CreatedUpdatedColumn;

CreatedUpdatedColumn::make('timestamps')
    ->label('Created & Updated')
    ->limit(15) // Truncate usernames to 15 chars
```

### StateSwitcher

[](#stateswitcher)

A toggle button column with configurable on/off states. Works with string-backed enums, plain strings, integers, or booleans.

```
use Codenzia\ProjectEssentials\Tables\Columns\StateSwitcher;

// With enum values
StateSwitcher::make('status')
    ->onState(StatusEnum::ACTIVE)
    ->offState(StatusEnum::INACTIVE)
    ->onLabel(__('Active'))
    ->offLabel(__('Inactive'))
    ->label('State')

// With plain strings
StateSwitcher::make('status')
    ->onState('enabled')
    ->offState('disabled')
    ->onLabel('On')
    ->offLabel('Off')
```

MethodDescription`onState(mixed)`Value to set when toggled on (default: `'Active'`)`offState(mixed)`Value to set when toggled off (default: `'Inactive'`)`onLabel(string)`Button label when on (default: `'Active'`)`offLabel(string)`Button label when off (default: `'Inactive'`)---

Infolist Entries
----------------

[](#infolist-entries)

### ColoredEnumEntry

[](#coloredenumentry)

TextEntry with enum-based coloring for infolists.

```
use Codenzia\ProjectEssentials\Infolists\Components\ColoredEnumEntry;

ColoredEnumEntry::make('status')
    ->enum(StatusEnum::class)
```

### ProgressBarEntry

[](#progressbarentry)

Progress bar entry for infolists.

```
use Codenzia\ProjectEssentials\Infolists\Components\ProgressBarEntry;

ProgressBarEntry::make('progress')
    ->progressLabel('Done')
    ->alignValue('after')
```

### UserAvatarEntry

[](#useravatarentry)

User avatar display for infolists.

```
use Codenzia\ProjectEssentials\Infolists\Components\UserAvatarEntry;

UserAvatarEntry::make('assignee.avatar')
    ->size('size-12')
```

### TagEntry

[](#tagentry)

Tag display for infolists. Same rendering as `TagColumn`.

```
use Codenzia\ProjectEssentials\Infolists\Components\TagEntry;

TagEntry::make('tags')
    ->label('Tags')
```

### PriorityEntry

[](#priorityentry)

Priority display for infolists with icon and color from your enum.

```
use Codenzia\ProjectEssentials\Infolists\Components\PriorityEntry;

PriorityEntry::make('priority')
    ->label('Priority')
```

### CreatedUpdatedEntry

[](#createdupdatedentry)

Created/updated timestamps with user avatars for infolists.

```
use Codenzia\ProjectEssentials\Infolists\Components\CreatedUpdatedEntry;

CreatedUpdatedEntry::make('timestamps')
    ->label('Created & Updated')
    ->limit(20)
```

---

Filament Actions
----------------

[](#filament-actions)

### SplitButtonDropdownAction

[](#splitbuttondropdownaction)

A split button with a main action on the left and a dropdown chevron on the right showing all actions. Works in both **page-level** header actions (`getHeaderActions()`) and **table** header/record actions — it auto-detects table context and injects it into child actions when available.

> **Important:** Only use `Action::make()` (`Filament\Actions\Action`) inside the split button. **Do not** use `CreateAction`, `EditAction`, `DeleteAction`, or any other specialized Filament action class. These specialized actions rely on internal Livewire method routing (e.g. `mountAction('create')`) that breaks when nested inside an `ActionGroup`. The primary (left) button will silently fail to fire. Instead, use a regular `Action::make()` with an explicit `->schema()` and `->action()` callback.

```
use Codenzia\ProjectEssentials\Filament\Actions\SplitButtonDropdownAction;

// Page-level header action
SplitButtonDropdownAction::make([
    Action::make('createProject')
        ->label('New Project')
        ->icon('heroicon-o-plus')
        ->slideOver()
        ->model(Project::class)
        ->schema(ProjectForm::getFields(true))
        ->action(function (array $data) {
            $project = Project::create($data);
        }),
    Action::make('fromTemplate')
        ->label('From Template')
        ->icon('heroicon-o-document-duplicate'),
])

// Table header action (table context is auto-detected)
$table->headerActions([
    SplitButtonDropdownAction::make([
        Tables\Actions\Action::make('edit')->label('Edit'),
        Tables\Actions\Action::make('delete')->label('Delete')->color('danger'),
    ]),
])

// Wrong — CreateAction will not fire from the primary button
SplitButtonDropdownAction::make([
    CreateAction::make(), // Primary button does nothing
    Action::make('other'),
])
```

---

Helpers
-------

[](#helpers)

### TailwindHelper

[](#tailwindhelper)

Resolves Tailwind v4 dynamic color class issues. Maps Filament color names to full, statically-analyzable class strings.

```
use Codenzia\ProjectEssentials\Helpers\TailwindHelper;

TailwindHelper::text('primary');         // "text-primary-500"
TailwindHelper::text('danger', '600');   // "text-danger-600"
TailwindHelper::bg('success', '100');    // "bg-success-100"
TailwindHelper::border('warning');       // "border-warning-500"
```

### DateHelper

[](#datehelper)

```
use Codenzia\ProjectEssentials\Helpers\DateHelper;

DateHelper::readableDateFormat();          // "dd/mm/yyyy" (based on config)
DateHelper::readableDateTimeFormat();      // "dd/mm/yyyy hh:mm"
DateHelper::getHumanReadableDuration($start, $end); // "30 days (15 left)"
DateHelper::getDelayPeriods();             // [1 => '1 month', 2 => '2 months', ...]
```

### DateRangeHelper

[](#daterangehelper)

```
use Codenzia\ProjectEssentials\Helpers\DateRangeHelper;

DateRangeHelper::make('2024-01-01', '2024-12-31');     // "01/01/2024 - 31/12/2024"
DateRangeHelper::makeShort('2024-01-01', '2024-03-15'); // "1 Jan - 15 Mar '24"
DateRangeHelper::parse('01/01/2024 - 31/12/2024');      // ['start_date' => ..., 'end_date' => ...]
```

### FileHelper

[](#filehelper)

```
use Codenzia\ProjectEssentials\Helpers\FileHelper;

FileHelper::getFileType('photo.jpg');   // "image"
FileHelper::getFileType('report.pdf');  // "document"
FileHelper::getFileType('song.mp3');    // "audio"
FileHelper::getFileType('movie.mp4');   // "video"
```

### FormatHelper

[](#formathelper)

```
use Codenzia\ProjectEssentials\Helpers\FormatHelper;

FormatHelper::truncateText('Long text here...', 10);  // "Long text ..."
FormatHelper::hexToRgba('#FF5733', 0.8);               // "rgba(255, 87, 51, 0.8)"
FormatHelper::getFormattedIdString(42, 'INV');           // "#INV0042"
```

### FilamentTableHelper

[](#filamenttablehelper)

Adds reusable timestamp and userstamp columns to any Filament table.

```
use Codenzia\ProjectEssentials\Tables\FilamentTableHelper;

// Append to a Table instance
FilamentTableHelper::appendStampColumns($table);

// Or merge with an array of columns
$columns = FilamentTableHelper::withStampColumns([
    TextColumn::make('name'),
    TextColumn::make('email'),
]);

// Add a search filter
$filters = FilamentTableHelper::withSearchFilter([], 'name', 'Search by name');
```

---

Blade Components
----------------

[](#blade-components)

### DropdownCheckList

[](#dropdownchecklist)

A multi-select dropdown with checkboxes, optional search, avatar support, and enum integration.

```
{{-- Simple options --}}

{{-- With enum --}}

{{-- Rich options with avatars --}}

```

PropTypeDefaultDescription`options`array`[]`Array of `['value' => ..., 'label' => ...]``enumClass`string`null`Enum class (auto-generates options)`label`string`''`Trigger button label`icon`string`null`Trigger button icon`color`string`'gray'`Button color`allowAll`bool`true`Show "All" radio option`searchable`bool`false`Enable search input`maxHeight`string`'14rem'`Max dropdown height### ResponsiveTabs

[](#responsivetabs)

A responsive tab component that automatically folds overflow tabs into a "More" dropdown when space is limited. Supports Livewire binding, localStorage persistence, badges, icons, disabled tabs, and two layout modes.

```
{{-- Inline layout (default) — icon and label side by side --}}

{{-- Stacked layout — icon on top, label below (compact, fits more tabs) --}}

{{-- With colored icons --}}

```

PropTypeDefaultDescription`tabs`array`[]`Array of tab definitions (keyed or indexed)`active`string`null`Initial active tab ID (when not using `wire:model`)`align`string`'center'`Tab alignment: `'left'`, `'center'`, or `'right'``moreLabel`string`'More'`Label for the overflow dropdown button`persist`string`null`localStorage key for tab persistence`layout`string`'inline'``'inline'` (icon + label side by side) or `'stacked'` (icon above label — more compact)**Tab options** — each entry in the `tabs` array supports:

PropertyTypeRequiredDescription`id`stringYes\*Unique identifier (\*auto from key if keyed array)`label`stringYesDisplay text for the tab`icon`stringNoIcon component name (e.g. `'heroicon-o-home'`)`iconColor`stringNoTailwind text color class for the icon (e.g. `'text-amber-500'`). Overridden by primary color when the tab is active.`badge`int/stringNoBadge value (rendered as Filament badge or floating pill in stacked mode)`params`arrayNoCustom parameters passed through on tab change`disabled`boolNoWhether the tab is disabled**Stacked layout** is ideal when you have many tabs (8+). It renders each tab as a vertical column with the icon on top and label below, reducing per-tab width by ~40% so more tabs fit before overflowing into the "More" dropdown. Badges are rendered as floating pills on the icon's top-right corner.

Requires importing the JS component in your app.js:

```
import '../../vendor/codenzia/project-essentials/resources/js/responsive-tabs.js';
```

### LoadingSpinner

[](#loadingspinner)

Advanced loading overlay with 4 visual variants, configurable blur, opacity, and theme.

```
{{-- Basic --}}

{{-- Full configuration --}}

```

PropTypeDefaultDescription`show`bool`false`Initial visibility`variant`string`'elegant'``'minimal'`, `'elegant'`, `'orbital'`, `'pulse'``size`string`'md'``'sm'`, `'md'`, `'lg'`, `'xl'``blur`string`'md'`Backdrop blur: `'none'`, `'sm'`, `'md'`, `'lg'`, `'xl'``opacity`string`'0'`Background opacity: `'0'`-`'95'``message`string`'Please wait'`Loading message`fullscreen`bool`true`Cover entire viewport`showProgress`bool`false`Indeterminate progress bar`theme`string`'auto'``'auto'`, `'light'`, `'dark'``delay`int`200`Delay (ms) before showing### LocaleSwitcher

[](#localeswitcher)

A standard language-switcher dropdown that renders identically inside a Filament panel **and** on any public Blade page. It ships its own scoped CSS — no `flag-icons` library and no reliance on the host's Tailwind build (the failure mode that breaks utility-class-based switchers on public sites). It shows a globe glyph + the current code, and lists locales by native name with a checkmark on the active one. Dark mode and RTL are handled automatically.

```
{{-- Zero-config: auto-resolves locales (filament-panel-base → config('app.available_locales') → app locale) --}}

{{-- Explicit locales + alignment --}}

{{-- Passing filament-panel-base's active locales --}}

```

Requires a named route to switch locale (default `locale.switch`, receiving the locale code):

```
Route::get('/locale/{locale}', function (string $locale) {
    session()->put('locale', $locale);
    return back();
})->name('locale.switch');
```

PropTypeDefaultDescription`locales`array|nullauto`['en' => [...], 'ar' => [...]]` or list `['en','ar']`. Entries may carry `native`/`dir`; missing values are filled from a built-in native-name map.`currentLocale`string|null`app()->getLocale()`The active locale code.`switchRoute`string`'locale.switch'`Named route to link each locale to.`align`string`'end'`Dropdown alignment: `'start'` or `'end'`.The dropdown only renders when more than one locale is available. Alpine.js (bundled with Filament/Livewire) powers the open/close.

### Banner

[](#banner)

Top-of-page notification banner with success/danger/warning styles.

```

{{-- Trigger from Livewire/Alpine --}}

    window.dispatchEvent(new CustomEvent('banner-message', {
        detail: { style: 'success', message: 'Saved successfully!' }
    }));

```

### UserAvatar

[](#useravatar)

Displays user avatars with automatic fallback. Works standalone or within Filament Column/Entry context.

```

```

### DropdownLink

[](#dropdownlink)

A styled link for use inside dropdown menus.

```

    My Profile

```

### Progress

[](#progress)

A circular progress indicator with SVG arc and gradient colors.

```

```

### Pagination

[](#pagination)

```
{{ $items->links('project-essentials::components.pagination') }}
```

### IconPicker (Form Component)

[](#iconpicker-form-component)

```
use Codenzia\ProjectEssentials\Forms\Components\IconPicker;

IconPicker::make('icon')
    ->label('Icon')
    ->required()
```

---

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

43

—

FairBetter than 89% of packages

Maintenance98

Actively maintained with recent releases

Popularity12

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity43

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 50% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~13 days

Total

3

Last Release

8d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/10361843?v=4)[Mohammad El-Haj](/maintainers/mh2x)[@mh2x](https://github.com/mh2x)

---

Top Contributors

[![sehsah](https://avatars.githubusercontent.com/u/8730764?v=4)](https://github.com/sehsah "sehsah (11 commits)")[![mh2x](https://avatars.githubusercontent.com/u/10361843?v=4)](https://github.com/mh2x "mh2x (9 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (1 commits)")

---

Tags

laravelcodenziaproject-essentials

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/codenzia-project-essentials/health.svg)

```
[![Health](https://phpackages.com/badges/codenzia-project-essentials/health.svg)](https://phpackages.com/packages/codenzia-project-essentials)
```

###  Alternatives

[stephenjude/filament-feature-flags

Filament implementation of feature flags and segmentation with Laravel Pennant.

122177.8k1](/packages/stephenjude-filament-feature-flags)[ysfkaya/filament-phone-input

A phone input component for Laravel Filament

3161.3M25](/packages/ysfkaya-filament-phone-input)[rawilk/profile-filament-plugin

Profile &amp; MFA starter kit for filament.

3914.6k](/packages/rawilk-profile-filament-plugin)[marcelweidum/filament-expiration-notice

Customize the livewire expiration notice

94135.4k5](/packages/marcelweidum-filament-expiration-notice)[biostate/filament-menu-builder

An Elegant Menu Builder for FilamentPHP

6528.1k2](/packages/biostate-filament-menu-builder)[stephenjude/filament-debugger

About

104162.2k2](/packages/stephenjude-filament-debugger)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
