feat: Worker portal Stage 5 — case detail (3 shell strategies + 13 section types)
Description
Reframe the case detail surface around 13 section types and 3 shell strategies (scroll / card-grid / tabs), driven by the Stage-3 composition loader and a rulesets/{jurisdiction}/composition/case-detail.toml. The current 6-tab implementation maps to the "tabs" shell with current section types; this issue generalizes to all 3 shells.
Largest single surface in this redesign.
Acceptance Criteria
- Template at
services/canopy-web/templates/case/detail.htmlreadsComposedSurfacefrom composition loader and selects shell strategy from composition TOML per role (not per breakpoint) - 13 section types (one Askama partial each, using Stage 1 primitives):
- Household summary, Persons, Income, Assets, Expenses, Verifications, Determinations, Notices, Appeals, Audit, Cross-program, Worker activity, Documents
- 3 shell strategies:
scroll: all sections rendered in vertical document; in-page nav railcard_grid: sections as cards in CSS grid; clicking a card opens its detailtabs: classic horizontal tabs (current behavior preserved as default)
- Per-role TOML shape supported (see Design answers below) — composition loader picks the strategy by the authenticated user's role, not by viewport width
- Existing 30 caseworker actions preserved (per #392 (closed)/#393 (closed)/#394 (closed) work) — wired to whatever shell strategy the jurisdiction picks
- Per-section four-state rendering (loading / error / empty / populated)
- Default Georgia baseline
composition/case-detail.tomlshipstabsshell with current 6 section slugs (zero regression) - Playwright E2E: all 3 shells render; section nav works in each; actions fire in each
- axe-core WCAG 2.1 AA clean for all 3 shells
- CHANGELOG entry under
=== Changed
Design answers (2026-05-19)
- Shell strategies are jurisdiction-selectable per role, not progressive enhancements. Same jurisdiction can run different shells per role, but a given user in a given context sees exactly one shell. No breakpoint-based shell-switching in v1.
- Reasons: desktop-first product; runtime cost of two shells live (double templates, double htmx swap targets, ambiguous focus management mid-action); the responsive escape hatch is
tabs(the most viewport-tolerant shell — Mississippi composition in the design package uses this). - TOML shape: per-role
[shell.<role-slug>]tables incase-detail.toml:
[shell.eligibility_worker]
strategy = "scroll"
[shell.intake_screener]
strategy = "card_grid"- Section list and shell strategy are independent knobs. A jurisdiction on tabs can still reorder sections, mark some
required = true, or exclude program-specific ones via the same TOML. Section list lives insections = [...]; strategy lives in[shell.<role>]. - Georgia migration default: the existing 6-tab implementation becomes
strategy = "tabs"with the current section slugs insections = [...].scrollandcard_gridship as opt-in. No auto-migration — Studio admin switches when ready. - Section content shape is identical across shells. Only the chrome (in-page rail / CSS grid of cards / horizontal tab bar) changes per strategy. Section partials know nothing about which shell hosts them.
Blocked by
- Stage 1 design system extraction merged (#485 (closed))
- Stage 3 composition loader issue merged (#490 (closed))
Context & References
- Tracking issue: #460
- Epic: &51
- Plan: worker-portal-redesign.adoc, Stage 5
- Design canvas: case-detail refined + reframed, case-detail composability (13 section types × 3 shells × 3 jurisdictions)
- Related: #392 (closed)/#393 (closed)/#394 (closed) (per-program action handlers already shipped)
Labels
type::feature, priority::medium, program::infrastructure, service::web, workflow::needs-spec, compliance::wcag-21-aa
Edited by Ghost User