Detalles del ejemplo
Filament Kanban Board
Tablero Kanban interactivo con drag & drop para Filament. Columnas basadas en enums, reordenamiento con SortableJS (bundleado via esbuild), vistas publicables y personalizables, soporte para adjuntos (imágenes y archivos), quick add, y acciones de edición/eliminación con modales Filament.
Arquitectura
Este paquete sigue un diseño abstracto/headless: proporciona toda la lógica del tablero kanban (drag & drop, reordenamiento, CRUD, adjuntos), pero tú defines qué modelo, qué estados y qué formulario usar.
El paquete proporciona:
KanbanBoard— Página abstracta con toda la lógica del tableroKanbanAttachment— Modelo polimórfico para adjuntosHasKanbanAttachments— Trait para habilitar adjuntos en tu modeloKanbanPlugin— Plugin de Filament para registrar las páginas- Vistas Blade publicables, CSS, traducciones (es/en) y configuración
Tú defines:
- Tu modelo Eloquent (ej.
Task,Ticket,Order...) - Tu enum de estados (las columnas del tablero)
- Tu formulario de edición/creación (campos Filament)
Solo necesitas implementar 3 métodos abstractos:
getModel() // → Tu modelo Eloquent
getStatusEnum() // → Tu enum de columnas
getEditFormSchema() // → Tus campos de formulario
El paquete accede a los datos de tu modelo de forma dinámica mediante atributos configurables (getTitleAttribute(), getStatusAttribute(), etc.), lo que permite usar cualquier modelo sin importar cómo se llamen sus campos.
Instalación
composer require cursosdesarrolloweb/filament-kanban
Publica las migraciones (solo si usas adjuntos):
php artisan vendor:publish --tag="filament-kanban-migrations"
php artisan migrate
Publica la configuración (opcional):
php artisan vendor:publish --tag="filament-kanban-config"
Uso
1. Crea un enum de estados
Cada caso del enum representa una columna del tablero. Debe ser un BackedEnum con valores string e implementar HasLabel:
use Filament\Support\Contracts\HasLabel;
enum TaskStatus: string implements HasLabel
{
case Pending = 'pending';
case InProgress = 'in_progress';
case Done = 'done';
public function getLabel(): string
{
return match ($this) {
self::Pending => 'Pendiente',
self::InProgress => 'En progreso',
self::Done => 'Hecho',
};
}
}
2. Crea tu modelo y migración
El paquete no incluye un modelo propio para las tarjetas — tú creas el tuyo. Esto permite que uses cualquier modelo (Task, Ticket, Order, Lead...) con los campos que tu proyecto necesite.
Como mínimo, tu modelo necesita 3 campos (los nombres son configurables):
- Un campo de título (por defecto
title) - Un campo de estado (por defecto
status) — corresponde a las columnas del tablero - Un campo de orden (por defecto
sort_order) — para el ordenamiento dentro de cada columna
Crea la migración
php artisan make:migration create_tasks_table
Schema::create('tasks', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('description')->nullable();
$table->string('status')->default('pending');
$table->integer('sort_order')->default(0);
// Añade aquí los campos extra que necesites:
// $table->string('priority')->nullable();
// $table->date('due_date')->nullable();
// $table->foreignId('user_id')->nullable()->constrained();
$table->timestamps();
});
Crea el modelo
php artisan make:model Task
namespace App\Models;
use App\Enums\TaskStatus;
use Illuminate\Database\Eloquent\Model;
class Task extends Model
{
protected $fillable = [
'title',
'description',
'status',
'sort_order',
// Añade aquí todos los campos que sean fillable
];
protected function casts(): array
{
return [
'status' => TaskStatus::class,
'sort_order' => 'integer',
];
}
}
Importante: Todos los campos que uses en el formulario (
getEditFormSchema()) deben estar en$fillable, o el modelo no los guardará.
Nombres de campo personalizados
Si tu modelo usa nombres distintos a los valores por defecto (ej. name en vez de title), sobrescribe los métodos correspondientes en tu página Kanban:
protected function getTitleAttribute(): string
{
return 'name'; // default: 'title'
}
protected function getStatusAttribute(): string
{
return 'state'; // default: 'status'
}
protected function getSortAttribute(): string
{
return 'position'; // default: 'sort_order'
}
3. Crea tu página Kanban
Extiende KanbanBoard e implementa los 3 métodos abstractos:
use CursosDesarrolloWeb\Kanban\Pages\KanbanBoard;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
class MyKanban extends KanbanBoard
{
protected static ?string $navigationLabel = 'Mi Kanban';
protected function getModel(): string
{
return Task::class;
}
protected function getStatusEnum(): string
{
return TaskStatus::class;
}
protected function getEditFormSchema(): array
{
return [
TextInput::make('title')
->label('Título')
->required()
->maxLength(255),
Select::make('status')
->label('Estado')
->options(TaskStatus::class)
->required(),
];
}
}
4. Registra el plugin en tu panel
use CursosDesarrolloWeb\Kanban\KanbanPlugin;
public function panel(Panel $panel): Panel
{
return $panel
->plugins([
KanbanPlugin::make(),
]);
}
Si tu panel usa discoverPages() (que es lo habitual), tu página Kanban se registrará automáticamente y no necesitas hacer nada más.
Si tu página Kanban no está en la carpeta autodescubierta (ej. está en otro namespace o módulo), pásala explícitamente al plugin:
KanbanPlugin::make()
->pages([MyKanban::class]),
Personalización
Todos los métodos de personalización se sobrescriben en tu página Kanban (la clase que extiende KanbanBoard):
class MyKanban extends KanbanBoard
{
// Aquí van todos los métodos de personalización
}
Para personalización visual (colores, tamaños, espaciado...), consulta la sección Personalización CSS donde se documentan todas las clases fi-kanban-* que puedes sobrescribir.
Vistas publicables
El paquete divide su interfaz en 6 vistas independientes que puedes publicar y personalizar:
views/
├── pages/
│ └── kanban-board.blade.php ← Board completo (orquesta columnas)
├── column.blade.php ← Columna (header + cards + quick-add)
├── column-header.blade.php ← Cabecera (label, contador, botón +)
├── card.blade.php ← Tarjeta (topbar, contenido, detalles, adjuntos)
├── quick-add.blade.php ← Input inline para añadir rápido
└── attachment-list.blade.php ← Listado de adjuntos en el modal de edición
Publicar todas las vistas
php artisan vendor:publish --tag="filament-kanban-views"
Esto copia las vistas a resources/views/vendor/filament-kanban/. Cualquier cambio se aplica a todos los boards de tu aplicación.
Personalizar por board
Si quieres que un board específico use una vista distinta sin afectar al resto, sobrescribe el método correspondiente en tu clase:
| Método | Default | Controla |
|---|---|---|
getColumnView() |
filament-kanban::column |
La columna completa |
getColumnHeaderView() |
filament-kanban::column-header |
La cabecera de columna |
getCardView() |
filament-kanban::card |
La tarjeta |
getQuickAddView() |
filament-kanban::quick-add |
El input de añadido rápido |
Ejemplo: card personalizada para un Sales Pipeline
Crea tu vista en resources/views/kanban/sales-card.blade.php:
@props([
'record',
'canReorder' => false,
'canEdit' => false,
'canDelete' => false,
'priorityAttr' => null,
'titleAttr' => 'title',
'details' => [],
'hasAttachments' => false,
'imageUrl' => null,
'attachCount' => 0,
])
@php
$stage = $record->stage;
$dealValue = $record->deal_value ?? 0;
$percentage = min(100, round(($dealValue / 200000) * 100));
$color = match($stage->value) {
'new' => '#38bdf8',
'qualified' => '#fbbf24',
'won' => '#34d399',
default => '#6366f1',
};
@endphp
{{-- Top bar (mantén el drag handle y botones del paquete) --}}
<div class="fi-kanban-card-topbar">
@if ($canReorder)
<div class="fi-kanban-drag-handle">
<x-filament::icon icon="heroicon-m-bars-2" style="width: 0.875rem; height: 0.875rem;" />
</div>
@endif
@if ($canEdit || $canDelete)
<div style="display: flex; align-items: center;">
@if ($canEdit)
<button type="button"
x-on:click.stop="$wire.mountAction('editRecord', { record: '{{ $record->getKey() }}' })"
class="fi-kanban-edit-btn">
<x-filament::icon icon="heroicon-m-pencil-square" style="width: 0.875rem; height: 0.875rem;" />
</button>
@endif
@if ($canDelete)
<button type="button"
x-on:click.stop="$wire.mountAction('deleteQuickRecord', { record: '{{ $record->getKey() }}' })"
class="fi-kanban-delete-btn">
<x-filament::icon icon="heroicon-m-trash" style="width: 0.875rem; height: 0.875rem;" />
</button>
@endif
</div>
@endif
</div>
{{-- Tu contenido custom --}}
<div class="fi-kanban-card-content">
<div style="display: flex; align-items: center; gap: 0.375rem;">
<x-filament::icon :icon="$stage->getIcon()"
style="width: 1rem; height: 1rem; color: {{ $color }};" />
<p class="fi-kanban-card-title" style="margin: 0;">{{ $record->company }}</p>
</div>
@if ($dealValue > 0)
<div style="margin-top: 0.5rem;">
<span style="font-size: 1.125rem; font-weight: 700; color: {{ $color }};">
${{ number_format($dealValue, 0) }}
</span>
<div style="height: 4px; border-radius: 9999px; background: rgba(148,163,184,0.2); margin-top: 0.25rem;">
<div style="height: 100%; width: {{ $percentage }}%; border-radius: 9999px; background: {{ $color }};"></div>
</div>
</div>
@endif
</div>
Y apunta a ella desde tu board:
class SalesPipeline extends KanbanBoard
{
protected function getCardView(): string
{
return 'kanban.sales-card';
}
// ... resto de tu configuración
}
Nota: La vista recibe todas las props que necesitas (
$record,$canReorder,$canEdit,$canDelete,$details, etc.). Consulta la vistacard.blade.phpdel paquete como referencia para ver todas las props disponibles.
Colores de columnas
Los colores usan valores CSS (hex, rgb, rgba), no clases Tailwind:
protected function getColumnColors(): array
{
return [
'pending' => 'rgba(0,0,0,0.04)',
'in_progress' => 'rgba(251,191,36,0.08)',
'done' => 'rgba(52,211,153,0.08)',
];
}
protected function getColumnHeaderColors(): array
{
return [
'pending' => '#9ca3af',
'in_progress' => '#fbbf24',
'done' => '#34d399',
];
}
Prioridad visual en cards
Activa la barra de prioridad indicando qué atributo del modelo la contiene:
protected function getPriorityAttribute(): ?string
{
return 'priority'; // default: null (desactivado)
}
Los valores de prioridad por defecto son low, medium, high y critical, con colores definidos en CSS. Si tu modelo usa valores distintos, sobrescribe:
protected function getPriorityValues(): array
{
return ['low', 'medium', 'high'];
}
Y añade los estilos correspondientes en tu CSS:
.fi-kanban-priority--low { background: rgb(209, 213, 219); }
.fi-kanban-priority--medium { background: rgb(56, 189, 248); }
.fi-kanban-priority--high { background: rgb(251, 191, 36); }
Detalles en las cards
Añade información extra debajo del título. Tipos soportados: badge, date, avatar, text.
protected function getCardDetails(Model $record): array
{
$details = [];
if ($record->assignee) {
$details[] = ['type' => 'avatar', 'value' => $record->assignee];
}
if ($record->due_date) {
// urgency: true activa estilos de "próximo" (2 días) y "vencido"
$details[] = ['type' => 'date', 'value' => $record->due_date, 'urgency' => true];
}
if ($record->category) {
$details[] = ['type' => 'badge', 'value' => $record->category];
}
$details[] = ['type' => 'text', 'value' => 'Nota adicional'];
return $details;
}
Eager loading de relaciones
protected function getRecordEagerLoads(): array
{
return ['assignee', 'project'];
}
Quick add (añadido rápido)
El quick add permite crear tarjetas directamente desde cada columna. Puedes asignar valores por defecto:
protected function getQuickAddDefaults(string $status): array
{
return [
'priority' => 'medium',
'user_id' => auth()->id(),
];
}
Para desactivar el quick add:
protected function hasQuickAdd(): bool
{
return false;
}
Hook de cambio de estado
Se ejecuta cuando una tarjeta se mueve a otra columna por drag & drop. Devuelve un array con datos extra para actualizar:
protected function onStatusChanged(Model $record, string $newStatus): array
{
if ($newStatus === TaskStatus::InProgress->value && $record->started_at === null) {
return ['started_at' => now()];
}
if ($newStatus === TaskStatus::Done->value) {
return ['completed_at' => now()];
}
return ['completed_at' => null];
}
Autorización
Controla quién puede crear, editar, eliminar o reordenar tarjetas:
protected function canCreateRecord(): bool
{
return auth()->user()->can('create', Task::class);
}
protected function canEditRecord(Model $record): bool
{
return auth()->user()->can('update', $record);
}
protected function canDeleteRecord(Model $record): bool
{
return auth()->user()->can('delete', $record);
}
protected function canReorderRecords(): bool
{
return auth()->user()->can('reorder', Task::class);
}
Ancho de columnas y animación
protected function getColumnWidth(): string
{
return '24rem'; // default: '20rem'
}
protected function getCardAnimation(): int
{
return 200; // milisegundos, default: 150
}
Adjuntos
Activación
- Publica y ejecuta la migración:
php artisan vendor:publish --tag="filament-kanban-migrations"
php artisan migrate
- Añade el trait a tu modelo:
use CursosDesarrolloWeb\Kanban\Concerns\HasKanbanAttachments;
class Task extends Model
{
use HasKanbanAttachments;
}
- Activa los adjuntos en tu página (o en la configuración):
protected function hasAttachments(): bool
{
return true;
}
Configuración de adjuntos
En config/filament-kanban.php:
'attachments' => [
'enabled' => false, // Activar/desactivar globalmente
'disk' => 'public', // Disco de almacenamiento
'directory' => 'kanban-attachments', // Directorio
'max_size' => 5120, // Tamaño máximo en KB
'accepted_types' => ['image/*', 'application/pdf', ...],
'max_files' => 10, // Máximo de archivos por tarjeta
],
Almacenamiento en disco
Los archivos se organizan por tarjeta en subdirectorios del disco configurado:
storage/app/public/
└── kanban-attachments/
├── 1/
│ ├── foto.jpg
│ └── documento.pdf
├── 2/
│ └── captura.png
└── 3/
├── informe.xlsx
└── logo.svg
Cuando se crea o edita una tarjeta, los archivos subidos se mueven automáticamente a {directory}/{record_id}/. Si se eliminan adjuntos, los archivos también se borran del disco.
Modal de edición
Al abrir el modal de edición de una tarjeta con adjuntos:
- Arriba: El formulario de edición con el campo FileUpload, que muestra los archivos existentes y permite subir nuevos
- Abajo: Un listado de los adjuntos existentes con:
- Thumbnail (si es imagen) o icono de documento
- Nombre del archivo y tamaño
- Botón de descarga directa
- Botón de eliminar (con confirmación, borra registro y archivo del disco)
En la tarjeta
- Las imágenes se muestran como miniatura en la tarjeta
- Se muestra un contador de adjuntos con icono de clip, clicable para abrir el modal de edición
- Los adjuntos usan relación polimórfica (
MorphMany), por lo que funcionan con cualquier modelo - Puedes personalizar el modelo de adjuntos en la config:
models.attachment
Personalización CSS — Sobrescribir clases fi-kanban-*
Todos los estilos del tablero usan clases CSS con prefijo fi-kanban-, siguiendo la convención de Filament (fi- = Filament). Todas incluyen variantes para dark mode con .dark .fi-kanban-*.
Cómo aplicar tus sobrescrituras
La forma recomendada es usar un custom theme de Filament. Si aún no tienes uno, créalo con:
php artisan make:filament-theme admin
Esto genera resources/css/filament/admin/theme.css. Añade tus sobrescrituras al final del archivo:
@import '../../../../vendor/filament/filament/resources/css/theme.css';
@source '../../../../app/Filament/**/*.php';
/* Tus sobrescrituras del kanban */
.fi-kanban-card {
border-radius: 1rem;
border-left: 4px solid var(--color-primary-500);
}
Registra el tema en tu panel provider y en vite.config.js:
// AdminPanelProvider.php
$panel->viteTheme('resources/css/filament/admin/theme.css');
// vite.config.js
input: [
'resources/css/app.css',
'resources/js/app.js',
'resources/css/filament/admin/theme.css',
]
Clases disponibles
Tablero y columnas
| Clase | Descripción |
|---|---|
.fi-kanban-board |
Contenedor principal del tablero (flex horizontal con scroll) |
.fi-kanban-column |
Columna individual |
.fi-kanban-column-header |
Cabecera de columna (label + contador) |
.fi-kanban-column-label |
Texto del nombre de la columna |
.fi-kanban-count |
Badge con número de tarjetas |
.fi-kanban-col-bg--default |
Fondo por defecto de las columnas |
Tarjetas
| Clase | Descripción |
|---|---|
.fi-kanban-cards |
Contenedor de tarjetas (scroll vertical) |
.fi-kanban-card |
Tarjeta individual |
.fi-kanban-card-topbar |
Barra superior (drag handle + botones editar/eliminar) |
.fi-kanban-card-content |
Contenido de la tarjeta |
.fi-kanban-card-title |
Título de la tarjeta |
Controles
| Clase | Descripción |
|---|---|
.fi-kanban-create-btn |
Botón "+" en el header de columna para crear tarjeta |
.fi-kanban-drag-handle |
Icono de arrastre (barras) |
.fi-kanban-edit-btn |
Botón de editar (lápiz) |
.fi-kanban-delete-btn |
Botón de eliminar (papelera, rojo) |
Detalles de la tarjeta
| Clase | Descripción |
|---|---|
.fi-kanban-details |
Contenedor de badges/fechas/texto |
.fi-kanban-badge |
Etiqueta de texto |
.fi-kanban-date |
Fecha con icono de calendario |
.fi-kanban-date--normal |
Fecha sin urgencia |
.fi-kanban-date--soon |
Fecha próxima (2 días o menos) |
.fi-kanban-date--overdue |
Fecha vencida |
.fi-kanban-text |
Texto auxiliar |
Avatares (stacked)
| Clase | Descripción |
|---|---|
.fi-kanban-avatars |
Contenedor de avatares apilados al pie de la card |
.fi-kanban-avatar |
Avatar circular con iniciales (indigo, 1.625rem) |
Prioridad
| Clase | Descripción |
|---|---|
.fi-kanban-priority-strip |
Barra de prioridad |
.fi-kanban-priority--low |
Prioridad baja (gris) |
.fi-kanban-priority--medium |
Prioridad media (azul) |
.fi-kanban-priority--high |
Prioridad alta (ámbar) |
.fi-kanban-priority--critical |
Prioridad crítica (rojo) |
Adjuntos (card)
| Clase | Descripción |
|---|---|
.fi-kanban-thumbnail |
Contenedor de miniatura de imagen |
.fi-kanban-attach-count |
Contador de adjuntos con icono |
.fi-kanban-attach-count--clickable |
Estilo hover para el contador clicable |
Adjuntos (modal de edición)
| Clase | Descripción |
|---|---|
.fi-kanban-attachment-list |
Contenedor del listado de adjuntos |
.fi-kanban-attachment-list-title |
Título "Adjuntos existentes (N)" |
.fi-kanban-attachment-items |
Contenedor de items |
.fi-kanban-attachment-item |
Fila de un adjunto |
.fi-kanban-attachment-preview |
Contenedor de thumbnail/icono |
.fi-kanban-attachment-thumb |
Imagen thumbnail |
.fi-kanban-attachment-icon |
Icono de documento |
.fi-kanban-attachment-info |
Nombre y tamaño |
.fi-kanban-attachment-name |
Nombre del archivo |
.fi-kanban-attachment-size |
Tamaño en KB |
.fi-kanban-attachment-actions |
Contenedor de botones |
.fi-kanban-attachment-download |
Botón de descarga |
.fi-kanban-attachment-delete |
Botón de eliminar |
Drag & drop (SortableJS)
| Clase | Descripción |
|---|---|
.fi-kanban-ghost |
Placeholder que ocupa la posición destino durante el arrastre |
.fi-kanban-chosen |
Tarjeta seleccionada (elevación con sombra) |
.fi-kanban-drag |
Tarjeta mientras se arrastra |
Quick add
| Clase | Descripción |
|---|---|
.fi-kanban-quick-add |
Sección de añadido rápido |
.fi-kanban-quick-add-btn |
Botón "Añadir tarjeta" |
.fi-kanban-quick-input |
Textarea de entrada |
.fi-kanban-quick-actions |
Contenedor de botones enviar/cancelar |
.fi-kanban-quick-submit |
Botón de enviar |
.fi-kanban-quick-cancel |
Botón de cancelar |
Ejemplo de sobrescritura
Ejemplo para personalizar las tarjetas:
/* Cambiar el fondo de las tarjetas */
.fi-kanban-card {
background: #f8fafc;
border-radius: 1rem;
}
.dark .fi-kanban-card {
background: rgb(15, 23, 42);
}
/* Hacer las prioridades más anchas */
.fi-kanban-priority-strip {
width: 100%;
height: 0.2rem;
}
/* Ocultar el drag handle en móvil */
@media (max-width: 768px) {
.fi-kanban-drag-handle { display: none; }
}
Configuración completa
// config/filament-kanban.php
return [
'board' => [
'column_width' => '20rem',
'card_animation' => 150,
'quick_add' => true,
],
'attachments' => [
'enabled' => false,
'disk' => 'public',
'directory' => 'kanban-attachments',
'max_size' => 5120,
'accepted_types' => ['image/*', 'application/pdf', '.doc', '.docx', '.xls', '.xlsx', '.zip'],
'max_files' => 10,
],
'models' => [
'attachment' => \CursosDesarrolloWeb\Kanban\Models\KanbanAttachment::class,
],
'tables' => [
'attachments' => 'kanban_attachments',
],
];
Traducciones
El paquete incluye traducciones en español e inglés. Las claves disponibles son:
| Clave | ES | EN |
|---|---|---|
kanban.board.add_card |
Añadir tarjeta | Add card |
kanban.board.add |
Añadir | Add |
kanban.board.cancel |
Cancelar | Cancel |
kanban.board.placeholder |
Escribe un título... | Enter a title... |
kanban.board.edit |
Editar | Edit |
kanban.board.delete |
Eliminar | Delete |
kanban.board.delete_confirm |
¿Estás seguro de que quieres eliminar esta tarjeta? | Are you sure you want to delete this card? |
kanban.notifications.card_created |
Tarjeta creada | Card created |
kanban.notifications.card_deleted |
Tarjeta eliminada | Card deleted |
kanban.notifications.unauthorized |
No tienes permiso para realizar esta acción | You are not authorized to perform this action |
kanban.attachments.label |
Adjuntos | Attachments |
kanban.attachments.existing |
Adjuntos existentes | Existing attachments |
kanban.attachments.download |
Descargar | Download |
kanban.attachments.delete |
Eliminar adjunto | Delete attachment |
kanban.attachments.delete_confirm |
¿Estás seguro de que quieres eliminar este adjunto? | Are you sure you want to delete this attachment? |
Para publicar y personalizar las traducciones:
php artisan vendor:publish --tag="filament-kanban-translations"
Métodos disponibles
Abstractos (obligatorios)
| Método | Retorno | Descripción |
|---|---|---|
getModel() |
string |
Clase Eloquent del modelo |
getStatusEnum() |
string |
Enum BackedEnum con HasLabel |
getEditFormSchema() |
array |
Componentes Filament para el formulario |
Configuración de atributos
| Método | Default | Descripción |
|---|---|---|
getTitleAttribute() |
'title' |
Campo del modelo mostrado como título |
getStatusAttribute() |
'status' |
Campo del modelo con el estado |
getSortAttribute() |
'sort_order' |
Campo del modelo para ordenamiento |
getPriorityAttribute() |
null |
Campo de prioridad (null = desactivado) |
getPriorityValues() |
['low', 'medium', 'high', 'critical'] |
Valores de prioridad (mapean a clases CSS) |
Vistas
| Método | Default | Descripción |
|---|---|---|
getColumnView() |
'filament-kanban::column' |
Vista de la columna completa |
getColumnHeaderView() |
'filament-kanban::column-header' |
Vista de la cabecera de columna |
getCardView() |
'filament-kanban::card' |
Vista de la tarjeta |
getQuickAddView() |
'filament-kanban::quick-add' |
Vista del input de añadido rápido |
Apariencia
| Método | Default | Descripción |
|---|---|---|
getColumnColors() |
[] |
Fondo de columnas (valores CSS, no Tailwind) |
getColumnHeaderColors() |
[] |
Color del borde inferior del header |
getCardDetails(Model) |
[] |
Detalles extra: badge, date, avatar, text |
getColumnWidth() |
'20rem' |
Ancho de cada columna (valor CSS) |
getCardAnimation() |
150 |
Duración de animación en ms |
Funcionalidades
| Método | Default | Descripción |
|---|---|---|
hasQuickAdd() |
true |
Habilitar añadido rápido |
hasAttachments() |
false |
Habilitar adjuntos |
getQuickAddDefaults(string) |
[] |
Valores por defecto al crear rápido |
getRecordEagerLoads() |
[] |
Relaciones a precargar |
onStatusChanged(Model, string) |
[] |
Hook al mover tarjeta (devuelve datos extra) |
Acciones integradas
Cada columna y tarjeta incluye acciones Filament que se pueden sobrescribir:
| Método | Descripción |
|---|---|
createRecordAction() |
Botón "+" en el header de columna. Abre modal con formulario y status pre-seleccionado |
editRecordAction() |
Botón lápiz en la tarjeta. Abre modal de edición con opción de eliminar |
deleteQuickRecordAction() |
Botón papelera en la tarjeta. Elimina con confirmación sin abrir modal |
Autorización
| Método | Default | Descripción |
|---|---|---|
canCreateRecord() |
true |
Permiso para crear tarjetas (oculta "+", quick add) |
canEditRecord(Model) |
true |
Permiso para editar una tarjeta (oculta lápiz) |
canDeleteRecord(Model) |
true |
Permiso para eliminar una tarjeta (oculta papelera) |
canReorderRecords() |
true |
Permiso para reordenar y mover tarjetas (oculta drag handle, desactiva drag & drop) |
Requisitos
- PHP 8.2+
- Laravel 11+
- Filament 4.x / 5.x
Licencia
Propietario - Solo para suscriptores de CursosDesarrolloWeb.