## Summary - standardize Filament table defaults across resources, relation managers, widgets, custom pages, and picker tables - add shared pagination profiles, calm default column visibility, explicit empty states, and session persistence on designated critical resource lists - complete Spec 125 artifacts, regression tests, and dashboard widget follow-up for lazy loading, sortable columns, and toggleable detail columns ## Verification - `docker exec tenantatlas-laravel.test-1 php artisan test --compact --filter=BaselineCompareNow` - `docker exec tenantatlas-laravel.test-1 php artisan test --compact --filter=TableStandardsBaseline` - `docker exec tenantatlas-laravel.test-1 php artisan test --compact --filter=TableDetailVisibility` - `docker exec tenantatlas-laravel.test-1 php artisan test --compact --filter=FilamentTableRiskExceptions` - full suite run completed: `2017 passed, 10 failed, 8 skipped` - manual browser QA completed on the tenant dashboard for lazy loading, sortable widget columns, toggleable hidden status columns, badges, and pagination ## Known Failures The full suite still has 10 pre-existing failures unrelated to this branch: - `Tests\\Unit\\OpsUx\\SummaryCountsNormalizerTest` - `Tests\\Feature\\BackupWithAssignmentsConsistencyTest` (2 tests) - `Tests\\Feature\\BaselineDriftEngine\\CaptureBaselineContentTest` - `Tests\\Feature\\BaselineDriftEngine\\CompareContentEvidenceTest` - `Tests\\Feature\\BaselineDriftEngine\\ResolverTest` - `Tests\\Feature\\Filament\\TenantDashboardDbOnlyTest` - `Tests\\Feature\\Operations\\ReconcileAdapterRunsJobTrackingTest` - `Tests\\Feature\\ReviewPack\\ReviewPackRbacTest` - `Tests\\Feature\\Verification\\VerificationReportRedactionTest` Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #152
7.1 KiB
7.1 KiB
Research: Filament Table UX Standardization & List Consistency
Decision 1: Use native Filament table configuration as the primary implementation path
- Decision: Standardize behavior directly in each table’s existing
table()definition and page-level empty-state hooks, using native Filament methods as the default approach. - Rationale: The repo already defines table behavior locally across resources, relation managers, widgets, system pages, and Livewire picker tables. Keeping the standard inline preserves clarity, aligns with the spec’s convention-first goal, and avoids introducing a second configuration language on top of Filament.
- Alternatives considered:
- Build a generic table DSL with primary/context/detail declarations: rejected because it would hide normal Filament behavior and create a parallel framework to maintain.
- Make macros the default rollout path: rejected because the current inconsistencies are mostly judgment and information-architecture issues, not missing framework capability.
Decision 2: Keep shared support intentionally tiny and mechanical
- Decision: Do not introduce a large shared base class or trait hierarchy. Only allow tiny shared support where duplication is purely mechanical, with pagination-profile helpers as the most likely candidate.
- Rationale: The workspace currently has no shared
StandardTableDefaultsor equivalent helper. Introducing a broad helper layer at the same time as a repo-wide cleanup would increase migration risk and make reviews harder. - Alternatives considered:
- Add a
StandardTableDefaultstrait and force every table through it: rejected because it would centralize too many domain-specific decisions and make exceptions harder to reason about. - Keep every pagination and persistence setting fully duplicated forever: rejected because a very small helper for page-size arrays may be justified once the first rollout wave proves the pattern is stable.
- Add a
Decision 3: Treat resource-list persistence as mandatory and relation-manager persistence as optional
- Decision: Enable session persistence for search, sort, and filters on resource list tables in the first rollout wave. Leave relation managers, widgets, picker tables, and custom pages on an opt-in basis where the behavior fits naturally.
- Rationale: The audit gap is strongest on resource lists, and Filament-native session persistence maps directly to that need. Extending persistence to every table surface immediately would expand scope and create more state-management edge cases than the spec requires.
- Alternatives considered:
- Add persistence to every table surface immediately: rejected because it increases rollout complexity without matching the strongest user pain first.
- Skip persistence and rely only on query-string state: rejected because the spec explicitly targets keeping list context across refreshes.
Decision 4: Use a documented Primary / Context / Detail model rather than code-level column metadata
- Decision: Express Primary, Context, and Detail as a repo review convention backed by examples, not as a new code abstraction.
- Rationale: The missing consistency is mostly a design-review problem. A documented tier model gives reviewers and implementers a common language while letting each table remain explicit and readable.
- Alternatives considered:
- Add a
primaryColumn()/detailColumn()API wrapper: rejected because it would obscure normal Filament column configuration and encourage over-abstraction. - Leave visibility choices fully ad hoc: rejected because that is the exact drift pattern the spec is meant to stop.
- Add a
Decision 5: Standardize timestamps, nulls, and IDs using native column methods
- Decision: Use native Filament column behavior for relative timestamps, placeholders, toggle-hidden detail fields, copyable identifiers, truncation, and tooltips instead of custom renderers wherever possible.
- Rationale: The repo already uses
since(),dateTime(),toggleable(),copyable(), and empty-state APIs in several places. Extending those patterns is lower risk than inventing custom rendering helpers. - Alternatives considered:
- Introduce custom Blade column views for standard timestamp and ID rendering: rejected because it would be more fragile and harder to apply consistently across many surfaces.
- Leave timestamp and null formatting untouched during rollout: rejected because inconsistent rendering is one of the audited usability defects.
Decision 6: Preserve existing badge, action, and RBAC architecture
- Decision: Do not redesign actions, badge mappings, or authorization mechanics as part of this feature. Keep actions and empty-state CTAs table-local, preserve centralized badge rendering through
BadgeCatalogandBadgeRenderer, and maintain existing UI enforcement helpers. - Rationale: The repo already has centralized badge infrastructure and explicit action-level UI enforcement patterns. The spec explicitly excludes action redesign, and mixing that work into the rollout would create unnecessary risk.
- Alternatives considered:
- Standardize row actions and header actions in the same feature: rejected because actions are comparatively consistent and would create avoidable scope creep.
- Rebuild badges as part of a broader “table facelift”: rejected because BADGE-001 requires centralized semantics and the current badge layer already exists.
Decision 7: Use performance exceptions deliberately and document them per table
- Decision: Any new sort or search behavior on relation-backed or computed columns requires explicit query review, and some tables may keep documented exceptions instead of forcing full compliance.
- Rationale: Direct code inspection already shows query-sensitive surfaces.
app/Filament/System/Pages/Directory/Workspaces.phpcomputes health and recent failures per row, andapp/Filament/Resources/BackupSetResource/RelationManagers/BackupItemsRelationManager.phpalready mixes operational actions with a dense relation-backed list. The standard must not worsen those hotspots. - Alternatives considered:
- Force every meaningful-looking column to become sortable or searchable: rejected because that would create hidden N+1 or aggregate query regressions.
- Exclude risk tables from the rollout entirely: rejected because the spec requires broad alignment, but exceptions can be documented where needed.
Decision 8: Roll out by table class and business criticality, not alphabetically
- Decision: Implement the standard in phases: documentation and baseline, first-wave critical resource tables, then remaining resources and relation managers, then widgets, custom pages, and picker tables, followed by performance hardening.
- Rationale: The current table surface spans roughly three dozen screens with uneven complexity. A phased rollout lets the project prove the standard on high-value tables before applying it repo-wide.
- Alternatives considered:
- Update every table in one large pass: rejected because it would be hard to review and too risky for query behavior.
- Limit the effort to a small set of flagship resources: rejected because the spec is explicitly repo-wide and aims to stop future drift.