Files
pos-system/microservices/docs/audit/ux-ui-designer.md
Ho Ngoc Hai 76d75c753b Migrate
2026-05-23 18:37:02 +07:00

12 KiB
Raw Permalink Blame History

UX/UI Designer Audit — GoodGo POS System

Auditor: UX/UI Designer Agent Date: 2026-03-20 Scope: apps/web-client-tpos-net — Blazor WASM + MudBlazor frontend Focus: UI consistency, component reuse, theme & styling, accessibility, UX flows


Executive Summary

The GoodGo POS frontend has a solid design foundation — centralized theming via AppTheme.cs, a reusable auth component library, and responsive multi-layout architecture. However, the codebase suffers from critical accessibility failures (no keyboard navigation, missing ARIA attributes, no focus-visible styles), 2,316+ inline style attributes that undermine design system consistency, and pervasive hardcoded Vietnamese strings that break English localization throughout the POS UI. Overall UI/UX maturity: 6/10.


Critical Issues

Issues that block production readiness or violate WCAG 2.1 AA standards.

1. Missing :focus-visible Styles — WCAG 2.1 §2.4.7

Files: wwwroot/css/admin.css, wwwroot/css/pos.css, wwwroot/css/auth.css, wwwroot/css/marketing.css Impact: Keyboard users cannot see which element has focus — entire app is effectively unusable without a mouse.

No CSS file defines :focus-visible styles. Browsers' default focus ring is often suppressed by MudBlazor reset styles.

Fix:

/* Add to app.css global scope */
:focus-visible {
    outline: 2px solid #FF5C00;
    outline-offset: 2px;
    border-radius: 4px;
}

2. Clickable <div> Elements Instead of <button> — WCAG 2.1 §4.1.2

Files: Pages/Pos/Cafe/CafeDesktop.razor, Pages/Pos/Restaurant/RestaurantDesktop.razor, and all other POS vertical desktop pages Impact: Product cards, order items, and action elements are <div> with @onclick handlers. Screen readers cannot identify them as interactive. Keyboard users cannot Tab to them or activate with Enter/Space.

Example (CafeDesktop.razor):

<!-- BAD: div with onclick -->
<div class="pos-product-card" @onclick="() => AddToCart(product)">
    ...
</div>

<!-- GOOD: semantic button -->
<button class="pos-product-card" @onclick="() => AddToCart(product)"
        aria-label="Thêm @product.Name vào giỏ hàng">
    ...
</button>

3. No ARIA Labels on Interactive Icons — WCAG 2.1 §4.1.2

Files: Components/Auth/AuthButton.razor, Components/Auth/AuthInput.razor (line 37), all layout files Impact: Icon-only buttons (close, toggle, back) have no accessible names — screen readers announce nothing or raw Unicode.

Example (AuthInput.razor ~line 37):

<!-- BAD: no aria-label -->
<button @onclick="TogglePassword">
    <i data-lucide="eye"></i>
</button>

<!-- GOOD -->
<button @onclick="TogglePassword"
        aria-label="@(showPassword ? "Ẩn mật khẩu" : "Hiện mật khẩu")"
        aria-pressed="@showPassword">
    <i data-lucide="@(showPassword ? "eye-off" : "eye")"></i>
</button>

4. Error/Success Messages Missing role="alert" — WCAG 2.1 §4.1.3

Files: Pages/Auth/LoginAdmin.razor (lines 2840), Pages/Pos/Cafe/CafeDesktop.razor Impact: Dynamic status changes (login error, payment success, cart update) are not announced to screen readers.

Example (LoginAdmin.razor ~line 29):

<!-- BAD: static div, not announced -->
<div style="background:rgba(239,68,68,0.12);color:#EF4444;">
    @_errorMessage
</div>

<!-- GOOD -->
<div role="alert" aria-live="assertive" class="auth-error-message">
    @_errorMessage
</div>

5. Hardcoded Vietnamese Strings in POS UI — Localization Failure

File: Pages/Pos/Cafe/CafeDesktop.razor and all POS vertical pages Impact: English-language users see Vietnamese text. App cannot support international merchants.

