Portal v3 task page — join the authored portal experience
Restyle and re-architect the customer task detail / completion page so a project with a published Studio portal presents one cohesive, branded experience from home page to task and back.
Goal
The task page is the last v3 surface still rendering the legacy visual system. A customer moving from a branded portal home (authored chrome, brand wash, themed hero, tokenized cards) into a task today gets: the shell's TopHeader instead of the portal nav, a plain white background instead of the theme wash, 2019-era white cards with hard shadows, --vendor-color (the legacy branding column) instead of the portal brand, and no route back to the portal's pages. This proposal makes the task page a first-class authored-chassis page.
Current state
pages/v3/private/pages/project/projectTask/ProjectTask.vueis a port of the legacy page: it still importsTaskOverview,TaskMobileDrawer,TaskReassign, andTaskAssignmentDialogfrompages/private/…, and its styles are legacy (box-shadow: rgba(0,0,0,.12)/.24, white cards,--vendor-colorbuttons,$cp-break-point-*media queries instead of@container portaltiers).authoredChrome.jsdocuments the seam by name: the task detail page "has no authored chrome to replace it, so the shell keeps providing one." On a portal-published project this is exactly the double standard the customer sees.- The authored chassis (
PortalLayoutShell+PortalNav+PortalFooter+portal-chassis.css) and the theme pipeline (themeToCssVars,usePortalPageBackground,PortalThemeKey) are all host-agnostic and already consumed by ProjectHome, Studio canvas, and previews. Nothing about them is page-specific — the task page can mount the same frame. - Navigation into a task comes from
WidgetTaskChecklistrows andWidgetNextStepviaadapter.openTask→projectStore.selectNextTask(ref)→ the existingv3.portal.project.taskroute. Routing needs no change.
Design direction
Mockups: three concepts + a shared completion state were explored (scratchpad task-page-mockups/, screenshots in the design thread). Recommendation:
- Base = Concept A ("portal page"): full authored chassis (PortalNav, brand wash, PortalFooter); a slim context strip (back link, phase · task position, compressed phase segments, next-task action); a brand-gradient task band (hero-family styling, orb/gradient per theme
hero_style) carrying eyebrow, title, status/owner/due meta; then a work column (about + steps cards) and a sticky rail (details card, comments card). - Concept B is the narrow-container behavior of A, not a separate build: below the
lgcontainer tier the rail stacks under the work column and the completion affordance becomes the sticky pill bar. - Concept C ("guided workspace", left checklist navigator + work/conversation tabs) is a candidate second iteration — it changes IA (kills prev/next in favor of direct navigation) and should be validated against real playbooks with many tasks before committing. Out of scope here.
- Completion state: keep the store's
transitionToFeedbackflow, but the panel becomes a celebration card — check ring, phase progress ("6 of 8 in Configuration & training"), primary CTA to the canonical next task, ghost CTA back to project. Confetti stays.
Architecture
- Chrome claim + theme, same contract as ProjectHome. The task page resolves the published config through
portalConfigPolicyStore.resolveConfig(request-shared, cached per project), claimsuseAuthoredChromefrom the moment a fetch is in flight (the counted claim absorbs the task↔home route overlap), appliesthemeToCssVarson a.portal-themedroot, and callsusePortalPageBackgroundfor the wash. - Extract the chassis-host pattern. ProjectHome already carries the resolve → claim → theme → shell composition inline; the task page would be its second copy. Extract a
PortalChassisHost.vue(or composableusePortalChassisPage) owning: config resolution + loading gate, chrome claim, theme vars,PortalLayoutShell/PortalNav/account-menu wiring, and the no-config fallback slot. ProjectHome migrates onto it in the same PR so there is exactly one implementation. - Brand token scope. The PrimeVue token re-point (
--p-primary-color, button family →--portal-brand) currently lives on.portal-page-renderer. The task page's content is not a widget page, so extract that token block into a.portal-brand-scopeclass inportal-chassis.css(applied by both.portal-page-rendererand the task page root) rather than duplicating the list. - Nav behavior on a task page.
PortalNavrenders withhome-linkand the portal's pages; selecting a page routes to project home with that page active (nav emit →router.pushhome + page id in state/query — small addition to the emit contract, the shell stays dumb). - Steps engine reuse, not rebuild.
TaskOverview(+TaskSteps.js, the subtask/answer-path/forms logic) is the risk center. Phase 1 embeds it unchanged inside the new work card with a scoped restyle layer (tokens, row styling towardPortalTaskRowlanguage). A later phase may rebuild the step rows natively on chassis primitives; that is deliberately not this proposal. - Fallback stays legacy. A project without a published portal (or preview without config) keeps today's shell-chrome render. No change for v2-parity projects; the guard is
resolveConfig's answer, mirroring ProjectHome's gate exactly.
Phases
- Chassis host extraction —
PortalChassisHost+ ProjectHome migration; no visual change. Unit: chrome-claim behavior (mirrorauthoredChrome.test.js), fallback path, one-request sharing. - Task page on the chassis — mount the host, add context strip + task band
- work/rail grid; restyle comments card + details rail; kill legacy
TaskNavBarvisuals (module progress moves into the context strip).TaskOverviewembedded with restyle layer. Container-query tiers, not viewport media queries.
- work/rail grid; restyle comments card + details rail; kill legacy
- Completion state — celebration card w/ phase progress + next-task routing (uses existing
selectNextTask/TaskCompletePanelemits). - Mobile pass — narrow-tier stacking, sticky completion bar, comments below work (drawer retired at this tier if the stack reads well).
- Tests + seeds — component tests per phase; one Playwright happy path (open task from checklist → complete → celebration → next task) once the golden seed carries a published v5 portal (see note below).
Out of scope
- Concept C's navigator-rail IA.
- Rebuilding the steps/answer-path engine.
- The Conversations-widget rollup (own proposal) — the task page keeps its task-scoped comments.
- v2/v1 task pages.
Seed-data note
Local/CI seed portal documents currently published from the remove-sections branch are schema v6 (flat pages[].widgets); main's renderer and contract are v5 (pages[].sections[].widgets). Until PR #10842 merges, a fresh main checkout renders zero widgets for those seeded portals. Any e2e for this page must seed a v5 document (or land after #10842 and seed v6).