ADR 0016: Workspace dashboard, shared tables and command navigation
- Status: Accepted
- Date: 2026-10-30
Decision
Section titled “Decision”Use the official shadcn base-nova dashboard-01 composition for the workspace Dashboard: four summary cards, an interactive area chart and a mixed-object record table. Adopt official Chart/Badge primitives and Recharts; keep workspace chart colors and regional formatting. Preserve dashboard-01’s semantic card gradients and SVG area gradients, using unique IDs per chart instance. Follow its responsive card number sizes/two-line footers and wide-screen period ToggleGroup with a small Select on narrower cards. Chart spacing and the dotted tooltip follow the reference; preserve regional value/date formatting. Keep monotone curves because natural interpolation can show negative intermediate counts around sparse spikes. Creation and edit counts can overlap, so their areas remain independent instead of being summed into a stack. Series names are exposed by the standard tooltip rather than an additional legend. Dashboard and object-list local search both expose / and a visible keyboard hint. Dashboard code loads separately from the application shell.
The common API/MCP operations get_workspace_dashboard and list_workspace_records resolve current authorization before reading business contents. Content access follows ADR 0026: object/field/record predicates apply before search, counts and pagination. Other workspace members see only authorized records and metrics; Administrators retain the installation-wide exception. Workspaces stay isolated, and inactive/deleted object types are excluded from the normal dashboard.
Summary cards count records across active object types, active object definitions, records created within 30 days and distinct records whose current update time differs from creation within seven days. The 7/30/90-day chart uses the effective personal/workspace time zone. It counts record creations by their creation timestamp and distinct edited records per day from record journal events after creation. One record may therefore appear in multiple daily edit counts. Zero days remain zero; no fictional production metrics or trend percentages are injected. Statistics describe active, retained data; they are not a complete lifetime archive of removed objects.
The mixed-object API projects installed active standard fields into a fixed schema. Missing Keyword/Type/Status/Category values remain null; the UI shows an em dash and uses identity when no Keyword exists. Resolve classification labels instead of showing option IDs. Include the installed readable Record number under ADR 0030, object identity/label, creator/editor, timestamps and version; never join unrelated custom columns by coincident technical names. Server-side filtering, allow-listed sorting and pagination operate on the combined dataset before a page is returned.
Dashboard and individual object record lists share RecordDataTable, column visibility, current-page selection, row menus and TablePagination. Individual object lists initially show only installed Keyword (or ID fallback), Record number, Type, Status, Category, Created at and Updated at, in that order. The protected number is included when installed under ADR 0030; custom business fields remain available through the column menu. Column visibility for object lists, Dashboard, Dossier and Journal tables is retained in this browser, scoped by account and stable view/workspace/object identities; only boolean presentation preferences and structural keys are stored, never business values or credentials. Missing/corrupt/unavailable browser storage falls back to usable defaults. Localized object names determine Sidebar, command navigation and Dashboard object-filter ordering. Empty filtered results show a no-matches message and object lists offer Clear search. Selection never implies a bulk mutation. A shared selection bar explains the current-page scope and clearing on result changes. Selected rows offer Copy selected IDs (one identity per line) and Clear selection, including Dossier, recycled-record and Journal tables. These actions do not change records or permissions. Row actions open the record, optionally open its object list, or copy its ID; no unsupported Delete action is shown. Identity/Keyword stays visible. The footer always shows selected/total counts, page size, page count and first/previous/next/last controls, including empty/single-page results. Search/filter/sort/page/page-size state uses URL parameters; switching size or filter resets the page. Additional Dashboard sections are object-type filter tabs encoded in the URL, not new business objects/modules. Column visibility is a local draft of the mounted view and is not a saved global schema change.
Use the same complete pagination footer for potentially growing user, group, membership, field-definition and account-session tables. Those administrative tables retain their existing explicit actions; record selection does not create administrative bulk actions. The instance Journal also uses this footer. Its filtering and paging remain server-side; already-complete management lists page locally. All table headers use the standard muted semantic surface.
Follow sidebar-02 for search placement below the workspace chooser, with a compact trigger when collapsed. Keep Command/Ctrl+K. The scrollable command menu includes Dashboard, Settings, keyboard help, permitted object definitions, resources and authorized record search. Local navigation works without a two-character minimum; remote record search retains its minimum/debounce. Base UI dialog focus handling and cmdk item navigation remain authoritative. Choosing a destination closes mobile navigation. Keep resource URLs in one shared source.
User menus use the standard example’s avatar/profile header and more generous item spacing. Resource links live in a bottom-aligned SidebarContent group, with the user button separately in SidebarFooter, matching the examples’ separation.
Validation
Section titled “Validation”Application tests cover heterogeneous/missing standard fields, classification labels and multi-category projection, global sorting/pagination/filtering, workspace isolation, inactive types, empty dashboards, actual counts/daily activity and API/MCP authorization. Existing tests remain green. Chrome acceptance on a disposable multi-object fixture verified page selection/count/reset, page sizes and navigation in both mixed and single-object lists, column hiding, adding an object section, row menus, command-search results and End/Enter navigation, Settings navigation, collapsed-sidebar access and light/dark rendering. Browser logs contained no errors or warnings. The fixture uses synthetic data and is removed after acceptance.
Loading presentation
Section titled “Loading presentation”Pending tables reuse RecordDataTable with the actual columns, control slots and selected page size. Only rows and unknown count/page values become Skeletons; pending state is announced and table actions are disabled. Empty results are shown only after a successful response. Background refresh keeps prior results. Metadata loading uses the destination-specific table/form structure; the Dashboard reserves four statistic cards and the chart area. Lazy settings and classification imports show their eventual dialog frame immediately, with dismissal available and decorative action placeholders. Unknown authentication state uses neutral progress rather than guessing a form. Skeletons use existing semantic theme tokens and responsive layouts.