Examples found (CafeDesktop.razor):

Line Hardcoded String Should Be
24 "Đang tải..." @L["Common_Loading"]
25 "Không thể tải dữ liệu" @L["Common_LoadError"]
66 "Đơn hàng" @L["Pos_OrderPanel_Title"]
67 "món" @L["Pos_CartItem_Unit"]
89 "Nhập mã voucher..." @L["Pos_Voucher_Placeholder"]
97 "Giảm giá" @L["Pos_Discount_Label"]
107 "Tổng cộng" @L["Pos_Total_Label"]
117 "Đang tạo đơn..." @L["Pos_CreatingOrder"]
122 "Thanh toán" @L["Pos_Checkout_Button"]

Also found in layouts:

  • AdminLayout.razor (line ~160): "Có lỗi xảy ra", "Vui lòng thử lại", "Tải lại"
  • StaffLayout.razor (line 148): Same error boundary text
  • PosLayout.razor (lines 29, 65, 115): "GoodGo POS", "Menu", "Đơn hàng"

6. Hardcoded Color Values Instead of CSS Variables

Files: Pages/Pos/Cafe/CafeDesktop.razor, Pages/Auth/LoginAdmin.razor, multiple admin pages Impact: Theme overrides are impossible. Colors are not consistent with the design token system.

Examples:

<!-- BAD: hardcoded rgba -->
style="background:rgba(139,92,246,0.1);color:#8B5CF6;"
style="background:rgba(239,68,68,0.12);color:#EF4444;"
style="background-color:rgba(139,92,246,0.125);"

<!-- GOOD: CSS variables -->
class="status-purple"
class="status-danger"

Hardcoded colors to replace:

Value Should Be
#16A34A var(--color-success)
#EF4444 var(--color-danger)
#8B5CF6 var(--color-purple)
rgba(139,92,246,0.1) var(--color-purple-subtle)
rgba(239,68,68,0.12) var(--color-danger-subtle)

Warnings

Issues that create significant technical debt or UX inconsistency.

7. 2,316 Inline Style Attributes

Inline styles are scattered across all pages — especially POS desktop views, admin shop pages, and dashboard. This makes CSS maintenance impossible and prevents design system enforcement.

Top offending patterns:

style="display:flex;flex-direction:column;gap:24px;"
style="padding:6px 12px;border-radius:8px;border:none;"
style="position:absolute;left:@{X}px;top:@{Y}px;"

Strategy: Create CSS utility classes and component classes. Move inline styles to scoped .razor.css files.


8. Inconsistent Spacing Scale

The design uses 10+ different spacing values without a defined scale:

  • Gaps: 4, 6, 8, 10, 12, 14, 16, 20, 24, 28, 32, 48px
  • Padding: 6, 8, 10, 12, 16, 20, 24px
  • Border radius: 6, 8, 10, 12, 14, 20, 24px

Recommended scale:

/* Spacing: 4-point scale */
--space-1: 4px;  --space-2: 8px;  --space-3: 12px;
--space-4: 16px; --space-5: 20px; --space-6: 24px;
--space-8: 32px; --space-12: 48px;

/* Border radius: 3 values */
--radius-sm: 8px;  --radius-md: 12px;  --radius-lg: 16px;

9. Missing Contrast Ratio for Secondary Text — WCAG 2.1 §1.4.3

File: wwwroot/css/admin.css

/* Current — MAY fail WCAG AAA */
--admin-text-secondary: #ADADB0;  /* ratio ~5.08:1 on #1A1A1D — FAILS AAA (7:1) */
--admin-text-tertiary: #8B8B90;   /* ratio ~4.13:1 on #1A1A1D — FAILS AA (4.5:1) */

--admin-text-tertiary likely fails WCAG AA for normal text. Needs contrast validation.


10. Cart Items Use <div> Instead of Semantic List

File: Pages/Pos/Cafe/CafeDesktop.razor Cart items rendered as generic <div> elements. Should be <ul>/<li> structure for screen readers to announce list count and items.


11. No .razor.css Scoped Stylesheets Per Component

