Universal filter + view-mode primitive across all entity-views #23
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
m's verbatim 2026-05-08 21:34, after reviewing /inbox?tab=mine:
Why this matters
Paliad already exposes ~7 list-shaped surfaces —
/deadlines,/appointments,/agenda,/inbox(both tabs),/projects(cards / tree / list), the custom user-views (/views/<id>), the new dashboard inline Agenda + Letzte Aktivität — and each one has reinvented its own filter chrome:?project=on /tools/fristenrechner; absent on /inbox.?sort=on a couple of routes; nothing on /inbox.The result is exactly what m saw on /inbox?tab=mine — bare list, no scope to project, no timeframe, no type, no sort, looks unfinished compared to the surfaces that did get filter polish. Filing each as a separate bug would mean re-deriving the same primitives 5+ times.
Inventor's brief
Design a single composable filter primitive that every list-shaped surface consumes. Take a position on:
Filter axes that are universal vs per-surface. Project-scope is universal; "requester / approver" only applies to /inbox; "deadline status" only applies to /deadlines. Decide which axes go in the shared bar and which stay per-surface, and how the bar declares its supported axes (config object? slot composition? higher-order component?).
State model. URL-driven (every filter is a query param, deep-linkable, refresh-survives) vs in-memory (faster but loses on reload) vs hybrid (URL for primary axes, localStorage for view-mode preferences). Match paliad's existing pattern where it makes sense; deviate where it improves.
View-mode switcher. cards / list / table — universal, or per-surface declared? table-mode implies sortable column headers — does the primitive own column-sort state, or does each surface manage that internally? Density toggle (compact vs comfortable) belongs here too.
Composability. The bar needs to drop into existing TSX pages (/inbox, /deadlines, /appointments, /agenda, custom views) without forcing every surface to refactor. Propose a clean API.
Reuse with the existing /projects layout-spec (custom user-views in
paliad.user_view_layouts). The custom-view editor already lets users pick filter axes — does the universal bar inherit from that spec, or does the spec become a special case of "saved bar state"? m's hint: "halfway there without custom views" — leaning towards the latter.Migration path. Each existing list surface has its own filter UI today. Phase the rollout: ship the primitive on one surface (likely /inbox since it has the least to lose), then port others as separate PRs. Identify the one surface with the most complex filter today (likely /deadlines or /events) so the primitive is designed wide enough to absorb it.
"Save this filter as a view". The custom-view editor already does this for a few surfaces. The universal bar should make this affordance trivial — every surface gets "save current filter as named view" for free.
Hard requirements
Read first (in this order):
frontend/src/client/projects-cards.ts— cards/tree/list switcher + layout-spec consumerfrontend/src/client/agenda.ts+client/agenda-render.ts— current chip + project filter patternfrontend/src/client/deadlines.ts+client/events.ts— bucket chips + multi-select filterfrontend/src/client/inbox.ts— what's missing todayfrontend/src/client/views.ts+client/views-editor.ts— saved-view shape + how layout specs persistfrontend/src/client/views/shape-cards.ts+views/shape-list.ts+views/shape-calendar.ts— view-mode renderersinternal/services/layout_spec.go— server-side layout-spec modelpaliad.user_view_layoutstableDO NOT auto-flip to coder. Report
mai report completed "DESIGN READY FOR REVIEW"and stop. Head will surface to m for go/no-go before any coder shift (m/mAi#142).No hour estimates. Slice/phase the rollout; describe order, not duration.
No
.entity-tablerow-click contract violations — the bar'scards | list | tablemodes must respect paliad's existing row-handler pattern (see CLAUDE.md frontend conventions).Output as
docs/design-universal-filter-2026-05-08.md. Commit + push to a branch.Out of scope
Filed by
paliad/head from m's 2026-05-08 21:34 instruction. Linked to the current dogfood on /inbox?tab=mine which is the most visibly under-filtered surface.
Locked positions (m greenlit 2026-05-08 21:47)
<dialog>s)approval_viewer_rolechip cluster?time=?sources=?d_status=etc.)?type=legacy redirect kept for one releaseurlNamespaceDesign doc:
docs/design-universal-filter-2026-05-08.mdonmai/riemann/inventor-universal(commit1e23745).riemann shifted to
/mai-coder. Phase 1 = /inbox +<FilterBar>primitive + axis registry + URL codec. Slices ship at boundaries; we discuss Phase 2 after m dogfoods Phase 1.