Files
L-Ami-Fiduciaire/_bmad-output/planning-artifacts/ux-design-specification.md
Saad Ibn-Ezzoubayr 35545c2a8f feat: L'Ami Fiduciaire V1.0.0 — full codebase with Story 0.1 complete
Initial commit of the L'Ami Fiduciaire SaaS platform built on Laravel 12,
Vue 3, Inertia.js 2, and Tailwind CSS 4.

Story 0.1 (rename folders to declarations in database) is implemented and
code-reviewed: migration, rollback, and 6 Pest tests all passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 23:33:10 +00:00

77 KiB

stepsCompleted, inputDocuments
stepsCompleted inputDocuments
1
2
3
4
5
6
7
8
9
10
11
12
13
14
_bmad-output/planning-artifacts/product-brief-l-ami-fiduciaire-2026-03-10.md
_bmad-output/planning-artifacts/prd.md
_bmad-output/planning-artifacts/prd-validation-report.md
_bmad-output/project-context.md
docs/index.md
docs/project-overview.md
docs/architecture.md
docs/development-guide.md
docs/source-tree-analysis.md

UX Design Specification L'Ami Fiduciaire

Author: Saad Date: 2026-03-11


Executive Summary

Project Vision

L'Ami Fiduciaire is a practice management orchestration platform for Moroccan fiduciary firms. It sits above existing accounting tools (Sage/JBS) and government portals (SIMPL/Damancom) to orchestrate the complete practice workflow -- tracking deadlines across dozens of clients, coordinating team workload, managing client document exchange, and ensuring nothing falls through the cracks. The platform targets Morocco's ~20,000+ small-to-mid-size fiduciary firms (majority under 10 staff) with a confirmed Experio partnership for distribution.

The product is a brownfield project with a Laravel 12 + Vue 3 + Inertia.js stack, using shadcn-vue components and Tailwind CSS 4. Core infrastructure (multi-tenant workspaces, client management, folder/dossier system, client portal, document exchange, messaging, email notifications, 2FA, activity logging) is already built. The MVP adds 5 phases: role system foundation, dashboard separation, collaboration/nudge features, workflow efficiency (bulk operations, advanced filtering), and a full archive system.

Target Users

Persona Role Usage Pattern Tech Level Primary Device
Karim (Owner/Manager) Firm owner, 120+ clients, manages team Morning dashboard check, escalation handling Moderate Desktop
Rachid (Chef de Mission) Supervises 3 workers, 90 dossiers Team coordination, workload balancing, reassignment Moderate Desktop
Fatima (Collaborateur) Manages 45 client dossiers All-day power user -- the primary platform user Moderate Desktop
Hassan (External Client) SARL owner, non-technical Drive-by: click link, upload document, leave Low Mobile (phone)
Saad (Platform Admin) SaaS owner Platform monitoring, support tickets High Desktop

Design priority: Fatima is the heaviest daily user and the UX must be optimized for her workflow first. Karim/Rachid need command-center visibility. Hassan needs zero-friction, mobile-first portal interactions.

Key Design Challenges

  1. Multi-role dashboard complexity -- One app shell must serve 4 internal roles with dramatically different information needs. Navigation, sidebar, and dashboard content must adapt per role without fragmenting the product experience.

  2. Tables-first, density-first design -- Moroccan fiduciary professionals work in Excel and think in rows/columns. The PRD mandates "tables over cards" and "practicality-first UI." Every screen must prioritize information density and task speed over visual aesthetics.

  3. Bulk operations at scale -- Creating declarations for 50 clients simultaneously, scheduling bulk notifications. These power-user flows must be fast yet error-proof, with clear multi-select, type selection, and date picking patterns.

  4. Client portal for non-technical users -- Hassan is on his phone, not tech-savvy, possibly on the go. The portal must be a single-action page with zero cognitive load: see what's needed, do it, leave. Mobile-first for this surface only.

  5. Information density vs. cognitive overload -- Owners see 120+ clients, workers see 45+ declarations with deadlines. Dense data tables must use smart color coding, status badges, and priority indicators to enable scanning without overwhelming.

  6. Brownfield constraints -- 31 existing Vue pages, shadcn-vue component library, Inertia.js page-based navigation patterns. UX design must extend and enhance what's built, not start from scratch.

Design Opportunities

  1. "Morning command center" moment -- A transformative dashboard experience where Karim sees his entire firm's status for the first time on one screen. Priority alerts (red/amber/green), deadline countdowns, and team activity create the "aha moment" that drives trial-to-paid conversion.

  2. Moroccan fiscal calendar intelligence -- Pre-loaded TVA deadlines (20th), CNSS (10th), IS (quarterly) in bulk creation flows. The system knows the calendar so users don't have to remember it.

  3. Progressive disclosure for power features -- Clean, simple defaults with advanced features (nudge system, archive, advanced filters) accessible but not in the way. Fatima discovers power features as she needs them.

  4. Consistent visual status language -- A unified color/badge/icon system for declaration statuses across all views (dashboards, tables, archive, portal). Enables instant scanning -- Fatima can assess 45 declarations' health in seconds.

Core User Experience

Defining Experience

The core product loop for L'Ami Fiduciaire centers on the declaration status scanning and action cycle. Fatima (the primary daily user) opens her scoped dashboard, scans her declaration list, identifies what needs attention based on visual status indicators, and takes immediate action -- sending a client notification, updating a status, or escalating to a manager. This scan-identify-act loop happens dozens of times per day and must be optimized for speed and accuracy.

For Karim (Owner), the core experience is the morning command center check -- a single-screen view of the entire firm's health: which declarations are at risk, which clients are unresponsive, which workers are overloaded. The dashboard-to-action flow (seeing a problem and resolving it in minimal clicks) is the critical interaction to get right.

For Hassan (External Client), the core experience is the single-action portal interaction -- click a link, see what's needed, do it, leave. The entire interaction should complete in under 60 seconds.

Platform Strategy

Dimension Decision Rationale
Primary platform Desktop web (Chrome/Firefox/Safari) Fiduciary professionals work at desks in offices
Secondary platform Mobile web (responsive) Client portal for Hassan; no native app for MVP
Input model Mouse/keyboard-first (firm users), touch-friendly (portal) Dense tables and power workflows for professionals, simple tap interactions for clients
Offline support Not required Firm users always connected; client portal interactions are brief
SPA model Inertia.js server-driven pages Brownfield constraint -- full page transitions, server-side filtering, pagination. No infinite scroll or complex client-side state

Effortless Interactions

  1. Status scanning -- Fatima opens her dashboard and knows in 2 seconds: "3 urgent, 5 on track, 2 waiting on clients." Color/badge visual language eliminates the need to read individual rows.

  2. One-click nudge -- Karim sees a problem declaration, clicks the nudge icon on the row, selects an employee. Done. No modal forms, no extra navigation.

  3. Bulk declaration creation -- Select 20 clients via checkboxes, pick declaration type (TVA Mensuel), set deadline (March 20), create. Three steps for 20 declarations.

  4. Client portal upload -- Hassan clicks email link, sees one sentence explaining what's needed, taps upload, takes photo of document, confirms. Under 60 seconds total.

  5. Filter persistence -- Fatima sets her preferred filters (Status = En cours, Assignee = Me) once. Filters persist across navigation until explicitly cleared.

Critical Success Moments

Moment Persona Description Impact
"Morning command center" Karim First time seeing all 120+ clients' status on one screen Trial-to-paid conversion trigger
"My list is clear" Fatima End of day, all declarations updated, all notifications sent Daily satisfaction, retention
"30-second upload" Hassan Click link, upload document, see confirmation Client portal adoption
"Nothing fell through" Karim End of month, zero penalty notices across all clients Long-term retention moment
"I can see everything" Rachid Reassigns declaration from absent worker in 2 clicks Team coordination value proof

Experience Principles

  1. Density is clarity -- More information on screen is better, not worse. Accountants are trained to read dense data. The UX removes noise, not data. Every row, badge, and number earns its place.

  2. Action at the point of recognition -- The moment a user recognizes something needs attention, the action should be available right there. Inline actions, row-level buttons, contextual menus. No navigate-to-another-page-to-do-the-thing.

  3. The system remembers, so you don't have to -- Fiscal calendar awareness, filter persistence, status history, audit trails. The platform carries the cognitive load that currently lives in users' heads and Excel sheets.

  4. Zero-friction boundaries -- Every boundary crossing (firm-to-client portal, dashboard-to-declaration detail, active-to-archive) should feel seamless. No dead ends, no "where was I?" moments.

  5. French-native, Morocco-aware -- Not a translated product. UI language, date formats (dd/mm/yyyy), currency (MAD), fiscal calendar, and professional terminology are natively Moroccan French.

Desired Emotional Response

Primary Emotional Goals

