Repository: filamentphp/filament (php)

Issue:
Deprecate BooleanColumn in return for IconColumn::make()->boolean()

Pull request description:
chore: Deprecate BooleanColumn
Fixes #4273

Patch:
diff --git a/packages/admin/docs/02-resources/02-listing-records.md b/packages/admin/docs/02-resources/02-listing-records.md
index ebc2f48268..120c90630e 100644
--- a/packages/admin/docs/02-resources/02-listing-records.md
+++ b/packages/admin/docs/02-resources/02-listing-records.md
@@ -9,7 +9,6 @@ The `$table->columns()` method is used to define the [columns](../../tables/colu
 We have many columns available for your tables, including:
 
 - [Text column](../../tables/columns/text)
-- [Boolean column](../../tables/columns/boolean)
 - [Image column](../../tables/columns/image)
 - [Icon column](../../tables/columns/icon)
 - [Badge column](../../tables/columns/badge)
diff --git a/packages/admin/src/Commands/Concerns/CanGenerateResources.php b/packages/admin/src/Commands/Concerns/CanGenerateResources.php
index 69b805c27b..1609c6ea5c 100644
--- a/packages/admin/src/Commands/Concerns/CanGenerateResources.php
+++ b/packages/admin/src/Commands/Concerns/CanGenerateResources.php
@@ -131,12 +131,12 @@ trait CanGenerateResources
 
             $columnData = [];
 
-            $columnData['type'] = $type = match ($column->getType()::class) {
-                Types\BooleanType::class => Tables\Columns\BooleanColumn::class,
-                default => Tables\Columns\TextColumn::class,
-            };
+            if ($column->getType() instanceof Types\BooleanType) {
+                $columnData['type'] = Tables\Columns\IconColumn::class;
+                $columnData['boolean'] = [];
+            } else {
+                $columnData['type'] = Tables\Columns\TextColumn::class;
 
-            if ($type === Tables\Columns\TextColumn::class) {
                 if ($column->getType()::class === Types\DateType::class) {
                     $columnData['date'] = [];
                 }
diff --git a/packages/tables/docs/02-getting-started.md b/packages/tables/docs/02-getting-started.md
index ea9acd6b56..c132adc472 100644
--- a/packages/tables/docs/02-getting-started.md
+++ b/packages/tables/docs/02-getting-started.md
@@ -100,7 +100,7 @@ class ListPosts extends Component implements Tables\Contracts\HasTable
                     'warning' => 'reviewing',
                     'success' => 'published',
                 ]),
-            Tables\Columns\BooleanColumn::make('is_featured'),
+            Tables\Columns\IconColumn::make('is_featured')->boolean(),
         ]; // [tl! collapse:end]
     }
     
@@ -393,7 +393,7 @@ class ListPosts extends Component implements Tables\Contracts\HasTable
                     'warning' => 'reviewing',
                     'success' => 'published',
                 ]),
-            Tables\Columns\BooleanColumn::make('is_featured'),
+            Tables\Columns\IconColumn::make('is_featured')->boolean(),
         ]; // [tl! collapse:end]
     }
     
@@ -544,7 +544,7 @@ class ListPosts extends Component implements Tables\Contracts\HasTable
                     'warning' => 'reviewing',
                     'success' => 'published',
                 ]),
-            Tables\Columns\BooleanColumn::make('is_featured'),
+            Tables\Columns\IconColumn::make('is_featured')->boolean(),
         ];
     } // [tl! collapse:end]
     
diff --git a/packages/tables/docs/03-columns/01-getting-started.md b/packages/tables/docs/03-columns/01-getting-started.md
index dcfb1290cd..10040300c2 100644
--- a/packages/tables/docs/03-columns/01-getting-started.md
+++ b/packages/tables/docs/03-columns/01-getting-started.md
@@ -44,9 +44,8 @@ Filament ships with two main types of columns - static and editable.
 Static columns display data to the user:
 
 - [Text column](text)
-- [Boolean column](boolean)
-- [Image column](image)
 - [Icon column](icon)
+- [Image column](image)
 - [Badge column](badge)
 - [Tags column](tags)
 - [Color column](color)