All 8 reusable components (AuthButton, AuthInput, OtpInput, etc.) have zero scoped CSS files. Styles are defined globally in auth.css. This creates unintended style leakage and makes component refactoring dangerous.


12. OTP Input Missing ARIA Group Label

File: Components/Auth/OtpInput.razor (lines 1219) The 6-digit OTP input is a group of individual <input> elements but lacks role="group" and aria-label="One-time password". Screen readers will announce 6 separate unlabeled inputs.


13. No Focus Trap in Modal Overlays

Files: Layout/PosLayout.razor, admin dialog pages When mobile overlays or modals open, focus is not trapped within them. Users pressing Tab will cycle through background content, violating WCAG 2.1 §2.1.2.


Improvements

Recommendations that would improve UX quality and developer experience.

A. Create Component-Scoped CSS Files

For each component in Components/, create a matching .razor.css file:

Components/Auth/AuthButton.razor.css
Components/Auth/AuthInput.razor.css
Components/Pos/ResponsiveOrderPanel.razor.css

B. Add Password Strength Indicator

File: Pages/Auth/Register.razor Registration form has no visual password strength feedback. Add a 4-step strength bar (weak → fair → good → strong) using the existing PasswordStrengthCalculator pattern from Swift app.

C. Standardize Icon Sizes to 3 Tiers

Currently uses: 12, 14, 16, 18, 20, 24, 28, 32px. Reduce to:

--icon-sm: 16px;  /* Inline, label */
--icon-md: 20px;  /* Button, nav */
--icon-lg: 24px;  /* Header, feature */

D. Add aria-expanded to Expandable Sections

File: Pages/Admin/Shop/ShopRecipes.razor Accordion-style expand/collapse sections lack aria-expanded and aria-controls. Screen readers cannot determine collapsed state.

E. Add aria-busy to Async Loading States

Async data-fetch loading spinners don't set aria-busy="true" on the container, so screen readers don't know content is loading.

F. Introduce Design Token Documentation

Create a living style guide page at /admin/design-system (dev only) that shows all color tokens, spacing, typography, and component variants. Reference: MudBlazor Theme Manager pattern.

G. Validate Table Semantics

Admin tables (staff management, inventory, orders) should verify <th scope="col"> on all headers. MudBlazor's MudTable typically handles this, but custom HTML tables may not.


Action Items

Prioritized next steps.

# Priority Effort Item Files
1 🔴 Critical Small Add :focus-visible styles globally wwwroot/css/app.css
2 🔴 Critical Large Replace clickable <div> with <button> in POS pages All *Desktop.razor
3 🔴 Critical Medium Add aria-label to all icon-only buttons Auth components, layouts
4 🔴 Critical Medium Add role="alert" to all error/success messages Login pages, POS
5 🔴 Critical Large Move hardcoded Vietnamese strings to L["key"] in POS All POS vertical pages
6 🔴 Critical Medium Replace hardcoded colors with CSS variables CafeDesktop, Dashboard
7 🟠 High XL Extract 2,316 inline styles to CSS classes All pages
8 🟠 High Medium Fix secondary text contrast (--admin-text-tertiary) admin.css
9 🟠 High Small Add role="group" + aria-label to OTP input OtpInput.razor
10 🟠 High Medium Implement focus trap in modal overlays Layouts, dialogs
11 🟠 High Small Localize error boundary strings in layouts AdminLayout, StaffLayout
12 🟡 Medium Medium Standardize spacing scale (4-point system) All CSS files
13 🟡 Medium Small Standardize border-radius (3 values) All CSS files
14 🟡 Medium Medium Create .razor.css per component Components/Auth/
15 🟡 Medium Small Add aria-expanded to expandable sections ShopRecipes.razor
16 🟡 Medium Small Add password strength indicator Register.razor
17 🟡 Medium Small Standardize icon size scale (3 tiers) Icon usage site-wide
18 🟡 Medium Medium Add cart item <ul>/<li> semantics POS order panels
19 🟢 Low Large Create design system documentation page New page
20 🟢 Low Medium Screen reader testing (NVDA/JAWS) Full app regression

Audit performed by UX/UI Designer Agent — GoodGo Platform — 2026-03-20