# Feature Specification: Filament Table UX Standardization & List Consistency **Feature Branch**: `125-table-ux-standardization` **Created**: 2026-03-08 **Status**: Draft **Input**: User description: "Spec 125 — Filament Table UX Standardization & List Consistency" ## Spec Scope Fields *(mandatory)* - **Scope**: workspace - **Primary Routes**: All Filament table surfaces under `/admin`, `/admin/t/{tenant}/...`, and `/system` that render resource lists, relation manager tables, table widgets, custom table pages, or picker tables - **Data Ownership**: Both workspace-owned and tenant-owned records are affected only at the presentation and interaction layer; this feature does not redefine underlying ownership or introduce new record types - **RBAC**: Existing workspace membership, tenant membership, plane separation, and capability gates remain unchanged; the standard applies only within each surface’s current authorization boundaries ## User Scenarios & Testing *(mandatory)* ### User Story 1 - Scan Core Lists Predictably (Priority: P1) As an operator moving between major product lists, I can rely on a consistent default table structure so I can find, sort, and compare records without relearning each screen. **Why this priority**: Predictable list behavior is the core value of the feature. If major tables still feel inconsistent, the repo-wide standardization effort fails even if individual tables improve cosmetically. **Independent Test**: Can be fully tested by updating one critical list page to follow the standard and verifying that its primary identifier is searchable and sortable, low-value technical detail is not dominant by default, and the table has a domain-specific empty state. **Acceptance Scenarios**: 1. **Given** a critical product table with multiple records, **When** the user opens the page, **Then** the table presents a calm default view with a clear primary identifier, meaningful contextual columns, and technical detail kept secondary. 2. **Given** a populated critical table, **When** the user sorts by the primary identifier or recency field, **Then** the list responds in a way that matches the table’s domain purpose. --- ### User Story 2 - Keep List Context Across Refresh (Priority: P2) As a user investigating records over several page loads, I can refresh or return to key list pages without losing my search, sort, or filter context. **Why this priority**: Losing table state creates repeated work and breaks operational flow. Persistence is one of the clearest gaps identified in the audit and materially affects day-to-day usability. **Independent Test**: Can be tested by applying search, sort, and filters on a resource list, refreshing the page, and confirming that the list reopens in the same state. **Acceptance Scenarios**: 1. **Given** a resource list with an active search term, sort order, and filter selection, **When** the user refreshes the page, **Then** the same list context remains active. 2. **Given** a user returns to a key resource list after navigating away, **When** the page loads again in the same session, **Then** the previously chosen list state is preserved. --- ### User Story 3 - Reveal Detail Only When Needed (Priority: P3) As an advanced operator, I can access technical fields such as identifiers and timestamps when needed without having those fields dominate every list by default. **Why this priority**: Enterprise operators still need detail, but the product should present it on demand instead of overwhelming the default table surface. **Independent Test**: Can be tested by opening a standardized table, confirming that technical detail is hidden by default, and then exposing the detail without losing access to the record’s primary context. **Acceptance Scenarios**: 1. **Given** a standardized list that contains technical identifiers or low-frequency metadata, **When** the user opens column controls, **Then** those detail fields are available without being forced into the default layout. 2. **Given** a table with long identifiers or technical strings, **When** the user inspects the list, **Then** those values remain readable and accessible without breaking the page layout. ### Edge Cases - When a table has no records at all, it shows a domain-specific empty state with a clear explanation and only RBAC-allowed next steps. - When a table contains relation-backed or computed fields that would create unacceptable sort or search cost, the standard allows a documented exception instead of forcing an expensive interaction. - When a cross-tenant or cross-workspace list is shown, the default visible columns still preserve enough context to distinguish records safely. - When exact chronology matters more than quick scanning, the table may keep an absolute time presentation as a documented exception to the general relative-time convention. ## Requirements *(mandatory)* **Constitution alignment (required):** This feature does not introduce Microsoft Graph calls, new write behavior, queue or schedule behavior, or `OperationRun` usage. It standardizes existing table UX on already-authorized screens only. **Constitution alignment (RBAC-UX):** This feature touches both the tenant/admin plane and the platform plane, but it does not change authorization semantics. Non-membership remains deny-as-not-found, capability denial remains unchanged where it already applies, and all existing action-level server-side authorization must remain intact. Any new empty-state action shown on a surface must stay capability-gated and tenant-safe. **Constitution alignment (BADGE-001):** Existing centralized badge semantics for status, outcome, severity, and boolean-like signals remain the source of truth. The standard may improve consistency of where badges appear in tables, but it must not introduce local badge vocabularies or ad-hoc status mappings. **Constitution alignment (Filament Action Surfaces):** This feature satisfies the Action Surface Contract by preserving each table’s existing action architecture as table-local behavior. The scope is limited to list consistency, empty states, pagination, persistence, and column visibility; row actions, bulk actions, header actions, and inspection affordances remain explicit per surface and are not globally redesigned. **Constitution alignment (UX-001 — Layout & Information Architecture):** This feature directly supports the table portions of UX-001 by requiring meaningful empty states and consistent search, sort, and filtering behavior for core dimensions. It does not change create, edit, or view form layout patterns. ### Functional Requirements - **FR-001**: The system MUST define and document a repo-wide table standard for all production Filament list surfaces. - **FR-002**: The standard MUST classify visible table columns into Primary, Context, and Detail tiers as a review and implementation convention. - **FR-003**: Every production table MUST expose a searchable primary identifier unless a documented exception establishes that search provides no user value for that surface or would introduce unacceptable query cost. - **FR-004**: Every production table MUST define an explicit default sort unless a documented exception is required for domain or query-safety reasons. - **FR-005**: Meaningful identifiers, recency fields, statuses, and operational counts MUST be sortable when doing so is useful and safe for the underlying query. - **FR-006**: Technical identifiers, low-frequency metadata, and secondary timestamps MUST not dominate the default list surface and SHOULD be available as on-demand detail where practical. - **FR-007**: General-purpose tables SHOULD present no more than seven columns by default unless a denser default view is explicitly justified. - **FR-008**: Timestamp, null-value, and identifier presentation MUST follow consistent product-wide rules so similar values scan the same way across tables. - **FR-009**: Every production table MUST provide a domain-specific empty state with clear explanatory copy, and it MUST include a next step only when one is meaningful and authorized. - **FR-010**: Pagination options and default page sizes MUST follow explicit conventions by table class rather than relying on inconsistent implicit defaults. - **FR-011**: The designated critical resource lists (`TenantResource`, `PolicyResource`, `BackupSetResource`, `BackupScheduleResource`, `ProviderConnectionResource`, `FindingResource`, and `OperationRunResource`) MUST preserve search, sort, and filter state across refresh within the same session. - **FR-012**: The standard MUST reduce default horizontal overload by moving lower-value detail out of the initial view before any cosmetic workaround is considered. - **FR-013**: The rollout MUST not worsen known query-risk tables by forcing expensive sorts, searches, or row-level computations without review. - **FR-014**: The feature MUST preserve existing RBAC behavior, tenancy boundaries, action semantics, and audit expectations for every affected table surface. - **FR-015**: The rollout MUST be phased so that conventions and critical high-value tables are addressed before the remaining table surface is aligned. - **FR-016**: Future table changes MUST be reviewable against the same standard so new list surfaces do not drift back to ad hoc behavior. ## UI Action Matrix *(mandatory when Filament is changed)* If this feature adds/modifies any Filament Resource / RelationManager / Page, fill out the matrix below. For each surface, list the exact action labels, whether they are destructive (confirmation? typed confirmation?), RBAC gating (capability + enforcement helper), and whether the mutation writes an audit log. | Surface | Location | Header Actions | Inspect Affordance (List/Table) | Row Actions (max 2 visible) | Bulk Actions (grouped) | Empty-State CTA(s) | View Header Actions | Create/Edit Save+Cancel | Audit log? | Notes / Exemptions | |---|---|---|---|---|---|---|---|---|---|---| | Resource list tables | app/Filament/Resources/**/Pages/List*.php | Existing table-local actions retained | Existing row inspection affordance retained per resource | Existing resource-local actions retained | Existing grouped bulk actions retained where already supported | Added or refined per table when meaningful and authorized | Unchanged by this spec | Unchanged by this spec | Unchanged | Standardizes list behavior only; no action redesign | | Relation manager tables | app/Filament/Resources/**/RelationManagers/*.php | Existing relation-manager actions retained | Existing table-local inspection pattern retained | Existing relation-manager row actions retained | Existing grouped bulk actions retained where applicable | Added or refined per table when meaningful and authorized | Unchanged by this spec | Unchanged by this spec | Unchanged | Detail visibility and pagination are standardized without changing mutation semantics | | Table widgets and custom table pages | app/Filament/Widgets/*.php and app/Filament/Pages/*.php | Existing page or widget actions retained | Existing inspection affordance retained where records are inspectable | Existing row actions retained | Existing grouped bulk actions retained where applicable | Added or refined per surface when meaningful and authorized | Unchanged by this spec | Not applicable unless the page already provides forms | Unchanged | Read-only or operational surfaces may have no row actions; this spec does not force them | | Picker or selection tables | app/Livewire/** and table-backed selection pages | Existing selection or header actions retained | Existing selection affordance retained | Existing selection-related row actions retained | Existing grouped bulk actions retained where applicable | Added only when it helps a blocked user recover | Unchanged by this spec | Unchanged by this spec | Unchanged | This spec standardizes calm defaults and pagination, not picker workflow semantics | ### Key Entities *(include if feature involves data)* - **Table Surface**: Any production Filament-backed list surface, including resource lists, relation managers, widgets, custom pages, and picker tables. - **Column Visibility Tier**: The conceptual classification of a column as Primary, Context, or Detail, used to decide whether it should be dominant, visible by default, or available on demand. - **Table Behavior Profile**: The combination of default sort, search scope, empty-state behavior, pagination, state persistence, and overflow handling expected for a given table. - **Documented Exception**: A justified, reviewable deviation from the standard where domain clarity, tenant safety, or query cost makes the default rule inappropriate. ## Assumptions - The existing audit inventory of approximately 36 production tables is sufficiently accurate to drive phased rollout planning, with minor recount differences allowed during implementation. - Existing action labels, filters, query scopes, and badge mappings remain table-local unless a later spec proves a shared change is required. - Critical rollout tables include `TenantResource`, `PolicyResource`, `BackupSetResource`, `BackupScheduleResource`, `ProviderConnectionResource`, `FindingResource`, `OperationRunResource`, and `BackupItemsRelationManager`; query-risk system pages such as `Directory/Workspaces` remain in scope for the broader rollout with documented exceptions where needed. - Resource-list persistence is mandatory in this phase, while broader persistence beyond those surfaces may be adopted later only where it fits cleanly. ## Dependencies - The feature depends on an up-to-date inventory of production table surfaces and their current behavior gaps. - The feature depends on retaining current authorization policies, capability registries, and centralized badge semantics during rollout. - The feature depends on performance review of relation-backed and computed columns before new sort or search behavior is enabled. ## Success Criteria *(mandatory)* ### Measurable Outcomes - **SC-001**: In the post-rollout audit, 100% of production tables have an explicit default sort or a documented exception. - **SC-002**: In the post-rollout audit, 100% of production tables provide a domain-specific empty state. - **SC-003**: At least 90% of general-purpose production tables present seven or fewer columns by default unless a documented exception exists. - **SC-004**: On all designated critical resource lists, a user can refresh the page without losing the current search, sort, and filter context during the same session. - **SC-005**: In manual QA of critical tables, an operator can reach any hidden technical identifier or timestamp needed for troubleshooting in two interactions or fewer.