@@ -346,9 +345,9 @@ Column::configureUsing(function (Column $column): void {
 Additionally, you can call this code on specific column types as well:
 
 ```php
-use Filament\Tables\Columns\BooleanColumn;
+use Filament\Tables\Columns\TextColumn;
 
-BooleanColumn::configureUsing(function (BooleanColumn $column): void {
+TextColumn::configureUsing(function (TextColumn $column): void {
     $column
         ->toggleable()
         ->sortable();
@@ -358,7 +357,7 @@ BooleanColumn::configureUsing(function (BooleanColumn $column): void {
 Of course, you are still able to overwrite this on each column individually:
 
 ```php
-use Filament\Tables\Columns\BooleanColumn;
+use Filament\Tables\Columns\TextColumn;
 
-BooleanColumn::make('is_admin')->toggleable(false)
+TextColumn::make('name')->toggleable(false)
 ```
diff --git a/packages/tables/docs/03-columns/03-boolean.md b/packages/tables/docs/03-columns/03-boolean.md
deleted file mode 100644
index c026c6d5b0..0000000000
--- a/packages/tables/docs/03-columns/03-boolean.md
+++ /dev/null
@@ -1,35 +0,0 @@
----
-title: Boolean column
----
-
-Boolean columns display a check or cross icon based on the contents of the database column, either true or false:
-
-```php
-use Filament\Tables\Columns\BooleanColumn;
-
-BooleanColumn::make('is_featured')
-```
-
-## Customizing the icons
-
-You may customize the icon representing each state. Icons are the name of a Blade component present. By default, [Heroicons](https://heroicons.com) are installed:
-
-```php
-use Filament\Tables\Columns\BooleanColumn;
-
-BooleanColumn::make('is_featured')
-    ->trueIcon('heroicon-o-badge-check')
-    ->falseIcon('heroicon-o-x-circle')
-```
-
-## Customizing the colors
-
-You may customize the icon color representing each state. These may be either `primary`, `secondary`, `success`, `warning` or `danger`:
-
-```php
-use Filament\Tables\Columns\BooleanColumn;
-
-BooleanColumn::make('is_featured')
-    ->trueColor('primary')
-    ->falseColor('warning')
-```
diff --git a/packages/tables/docs/03-columns/05-icon.md b/packages/tables/docs/03-columns/03-icon.md
similarity index 59%
rename from packages/tables/docs/03-columns/05-icon.md
rename to packages/tables/docs/03-columns/03-icon.md
index cf68d3d8aa..7631fec0ea 100644
--- a/packages/tables/docs/03-columns/05-icon.md
+++ b/packages/tables/docs/03-columns/03-icon.md
@@ -51,3 +51,39 @@ IconColumn::make('is_featured')
         'success' => 'published',
     ])
 ```
+
+## Handling booleans
+
+Icon columns can display a check or cross icon based on the contents of the database column, either true or false, using the `boolean()` method:
+
+```php
+use Filament\Tables\Columns\IconColumn;
+
+IconColumn::make('is_featured')
+```
+
+### Customizing the boolean icons
+
+You may customize the icon representing each state. Icons are the name of a Blade component present. By default, [Heroicons](https://heroicons.com) are installed:
+
+```php
+use Filament\Tables\Columns\IconColumn;
+
+IconColumn::make('is_featured')
+    ->boolean()
+    ->trueIcon('heroicon-o-badge-check')
+    ->falseIcon('heroicon-o-x-circle')
+```
+
+### Customizing the boolean colors
+
+You may customize the icon color representing each state. These may be either `primary`, `secondary`, `success`, `warning` or `danger`:
+
+```php
+use Filament\Tables\Columns\IconColumn;
+
+IconColumn::make('is_featured')
+    ->boolean()
+    ->trueColor('primary')
+    ->falseColor('warning')
+```
diff --git a/packages/tables/docs/03-columns/06-badge.md b/packages/tables/docs/03-columns/05-badge.md
similarity index 100%
rename from packages/tables/docs/03-columns/06-badge.md
rename to packages/tables/docs/03-columns/05-badge.md
diff --git a/packages/tables/docs/03-columns/07-tags.md b/packages/tables/docs/03-columns/06-tags.md
similarity index 100%
rename from packages/tables/docs/03-columns/07-tags.md
rename to packages/tables/docs/03-columns/06-tags.md
diff --git a/packages/tables/docs/03-columns/08-color.md b/packages/tables/docs/03-columns/07-color.md
similarity index 100%
rename from packages/tables/docs/03-columns/08-color.md
rename to packages/tables/docs/03-columns/07-color.md
diff --git a/packages/tables/docs/03-columns/09-select.md b/packages/tables/docs/03-columns/08-select.md
similarity index 100%
rename from packages/tables/docs/03-columns/09-select.md
rename to packages/tables/docs/03-columns/08-select.md
diff --git a/packages/tables/docs/03-columns/10-toggle.md b/packages/tables/docs/03-columns/09-toggle.md
similarity index 100%
rename from packages/tables/docs/03-columns/10-toggle.md
rename to packages/tables/docs/03-columns/09-toggle.md
diff --git a/packages/tables/docs/03-columns/11-text-input.md b/packages/tables/docs/03-columns/10-text-input.md
similarity index 100%
rename from packages/tables/docs/03-columns/11-text-input.md
rename to packages/tables/docs/03-columns/10-text-input.md
diff --git a/packages/tables/docs/03-columns/12-checkbox.md b/packages/tables/docs/03-columns/11-checkbox.md
similarity index 100%
rename from packages/tables/docs/03-columns/12-checkbox.md
rename to packages/tables/docs/03-columns/11-checkbox.md
diff --git a/packages/tables/docs/03-columns/13-custom.md b/packages/tables/docs/03-columns/12-custom.md
similarity index 100%
rename from packages/tables/docs/03-columns/13-custom.md
rename to packages/tables/docs/03-columns/12-custom.md
diff --git a/packages/tables/docs/03-columns/14-relationships.md b/packages/tables/docs/03-columns/13-relationships.md
similarity index 100%
rename from packages/tables/docs/03-columns/14-relationships.md
rename to packages/tables/docs/03-columns/13-relationships.md
diff --git a/packages/tables/resources/views/columns/boolean-column.blade.php b/packages/tables/resources/views/columns/boolean-column.blade.php
deleted file mode 100644
index 14c3b9c119..0000000000
--- a/packages/tables/resources/views/columns/boolean-column.blade.php
+++ /dev/null
@@ -1,26 +0,0 @@
-@php
-    $state = $getState();
-
-    $stateIcon = $getStateIcon() ?? ($state ? 'heroicon-o-check-circle' : 'heroicon-o-x-circle');
-    $stateColor = $getStateColor() ?? ($state ? 'success' : 'danger');
-
-    $stateColor = match ($stateColor) {
-        'danger' => 'text-danger-500',
-        'primary' => 'text-primary-500',
-        'success' => 'text-success-500',
-        'warning' => 'text-warning-500',
-        default => 'text-gray-700',
-    };
-@endphp
-
-<div {{ $attributes->merge($getExtraAttributes())->class([
-    'filament-tables-boolean-column',
-    'px-4 py-3' => ! $isInline(),
-]) }}>
-    @if ($state !== null)
-        <x-dynamic-component
-            :component="$stateIcon"
-            :class="'w-6 h-6' . ' ' . $stateColor"
-        />
-    @endif
-</div>
diff --git a/packages/tables/src/Columns/BooleanColumn.php b/packages/tables/src/Columns/BooleanColumn.php
index c359632a44..5d3809b223 100644
--- a/packages/tables/src/Columns/BooleanColumn.php
+++ b/packages/tables/src/Columns/BooleanColumn.php
@@ -2,103 +2,13 @@
 
 namespace Filament\Tables\Columns;
 
-use Closure;
-
-class BooleanColumn extends Column
+/**
+ * @deprecated Use IconColumn with the `boolean()` method instead.
+ */
+class BooleanColumn extends IconColumn
 {
-    protected string $view = 'tables::columns.boolean-column';
-
-    protected string | Closure | null $falseColor = null;
-
-    protected string | Closure | null $falseIcon = null;
-
-    protected string | Closure | null $trueColor = null;
-
-    protected string | Closure | null $trueIcon = null;
-
-    public function false(string | Closure | null $icon = null, string | Closure | null $color = null): static
-    {
-        $this->falseIcon($icon);
-        $this->falseColor($color);
-
-        return $this;
-    }
-
-    public function falseColor(string | Closure | null $color): static
-    {
-        $this->falseColor = $color;
-
-        return $this;
-    }
-
-    public function falseIcon(string | Closure | null $icon): static
-    {
-        $this->falseIcon = $icon;
-
-        return $this;
-    }
-
-    public function true(string | Closure | null $icon = null, string | Closure | null $color = null): static
-    {
-        $this->trueIcon($icon);
-        $this->trueColor($color);
-
-        return $this;
-    }
-
-    public function trueColor(string | Closure | null $color): static
-    {
-        $this->trueColor = $color;
-
-        return $this;
-    }
-
-    public function trueIcon(string | Closure | null $icon): static
-    {
-        $this->trueIcon = $icon;
-
-        return $this;
-    }
-
-    public function getFalseColor(): ?string
-    {
-        return $this->evaluate($this->falseColor);
-    }
-
-    public function getFalseIcon(): ?string
-    {
-        return $this->evaluate($this->falseIcon);
-    }
-
-    public function getStateColor(): ?string
-    {
-        $state = $this->getState();
-
-        if ($state === null) {
-            return null;
-        }
-
-        return $state ? $this->getTrueColor() : $this->getFalseColor();
-    }
-
-    public function getStateIcon(): ?string
-    {
-        $state = $this->getState();
-
-        if ($state === null) {
-            return null;
-        }
-
-        return $state ? $this->getTrueIcon() : $this->getFalseIcon();
-    }
-
-    public function getTrueColor(): ?string
-    {
-        return $this->evaluate($this->trueColor);
-    }
-
-    public function getTrueIcon(): ?string
+    public function isBoolean(): bool
     {
-        return $this->evaluate($this->trueIcon);
+        return true;
     }
 }
diff --git a/packages/tables/src/Columns/IconColumn.php b/packages/tables/src/Columns/IconColumn.php
index 29c162d61a..f84875d65a 100644
--- a/packages/tables/src/Columns/IconColumn.php
+++ b/packages/tables/src/Columns/IconColumn.php
@@ -7,12 +7,24 @@ use Illuminate\Contracts\Support\Arrayable;
 
 class IconColumn extends Column
 {
-    use Concerns\HasColors;
+    use Concerns\HasColors {
+        getStateColor as getBaseStateColor;
+    }
 
     protected string $view = 'tables::columns.icon-column';
 
     protected array | Arrayable | Closure $options = [];
 
+    protected bool | Closure $isBoolean = false;
+
+    protected string | Closure | null $falseColor = null;
+
+    protected string | Closure | null $falseIcon = null;
+
+    protected string | Closure | null $trueColor = null;
+
+    protected string | Closure | null $trueIcon = null;
+
     public function options(array | Arrayable | Closure $options): static
     {
         $this->options = $options;
@@ -20,9 +32,73 @@ class IconColumn extends Column
         return $this;
     }
 
+    public function boolean(bool | Closure $condition = true): static
+    {
+        $this->isBoolean = $condition;
+
+        return $this;
+    }
+
+    public function false(string | Closure | null $icon = null, string | Closure | null $color = null): static
+    {
+        $this->falseIcon($icon);
+        $this->falseColor($color);
+
+        return $this;
+    }
+
+    public function falseColor(string | Closure | null $color): static
+    {
+        $this->boolean();
+        $this->falseColor = $color;
+
+        return $this;
+    }
+
+    public function falseIcon(string | Closure | null $icon): static
+    {
+        $this->boolean();
+        $this->falseIcon = $icon;
+
+        return $this;
+    }
+
+    public function true(string | Closure | null $icon = null, string | Closure | null $color = null): static
+    {
+        $this->trueIcon($icon);
+        $this->trueColor($color);
+
+        return $this;
+    }
+
+    public function trueColor(string | Closure | null $color): static
+    {
+        $this->boolean();
+        $this->trueColor = $color;
+
+        return $this;
+    }
+
+    public function trueIcon(string | Closure | null $icon): static
+    {
+        $this->boolean();
+        $this->trueIcon = $icon;
+
+        return $this;
+    }
+
     public function getStateIcon(): ?string
     {
         $state = $this->getState();
+
+        if ($this->isBoolean()) {
+            if ($state === null) {
+                return null;
+            }
+
+            return $state ? $this->getTrueIcon() : $this->getFalseIcon();
+        }
+
         $stateIcon = null;
 
         foreach ($this->getOptions() as $icon => $condition) {
@@ -38,6 +114,21 @@ class IconColumn extends Column
         return $stateIcon;
     }
 
+    public function getStateColor(): ?string
+    {
+        if ($this->isBoolean()) {
+            $state = $this->getState();
+
+            if ($state === null) {
+                return null;
+            }
+
+            return $state ? $this->getTrueColor() : $this->getFalseColor();
+        }
+
+        return $this->getBaseStateColor();
+    }
+
     public function getOptions(): array
     {
         $options = $this->evaluate($this->options);
@@ -48,4 +139,29 @@ class IconColumn extends Column
 
         return $options;
     }
+
+    public function getFalseColor(): string
+    {
+        return $this->evaluate($this->falseColor) ?? 'danger';
+    }
+
+    public function getFalseIcon(): string
+    {
+        return $this->evaluate($this->falseIcon) ?? 'heroicon-o-x-circle';
+    }
+
+    public function getTrueColor(): string
+    {
+        return $this->evaluate($this->trueColor) ?? 'success';
+    }
+
+    public function getTrueIcon(): string
+    {
+        return $this->evaluate($this->trueIcon) ?? 'heroicon-o-check-circle';
+    }
+
+    public function isBoolean(): bool
+    {
+        return (bool) $this->evaluate($this->isBoolean);
+    }
 }


Test patch:
diff --git a/tests/src/Tables/Fixtures/PostsTable.php b/tests/src/Tables/Fixtures/PostsTable.php
index 875efd9dd4..831b6743cb 100644
--- a/tests/src/Tables/Fixtures/PostsTable.php
+++ b/tests/src/Tables/Fixtures/PostsTable.php
@@ -28,7 +28,7 @@ class PostsTable extends Component implements Tables\Contracts\HasTable
                     Tables\Actions\Action::make('column-action-object')
                         ->action(fn () => $this->emit('column-action-object-called')),
                 ),
-            Tables\Columns\BooleanColumn::make('is_published'),
+            Tables\Columns\IconColumn::make('is_published')->boolean(),
             Tables\Columns\TextColumn::make('visible'),
             Tables\Columns\TextColumn::make('hidden')
                 ->hidden(),