TenantAtlas/docs/ui/filament-table-standard.md
ahmido a4f5c4f122 Spec 125: standardize Filament table UX (#152)
## 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
2026-03-08 22:54:56 +00:00

7.3 KiB
Raw Permalink Blame History

Filament Table Standard

Standard

TenantPilot standardizes production Filament list surfaces with a convention-first model:

  • Primary: searchable identifier or record title that anchors the row.
  • Context: status, ownership, recency, and counts needed for a normal scan.
  • Detail: technical IDs, secondary timestamps, verbose metadata, and low-frequency troubleshooting fields.

Required Rules

  • Every production table defines an explicit default sort unless a documented exception exists.
  • Every production table provides a domain-specific empty state heading and description.
  • General-purpose tables should expose seven or fewer columns by default unless density is part of the job.
  • Primary identifiers should be searchable and sortable when query-safe.
  • Technical identifiers and secondary metadata should be toggleable and hidden by default where practical.
  • Resource lists in the critical set persist search, sort, and filters in session.
  • Existing action surfaces, RBAC behavior, confirmations, and centralized badge semantics stay unchanged.

Pagination Profiles

Surface Page sizes Default
Resource 25, 50, 100 25
Relation manager 10, 25, 50 10
Widget 10 10
Picker 25, 50, 100 25
Custom page 25, 50, all 25 unless a page overrides it explicitly

Implementation uses TablePaginationProfiles.php.

Timestamp, Null, and ID Rules

  • Prefer ->since() for scan-first timestamps unless exact chronology is the primary task.
  • Use for missing values unless the domain needs a more specific placeholder.
  • Long identifiers should remain copyable and readable without dominating the default layout.
  • Prefer monospaced styling and tooltips for truncated technical identifiers.

Review Checklist

  • Primary column is obvious and query-safe.
  • Default sort matches the tables operational purpose.
  • Empty-state copy explains what the list is waiting for.
  • Hidden detail can be revealed in one toggle or one drill-in.
  • Pagination profile matches the table class.
  • Critical resource lists declare session persistence.
  • No destructive action lost its confirmation or authorization guard.

Rollout Audit

Persistence Surfaces

The following resource lists must persist search, sort, and filters in session:

  • TenantResource
  • PolicyResource
  • BackupSetResource
  • BackupScheduleResource
  • ProviderConnectionResource
  • FindingResource
  • OperationRunResource

Documented Exceptions

  • RecentDriftFindings and RecentOperations do not add table search because dashboard widgets are glance surfaces, not investigative workbenches.
  • Directory/Workspaces keeps computed health and recent-failure metrics non-sortable and non-searchable because those values are derived per row.
  • InventoryCoverage uses the custom-page pagination profile but keeps the broader all option and a 50-row default because operators sometimes need a full matrix pass.
  • Picker tables keep workflow-local search only; they do not persist state in session.

Surface Inventory

Surface Class Pagination Default sort Empty state Persistence Notes
Tenant list resource resource name asc yes yes Workspace-scoped create CTA remains in list page
Policy list resource resource display_name asc yes yes Sync CTA remains list-local
Backup set list resource resource created_at desc yes yes Create CTA remains list-local
Backup schedule list resource resource next_run_at asc yes yes Create CTA remains list-local
Provider connections resource resource display_name asc yes yes Empty-state CTA remains tenant-aware
Findings resource resource created_at desc yes yes Open filter remains the default
Monitoring operations resource-backed page resource created_at desc yes yes Canonical operations view uses OperationRunResource::table()
Entra groups resource resource display_name asc yes no Directory browse remains read-only
Alert deliveries resource resource id desc yes no Delivery history stays read-only
Alert rules resource resource name asc yes no Rule actions remain explicit per row
Alert destinations resource resource name asc yes no Destination test/send actions remain unchanged
Baseline profiles resource resource name asc yes no Create CTA remains list-local
Baseline snapshots resource resource captured_at desc yes no Snapshot browsing remains read-only
Inventory items resource resource last_seen_at desc yes no Scan-first recency view
Policy versions resource resource resource captured_at desc yes no Version history remains inspectable and immutable
Review packs resource resource created_at desc yes no Review workflow actions unchanged
Workspace resource resource resource name asc yes no Workspace create CTA remains list-local
Backup items relation_manager relation manager policy.display_name asc yes no Action semantics unchanged
Policy versions relation_manager relation manager version_number desc yes no Existing relation query preserved
Backup schedule operation runs relation_manager relation manager created_at desc yes no Existing record view preserved
Tenant memberships relation_manager relation manager created_at desc yes no Role management unchanged
Workspace memberships relation_manager relation manager created_at desc yes no Role management unchanged
Baseline tenant assignments relation_manager relation manager created_at desc yes no Assignment action unchanged
Inventory coverage custom_page custom page label asc yes no Keeps all pagination option
System directory tenants custom_page custom page name asc yes no Search stays on meaningful identity fields
System directory workspaces custom_page custom page name asc yes no Computed metrics remain exceptions
Ops runs custom_page custom page id desc yes no Platform triage actions unchanged
Ops failures custom_page custom page id desc yes no Platform triage actions unchanged
Ops stuck custom_page custom page id desc yes no Platform triage actions unchanged
Access logs custom_page custom page recorded_at desc yes no Read-only operational surface
Repair workspace owners custom_page custom page name asc yes no Repair action unchanged
Recent drift findings widget widget created_at desc yes no No search by design
Recent operations widget widget created_at desc yes no No search by design
Backup set policy picker picker picker display_name asc yes no Workflow-local search only
Entra group picker picker picker display_name asc yes no Workflow-local search only
Settings catalog table picker picker definition asc yes no Workflow-local search only