# 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