Adding filament style hidden option to columns#101
Adding filament style hidden option to columns#101paulhennell wants to merge 1 commit intorelaticle:4.xfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds Filament-style conditional visibility controls for Flowforge board columns, allowing columns to be hidden or shown per user/context.
Changes:
- Introduces a
CanBeHiddenconcern for columns withhidden(),visible(),isHidden(), andisVisible(). - Updates board column retrieval to exclude non-visible columns from rendering.
- Expands Livewire and standalone board tests to verify hidden columns don’t render by default and can be revealed.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
src/Concerns/HasBoardColumns.php |
Filters returned columns to only those that are visible. |
src/Concerns/CanBeHidden.php |
Adds new visibility/hidden API and evaluation logic for columns. |
src/Column.php |
Applies the new hiding/visibility concern to board columns. |
tests/Feature/LivewireBoardTest.php |
Adds coverage for a conditionally visible “Hidden Column”. |
tests/Standalone/StandaloneBoardTest.php |
Mirrors coverage for standalone Livewire board rendering. |
tests/Fixtures/TestBoard.php |
Adds a conditionally visible column and state toggle for tests. |
tests/Fixtures/TestStandaloneBoard.php |
Adds a conditionally visible column and state toggle for tests. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| public function getColumns(): array | ||
| { | ||
| return $this->columns; | ||
| return array_filter($this->columns, fn (Column $column) => $column->isVisible()); | ||
| } |
There was a problem hiding this comment.
getColumns() now uses array_filter() which preserves the original array keys; if callers ever JSON-encode or otherwise depend on a sequential list, this can unexpectedly produce a sparse array / object-like structure. Consider wrapping with array_values(...) to reindex after filtering. Also, the callback is type-hinted as fn (Column $column) which will throw a TypeError if $this->columns ever contains non-Column values (even though they’re not prevented in columns()); either validate/throw when setting columns, or make the filter tolerant of non-Column entries.
| trait CanBeHidden | ||
| { | ||
| protected bool | Closure $isHidden = false; | ||
|
|
||
| protected bool | Closure $isVisible = true; | ||
|
|
||
| public function hidden(bool | Closure $condition = true): static | ||
| { | ||
| $this->isHidden = $condition; | ||
|
|
||
| return $this; | ||
| } | ||
|
|
||
| public function visible(bool | Closure $condition = true): static | ||
| { | ||
| $this->isVisible = $condition; | ||
|
|
||
| return $this; | ||
| } | ||
|
|
||
| public function isHidden(): bool | ||
| { | ||
| if ($this->evaluate($this->isHidden)) { | ||
| return true; | ||
| } | ||
|
|
||
| return ! $this->evaluate($this->isVisible); | ||
| } |
There was a problem hiding this comment.
CanBeHidden calls $this->evaluate(...), but the trait itself doesn’t document or enforce that the consuming class provides an evaluate() implementation. If this trait is ever reused outside Filament\Support\Components\ViewComponent, it will fatally error. Consider adding a docblock contract (e.g., @method mixed evaluate(mixed $value) / @mixin \Filament\Support\Components\ViewComponent) or otherwise constraining usage so the requirement is explicit.
| ->set('showAllColumns', true) | ||
| ->assertSee('Hidden Column'); | ||
| }); | ||
|
|
There was a problem hiding this comment.
These tests cover the new visible(...) behavior, but the newly added hidden(...) API isn’t exercised anywhere in the suite. To prevent regressions, add a test case that configures a column with ->hidden(...) (and ideally one that verifies precedence when both hidden() and visible() are set).
| test('re-hides hidden column when hidden condition becomes true again', function () { | |
| Livewire::test(TestBoard::class) | |
| ->assertStatus(200) | |
| ->assertDontSee('Hidden Column') | |
| ->set('showAllColumns', true) | |
| ->assertSee('Hidden Column') | |
| ->set('showAllColumns', false) | |
| ->assertDontSee('Hidden Column'); | |
| }); |
ManukMinasyan
left a comment
There was a problem hiding this comment.
The CanBeHidden trait and API design look good -- clean implementation that follows Filament patterns. However, there's a consistency issue in HasBoardColumns that will cause bugs:
Critical Issue
getColumns() now filters hidden columns, but getColumnIdentifiers(), getColumnLabels(), and getColumnColors() still iterate over ALL columns (including hidden ones). This creates array mismatches where these methods return data for columns that getColumns() excluded.
Recommended fix: Extract a getVisibleColumns() helper and use it in all getter methods:
private function getVisibleColumns(): array
{
return array_filter($this->columns, fn (Column $column) => $column->isVisible());
}
public function getColumns(): array
{
return $this->getVisibleColumns();
}
public function getColumnIdentifiers(): array
{
return array_map(fn (Column $column) => $column->getName(), $this->getVisibleColumns());
}
// Same for getColumnLabels(), getColumnColors()Missing Test Coverage
- No test for
->hidden(true)with boolean literal (only Closure tested) - No test for
getColumnIdentifiers()/getColumnLabels()excluding hidden columns - No test for edge case: all columns hidden
The trait itself is well-written -- just needs the getter consistency fix to be safe.
Needed a way to hide columns for some users and instinctively reached for Filament style
->hidden()options but it wasn't there so thought I'd add it.Added tests to confirm it doesn't show when unintended, nor break any other functions.
I had originally thought to use existing Filament\CanBeHidden trait, but there are multiple versions and all appear to add additional properties I am not confident would always work in this projects context. (See say
Filament\Schemas\Components\Concerns\CanBeHiddenwhich addshiddenOnand many other options).It seemed easier to simply duplicate only the few required options to a project CanBeHidden trait.