4.3 KiB
4.3 KiB
UI / UX Rules
These rules freeze the approved UI behavior for ALLA OS and CRM-facing work.
Future UI should reuse existing dashboard patterns rather than introducing a parallel visual system.
UX.1 Thai CRM Terminology
docs/business/crm-terminology.mdis the source of truth for CRM business labels.- Use
src/features/crm/shared/terminology.tswhen CRM UI needs shared stage or role labels. - Keep
CRMandDashboardin English where the existing product already does so. - Do not rename schema fields, API routes, or internal codes just to match UI wording.
Dashboard Layout Standards
- Use
PageContainerfor dashboard page framing and page headers. - Keep pages inside the existing dashboard shell; do not build a separate CRM shell.
- Prefer small, composable sections instead of one oversized page component.
- Use cards, tables, and filter bars consistent with existing CRM dashboard and report pages.
Reference files:
src/components/layout/page-container.tsxsrc/features/crm/dashboard/components/crm-dashboard.tsxsrc/features/crm/reports/components/pipeline-report-view.tsx
Bento Grid Guidelines
- Reuse the existing dashboard-card rhythm: summary cards first, then charts/tables/detail sections.
- Keep KPI modules visually scannable with clear grouping and limited density per row.
- Avoid creating a radically different grid language inside CRM pages.
- Match existing spacing, border radius, and card hierarchy from current dashboard/report pages.
Form Standards
- Use TanStack Form via
@/components/ui/tanstack-form. - Use Zod for submit validation.
- Reuse field components from
@/components/forms/fields. - Keep labels and helper text business-readable.
- Use
<Button isLoading={isPending}>for submit/loading actions. - Close sheets/dialogs only after successful mutation completion and cache invalidation.
Reference docs and files:
docs/forms.mdsrc/features/crm/customers/components/customer-form-sheet.tsxsrc/features/crm/opportunities/components/opportunity-form-sheet.tsxsrc/features/crm/quotations/components/quotation-form-sheet.tsx
Table Standards
- Use
DataTable,DataTableToolbar, anduseDataTable. - Define columns close to the feature component tree.
- Keep filters URL-driven when the list page is shareable/bookmarkable.
- Use
useSuspenseQuery()for table data that is prefetched on the server.
Reference files:
src/components/ui/table/data-table.tsxsrc/features/users/components/users-table/index.tsxsrc/features/crm/customers/components/customers-table.tsxsrc/features/crm/opportunities/components/opportunities-table.tsx
Filter Standards
- Reuse shared filter metadata and existing select/date input patterns.
- Prefer
nuqsquery-state filters for reports and list pages. - Keep "clear filters" behavior explicit.
- Report exports must use the same filter contract as on-screen data.
Reference files:
src/features/crm/reports/components/report-filter-bar.tsxsrc/features/crm/reports/server/filters/shared.ts
Empty State Standards
- Empty states should explain what is missing and what the next action is.
- Prefer existing placeholder/skeleton components before inventing one-off empty-state systems.
- Keep empty states within the same page shell and card layout as loaded content.
Loading State Standards
- Use skeletons or suspense-friendly loading states for lists, charts, and dashboard panels.
- Preserve layout stability while loading.
- Keep button loading width stable with the existing button loading pattern.
Reference files:
src/components/ui/table/data-table-skeleton.tsxsrc/features/overview/components/*-skeleton.tsxsrc/components/ui/button.tsx
Error State Standards
- Use existing route-level
error.tsxboundaries where available. - Return actionable copy for recoverable failures.
- Do not expose raw backend or SQL detail in business-facing UI.
- Security denials should remain server-enforced even if the UI also hides the surface.
Reference files:
src/app/dashboard/overview/error.tsxsrc/app/global-error.tsx
Reuse Rules
- Do not create a new CRM design language.
- Do not create a second terminology registry.
- Do not create report-specific filter widgets when shared report filters already fit.
- Do not introduce UI-level permission checks as the only enforcement layer.