Persona Primary Emotion Emotional Shift
Karim (Owner) In control, confident From anxiety ("what's falling through?") to mastery ("I see everything")
Fatima (Worker) Competent, unburdened From overwhelmed ("45 clients in my head") to methodical ("I work the list")
Hassan (Client) Respected, not confused From friction ("another system to figure out") to ease ("that was quick")
Rachid (Manager) Effective, empowered From relay ("WhatsApp forwarding") to leader ("I coordinate, I don't chase")

Emotional Journey Mapping

Stage Desired Emotion Anti-Emotion (Avoid)
First discovery / signup Curiosity, "this is made for me" Skepticism, "just another tool"
Onboarding (first 30 min) Confidence, progressive competence Overwhelm, confusion
First morning dashboard Relief, revelation Information overload
Daily use (Fatima's loop) Flow state, productive rhythm Tedium, friction
Bulk operations Power, efficiency Fear of mistakes at scale
Client portal (Hassan) Ease, "that was quick" Confusion, abandonment
Something goes wrong Trust, "I can fix this" Panic, blame, data loss fear
End of month review Pride, accomplishment Dread, surprise penalties
Returning next day Familiarity, continuity Disorientation, "where was I?"

Micro-Emotions

  • Confidence over confusion -- Every screen immediately answers "where am I, what can I do here?" through role-based views, clear headings, and breadcrumbs.
  • Trust over skepticism -- Data integrity signals throughout: timestamps, audit trails, upload confirmations, action feedback. Never leave users wondering if something worked.
  • Accomplishment over frustration -- Progress indicators, completion states, visual reward as task lists clear through the day. Fatima's dashboard shifting from red to green is the emotional payoff.
  • Calm over anxiety -- During peak season (bilan Jan-Mar), the platform reduces stress. No alarm fatigue, smart priority levels, achievable daily task scope. Not everything can be red.

Design Implications

Desired Emotion UX Design Approach
In control (Karim) Dashboard summary cards with real-time counts, color-coded priority system, no hidden information
Unburdened (Fatima) Scoped view showing only assigned work, clear next-action indicators, persistent filters
Respected (Hassan) Single-purpose portal pages, large touch targets, plain French copy, immediate confirmation feedback
Effective (Rachid) One-click reassignment, team workload overview, nudge system with direct-link notifications
Confident (all internal) Consistent layout patterns, breadcrumb navigation, undo/correction flows, visible activity logs
Calm during peak (all firm) Smart alert prioritization, deadline countdown gradients (green to amber to red), manageable daily scope
Trust (all) Timestamps on every action, explicit confirmations, archive as preservation (not deletion), accessible audit trail

Emotional Design Principles

  1. Professional calm, not consumer excitement -- This is a daily-use B2B tool for accountants during high-stress periods. The design should feel reliable, structured, and calming -- like a well-organized filing cabinet, not a flashy app.

  2. Earned urgency only -- Red alerts, warning badges, and urgent indicators must be meaningful and sparse. If the system cries wolf, users stop trusting it. Priority levels (critical/warning/info) must reflect real deadline proximity.

  3. Collaborative, not surveillance -- Activity logs and nudges exist to coordinate work, not monitor employees. The nudge system should feel like a helpful tap on the shoulder, not a manager looking over your shoulder.

  4. Immediate feedback, always -- Every user action gets visible confirmation. Uploads confirmed, status changes reflected, nudges acknowledged. Silence creates anxiety; feedback creates trust.

  5. Graceful degradation of pressure -- As deadlines approach, the UI should communicate increasing urgency gradually (green to amber to red) rather than suddenly. Users should never be surprised by an overdue declaration -- the system warned them progressively.

UX Pattern Analysis & Inspiration

Inspiring Products Analysis

1. Linear (Project/Issue Tracking)

Why relevant: Linear's issue tracker is the closest UX analog to Fatima's declaration list -- dense rows of work items with statuses, assignees, priorities, and deadlines. It's the gold standard for "tables-first, keyboard-driven B2B SaaS."

What they do well:

  • Scannable list views -- Status icons (colored circles), priority indicators, and assignee avatars are visible at the row level without expanding anything. One glance tells you the state of each item.
  • Inline actions -- Right-click context menus and keyboard shortcuts for status changes, assignment, priority updates. No page navigation required for common actions.
  • Filter bar with persistence -- Filters sit above the list, stay active across sessions, and can be saved as custom views.
  • Progressive disclosure -- Simple by default, powerful when you dig in. New users see a clean list; power users build custom workflows.
  • Sidebar navigation -- Collapsible sidebar with workspace-level navigation. Clean, not cluttered.

Transferable to L'Ami Fiduciaire: Declaration list UX, filter persistence, inline row actions, sidebar navigation pattern, status icon system.

2. Excel / Google Sheets (The Users' Mental Model)

Why relevant: This is how Fatima and Karim currently work. Excel is not a product to emulate but a mental model to respect. Users think in rows, columns, sorting, and filtering. Any table in L'Ami Fiduciaire must feel at least as natural as a spreadsheet.

What they do well:

  • Information density -- Maximum data per screen. No wasted whitespace. Users are trained to scan dense grids.
  • Sort and filter as primary interaction -- Click a column header to sort, filter dropdowns on columns. This is muscle memory.
  • Cell-level editing -- Click a cell, change the value, move on. Minimal friction for status updates.
  • Familiarity -- Zero learning curve for the basic interaction model.

Transferable to L'Ami Fiduciaire: Table density expectations, column sorting, filter-first navigation, minimal whitespace in data views. The UX should feel like "Excel that thinks for you" -- same density, but with status intelligence, deadline awareness, and collaboration built in.

3. Sage (Accounting Software -- The Legacy Baseline)

Why relevant: Every firm user has Sage open daily. It's a Windows-era desktop application with a functional but dated UI. Understanding what users tolerate (and what frustrates them) about Sage informs what L'Ami Fiduciaire should avoid.

What they tolerate:

  • Dense forms with many fields -- accountants are used to data-heavy screens
  • Menu-driven navigation (File > Client > Dossier) -- hierarchical mental model
  • Modal dialogs for data entry -- not ideal, but familiar

What frustrates them:

  • No web access, no collaboration, no real-time updates
  • No dashboard or overview -- you must drill into each client individually
  • No notification system -- everything is manual recall
  • Dated visual design that feels like work, not empowerment

Lesson for L'Ami Fiduciaire: Don't try to look like Sage. But respect the density and data-first expectations that Sage users carry. The platform should feel modern and web-native while maintaining the information density that accountants expect.

4. Experio (AI Pre-Accounting -- The Partner Product)

Why relevant: Confirmed partnership. Many L'Ami Fiduciaire users will also be Experio users. Their UX is a cautionary reference.

What to learn from their weaknesses:

  • Bad UX on core pages creates an opportunity -- L'Ami Fiduciaire can set a higher standard that makes the combined Experio + L'Ami stack feel premium
  • If Experio's onboarding works (landing page is good), users arrive with expectations that the product behind the landing page will be equally polished
  • Integration UX (future) must be seamless enough to compensate for Experio's own UX gaps

Lesson for L'Ami Fiduciaire: Be the product in the stack that users actually enjoy using. Set the UX bar for the Moroccan fiduciary SaaS ecosystem.

Transferable UX Patterns

Navigation Patterns:

  • Collapsible sidebar with role-driven sections (from Linear) -- Sidebar shows different nav items based on role. Owner/Manager sees "Dashboard, Clients, Declarations, Archive, Team, Settings." Worker sees "Dashboard, My Declarations, Archive, Settings." Clean separation without separate apps.
  • Breadcrumb trail for depth navigation (standard B2B) -- Dashboard > Client Benani > TVA Janvier 2026. Always know where you are, always able to go back.

Interaction Patterns:

  • Inline status updates on table rows (from Linear) -- Click a status badge directly on the declaration row to cycle through statuses or open a dropdown. No need to open the full detail page for common actions.
  • Row-level action menu (from Linear) -- Three-dot menu or right-click on any declaration row reveals: Edit, Nudge, Reassign, View Detail, Archive. Actions at the point of recognition.
  • Bulk selection with action bar (from Gmail/Linear) -- Checkboxes on rows, floating action bar appears: "23 selected: Create Declarations | Send Notifications | Change Status."

Visual Patterns:

  • Color-coded status badges (from Linear/GitHub) -- Consistent colored dots/pills for declaration statuses across all views. Same color = same meaning everywhere.
  • Deadline proximity indicators (unique to L'Ami) -- Days-remaining counter with color gradient: green (>7 days) → amber (3-7 days) → red (<3 days) → dark red (overdue). More informative than a simple date.
  • Summary cards above tables (from dashboard patterns) -- "12 En cours | 3 En retard | 5 En attente client | 2 Urgent" as clickable cards that filter the table below.

Data Patterns:

  • Server-side pagination with page size control (Inertia constraint) -- Standard pagination (25/50/100 rows per page) with persistent preference. Respects the server-driven SPA model.
  • Column sorting (from Excel mental model) -- Click column headers to sort. Users expect this from their spreadsheet habits.
  • Persistent filter bar (from Linear) -- Filter pills visible above the table, removable with X, persisted in session/URL params.

Anti-Patterns to Avoid

  1. Card-based layouts for data lists -- Cards waste space and break the row-scanning mental model accountants rely on. Declarations, clients, and archive items must be table rows, not cards. Cards are acceptable only for dashboard summary metrics.

  2. Over-modalization -- Opening a modal for every action (edit status, send notification, reassign) creates friction. Prefer inline edits, dropdowns, and popovers over full modals. Reserve modals for destructive or multi-step actions only (bulk creation, delete confirmation).

  3. Hidden navigation behind hamburger menus -- Desktop users expect a visible sidebar. Never hide the primary navigation behind a toggle on desktop viewports. The sidebar is always visible (collapsible to icons is acceptable).

  4. Alarm fatigue through over-notification -- Not every declaration needs a red badge. Priority indicators must use 3-4 levels (critical/warning/info/neutral) with clear thresholds tied to deadline proximity. Default state is calm.

  5. Onboarding wizards that block usage -- Multi-step setup wizards create friction. Prefer progressive onboarding: let users into the product immediately, guide them contextually. "Add your first client" prompt on an empty client list is better than a 5-step wizard.

  6. Whitespace-heavy "modern" design -- Fiduciary professionals want density, not aesthetics. Large padding, oversized cards, and spacious layouts feel wasteful to users who work in Excel all day. Keep spacing tight and purposeful.

Design Inspiration Strategy

What to Adopt:

  • Linear's list view UX (scannable rows, inline actions, filter persistence) → Declaration and client list views
  • Linear's sidebar navigation (collapsible, workspace-scoped) → App shell navigation
  • Summary-cards-above-table pattern → Dashboard command center and list view headers
  • Color-coded status badge system → Universal declaration status language

What to Adapt:

  • Excel's density expectations → Adapt for web (slightly more spacing than a spreadsheet, but far less than typical SaaS)
  • Linear's keyboard shortcuts → Start with mouse-first, add keyboard shortcuts as power-user feature post-MVP
  • Gmail's bulk selection bar → Adapt for declaration bulk operations (create, notify, status change)

What to Avoid:

  • Experio's core page UX patterns → Set a higher bar
  • Sage's modal-heavy, menu-driven navigation → Use modern web navigation (sidebar + breadcrumbs)
  • Card layouts for data → Tables everywhere except dashboard summaries
  • Consumer SaaS aesthetic (Notion-like spaciousness) → Too sparse for accountant workflows

Design System Foundation

Design System Choice

Selected: shadcn-vue (reka-ui) + Tailwind CSS 4 -- extending the existing brownfield design system.

This is a brownfield project with 20+ shadcn-vue component groups already installed and 31 Vue pages built on them. The design system choice is to confirm, extend, and customize what exists rather than replace it.

Component Library: shadcn-vue (headless reka-ui primitives with Tailwind styling) Styling Framework: Tailwind CSS 4 with CVA (Class Variance Authority) for component variants Icons: Lucide (lucide-vue-next) Utility Layer: cn() helper (clsx + tailwind-merge) in resources/js/lib/utils.ts

Rationale for Selection

  1. Brownfield reality -- 31 Vue pages and 20+ component groups already built on shadcn-vue. Migration cost would exceed any benefit of an alternative system.
  2. Density-compatible -- Headless primitives with Tailwind styling allow full control over spacing and density. Unlike Material Design or Ant Design, there's no opinionated spacing to fight against.
  3. Accessibility built-in -- reka-ui handles ARIA attributes, keyboard navigation, and focus management at the primitive level. Accessible by default without extra work.
  4. Tailwind 4 synergy -- CVA-based component variants make it straightforward to create "compact" and "dense" variants of existing components for data-heavy views.
  5. No vendor lock-in -- Components live in the project (resources/js/components/ui/), not in node_modules. Full ownership and customization capability.
  6. Team familiarity -- Both developers (Saad + Ilyas) already work with this stack daily. Zero learning curve.

Implementation Approach

Extend, don't replace:

  • Existing resources/js/components/ui/ components remain untouched (auto-generated via npx shadcn-vue)
  • New custom components built in resources/js/components/ (app-level) following the same Tailwind + CVA patterns
  • Dense/compact variants added via CVA variant props (e.g., size="compact") rather than separate components

Component organization:

  • resources/js/components/ui/ -- shadcn-vue base components (do not modify)
  • resources/js/components/ -- app-level business components (ClientForm, FolderForm, etc.)
  • New dashboard, filter, and notification components added to resources/js/components/

Customization Strategy

1. Design Tokens (via Tailwind CSS 4 theme):

  • Declaration status colors (universal across all views)
  • Priority level colors (deadline proximity gradient)
  • Alert severity colors (critical/warning/info/neutral)
  • Spacing scale optimized for density (tighter than default Tailwind)

2. Component Variants to Create:

  • Dense Table -- Compact row height, tighter padding, optimized for 25-50 rows visible without scrolling
  • Status Badge -- Color-coded pill with consistent mapping to declaration statuses
  • Priority Indicator -- Days-remaining counter with deadline proximity color
  • Summary Card -- Dashboard metric card with count, label, and click-to-filter behavior
  • Filter Bar -- Persistent filter pills with dropdown selectors and clear-all action
  • Nudge Button -- Inline row-level action for one-click team coordination
  • Bulk Action Bar -- Floating bar that appears on multi-select with available bulk operations

3. Layout Customizations:

  • Sidebar navigation adapted for role-driven sections
  • Dashboard grid layout for command center summary cards
  • Table-first page templates for Clients, Declarations, and Archive views
  • Single-action portal page template for client-facing interactions

Defining Core Experience

The Defining Interaction

L'Ami Fiduciaire's defining experience is: "Open the app and instantly know what needs your attention across all your clients."

This is the interaction that drives trial-to-paid conversion, daily engagement, and word-of-mouth referral. Karim describes it as: "I open L'Ami Fiduciaire and I see everything -- which clients are at risk, which declarations are overdue, who needs to submit documents. Nothing surprises me." For Fatima: "I log in and my list tells me exactly what to do today."

User Mental Model

Persona Mental Model Primary Question Design Implication
Karim (Owner) Thinks in "risk" "What's about to go wrong?" Exception-based dashboard: surface problems first, details on drill-down
Fatima (Worker) Thinks in "task lists" "What do I need to do today?" Ordered action list: next action per client, sorted by urgency
Hassan (Client) Thinks in "requests" "What do they want from me?" Single-action page: one clear instruction, one button

Key mental model constraints:

  • Karim expects a command center that surfaces exceptions, not an exhaustive inventory. Summary cards for the big picture, alert lists for what needs attention.
  • Fatima expects Excel-like table interactions: sort, filter, scan rows. Table patterns must support this muscle memory.
  • Hassan needs explicit, action-oriented copy. "Telecharger votre releve bancaire de janvier" not "Documents requis."

Success Criteria

Criterion Measure Threshold
Time to situational awareness Karim understands firm status after opening dashboard < 10 seconds
Time to first action Fatima identifies and starts working on most urgent item < 30 seconds from login
Task completion rate Hassan completes portal action without help > 95% success rate
Scan accuracy Fatima identifies 3 most urgent declarations from list of 45 Instant via visual status language
Zero-miss rate Priority alerts catch all approaching deadlines 100% coverage

Pattern Innovation

The core experience uses established interaction patterns combined in novel ways:

  • Established: Data tables with sorting/filtering (Excel mental model), status badges with color coding (Linear/GitHub), dashboard summary cards (standard B2B SaaS), bulk selection with action bars (Gmail)
  • Novel combination: Deadline proximity indicators that auto-calculate days remaining and color-code based on Moroccan fiscal calendar awareness
  • Novel combination: Summary cards that double as table filters -- clicking "3 En retard" filters the table below to overdue declarations only
  • Novel combination: Role-based dashboard layouts serving different mental models (Karim's risk-first vs. Fatima's task-first) from the same underlying data

No user education required. Every pattern feels familiar to users of Excel, email, and basic web apps. The intelligence is in the system, not in asking users to learn new interactions.

Experience Mechanics

The Core Loop: Open → Scan → Act → Confirm

1. Initiation (Opening the App):

  • Owner/Manager lands on Command Center Dashboard: summary cards (active clients, declarations by status, overdue count, pending client actions), priority alert list, recent activity feed
  • Worker lands on Scoped Dashboard: same structure filtered to assigned clients only, "My Declarations" as primary view
  • Data is server-rendered (Inertia) -- no loading spinners for primary content

2. Scanning (Identifying What Needs Attention):

  • Visual hierarchy: red = overdue (act now), amber = approaching deadline (plan), green = on track (ignore), gray = completed/archived
  • Summary cards are clickable filters: click "3 En retard" → table filters to overdue declarations
  • Column sorting on all data columns, default sort by deadline ascending (most urgent first)

3. Acting (Taking Action):

  • Inline status change: click status badge → dropdown → select new status → instant update with toast confirmation
  • One-click nudge: click nudge icon → popover with assignee → click send → toast confirmation, no page navigation
  • Bulk operations: select rows via checkboxes → floating action bar → choose action → confirmation → execute → toast with count

4. Confirming (Knowing You're Done):

  • Summary cards update as statuses change ("3 En retard" → "2 En retard")
  • Task list visually clears through the day -- urgent count decreases as work progresses
  • End-of-day state: "0 En retard, 0 Actions en attente" -- the "nothing fell through" emotional payoff

Visual Design Foundation

Color System

Base Theme (Existing -- Confirmed): The brownfield codebase uses shadcn-vue "new-york-v4" style with OKLCH color tokens. The existing palette serves as the foundation:

  • Primary: Blue/purple (oklch(0.488 0.243 264.376)) -- main interactive elements, active states, sidebar highlights
  • Primary Foreground: Near-white (oklch(0.97 0.014 254.604)) -- text on primary backgrounds
  • Destructive: Red (oklch(0.577 0.245 27.325)) -- delete actions, critical errors
  • Background: White (oklch(1 0 0)) -- page backgrounds
  • Foreground: Near-black (oklch(0.141 0.005 285.823)) -- primary text
  • Muted: Light gray (oklch(0.967 0.001 286.375)) -- secondary backgrounds
  • Muted Foreground: Medium gray (oklch(0.552 0.016 285.938)) -- secondary text, labels
  • Border: Light gray (oklch(0.92 0.004 286.32)) -- dividers, input borders
  • Dark mode: Full dark theme variant with inverted tokens, togglable via system/user preference

New Semantic Colors (To Add):

Declaration status colors -- the universal visual language used across dashboards, tables, archive, and portal:

Status Color Token OKLCH Value Usage
Overdue (En retard) --status-overdue Red -- high chroma, clearly urgent Declarations past deadline
Urgent (Urgent) --status-urgent Dark amber/orange -- approaching deadline Declarations due within 3 days
In Progress (En cours) --status-in-progress Blue (primary) Active work, normal state
Waiting Client (En attente client) --status-waiting Amber/yellow Blocked on external action
Completed (Termine) --status-completed Green -- muted, not celebratory Successfully closed
Draft (Brouillon) --status-draft Gray (muted foreground) Not yet active
Archived (Archive) --status-archived Light gray, desaturated Read-only historical

Priority/deadline proximity gradient:

Proximity Color Threshold
Safe Green > 7 days remaining
Approaching Amber 3-7 days remaining
Urgent Orange-red 1-3 days remaining
Overdue Red Past deadline

Alert severity levels:

Level Color Usage
Critical Red (destructive) Overdue declarations, system errors
Warning Amber Approaching deadlines, missing documents
Info Blue (primary) Nudge received, status update, new upload
Neutral Gray (muted) Activity log entries, completed items

Typography System

Primary Typeface: Instrument Sans (already configured)

  • Clean, modern sans-serif with excellent readability at small sizes
  • Appropriate for dense data tables and professional B2B context
  • Full stack fallback: Instrument Sans, ui-sans-serif, system-ui, sans-serif

Type Scale (optimized for density):

Level Size Weight Line Height Usage
Page Title 1.5rem (24px) 600 (semibold) 1.33 Page headings (Declarations, Clients, Archive)
Section Title 1.125rem (18px) 600 (semibold) 1.33 Dashboard section headers, card titles
Card Metric 1.5rem (24px) 700 (bold) 1.2 Summary card numbers ("12", "3", "45")
Table Header 0.75rem (12px) 500 (medium) 1.5 Column headers, uppercase tracking
Table Body 0.8125rem (13px) 400 (regular) 1.5 Table row content -- slightly smaller than default for density
Body 0.875rem (14px) 400 (regular) 1.5 General content, form labels
Small/Caption 0.75rem (12px) 400 (regular) 1.5 Timestamps, metadata, secondary info
Badge 0.6875rem (11px) 500 (medium) 1.2 Status badges, tags, counts

Density note: Table body text at 13px (not the default 14px) allows approximately 20% more rows visible without scrolling, directly supporting our "density is clarity" principle. This small reduction is still readable on standard monitors.

Spacing & Layout Foundation

Base Spacing Unit: 4px (Tailwind default) Density Strategy: Use tighter spacing in data-heavy views, standard spacing in forms and settings.

Context Spacing Approach
Dashboard summary cards Standard padding (p-4/p-6), comfortable spacing between cards
Data tables (dense) Compact padding: py-2 px-3 per cell (not default py-4). Reduced row height to show 25-50 rows without scrolling
Filter bar Compact: gap-2 between filter pills, py-1.5 px-3 per pill
Forms Standard spacing: gap-4 between fields, comfortable padding
Portal pages Generous spacing: p-6/p-8, large touch targets (min 44px), mobile-friendly
Sidebar navigation Compact: py-1.5 px-3 per nav item, visually tight but clickable

Layout Grid:

  • Dashboard: CSS Grid -- 4-column layout for summary cards, full-width table below
  • List views (Clients, Declarations): Full-width table with filter bar above
  • Detail pages: Two-column layout (main content + sidebar with metadata/actions)
  • Portal pages: Single-column, centered, max-width 480px (mobile-optimized)
  • Sidebar: Fixed 240px collapsed to 64px (icon-only). Always visible on desktop.

Border Radius (Existing):

  • Base: 0.65rem -- kept for buttons, cards, inputs
  • Badges/pills: full rounded (rounded-full) for status indicators
  • Tables: square corners (rounded-none) -- tables should feel sharp and data-like

Accessibility Considerations

Color Contrast:

  • All text meets WCAG 2.1 AA standard (4.5:1 for normal text, 3:1 for large text)
  • Status colors must be distinguishable without relying solely on color -- pair with icons or text labels
  • OKLCH color space (already used) provides perceptually uniform colors, improving accessibility

Color Blindness:

  • Status system uses both color AND shape/icon: overdue = red + warning triangle, completed = green + checkmark, waiting = amber + clock
  • Never use red/green distinction alone -- always paired with secondary visual cue

Keyboard Navigation:

  • reka-ui (shadcn-vue foundation) provides keyboard navigation for all interactive components by default
  • Focus rings visible (existing ring tokens configured)
  • Tab order follows visual layout

Text Readability:

  • Minimum body text size: 13px (table dense) / 14px (general)
  • Line height minimum: 1.5 for body text, 1.33 for headings
  • Instrument Sans has excellent x-height for readability at small sizes

Dark Mode:

  • Full dark theme already configured with OKLCH tokens
  • Status colors must maintain distinguishability and contrast in both light and dark modes
  • New semantic color tokens will include both light and dark variants

Design Direction Decision

Design Directions Explored

Four distinct visual directions were generated and presented via an interactive HTML showcase (ux-design-directions.html):

  1. Linear Dense — Ultra-compact, keyboard-first, minimal chrome, maximum data density
  2. Command Center Dashboard — Bold KPI cards, full sidebar, activity/alerts panels, strong visual hierarchy
  3. Balanced Professional — Standard-density tables, prominent filter bars, clean spacing, professional tone
  4. Split-View Action — Master-detail layout, persistent context panel, action-oriented sidebar

Each direction applied the established visual foundation (OKLCH color tokens, Instrument Sans, shadcn-vue components) in different layout and density configurations.

Chosen Direction

Hybrid: "Command Professional" — A combination of Direction 2 (Command Center Dashboard) and Direction 3 (Balanced Professional).

Key elements from Command Center Dashboard:

  • Large KPI summary cards prominently displayed on dashboard views
  • Full sidebar navigation with logically grouped sections (Clients, Declarations, Archive, Team, Settings)
  • Activity feed and alerts panel for real-time operational awareness
  • Bold visual hierarchy with distinct information zones

Key elements from Balanced Professional:

  • Standard-density data tables with comfortable row height (~48px)
  • Persistent filter bar above all list views for quick filtering
  • Clean, balanced spacing (not ultra-dense, not airy) — professional middle ground
  • Restrained color application — primary blue accents on interactive elements only

Design Rationale

  • Dashboard pages benefit from Command Center's bold KPI cards and activity panels — fiduciary managers (Chef de Mission) need at-a-glance operational status
  • List/table pages benefit from Balanced Professional's readable density — workers processing many dossiers need comfortable scanning without fatigue
  • The full sidebar supports the deep navigation structure (Clients, Declarations, Archive, Team, Settings) without hiding sections behind hamburger menus
  • Standard density tables with persistent filters align with the "scan-decide-act" core experience — users scan filtered lists, decide on priority, and act inline
  • The combination respects the Moroccan accounting context where precision and clarity are paramount, while keeping the interface modern and approachable

Implementation Approach

  • Layout structure: Fixed full sidebar (240px collapsed to icon-only on mobile) + main content area with top breadcrumb bar
  • Dashboard pattern: CSS Grid for KPI card rows (auto-fill, minmax 280px) + two-column layout for activity feed + deadline alerts
  • Table pattern: shadcn-vue DataTable with sticky header, persistent filter bar (Combobox + DateRangePicker + Search), inline row actions (dropdown menu)
  • Responsive strategy: Sidebar collapses to overlay drawer on mobile; KPI cards stack single-column; tables switch to card-based list view below 768px
  • Component density: Use shadcn-vue default sizing (not size="sm") for comfortable touch targets and readability; compact mode available as user preference toggle

User Journey Flows

Journey 1: Owner/Manager Morning Dashboard (Scan-Decide-Act)

Entry Point: User logs in or opens the app → lands on role-appropriate dashboard

Flow Summary: The dashboard is the operational command center. Owners and Managers share the same view (all clients, all declarations). The flow follows the "scan-decide-act" pattern established as the core experience.

flowchart TD
    A[Login / Open App] --> B[Dashboard Loads]
    B --> C[KPI Summary Cards]
    C --> C1[Overdue Declarations - RED]
    C --> C2[Due This Week - AMBER]
    C --> C3[Waiting for Client - BLUE]
    C --> C4[On Track - GREEN]

    C1 --> D{Click KPI Card}
    C2 --> D
    C3 --> D
    C4 --> D

    D --> E[Filtered Declaration List]
    E --> F{Scan & Decide}

    F --> G[Nudge Worker]
    F --> H[Reassign Declaration]
    F --> I[View Declaration Detail]
    F --> J[Bulk Select & Act]

    G --> G1[One-Click Nudge Notification]
    G1 --> K[Return to List]

    H --> H1[Select New Assignee]
    H1 --> H2[Confirm Reassignment]
    H2 --> K

    I --> I1[View Status & Documents]
    I1 --> I2{Action Needed?}
    I2 -->|Yes| I3[Take Action from Detail]
    I2 -->|No| K
    I3 --> K

    J --> J1[Select Multiple Rows]
    J1 --> J2[Bulk Action Menu]
    J2 --> J3[Confirm Bulk Action]
    J3 --> K

    K --> F

    B --> L[Activity Feed Panel]
    L --> L1[Recent Changes Stream]
    L1 --> L2{Requires Attention?}
    L2 -->|Yes| I
    L2 -->|No| M[Continue Scanning]

    B --> N[Alerts Panel]
    N --> N1[Deadline Alerts]
    N --> N2[Missing Documents]
    N --> N3[Unread Client Messages]

Key Interaction Details:

  • KPI cards as filters: Clicking a KPI card filters the declaration table below — no page navigation needed
  • Inline row actions: Hover a declaration row → action icons appear (nudge, reassign, view detail)
  • Nudge = one click: No modal, no message composition — instant notification sent, toast confirms
  • Activity feed: Right-side panel showing real-time changes (document uploads, status updates, reassignments)
  • Alerts panel: Below KPI cards or in sidebar — sorted by urgency, each alert links directly to the relevant declaration

Journey 2: Worker Daily Workflow (Filter-Process-Update)

Entry Point: Worker logs in → sees scoped dashboard (only their assigned clients/declarations)

Flow Summary: Workers focus on processing declarations efficiently. Their flow is a tight loop: filter by priority, check what's needed, notify clients for missing docs, process ready declarations, update statuses.

flowchart TD
    A[Login] --> B[Worker Dashboard]
    B --> C[Scoped KPI Cards - My Declarations Only]
    C --> D[Filtered Declaration List]

    D --> E{Filter by Priority}
    E --> E1[Overdue First]
    E --> E2[Due This Week]
    E --> E3[Waiting for Documents]
    E --> E4[Ready to Process]

    E1 --> F{For Each Declaration}
    E2 --> F
    E3 --> G[Select Missing-Docs Declarations]
    E4 --> H[Open Declaration Detail]

    F --> F1{Status?}
    F1 -->|Missing Docs| G
    F1 -->|Docs Ready| H
    F1 -->|In Progress| H

    G --> G1[Select Multiple Declarations]
    G1 --> G2[Bulk Notify Clients]
    G2 --> G3[Email Sent to Each Client with Token Link]
    G3 --> G4[Status Auto-Updates to 'Client Notified']
    G4 --> D

    H --> H1[View Declaration Details]
    H1 --> H2[Download Client Documents]
    H2 --> H3[Process in Sage/JBS]
    H3 --> H4[Return to L'Ami Fiduciaire]
    H4 --> H5[Update Declaration Status]
    H5 --> H6{New Status}
    H6 -->|Completed| H7[Mark as Filed]
    H6 -->|Blocked| H8[Add Note + Flag Issue]
    H6 -->|In Progress| D
    H7 --> D
    H8 --> D

    B --> I[Notification Badge]
    I --> I1{Notification Type}
    I1 -->|Nudge from Manager| I2[View Nudged Declaration]
    I1 -->|Client Upload| I3[View New Document]
    I1 -->|Reassignment| I4[New Declaration Added to List]
    I2 --> H
    I3 --> H
    I4 --> D

Key Interaction Details:

  • Scoped view: Workers only see their assigned declarations — no information overload
  • Bulk notify: Select multiple "waiting for docs" declarations → one click sends personalized emails to each client
  • Status updates: Dropdown or inline button to change status — no separate form or modal
  • Notification badge: Sidebar icon shows count — clicking opens notification panel with direct links
  • Client upload awareness: When a client uploads via portal, the worker's list updates in real-time (or on next refresh) with a visual indicator ("New document")

Journey 3: Client Document Upload (Zero-Friction Portal)

Entry Point: Client receives email notification with "Voir la demande" button containing token link

Flow Summary: The client portal is intentionally minimal — no account, no login, no navigation. Single-purpose: see what's needed, upload it, done.

flowchart TD
    A[Client Receives Email] --> B[Clicks 'Voir la demande' Button]
    B --> C[Token-Authenticated Portal Page Loads]

    C --> D[Portal Shows:]
    D --> D1[Firm Name & Logo]
    D --> D2[Declaration Type & Period]
    D --> D3[Documents Requested - Checklist]
    D --> D4[Upload Zone]
    D --> D5[Message Thread with Firm]

    D4 --> E{Upload Document}
    E --> E1[Drag & Drop or Tap to Browse]
    E1 --> E2[File Selected]
    E2 --> E3[Upload Progress Bar]
    E3 --> E4{Upload Success?}
    E4 -->|Yes| E5[Document reçu. Merci.]
    E4 -->|No| E6[Error Message + Retry]
    E6 --> E1

    E5 --> F{More Documents Needed?}
    F -->|Yes| D3
    F -->|No| G[All Documents Submitted]
    G --> G1[Thank You Message]
    G1 --> G2[Page Can Be Closed]

    D5 --> H[View Messages from Firm]
    H --> H1[Reply to Message]
    H1 --> H2[Message Sent Confirmation]
    H2 --> D

    C --> I[Token Expired or Invalid]
    I --> I1[Friendly Error Page]
    I1 --> I2[Contact Your Accountant Message]

Key Interaction Details:

  • No authentication wall: Token in URL = instant access. No signup, no password, no friction
  • Mobile-first layout: Large tap targets, single-column layout, camera-friendly upload (photo of documents)
  • Progress feedback: Upload progress bar → success checkmark → remaining items count updates
  • Document checklist: Each required document shown as a checklist item — green check when uploaded
  • Messaging: Simple thread view — client can ask questions, firm can clarify requests
  • Token expiry: Graceful error with clear "contact your accountant" message — no dead ends

Journey 4: Declaration Lifecycle (Cross-Role Flow)

Entry Point: Owner/Manager creates declaration(s) → flows through assignment, client notification, document collection, processing, and filing

Flow Summary: This is the end-to-end lifecycle showing how a declaration moves through the system, touching all roles.

flowchart TD
    A[Owner/Manager: Create Declaration] --> A1{Creation Type}
    A1 -->|Single| A2[Select Client + Type + Deadline]
    A1 -->|Bulk| A3[Select Multiple Clients + Type + Deadline]
    A2 --> B[Assign to Worker]
    A3 --> B

    B --> C[Status: created]
    C --> D[Worker Sees in Dashboard]

    D --> E{Documents Needed?}
    E -->|Yes| F[Worker Triggers Client Notification]
    E -->|No| K[Worker Begins Processing]

    F --> F1[Status: en_attente_client]
    F1 --> G[Client Receives Email]
    G --> H[Client Uploads via Portal]
    H --> I[Worker Notified of Upload]
    I --> J[Worker Downloads & Reviews]
    J --> J1{Documents OK?}
    J1 -->|Yes| K
    J1 -->|No| J2[Worker Messages Client via Portal]
    J2 --> F1

    K --> K1[Status: en_cours]
    K1 --> L[Worker Processes in Sage/JBS]
    L --> M[Worker Updates Status]
    M --> M1[Status: termine]
    M1 --> N[Declaration Complete]

    N --> N1[Status: ferme]
    N1 --> O[Auto-Archive]
    O --> O1[Status: archive]

    subgraph Edge Cases
        EC1[Manager Nudges Worker] --> D
        EC2[Manager Reassigns Declaration] --> B
        EC3[Worker Edits Declaration Type] --> EC4[Activity Log Updated]
        EC4 --> D
        EC5[Deadline Approaching] --> EC6[System Alerts Owner/Manager]
        EC6 --> EC1
    end

Declaration Status Flow:

created → en_attente_client → en_cours → termine → ferme → archive
              ↑                    |
              └────────────────────┘

Key Interaction Details:

  • Bulk creation: Select multiple clients from a filtered list → set shared type + deadline → create all at once
  • Status auto-transitions: Some status changes happen automatically while others require worker action (mark as termine/ferme)
  • Nudge system: Manager clicks nudge → worker gets notification with direct link to the declaration — no message composition, pure signal
  • Activity log: Every status change, reassignment, edit, upload, and nudge is logged with timestamp and actor — visible in declaration detail
  • Deadline escalation: System generates alerts as deadlines approach (7 days → amber, 3 days → red, overdue → critical alert to owner)

Journey Patterns

Common patterns extracted across all journeys:

Navigation Patterns:

  • KPI-to-List filtering: Click summary card → filtered table (used in Owner, Manager, and Worker dashboards)
  • Direct-link navigation: Notifications, nudges, and alerts all deep-link directly to the relevant declaration — no hunting
  • Breadcrumb context: Dashboard → Client → Declaration — always know where you are and how to go back

Decision Patterns:

  • Inline actions: Most decisions happen without leaving the list view (nudge, reassign, status change)
  • Confirmation for destructive actions: Reassignment and bulk operations show a confirmation step; simple status updates do not
  • Progressive disclosure: List view shows summary → click for detail → expand sections for full history

Feedback Patterns:

  • Toast notifications: Quick actions (nudge sent, status updated) confirmed with non-blocking toast
  • Real-time indicators: New document uploads, status changes reflected with visual badges ("New", dot indicators)
  • Deadline color gradient: Green (>7 days) → Amber (3-7 days) → Red (<3 days) → Critical pulse (overdue) — consistent across all views

Flow Optimization Principles

  1. Minimize clicks to value: Dashboard → filtered list → action = 2 clicks maximum for any priority task
  2. No dead ends: Every screen has a clear next action; error states include recovery paths
  3. Batch over individual: Bulk creation, bulk notification, multi-select actions — respect the user's time when dealing with 45+ clients
  4. Context preservation: Opening a declaration detail doesn't lose the list context — use slide-over panels or maintain scroll position on return
  5. Role-appropriate density: Owners/Managers see the full picture; Workers see only their scope — same components, different data filters
  6. Zero-friction client portal: Every additional field, button, or step on the client portal is a potential drop-off — keep it brutally simple

Component Strategy

Design System Components

shadcn-vue (reka-ui) — Installed (24 groups): alert, avatar, badge, breadcrumb, button, card, checkbox, collapsible, dialog, dropdown-menu, input, input-otp, item, label, navigation-menu, select, separator, sheet, sidebar, skeleton, spinner, tabs, timeline, tooltip

shadcn-vue — Need to Install:

  • table — Foundation for DataTable (sortable headers, row selection)
  • calendar + popover — Foundation for DateRangePicker
  • combobox — Searchable select for client/worker/type filtering
  • toast / sonner — Non-blocking feedback for quick actions (nudge sent, status updated)
  • progress — Upload progress bars (client portal)
  • switch — Toggle settings (compact mode, dark mode)
  • command — Command palette for power users (optional Phase 3)

Already Built Custom Components (30+): AppShell, AppSidebar, AppHeader, NavMain, NavFooter, NavUser, WorkspaceSwitcher, NotificationDropdown, Pagination, Breadcrumbs, ClientForm, FolderForm, UserForm, WorkspaceForm, FolderCalendar, MessageBubble, TwoFactorSetupModal, TwoFactorRecoveryCodes, InputError, TextLink, Heading, UserInfo, AppearanceTabs, DeleteUser, PlaceholderPattern

Custom Components

1. StatCard

  • Purpose: Display KPI metrics on dashboards (overdue count, due this week, waiting for client, on track)
  • Content: Metric label, value (number), trend indicator (optional), status color
  • Actions: Clickable — filters the declaration list below when clicked
  • States: Default, active (selected as filter), loading (skeleton)
  • Variants: status="danger|warning|info|success" maps to deadline proximity colors
  • Accessibility: Role="button", aria-pressed for active state, keyboard focusable
  • Implementation: Compose from shadcn-vue card + CVA variants for status colors

2. DataTable

  • Purpose: Primary data display for declarations, clients, and dossiers lists
  • Content: Sortable columns, row data, inline actions, selection checkboxes
  • Actions: Sort by column, select rows (single/multi), inline row actions (dropdown), click row to navigate
  • States: Default, loading (skeleton rows), empty (EmptyState), filtered (active filter indicators)
  • Variants: Default density (~48px rows), compact density (~36px rows, user preference)
  • Accessibility: Role="grid", aria-sort on headers, keyboard row navigation
  • Implementation: shadcn-vue table + TanStack Table v8 for sorting/filtering/selection logic

3. FilterBar

  • Purpose: Persistent filter controls above all list views
  • Content: Search input, status filter (Combobox), date range (DateRangePicker), assignee filter (Combobox), type filter (Select)
  • Actions: Apply filters (instant, no submit button), clear all, save filter presets (Phase 3)
  • States: Default, active filters (count badge), collapsed on mobile (expandable)
  • Variants: Full (dashboard lists), minimal (portal views)
  • Accessibility: Role="search", aria-label for each filter, clear keyboard navigation between filters
  • Implementation: Composite of shadcn-vue input + combobox + select + custom DateRangePicker

4. DateRangePicker

  • Purpose: Select date ranges for filtering declarations by deadline period
  • Content: Start date, end date, preset ranges (This week, This month, This quarter)
  • Actions: Select range via calendar, select preset, clear selection
  • States: Default (placeholder), selected (showing range), open (calendar visible)
  • Accessibility: Keyboard date navigation, aria-label for date inputs
  • Implementation: shadcn-vue popover + calendar (dual calendar view)

5. ActivityFeed

  • Purpose: Real-time stream of workspace events on dashboard right panel
  • Content: Event type icon, actor name, action description, target link, timestamp
  • Actions: Click event to navigate to related entity, load more (infinite scroll)
  • States: Default, loading, empty
  • Variants: Dashboard panel (compact, last 20 events), full page (all events, filterable)
  • Accessibility: Role="feed", aria-label for each entry, keyboard navigation
  • Implementation: Custom component using existing timeline styling, Inertia polling or WebSocket for real-time

6. BulkActionBar

  • Purpose: Contextual toolbar that appears when multiple table rows are selected
  • Content: Selected count, available actions (notify clients, reassign, change status, archive)
  • Actions: Execute bulk action with confirmation dialog
  • States: Hidden (no selection), visible (with selection count), processing (loading state during action)
  • Accessibility: Role="toolbar", announced via aria-live when appearing, keyboard operable
  • Implementation: Fixed bottom bar or sticky top bar, appears on row selection, uses existing button + dropdown-menu

7. StatusBadge

  • Purpose: Visual indicator for declaration status throughout the app
  • Content: Status label text, optional icon
  • States/Variants: Maps to declaration lifecycle — created (gray), en_attente_client (blue), en_cours (amber), termine (green), ferme (teal), archive (muted), overdue (red pulsing)
  • Accessibility: Status text readable by screen readers, color not sole indicator (icon + text)
  • Implementation: Extend existing badge with CVA status variants using OKLCH semantic tokens

8. FileUploadZone

  • Purpose: Document upload area for client portal and internal document management
  • Content: Drop zone area, file type/size constraints, upload progress, uploaded files list
  • Actions: Drag & drop, click to browse, remove uploaded file, retry failed upload
  • States: Default (empty), drag-over (highlighted), uploading (progress), success (file listed), error (retry option)
  • Variants: Portal (large, single-purpose), inline (compact, within declaration detail)
  • Accessibility: Role="button" for click-to-browse, keyboard operable, progress announced via aria-live
  • Implementation: Custom component with native drag-and-drop API, chunked upload for large files

9. EmptyState

  • Purpose: Placeholder for lists/pages with no data, guiding users toward action
  • Content: Illustration (optional), title, description, primary action button
  • Variants: Table empty (inline), page empty (centered), first-time (onboarding-oriented)
  • Accessibility: Descriptive text, action button focusable
  • Implementation: Simple layout component with slots for icon, text, and action

10. DeclarationStatusStepper

  • Purpose: Visual progress indicator showing where a declaration is in its lifecycle
  • Content: All status steps with current step highlighted, timestamps for completed steps
  • States: Each step can be: completed, current, upcoming, or skipped
  • Accessibility: Role="progressbar" or ordered list with aria-current
  • Implementation: Horizontal stepper using existing timeline tokens, shown in declaration detail view

Component Implementation Strategy

Design Token Integration:

  • All custom components use OKLCH color tokens from app.css — no hardcoded colors
  • CVA (Class Variance Authority) for all component variants — consistent with shadcn-vue patterns
  • Tailwind CSS 4 utility classes for layout and spacing — no custom CSS unless necessary
  • Dark mode support via existing dark: variants in all new components

Composition Pattern:

  • Custom components are composed from shadcn-vue primitives where possible (StatCard wraps Card, StatusBadge extends Badge, FilterBar combines Input + Combobox + Select)
  • Reuse reka-ui accessibility primitives (focus management, keyboard navigation, ARIA attributes)
  • TypeScript strict mode with proper prop typing and emits

State Management:

  • Component state managed locally (Vue 3 Composition API ref/computed)
  • Server state via Inertia.js props — no client-side data fetching library needed
  • Shared UI state (sidebar collapsed, compact mode) via composables or Pinia store

Implementation Roadmap

Phase 1 — Core (MVP Dashboard & Lists):

  • Install: table, combobox, toast/sonner, calendar, popover, progress
  • Build: StatCard, DataTable, FilterBar, StatusBadge, EmptyState, BulkActionBar
  • These components are required for Journey 1 (Dashboard) and Journey 2 (Worker Workflow)

Phase 2 — Client Portal & Communication:

  • Build: FileUploadZone, DeclarationStatusStepper
  • Enhance: ActivityFeed, DateRangePicker
  • These components are required for Journey 3 (Client Upload) and Journey 4 (Declaration Lifecycle)

Phase 3 — Power Features & Polish:

  • Install: command (command palette), switch
  • Build: SavedFilterPresets, KeyboardShortcutHelper, CompactModeToggle
  • Enhance: DataTable (column resizing, pinned columns), FilterBar (saved presets)
  • These components optimize efficiency for power users processing high volumes

UX Consistency Patterns

Button Hierarchy

Primary Action (one per screen section):

  • Solid fill with primary color (bg-primary text-primary-foreground)
  • Used for: Create declaration, Save changes, Submit, Send notification
  • Always positioned bottom-right of forms, or top-right of page headers for creation actions

Secondary Action:

  • Outline variant (border border-input bg-background)
  • Used for: Cancel, Back, Export, secondary options alongside a primary
  • Positioned left of primary action in button groups

Destructive Action:

  • Destructive variant (bg-destructive text-destructive-foreground)
  • Used for: Delete, Archive (with confirmation), Remove team member
  • Always requires confirmation dialog — never immediate

Ghost/Inline Action:

  • Ghost variant (no border, no background, text only)
  • Used for: Inline table row actions, "View all" links, tertiary options
  • Appears on hover in table rows via dropdown-menu trigger

Icon-Only Action:

  • Icon button with tooltip (mandatory for accessibility)
  • Used for: Nudge (bell icon), Refresh, Toggle sidebar, Quick actions
  • Always paired with tooltip for label — never icon-only without tooltip

Button Sizing:

  • Default size for all primary UI actions
  • size="sm" only inside table rows and compact toolbars
  • size="lg" only for client portal CTA buttons (mobile touch targets)

Feedback Patterns

Toast Notifications (non-blocking):

  • Success: Green check icon + message — auto-dismiss after 4 seconds
    • Used for: Status updated, Nudge sent, Declaration created, Document uploaded
  • Error: Red X icon + message — persists until dismissed
    • Used for: Save failed, Upload failed, Permission denied
  • Info: Blue info icon + message — auto-dismiss after 5 seconds
    • Used for: New document received, Declaration reassigned to you
  • Warning: Amber warning icon + message — persists until dismissed
    • Used for: Deadline approaching, Bulk action affects X items
  • Position: Top-right, stacked, max 3 visible at once

Inline Validation (forms):

  • Real-time validation on blur (not on keystroke)
  • Error text appears below the field in text-destructive with shake animation
  • Success state: Green check icon inside the input (not below)
  • Server-side errors (from Laravel Form Request) displayed inline on the relevant field via Inertia error bags

Confirmation Dialogs:

  • Required for: Delete, Archive, Bulk actions, Reassignment
  • Not required for: Status updates, Nudges, Single notifications
  • Dialog content: Clear description of what will happen, affected item count for bulk actions
  • Two buttons: Cancel (secondary, left) + Confirm (primary or destructive, right)
  • Destructive confirmations use red confirm button with action verb ("Delete 5 declarations" not "OK")

Loading States:

  • Initial page load: Skeleton screens matching the layout structure (StatCard skeletons, table row skeletons)
  • Action processing: Button shows spinner + disabled state, label changes to "Saving..." / "Sending..."
  • Table refresh: Subtle opacity reduction (0.6) on table body while loading, no full skeleton replacement
  • File upload: Progress bar with percentage inside FileUploadZone

Empty States:

  • Every list/table has a designed empty state via EmptyState component
  • Includes: Relevant illustration/icon, explanatory text, primary action button
  • Examples: "No declarations yet — Create your first declaration", "No overdue items — You're on track!"

Form Patterns

Form Layout:

  • Single-column layout for all forms (max-width 640px centered)
  • Labels above inputs (not inline/floating) — better for scanning and accessibility
  • Required fields: No asterisk — all fields required by default; mark optional fields with "(optional)" suffix
  • Field grouping: Use separator + section headings for logical groups (Client Info, Declaration Details, etc.)

Input Patterns:

  • Text inputs: shadcn-vue input with label above
  • Select/dropdown: shadcn-vue select for short lists (<10 items), combobox for searchable lists (>10 items)
  • Date selection: DateRangePicker for ranges, single calendar popover for individual dates
  • File upload: FileUploadZone component — drag-and-drop + click-to-browse

Form Submission:

  • Inertia.js useForm() for all form handling — provides processing state, errors, and recentlySuccessful
  • Submit button disables during processing with spinner
  • On success: Toast notification + redirect (for create) or toast + stay on page (for edit)
  • On error: Scroll to first error field, focus it, display inline error messages

Inline Editing:

  • Status changes on declarations: Inline dropdown, no modal, immediate save
  • Quick edits: Click to edit pattern only for simple fields (declaration type, deadline date)
  • Complex edits: Always navigate to edit form (client details, user profiles)

Navigation Patterns

Sidebar Navigation:

  • Full sidebar (240px) with grouped sections: Dashboard, Clients, Declarations, Archive, Team, Settings
  • Active section highlighted with primary color background
  • Collapsible groups for sub-items (e.g., Settings → Profile, Team, Workspace, Appearance)
  • Collapse to icon-only (64px) on smaller screens, overlay drawer on mobile (<768px)
  • WorkspaceSwitcher at the top of sidebar

Breadcrumbs:

  • Always visible below the page header: Dashboard / Clients / Client Name / Declaration
  • Last item is the current page (non-clickable, muted text)
  • All previous items are clickable links
  • Mobile: Show only current + parent (collapse middle items with "...")

Page Headers:

  • Every page has a consistent header: Page title (h1) + description (optional) + primary action button (top-right)
  • Examples: "Declarations" + "Create Declaration" button, "Client: Benani SARL" + "Edit" button

Back Navigation:

  • Browser back button works correctly (Inertia.js handles history)
  • No explicit "Back" buttons in the UI — breadcrumbs serve this purpose
  • Modals/sheets close with Escape key and clicking outside

Deep Linking:

  • Every notification, nudge, and alert links directly to the relevant entity
  • URL structure reflects navigation hierarchy: /clients/123/declarations/456
  • Sharing a URL always works — no client-side routing state that breaks on refresh

Additional Patterns

Table Interaction Patterns:

  • Row hover: Subtle background highlight + inline action icons appear (right side)
  • Row click: Navigates to detail page (entire row is clickable except action buttons)
  • Sort: Click column header to sort — ascending → descending → unsorted. Active sort shown with arrow icon
  • Selection: Checkbox column (first column) for multi-select. Header checkbox toggles all visible rows
  • Pagination: Bottom of table — "Showing 1-25 of 142" + page navigation. Default 25 rows per page, configurable (25/50/100)
  • Sticky header: Table header sticks when scrolling long lists

Search & Filter Patterns:

  • FilterBar always visible above data tables (not hidden behind a toggle)
  • Filters apply instantly on change (no "Apply" button needed)
  • Active filters shown as removable chips/badges below the filter bar
  • "Clear all filters" link when any filter is active
  • URL query parameters reflect filter state — shareable filtered views

Date & Time Patterns:

  • Dates displayed in Moroccan format: DD/MM/YYYY
  • Relative time for recent events: "il y a 2 heures", "hier"
  • Deadlines always show absolute date + relative countdown: "20/03/2026 (dans 5 jours)"
  • Deadline color coding consistent everywhere: Green (>7d), Amber (3-7d), Red (<3d), Pulsing red (overdue)

Notification Patterns:

  • In-app: Badge count on sidebar bell icon, dropdown panel with recent notifications, mark as read
  • Email: Triggered by: client document requests, nudges (configurable), deadline warnings (configurable)
  • Notification grouping: Multiple events for same entity grouped ("3 clients uploaded documents")
  • Quiet hours: No email notifications outside business hours (configurable per workspace)

Error & Recovery Patterns:

  • Network error: Toast with "Connection lost — changes will sync when reconnected" (Inertia handles gracefully)
  • Permission denied: Redirect to dashboard with toast "You don't have permission to access this page"
  • 404 Not Found: Custom error page with "Go to Dashboard" link
  • Server error (500): Custom error page with "Try again" + "Contact support" options
  • Session expired: Redirect to login with "Your session expired — please log in again" message, preserving intended destination URL

Responsive Design & Accessibility

Responsive Strategy

Desktop (Primary — Firm Staff):

  • Full "Command Professional" layout: 240px sidebar + main content area
  • Two-column dashboard: KPI cards + table left, activity feed + alerts right
  • Data tables at full width with all columns visible
  • Inline row actions on hover, keyboard shortcuts for power users
  • Multi-panel views where appropriate (e.g., declaration detail with document preview sidebar)

Tablet (Secondary — Firm Staff on the Go):

  • Sidebar collapses to icon-only (64px) by default, expandable on tap
  • Dashboard KPI cards reflow to 2-column grid
  • Activity feed moves below the main table (single column)
  • Tables maintain core columns, hide secondary columns behind a "More" expandable
  • Touch-optimized: Larger tap targets on action buttons, swipe gestures for table row actions (optional)

Mobile (Primary — Client Portal / Secondary — Firm Staff):

  • Client portal: Single-column, mobile-first layout — this is the primary device for Hassan-type users
  • Firm app: Sidebar becomes overlay drawer (hamburger trigger in top-left)
  • KPI cards stack single-column, full width
  • Tables transform to card-based list view — each row becomes a card showing key fields
  • Bottom sheet for actions instead of dropdown menus (better mobile UX)
  • Large touch targets: minimum 44x44px for all interactive elements
  • Camera integration for document upload (direct photo capture)

Device Priority Matrix:

User Role Primary Device Secondary Device
Owner (Karim) Desktop Tablet/Mobile (checking dashboard)
Manager (Rachid) Desktop Mobile (nudges, quick reassignment)
Worker (Fatima) Desktop Rarely mobile
Client (Hassan) Mobile Desktop
Admin (Saad) Desktop

Breakpoint Strategy

Tailwind CSS 4 Breakpoints (standard):

Breakpoint Width Layout Behavior
sm 640px+ Client portal: content max-width, centered
md 768px+ Sidebar visible (icon-only), tables show core columns
lg 1024px+ Sidebar expanded (240px), full table columns, two-column dashboard
xl 1280px+ Extra breathing room, wider tables, optional third column
2xl 1536px+ Max content width (1400px centered), prevent ultra-wide line lengths

Mobile-First Approach:

  • Base styles target mobile (< 640px)
  • Progressive enhancement via sm:, md:, lg: prefixes
  • Client portal designed mobile-first — desktop is the enhanced version
  • Firm app designed desktop-first conceptually, but implemented mobile-first in code

Key Responsive Behaviors:

Component Mobile (<768px) Tablet (768-1023px) Desktop (1024px+)
Sidebar Overlay drawer Icon-only (64px) Full (240px)
KPI Cards 1 column stack 2 column grid 4 column grid (auto-fill)
DataTable Card list view Table with fewer columns Full table with all columns
FilterBar Collapsed (expandable toggle) Single row, scrollable Full row, all filters visible
BulkActionBar Fixed bottom sheet Fixed bottom bar Sticky top bar
Activity Feed Hidden (accessible via tab) Below main content Right sidebar panel
Modals/Dialogs Full-screen sheet (bottom-up) Centered dialog Centered dialog

Accessibility Strategy

Target Compliance: WCAG 2.1 Level AA

  • This is the industry standard and appropriate for a B2B SaaS product
  • Level AAA is not targeted but specific AAA criteria will be met where practical (e.g., enhanced contrast)
  • Morocco does not have specific web accessibility legislation, but AA compliance ensures usability for all users and future-proofs against potential regulation

Color & Contrast:

  • Minimum 4.5:1 contrast ratio for normal text (< 18px)
  • Minimum 3:1 contrast ratio for large text (>= 18px bold or >= 24px)
  • OKLCH color tokens already tested for contrast compliance in light and dark modes
  • Color is never the sole indicator of status — always paired with icon and/or text label
  • Deadline color gradient (green → amber → red) supplemented by text labels ("On track", "Due soon", "Overdue")

Keyboard Navigation:

  • All interactive elements reachable via Tab key
  • Logical tab order following visual layout (left-to-right, top-to-bottom)
  • Skip-to-content link as first focusable element on every page
  • Visible focus indicators: 2px ring using ring-ring token (already configured in shadcn-vue)
  • Escape key closes modals, sheets, dropdowns, and popovers
  • Table keyboard navigation: Arrow keys for row/cell navigation within DataTable
  • Custom keyboard shortcuts documented and discoverable (Phase 3)

Screen Reader Support:

  • Semantic HTML5 elements: <nav>, <main>, <aside>, <header>, <footer>, <section>
  • ARIA landmarks: role="navigation", role="main", role="complementary" for sidebar
  • Dynamic content updates: aria-live="polite" for toast notifications, activity feed updates, and filter result counts
  • Form labels: Every input has an associated <label> — no placeholder-only fields
  • Table headers: <th scope="col"> for column headers, aria-sort for sortable columns
  • reka-ui (shadcn-vue foundation) provides ARIA patterns for all primitives (dialog, combobox, tabs, etc.)

Touch & Motor Accessibility:

  • Minimum touch target: 44x44px (WCAG 2.5.5 Target Size)
  • Adequate spacing between interactive elements (minimum 8px gap)
  • No time-dependent interactions — all actions wait for user input
  • Drag-and-drop (file upload) always has click-to-browse alternative
  • No complex gestures required — all functionality accessible via simple tap/click

Testing Strategy

Responsive Testing:

  • Browser matrix: Chrome (primary), Firefox, Safari (critical for iOS client portal), Edge
  • Device testing: Test on actual Android and iOS devices for client portal — emulators are insufficient for touch/camera behavior
  • Key test scenarios:
    • Client portal upload flow on iPhone Safari and Android Chrome
    • Dashboard KPI → filtered table flow on tablet
    • Table-to-card transformation at mobile breakpoint
    • Sidebar collapse/expand transitions

Accessibility Testing:

  • Automated (CI pipeline): axe-core via Playwright for every PR — catches ~30% of accessibility issues automatically
  • Manual keyboard testing: Tab through every page flow monthly — verify logical order and focus management
  • Screen reader testing: VoiceOver (macOS/iOS) quarterly for critical flows (dashboard, declaration creation, client portal upload)
  • Color contrast: Verified via OKLCH token definitions — re-verify when adding new semantic colors
  • Reduced motion: Respect prefers-reduced-motion media query — disable animations and transitions for users who prefer it

User Acceptance:

  • Include Moroccan fiduciary firm staff in usability testing (Karim/Rachid/Fatima personas)
  • Test client portal with non-technical business owners (Hassan persona) on their actual devices
  • Validate French/Arabic text rendering doesn't break layouts (text expansion for French, RTL considerations for future Arabic support)

Implementation Guidelines

Responsive Development:

  • Use Tailwind CSS 4 responsive prefixes (sm:, md:, lg:) — no custom media queries unless absolutely necessary
  • CSS Grid for dashboard layouts (grid-cols-1 md:grid-cols-2 lg:grid-cols-4)
  • Flexbox for component-level layout (button groups, filter bars, card content)
  • max-w-screen-xl mx-auto on main content to prevent ultra-wide layouts
  • Images: Use <img> with srcset for responsive images; SVG for icons (Lucide)
  • Test all layouts with long French text content — French is ~20% longer than English equivalents

Accessibility Development:

  • Semantic HTML first — ARIA only when native semantics are insufficient
  • import type for TypeScript type-only imports (per project coding rules)
  • Every custom component must pass axe-core automated checks before merge
  • Focus trap for modals/dialogs (provided by reka-ui Dialog primitive)
  • Skip link: <a href="#main-content" class="sr-only focus:not-sr-only">Skip to content</a> in AppLayout
  • Announce dynamic changes: Use aria-live regions for toast notifications, filter result counts ("Showing 12 of 142 declarations"), and real-time updates
  • prefers-reduced-motion: Wrap all CSS transitions/animations in @media (prefers-reduced-motion: no-preference) or use Tailwind's motion-safe: prefix
  • prefers-color-scheme: Already handled by existing dark mode toggle — respect system preference as default