425 lines
18 KiB
Markdown
425 lines
18 KiB
Markdown
# Phase 4 - UI/UX & Design System Audit
|
|
|
|
## Executive Summary
|
|
|
|
The dashboard already has a usable shared UI foundation through `PageContainer`, shadcn primitives, shared table utilities, and consistent card-based page composition. Responsive handling is generally better than average for an admin system because many key layouts already use `min-w-0`, wrapping button groups, and scoped table overflow.
|
|
|
|
The largest UI/UX problem is not layout instability but system inconsistency. Several feature areas still diverge from the intended design system, especially reports tables, file-upload flows, heading structure, and copy quality. The most visible issue across the entire UI is widespread Thai text encoding corruption, which materially harms readability, trust, and learnability.
|
|
|
|
## Screen Inventory
|
|
|
|
Primary screens reviewed:
|
|
|
|
- Dashboard shell and sidebar
|
|
- Organization switcher and user menu
|
|
- Employee directory list
|
|
- Training records form and review-oriented detail states
|
|
- Announcements form and detail view
|
|
- Online lessons form
|
|
- Reports page
|
|
- Notifications page
|
|
- Audit logs table
|
|
- Shared page header, heading, data table, toolbar, pagination, notification card
|
|
|
|
## Layout Assessment
|
|
|
|
Strengths:
|
|
|
|
- `src/components/layout/page-container.tsx` gives pages a stable shell with responsive spacing and full-width containment.
|
|
- Shared tables correctly scope horizontal overflow inside the table shell instead of the full page.
|
|
- Header actions commonly wrap well on small screens.
|
|
|
|
Weaknesses:
|
|
|
|
- Header patterns are inconsistent. Some pages use `PageContainer` header only, while others inject another local hero/header block inside the page body, creating double-header behavior.
|
|
- Reports stack multiple large cards and wide tables vertically, which is workable but visually heavy and cognitively dense.
|
|
- Access fallback inside `PageContainer` is centered plain text rather than a full empty/error-state pattern.
|
|
|
|
## Typography Assessment
|
|
|
|
Strengths:
|
|
|
|
- Core sizes are mostly sensible: large page titles, smaller descriptions, readable card body text.
|
|
- Tables generally keep compact admin-dashboard typography.
|
|
|
|
Weaknesses:
|
|
|
|
- Typography hierarchy is semantically inconsistent because `Heading` renders `h2` while feature pages often behave like top-level page titles.
|
|
- Some screens add their own `h1` under `PageContainer`, producing mixed heading structures across modules.
|
|
- Thai text corruption appears in navigation, headers, descriptions, pagination labels, and empty states across many files, which is the most serious typography/content issue in the system.
|
|
- Copy style mixes Thai and English unevenly, for example `PageContainer` access fallback remains English while most feature UI is Thai.
|
|
|
|
## Color & Status Assessment
|
|
|
|
Strengths:
|
|
|
|
- Shared `Badge` usage is established for workflow and report states.
|
|
- Content approval states appear to reuse shared variants through `content-approval` helpers.
|
|
|
|
Weaknesses:
|
|
|
|
- Status language is not fully standardized across features. Similar states use different wording such as archive/hide/remove-publish semantics depending on module.
|
|
- Some feedback and button copy rely on variant differences only, without additional structural separation for risky actions.
|
|
|
|
## Button Standard Assessment
|
|
|
|
Strengths:
|
|
|
|
- Most primary/secondary actions use shared `Button` variants.
|
|
- Mobile width handling is good in many forms and headers through `w-full sm:w-auto`.
|
|
- Action ordering is usually reasonable: cancel/back separated from primary submit action.
|
|
|
|
Weaknesses:
|
|
|
|
- Workflow buttons are not standardized across content modules. Announcements and online lessons use similar but not fully shared action group patterns.
|
|
- Some significant actions such as publish/archive are triggered directly from detail views without explicit confirmation, which weakens safety and workflow clarity.
|
|
- Loading labels are inconsistent and often use `...` instead of a consistent loading copy pattern.
|
|
|
|
## Table Standard Assessment
|
|
|
|
Strengths:
|
|
|
|
- Shared `DataTable`, toolbar, and pagination are good system-level primitives.
|
|
- Canonical table modules like employee directory and audit logs follow the shared pattern well.
|
|
- Action columns are generally handled in a stable way with pinning and reusable menus.
|
|
|
|
Weaknesses:
|
|
|
|
- Reports bypass the shared DataTable stack entirely and use manual `Table` cards, so sorting, pagination, column management, and interaction patterns differ from the rest of the app.
|
|
- Manual report tables rely on horizontal scrolling only and do not offer the stronger affordances already available in the shared table system.
|
|
- Table empty/loading states are reasonably present, but wording and visual treatment vary by module.
|
|
|
|
## Form Standard Assessment
|
|
|
|
Strengths:
|
|
|
|
- Major forms use TanStack Form wrappers and shared field primitives.
|
|
- Validation errors are shown inline and `scrollToFirstError()` is used in important flows.
|
|
- Training records form handles employee vs HRD mode clearly.
|
|
|
|
Weaknesses:
|
|
|
|
- Required mark style is inconsistent. Some screens use literal `*`, some use styled destructive spans, and some rely on validation only.
|
|
- Placeholder and helper-text patterns vary widely between modules.
|
|
- Inputs often omit `name` and `autocomplete` attributes, which is a lower-level accessibility and usability gap against modern form guidelines.
|
|
- Feature forms mix shared field wrappers with raw HTML elements such as custom `textarea`, creating slightly different spacing and behavior.
|
|
|
|
## File Attachment UX Assessment
|
|
|
|
Strengths:
|
|
|
|
- Training records use a shared `FileUploader` and attachment list, which gives a clearer system pattern.
|
|
- Content forms usually show current file, replace/remove flows, and post-save expectations.
|
|
|
|
Weaknesses:
|
|
|
|
- Attachment UX is fragmented across modules:
|
|
- Training records use shared uploader + attachment list
|
|
- Announcements use a raw file input
|
|
- Online lessons use custom `AssetPicker` sections
|
|
- This creates different expectations for drag-and-drop, file preview, replacement, and removal across similar content workflows.
|
|
- View-mode attachment presentation is not standardized across modules.
|
|
|
|
## Feedback State Assessment
|
|
|
|
Strengths:
|
|
|
|
- Most reviewed modules include loading, error, and empty states.
|
|
- Toasts are used consistently for mutation feedback.
|
|
- Audit logs and notifications have decent empty-state handling.
|
|
|
|
Weaknesses:
|
|
|
|
- Loading states are inconsistent between skeleton-style, spinner-in-card, and plain text messaging.
|
|
- `PageContainer` access denial uses a plain centered sentence rather than a richer restricted-state pattern.
|
|
- Success and error messaging quality varies and is harder to read because of copy encoding issues.
|
|
|
|
## Dialog / Sheet / Drawer Assessment
|
|
|
|
Observed strengths:
|
|
|
|
- Shared dialog/sheet primitives are clearly part of the system.
|
|
- Content review uses a shared action dialog component rather than ad hoc per-page modal markup.
|
|
|
|
Observed gaps:
|
|
|
|
- This audit did not fully validate focus trap, escape handling, and mobile height behavior for every dialog/sheet implementation.
|
|
- Action-safety patterns are not uniform; some important transitions use dialogs while other significant actions run immediately.
|
|
|
|
## Workflow UX Assessment
|
|
|
|
Strengths:
|
|
|
|
- Training records and content modules expose state-aware actions instead of showing every action at once.
|
|
- Review notes and current status are surfaced in key detail/form views.
|
|
|
|
Weaknesses:
|
|
|
|
- Reports page is functionally useful but visually dense; it reads like stacked exports rather than a guided reporting workspace.
|
|
- Content modules blur the line between draft editing, review transition, publish, and archive actions because button patterns are similar but not always grouped by risk or workflow stage.
|
|
- Employee directory uses an extra local page hero inside `PageContainer`, which makes it feel visually different from other management screens.
|
|
|
|
## Responsive Assessment
|
|
|
|
Strengths:
|
|
|
|
- Shared layouts use `min-w-0`, wrapped actions, and scoped overflow correctly.
|
|
- Employee directory and shared tables are intentionally built for horizontal table scroll on smaller screens.
|
|
- Forms generally collapse to a single column well.
|
|
|
|
Weaknesses:
|
|
|
|
- Reports is the most likely responsive pain point because of multiple wide manual tables on one page.
|
|
- Some custom card headers and action groups depend on wrapping rather than a stronger mobile-specific layout hierarchy.
|
|
- Sidebar behavior was not visually runtime-tested in browser during this audit.
|
|
|
|
## Accessibility Assessment
|
|
|
|
Positive observations:
|
|
|
|
- Many interactive controls use semantic elements such as `button`, `Link`, and form labels.
|
|
- Some icon-only actions already have `aria-label`, for example notification mark-as-read and table pagination buttons.
|
|
- Inline validation patterns exist in major forms.
|
|
|
|
Key gaps:
|
|
|
|
- No verified skip-link pattern was found for the dashboard shell.
|
|
- Decorative icons are widely rendered without explicit `aria-hidden`, which can add noise for assistive tech depending on the icon implementation.
|
|
- Heading hierarchy is inconsistent at the page level because of mixed `h1`/`h2` usage.
|
|
- Native form enhancements such as `autocomplete`, input naming consistency, and copy punctuation are not standardized.
|
|
- Notifications pagination uses `href='#'` plus click interception, which is weaker semantically than true navigation controls.
|
|
|
|
## Design System Inconsistencies
|
|
|
|
Most important system drifts:
|
|
|
|
1. Copy quality and encoding
|
|
- Thai labels are corrupted across multiple feature surfaces.
|
|
2. Page header structure
|
|
- Shared page shell exists, but some modules duplicate internal hero headers.
|
|
3. Table architecture
|
|
- Canonical modules use shared DataTable; reports does not.
|
|
4. File upload pattern
|
|
- Different modules use different uploader UX for similar tasks.
|
|
5. Form semantics
|
|
- Required markers, placeholders, descriptions, and input metadata are inconsistent.
|
|
6. Workflow action treatment
|
|
- Some risky actions confirm through dialogs; others execute directly.
|
|
|
|
## Findings by Severity
|
|
|
|
### [High] Thai UI copy is encoding-corrupted across major navigation, form, table, and feedback surfaces
|
|
|
|
**Module:**
|
|
|
|
Cross-cutting UI copy
|
|
|
|
**Location Found:**
|
|
|
|
- `src/config/nav-config.ts`
|
|
- `src/components/layout/page-container.tsx`
|
|
- `src/components/ui/table/data-table.tsx`
|
|
- `src/components/ui/table/data-table-pagination.tsx`
|
|
- `src/features/employee-directory/components/employee-directory-header.tsx`
|
|
- `src/features/reports/components/reports-page-content.tsx`
|
|
- `src/features/notifications/components/notifications-page.tsx`
|
|
- `src/features/announcements/components/announcement-form.tsx`
|
|
- `src/features/announcements/components/announcement-view-page.tsx`
|
|
- `src/features/training-records/components/training-record-form.tsx`
|
|
- `src/features/online-lessons/components/online-lesson-form.tsx`
|
|
|
|
**Details:**
|
|
|
|
Large portions of user-facing Thai text render as mojibake-like corrupted strings instead of readable Thai copy.
|
|
|
|
**Impact:**
|
|
|
|
- Severely damages readability and trust.
|
|
- Makes workflows harder to learn.
|
|
- Reduces accessibility because labels and feedback become harder to interpret.
|
|
|
|
**Evidence from Code:**
|
|
|
|
Corrupted Thai strings appear in page titles, descriptions, nav items, buttons, empty states, and pagination labels.
|
|
|
|
**Example Scenario:**
|
|
|
|
A user opening navigation, forms, or reports sees broken Thai labels in core actions and status descriptions, making the system feel unreliable even when the workflow itself works.
|
|
|
|
**Recommendation:**
|
|
|
|
Normalize file encoding and re-validate every user-facing Thai string before expanding UI work.
|
|
|
|
**Must Fix Before Production:** Yes
|
|
|
|
### [Medium] Heading and page-header patterns are semantically and visually inconsistent across modules
|
|
|
|
**Module:**
|
|
|
|
Shared layout and page composition
|
|
|
|
**Location Found:**
|
|
|
|
- `src/components/ui/heading.tsx`
|
|
- `src/components/layout/page-container.tsx`
|
|
- `src/features/employee-directory/components/employee-directory-header.tsx`
|
|
|
|
**Details:**
|
|
|
|
`Heading` renders `h2`, while some screens also introduce their own `h1` inside the page body. Other screens rely entirely on the shared heading component.
|
|
|
|
**Impact:**
|
|
|
|
- Inconsistent visual rhythm across pages.
|
|
- Weaker accessibility and document structure.
|
|
- Makes it harder to standardize page templates.
|
|
|
|
**Recommendation:**
|
|
|
|
Define one canonical page-title pattern for dashboard screens and apply it uniformly.
|
|
|
|
**Must Fix Before Production:** Consider
|
|
|
|
### [Medium] Reports UI diverges from the shared table system and creates a noticeably different interaction model
|
|
|
|
**Module:**
|
|
|
|
Reports
|
|
|
|
**Location Found:**
|
|
|
|
- `src/features/reports/components/reports-page-content.tsx`
|
|
- `src/features/reports/components/report-table-card.tsx`
|
|
|
|
**Details:**
|
|
|
|
Reports use manual tables instead of the shared DataTable stack used elsewhere in the dashboard.
|
|
|
|
**Impact:**
|
|
|
|
- Table behavior differs from the rest of the product.
|
|
- Large report cards become dense and harder to scan.
|
|
- Users lose familiar controls such as unified table toolbars and standardized interaction patterns.
|
|
|
|
**Recommendation:**
|
|
|
|
Either formally designate reports as a separate reporting presentation pattern, or migrate the module toward shared table conventions where practical.
|
|
|
|
**Must Fix Before Production:** Consider
|
|
|
|
### [Medium] File attachment UX is fragmented across modules instead of following one reusable pattern
|
|
|
|
**Module:**
|
|
|
|
Training Records, Announcements, Online Lessons
|
|
|
|
**Location Found:**
|
|
|
|
- `src/features/training-records/components/training-record-form.tsx`
|
|
- `src/features/announcements/components/announcement-form.tsx`
|
|
- `src/features/online-lessons/components/online-lesson-form.tsx`
|
|
|
|
**Details:**
|
|
|
|
Comparable upload tasks use different components and different interaction rules.
|
|
|
|
**Impact:**
|
|
|
|
- Increases cognitive load when users move between modules.
|
|
- Makes future improvements and accessibility hardening harder to apply consistently.
|
|
|
|
**Recommendation:**
|
|
|
|
Standardize a single attachment/upload UX contract for content and training modules, even if internal storage logic remains feature-specific.
|
|
|
|
**Must Fix Before Production:** Consider
|
|
|
|
### [Low] Form and pagination semantics miss several modern UX/a11y conventions
|
|
|
|
**Module:**
|
|
|
|
Shared forms and notifications
|
|
|
|
**Location Found:**
|
|
|
|
- `src/features/training-records/components/training-record-form.tsx`
|
|
- `src/features/announcements/components/announcement-form.tsx`
|
|
- `src/features/online-lessons/components/online-lesson-form.tsx`
|
|
- `src/features/notifications/components/notifications-page.tsx`
|
|
|
|
**Details:**
|
|
|
|
Common gaps include missing `autocomplete` conventions, inconsistent input metadata, and pagination links implemented with `href='#'` plus click interception.
|
|
|
|
**Impact:**
|
|
|
|
- Mostly incremental usability and accessibility debt rather than immediate blockers.
|
|
|
|
**Recommendation:**
|
|
|
|
Add a lightweight shared checklist for form semantics, link semantics, and icon accessibility before future UI expansion.
|
|
|
|
**Must Fix Before Production:** No
|
|
|
|
## Recommended UI Standard
|
|
|
|
Suggested system rules for this repo:
|
|
|
|
1. One dashboard page header pattern
|
|
- Top-level page title, description, optional info button, optional right-side action area.
|
|
2. One table family
|
|
- Use shared DataTable unless a page is intentionally a reporting surface with documented exceptions.
|
|
3. One attachment pattern
|
|
- Shared file state, current file preview, replace/remove actions, and empty state wording.
|
|
4. One required-field style
|
|
- Same marker, same placement, same helper/error rhythm.
|
|
5. One workflow action grouping rule
|
|
- Primary action, secondary action, destructive action, and confirmation behavior defined centrally.
|
|
6. One language-quality rule
|
|
- All user-facing Thai strings must be UTF-safe, readable, and consistently localized.
|
|
|
|
## Recommended Remediation Order
|
|
|
|
1. Fix Thai text encoding across all user-facing surfaces.
|
|
2. Standardize heading semantics and page-header composition.
|
|
3. Decide whether reports is an intentional exception or should move closer to the shared table pattern.
|
|
4. Unify attachment UX across training records, announcements, and online lessons.
|
|
5. Add a small accessibility/design checklist for forms, icon buttons, and navigation semantics.
|
|
|
|
## Files Reviewed
|
|
|
|
- `plans/tms-system-full-audit-prompts.md`
|
|
- `docs/AI_DEVELOPMENT_GUIDE.md`
|
|
- `docs/PROJECT_ARCHITECTURE.md`
|
|
- `src/components/layout/page-container.tsx`
|
|
- `src/components/layout/app-sidebar.tsx`
|
|
- `src/components/layout/user-nav.tsx`
|
|
- `src/components/org-switcher.tsx`
|
|
- `src/components/ui/heading.tsx`
|
|
- `src/components/ui/notification-card.tsx`
|
|
- `src/components/ui/table/data-table.tsx`
|
|
- `src/components/ui/table/data-table-toolbar.tsx`
|
|
- `src/components/ui/table/data-table-pagination.tsx`
|
|
- `src/config/nav-config.ts`
|
|
- `src/features/employee-directory/components/employee-directory-header.tsx`
|
|
- `src/features/employee-directory/components/employee-directory-table.tsx`
|
|
- `src/features/training-records/components/training-record-form.tsx`
|
|
- `src/features/announcements/components/announcement-form.tsx`
|
|
- `src/features/announcements/components/announcement-view-page.tsx`
|
|
- `src/features/announcements/components/announcement-status-badge.tsx`
|
|
- `src/features/online-lessons/components/online-lesson-form.tsx`
|
|
- `src/features/reports/components/reports-page-content.tsx`
|
|
- `src/features/reports/components/report-table-card.tsx`
|
|
- `src/features/notifications/components/notifications-page.tsx`
|
|
- `src/features/audit-logs/components/audit-log-listing.tsx`
|
|
- `src/features/audit-logs/components/audit-log-table.tsx`
|
|
- `src/features/content-approval/components/content-approval-status-badge.tsx`
|
|
|
|
## Areas Not Verified
|
|
|
|
- Runtime browser validation of focus order, keyboard traversal, and screen-reader output
|
|
- Visual contrast measurement against rendered theme tokens
|
|
- All dialogs/sheets/drawers at runtime, including focus trap and mobile height behavior
|
|
- Full mobile behavior of the sidebar and complex tables in a live viewport
|
|
- Every feature module in the repo; this review focused on canonical and high-traffic dashboard surfaces
|