Org Workspace Collection UX
Why This Exists
The current org pages prove the product model, but they do not yet express the intended day-to-day agency operating experience.
The main issue is not one page. It is the collection pattern across the org surface.
Today, projects, time, and billing mostly render as vertically stacked cards. That was acceptable for proving the schema and workflow spine, but it will break down once an agency has real volume.
Examples of the current gap:
- project collections are too tall and do not support board-style planning
- time entries behave like manual notes, not like a true running timer workflow
- billing and other record-heavy pages do not yet share a stronger dense collection shell
- quick actions are buried inside page-local buttons instead of staying available as workspace controls
This doc is the product-direction source of truth for the next org-surface UX step.
Non-Negotiable Outcome
The org workspace must feel like a real operations product, not a stack of admin cards.
That means:
- dense enough to handle dozens of records without becoming visually tall and exhausting
- consistent between customers, projects, time, billing, and the global drive finder
- flexible enough to support different collection modes per domain
- fast to act from, with persistent creation and workflow shortcuts
Shared Collection System
Every record-heavy org page should converge on the same collection shell.
Core parts:
- page top bar for title and page-level actions
- collection toolbar for search, segment filters, and view switching
- a borderless toolbar surface; search remains a fixed compact field on the left within a reserved desktop column
- density-aware record presentation instead of tall freeform cards
- selection and bulk-action affordances where the workflow benefits from them
- empty states that still preserve the surrounding shell
- a persistent quick-action dock for high-frequency org actions
The styling should remain minimal and restrained, but it should look intentional and operational.
Pagination and scale contract
Every growable record collection must use backend cursor pagination. The first
page should normally contain 20–30 records, with an explicit continuation
control while the backend reports CanLoadMore. A full collection page must
not use .take(...), .slice(0, ...), or a capped preview query as its data
source; older records must remain reachable until the cursor is exhausted.
Search and durable filters belong in the paginated backend query so later pages cannot contain hidden matches. Hydration must be scoped to the current page instead of collecting every related table for the organization. Preview strips, dashboard summaries, and compact recommendations may remain intentionally bounded, but their API and copy must identify them as previews rather than full directories.
Counts shown beside a paginated collection must come from a real aggregate or
dedicated count projection. Never label results.length as a global total while
more pages exist. The collection pagination policy tests protect the primary org
routes from regressing to unbounded or silently capped reads.
The page-frame implementation is shared through OrgCollectionPage and CollectionToolbar. Search is the only left-aligned control; filters, view switches, and actions stay right-aligned. The toolbar remains on one row whenever its actual controls fit and wraps naturally only when their combined width requires it, rather than switching layouts at a fixed desktop breakpoint. OperationalList is the only public org record-list API and owns its border directly; its records keep the desktop column grid at every viewport width and the bordered list region scrolls horizontally when those columns do not fit. Do not wrap it in another bordered Surface merely to provide spacing. Domain-specific bodies such as the Files finder, project board, grouped subscription sections, and catalog sections may vary inside that frame without redefining the toolbar or outer page anatomy.
Sidebar Grouping Note
For now, the org sidebar should stay on this grouped structure:
Home:Overview,AnalyticsAccounts:Clients,PortalsWork:Projects,Entries,Drive,ContractsRevenue:Quotes,Invoices,Subscriptions
This keeps the primary navigation simple while still separating account management from delivery work.
A lighter alternative IA was explored and is intentionally parked for later evaluation:
Home:Overview,AnalyticsWork:Clients,Portals,Projects,Entries,Drive,ContractsRevenue:Quotes,Invoices,Subscriptions
That three-group version is still a valid future option if the org surface needs a lighter, flatter navigation again.
Explicit Collection Taxonomy
Do not treat every org collection as the same kind of page.
The org workspace now has three collection types. New work should choose one of these deliberately instead of mixing patterns ad hoc.
Within those collection pages and detail tabs, use the composition that matches the record's job:
- operational records use
OperationalList - chronological narrative activity uses
FeedList - repeated inline editors use
EditableList - dashboard-only rankings and compressed summaries use
SummaryList - independent decisions, previews, notices, metrics, and spatial board items may remain cards
Lists own one outer border and separator rows. Do not recreate a list by mapping full bordered cards with gaps between them. Portal and platform use their own surface-owned list families rather than importing the org API.
Before choosing a type, separate four concepts that must not be conflated:
- workspace navigation changes the user's job or operating context and may point to a real route
- workflow queues switch between a small number of durable, operationally meaningful slices
- view modes change how the same records are presented because the alternate representation supports a genuinely different job
- collection controls search, filter, sort, group, select, or update records inside the current job
The secondary bar is scarce navigation space. It may hold workspace navigation, durable workflow queues, or a justified view-mode switch. It must not become a second collection toolbar. When page stats exist, their one valid home is the far right of this bar; stats never move into the primary page header or collection toolbar.
Search, ordinary status filters, client filters, sorting, grouping, density, saved views, selection, and bulk actions belong in the collection toolbar or table. A field being editable does not justify an Organize mode.
1. Queue-switched record lists
Use this when the page is still fundamentally a records table, but operators need a small number of durable workflow queues across the top.
Current examples:
timeentriesbilling/invoicesportals
Rules:
- the secondary bar owns the fixed queue switch
- the queue order is semantic and stable, not user-reorderable
- search and heavier filters stay in the local collection toolbar
- the content area is a dense list or table, not a board
- drag-and-drop is not the interaction model
Examples:
- entries:
All approvals,Draft,Submitted,Approved - invoices:
All invoices,Draft,Open,Past due,Paid - portals:
All portals,Live,Unlinked,Disabled,Attention
2. Multi-view operational collections
Use this when the same domain has two genuinely different representations because each supports a different job:
- a dense review/browse job
- a spatial planning or sequencing job
Current example:
projects
Rules:
- the secondary bar owns a concrete representation switch, for example
BoardandList - the default is the representation that best matches the domain's primary operational job
Listuses a dense table with scan-first columns and row actions- a board uses visible state lanes and may use drag-and-drop when spatial movement is central to planning
- search may exist in both modes when it helps find records
- filters that duplicate the board itself must not appear in board mode
- do not name a mode
Organize; name the actual representation or job
Example:
- projects board: status lanes for planning delivery work
- projects list: dense cross-project review with sortable columns and row actions
3. Pure record lists
Use this when the page is a dense operational list without a meaningful board mode or queue switch.
Current examples:
clientsbilling/subscriptions- most detail-adjacent record collections
Rules:
- the secondary bar is usually absent or reserved for page context, not list filtering
- search, filters, sort, and bulk actions stay local to the collection toolbar
- the content area defaults to an operational list: one bordered collection, separated rows, a flexible identity column, and stable comparison columns only when the list's own container is wide enough
- narrower list containers fold metadata beneath the identity instead of forcing routine horizontal scrolling; reserve horizontally scrolling tables for genuinely data-dense comparison work
- frequent row actions remain visible; overflow menus are for secondary or uncommon actions rather than the primary way to operate a record
- nested records remain lightweight inline rows rather than full peer cards
- drag-and-drop is not used
- mutable lifecycle fields may use inline selects or row actions when permissions allow
- sortable columns, grouping, saved views, and bulk changes are the scalable organization tools
Drive-specific extension:
- the org global drive route may add a client finder rail because retrieval across client workspaces is part of the job
- that client rail does not make the page a multi-view operational collection
- folder organization belongs primarily inside the client-specific drive tab, not the global finder
Guardrail:
- do not add drag-and-drop just to make a page feel more interactive
- only use drag-and-drop when moving items between visible states is itself the primary job
Secondary Bar Decision Rules
For every candidate item, ask these questions in order:
- Does it change to a different job or durable workspace? If yes, use a real route when the destination should be addressable and navigable independently.
- Is it a small, stable workflow queue operators return to repeatedly? If yes, it may be a secondary-bar queue.
- Does it change to a materially different representation that improves a distinct job? If yes, it may be a secondary-bar view mode.
- Is it search, filter, sort, grouping, density, saved-view selection, or a record mutation? Keep it in the collection toolbar or row.
Secondary-bar items must be stable and low in count. They should remain useful at both ten records and ten thousand records. Do not place transient filters, user-generated group values, or every lifecycle status there.
Current surface map:
| Surface | Secondary bar | Collection organization |
|---|---|---|
| Clients | lifecycle scopes: All, Active, Paused, Inactive, Archived | search, sortable columns, direct row status change, eventual bulk assignment/status changes |
| Projects | Board / List | board for spatial planning; list for sorting, filtering, grouping, and bulk operations |
| Entries | approval queues | search and record filters in toolbar; approval changed inline |
| Invoices | durable billing queues | client/search filters in toolbar; lifecycle actions on rows or detail |
| Quotes | commercial workflow queues only if operators actively work them as queues | otherwise move status to the toolbar |
| Contracts | legal workflow queues only if operators actively work them as queues | type/client filters and sorting in toolbar |
| Portals | access-health queues | search and client filters in toolbar; access actions on rows/detail |
| Subscriptions | none | search, client/status filters, sorting, row/detail lifecycle actions |
| Drive | client/retrieval context when needed | search, type filters, sort, folder operations, selection, and bulk file actions |
| Catalog | product/price workspace navigation when those remain distinct jobs | search, active/archive filters, sorting, and row actions |
This map is a product decision, not a mandate to make every page visually identical. Consistency comes from placing the same kind of decision at the same layer.
Collection Modes By Surface
Projects
Projects need multiple views, not one canonical tall list.
Required modes:
Boardas the primary planning viewListas the dense operational view
Board expectations:
- status columns such as planned, active, blocked, complete, archived
- drag-and-drop between columns
- compact project cards with only the fields needed for scanning
- visible tags such as client, priority, target date, owner, visibility, and at-risk signals
- archived work should not dominate the active board
List expectations:
- dense row height
- sortable columns
- quick filters for active, blocked, complete, archived
- visible tags instead of verbose body copy
- rows should open detail quickly without needing tall card bodies
Time
Time should stop behaving like a note-taking list and start behaving like time tracking software.
Time is not a multi-view operational collection. It is a queue-switched record list plus a timer utility route.
Timer expectations:
- start, pause, resume, stop
- active timer visible globally while working in the org surface
- quick project and client assignment
- running note field that does not require opening a full page dialog
- timer state should be obvious, persistent, and hard to lose
Entries expectations:
- secondary bar queue switch for
All approvals,Draft,Submitted,Approved - dense list or table for review and correction
- approval state, billable state, project, client, duration, and user shown clearly
- manual entry still supported, but secondary to live timing
- easy correction of recent entries without expanding large cards
- approval changes should use fast inline controls, not drag-and-drop lanes
Timer route expectations:
- lives as a utility route and shell-level utility affordance, not as a peer collection mode inside the entries workspace
Billing, Drive, Clients, Portals
These should share the same collection shell, but not the same collection type.
Expected behavior:
- dense rows or compact cards depending on the record type
- active filters and status segments at the top
- minimal repeated copy
- important flags and next actions visible at scan speed
Specific direction:
- invoices are queue-switched record lists
- portals are queue-switched record lists for agency-side client portal operations
- subscriptions are pure record lists
- the org global drive route is a client-first finder with a client rail plus a dense recent-items table
- clients are pure record lists with durable lifecycle scopes in the secondary bar and scalable toolbar/table organization
These pages do not all need kanban, but they should still feel like they belong to the same workspace system.
Customers And Portals Ownership Rule
The customer and portal surfaces must not drift into parallel identity models.
Canonical ownership is:
clientAccountis the company-level client recordclientContactis a person inside that company- portal access is state on that person
Surface responsibilities:
Customers/[clientId]/peopleis the canonical company people directory and access-management surfacePortalsis the cross-client operations workspace that summarizes and filters the same underlying person-level portal access state- the portals workspace must not infer readiness from only the client-account toggle or only the primary contact email when person-level access data exists
Quick Action Dock
The org surface should have a persistent quick-action dock in the bottom-right corner.
This is not decorative. It is a workspace control surface.
Initial actions should include:
- new project
- track time
- new client
- upload file
- create invoice or open billing action when that workflow exists
Design rules:
- desktop: floating vertical dock in the lower-right corner
- mobile: convert to a more compact sticky action surface instead of covering content
- keep labels concise and action-first
- avoid turning this into a noisy speed-dial full of rarely used actions
Density Rules
The current tall-card pattern should not remain the default for record-heavy pages.
Collection density rules:
- prefer rows, tables, board cards, or compact tiles over full-height narrative cards
- summary text should be optional metadata, not the main layout driver
- archived or inactive records should move behind a segment, filter, or collapsed group
- pages with dozens of records must still be scannable without feeling vertically punishing
- if a page is a record list, default to a responsive operational list and require a workflow reason before introducing board mechanics or a rigid horizontally scrolling table
Package Direction
If packages make this materially better, use them.
The likely direction is:
@dnd-kit/coreand@dnd-kit/sortableonly for justified spatial planning interactions such as the project board@tanstack/react-tableif the current table primitives are too thin for dense collection views
The current internal DataTable wrapper is too primitive on its own for the intended end state. It can either be evolved around a stronger table engine or replaced by a better internal abstraction.
Implementation Order
Do not redesign every list independently.
Implementation order:
- build the shared org collection shell
- build the org quick-action dock
- migrate
projectsfirst with board plus dense list - migrate
timesecond with real timer workflow plus dense entries view - move
billing, the global drive finder, andcustomersonto the same collection language
Guardrail
Do not keep adding more route-specific list UIs on top of the current stacked-card pattern.
Do not blur collection types once chosen.
- if a page is a queue-switched record list, do not smuggle organize-board behavior into the table
- if a page is a multi-view operational collection, keep the representations distinct instead of letting list filters fight the board
- if a page is a pure record list, do not add a secondary bar queue switch unless there is a durable workflow slice that truly deserves it
Before further heavy org workspace expansion, collection UX needs to become a deliberate system.