docs: add client portal tablo parity design spec
This commit is contained in:
parent
ebf6d8a255
commit
d69bfffd6f
1 changed files with 216 additions and 0 deletions
|
|
@ -0,0 +1,216 @@
|
|||
# Client Portal Tablo Parity
|
||||
|
||||
**Date**: 2026-04-15
|
||||
**Status**: Approved
|
||||
|
||||
## Overview
|
||||
|
||||
Make the client portal route in `apps/clients` match the visual design of the main app route `apps/main` `/tablos/:tabloId` as closely as possible.
|
||||
|
||||
The target route in `apps/clients` remains `/tablo/:tabloId`, but it should present the same shell language as `TabloDetailsPage`:
|
||||
|
||||
- same header structure
|
||||
- same metadata bar
|
||||
- same sticky tab navigation
|
||||
- same overview card layout and styling
|
||||
- same Tailwind/CSS visual system
|
||||
- same translation strategy through i18n
|
||||
|
||||
The client portal keeps its simpler local tab state and stays read-only except for discussion.
|
||||
|
||||
## Goals
|
||||
|
||||
- Match the current `apps/main` `TabloDetailsPage` look as closely as possible
|
||||
- Prevent visual drift between `apps/main` and `apps/clients`
|
||||
- Reuse the existing shared `@xtablo/tablo-views` section components
|
||||
- Keep the client portal safe by removing admin and mutation affordances
|
||||
- Use shared i18n keys wherever possible instead of hardcoded copy
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Rebuilding the client portal as a separate visual concept
|
||||
- Copying the main app's `?section=` route model into `apps/clients`
|
||||
- Enabling client file uploads, task completion, task creation, or layout editing
|
||||
- Refactoring unrelated app-level layout or navigation outside the tablo detail view
|
||||
|
||||
## Chosen Approach
|
||||
|
||||
Use a shared presentational shell for the tablo detail page, backed by a shared stylesheet source.
|
||||
|
||||
This shell should live close to the existing shared tablo view layer, likely in `packages/tablo-views`, because that package already contains the shared section components used by both apps.
|
||||
|
||||
Each app remains responsible for its own routing, data hooks, and permissions:
|
||||
|
||||
- `apps/main` keeps full `TabloDetailsPage` behavior
|
||||
- `apps/clients` keeps local internal tab state and client-specific data loading
|
||||
|
||||
The shared shell owns the route-level presentation so visual changes land in one place and are inherited by both apps.
|
||||
|
||||
## Shared CSS Source
|
||||
|
||||
Exact visual parity requires shared CSS, not just shared JSX.
|
||||
|
||||
Today both apps import `@xtablo/ui/styles/globals.css`, but `apps/main/src/main.css` and `apps/clients/src/main.css` already diverge on important visual tokens such as:
|
||||
|
||||
- navbar colors
|
||||
- dark mode tokens
|
||||
- chat surface colors
|
||||
- other route-level color variables
|
||||
|
||||
Because of that, `apps/clients` must not keep an independent competing style source for this page.
|
||||
|
||||
### Requirement
|
||||
|
||||
Extract the route-relevant visual styles currently coming from `apps/main/src/main.css` into a shared stylesheet layer that both apps import.
|
||||
|
||||
This shared stylesheet should include whatever is required for the tablo detail route to render identically, including:
|
||||
|
||||
- theme tokens needed by the page shell
|
||||
- chat-related styling used in the discussion tab
|
||||
- any utility styles relied on by the shared shell
|
||||
|
||||
### Constraint
|
||||
|
||||
Do not import `apps/main/src/main.css` directly from `apps/clients`. That would create brittle cross-app coupling and make ownership unclear.
|
||||
|
||||
Instead:
|
||||
|
||||
- move route-relevant shared styles into a shared import
|
||||
- keep app-specific styles in each app-local `main.css`
|
||||
|
||||
## Shared Shell Responsibilities
|
||||
|
||||
The shared tablo detail shell should own:
|
||||
|
||||
- the project header layout
|
||||
- the icon/image block next to the project title
|
||||
- header action placement
|
||||
- the metadata bar layout and styling
|
||||
- sticky tab navigation styling and behavior hooks
|
||||
- the overview page card grid and visual treatment
|
||||
|
||||
The shell should accept data and slots through props rather than owning app-specific mutations or routing decisions.
|
||||
|
||||
Suggested inputs:
|
||||
|
||||
- `tablo`
|
||||
- status label and badge styling
|
||||
- progress values
|
||||
- role label
|
||||
- created-at label
|
||||
- tab definitions
|
||||
- active tab
|
||||
- tab change handler
|
||||
- header action slot
|
||||
- overview capability flags or overview card content
|
||||
- per-section capability flags such as read-only settings
|
||||
|
||||
## `apps/main` Responsibilities
|
||||
|
||||
`apps/main` remains the owner of:
|
||||
|
||||
- `?section=` URL state
|
||||
- invite and share flows
|
||||
- client invite management
|
||||
- overview layout editing
|
||||
- task creation and mutation
|
||||
- file mutations
|
||||
- admin-only controls
|
||||
|
||||
The main app should adopt the shared shell without losing any existing behavior.
|
||||
|
||||
## `apps/clients` Responsibilities
|
||||
|
||||
`apps/clients` adopts the same visual shell, but keeps a restricted capability profile.
|
||||
|
||||
### Navigation
|
||||
|
||||
- Keep the current local tab state in React
|
||||
- Do not add `?section=` routing
|
||||
- Keep the same visible tab order, icons, and active styling as `apps/main`
|
||||
|
||||
### Header
|
||||
|
||||
- Keep the same header structure and spacing as `apps/main`
|
||||
- Keep the discussion CTA styling and placement
|
||||
- Remove the `Inviter` action entirely
|
||||
|
||||
### Metadata Bar
|
||||
|
||||
- Keep the same metadata structure and styling
|
||||
- Use client-safe translated labels for role and status copy
|
||||
|
||||
### Overview
|
||||
|
||||
- Use the same card layout and card styling as the main app
|
||||
- Remove layout edit controls
|
||||
- Remove task creation controls
|
||||
- Make task completion non-interactive
|
||||
- Keep file previews informational only
|
||||
|
||||
### Read-only Scope
|
||||
|
||||
The client portal should be read-only except for discussion.
|
||||
|
||||
That means:
|
||||
|
||||
- `discussion`: interactive
|
||||
- `tasks`: readable, no mutations
|
||||
- `etapes`: readable, no mutations
|
||||
- `events`: readable, no mutations
|
||||
- `roadmap`: readable, no mutations
|
||||
- `files`: readable, no upload, rename, move, create-folder, delete, or overflow action UI
|
||||
|
||||
## i18n
|
||||
|
||||
The shared shell must not introduce new hardcoded French strings.
|
||||
|
||||
### Rules
|
||||
|
||||
- Reuse existing translation keys from `apps/main` when the copy already matches the desired wording
|
||||
- Add missing keys only where the shared shell needs copy that does not already exist
|
||||
- Ensure both `apps/main` and `apps/clients` can resolve the keys used by the shared shell
|
||||
- Prefer shared wording for labels like tab names, metadata labels, and overview headings
|
||||
|
||||
This keeps parity at the copy level and avoids one app silently diverging from the other.
|
||||
|
||||
## Testing And Verification
|
||||
|
||||
Implementation should prove both parity and restrictions.
|
||||
|
||||
### Automated
|
||||
|
||||
- Add tests that verify the client shell renders the same key structure as the main shell
|
||||
- Add tests that verify client mode hides admin and mutation controls
|
||||
- Add tests that discussion remains interactive while other sections are read-only
|
||||
|
||||
### Manual
|
||||
|
||||
Perform side-by-side checks between:
|
||||
|
||||
- `apps/main` `/tablos/:tabloId`
|
||||
- `apps/clients` `/tablo/:tabloId`
|
||||
|
||||
Compare at minimum:
|
||||
|
||||
- header layout
|
||||
- metadata bar
|
||||
- sticky tabs
|
||||
- overview cards
|
||||
- tab content framing
|
||||
- discussion styling
|
||||
|
||||
## Risks
|
||||
|
||||
- Shared CSS extraction may expose assumptions currently embedded in app-local stylesheets
|
||||
- Some `TabloDetailsPage` copy is currently hardcoded and will need i18n cleanup before sharing
|
||||
- If the shared shell grows to own business logic, parity will become harder to maintain
|
||||
|
||||
## Success Criteria
|
||||
|
||||
This work is successful when:
|
||||
|
||||
- the client portal visually matches the main app tablo detail route
|
||||
- the shared shell and shared style source make future parity maintainable
|
||||
- the client portal remains read-only except for discussion
|
||||
- the route continues to use simpler internal navigation rather than query-param section routing
|
||||
Loading…
Reference in a new issue