admin/docs/admin-ui-guidelines.md
alisaza e1eaf5eff5 feat: initial ghabilee-admin backoffice app
Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js
app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
2026-09-05 13:12:59 +03:30

4.3 KiB

Admin UI guidelines

The admin panel uses HeroUI v3 through compatibility adapters and shared admin primitives. Page code should prefer these shared layers over importing HeroUI directly, unless a compound component has no adapter yet.

Theme boundary

DashboardShell owns the data-theme="ghabilee-admin" boundary. Admin semantic colors, fields, overlays, focus rings, radius, elevation, and scrollbars are defined under that selector in styles/globals.css.

Use semantic utilities inside admin UI:

  • bg-surface, bg-surface-secondary, and text-foreground
  • text-muted, border-border, and border-separator
  • text-link, ring-focus, and the accent, success, warning, and danger families

Avoid adding new hard-coded Slate colors or !important overrides. If a visual rule should apply to multiple components, add or adjust a semantic token at the admin theme boundary.

Consumer app overlays and layout rules are separate — see consumer-ui-guidelines.md (ConsumerModal only; mobile excellence; desktop polish is a non-goal).

Shared primitives

  • Use components/formElements/Button for actions and links.
  • Use components/formElements/Input for existing React Hook Form forms. New focused controls may compose the adapters in components/heroui.
  • Use components/modals/Modal for forms, previews, and record review that stay on the list page. Do not use Drawer / AdminDetailDrawer in admin UI.
  • Use useAlertModal for confirmations. It renders a WAI-ARIA AlertDialog and prevents duplicate async confirmation.
  • Use lib/toast instead of importing HeroUI's toast queue in business code.
  • Use AdminState and the exports from LoadingState for empty, error, and loading states.

Paginated admin lists

PaginatedList is the default list surface. It includes:

  • server pagination and sorting;
  • responsive table/card rendering;
  • desktop column filters and a mobile filter dialog;
  • active-filter chips;
  • column visibility;
  • optional quick search via searchField and searchPlaceholder;
  • optional row selection and bulkActions;
  • refresh, error, empty, and loading states.

Only connect searchField to a filter supported by the endpoint. Bulk action renderers receive the current HeroUI Selection; they must handle the special "all" value.

Sensitive workflows

Destructive or irreversible actions must:

  1. open useAlertModal with dangerAccept: true;
  2. use useAdminAction or an equivalent pending state;
  3. disable competing actions while the request is pending;
  4. show success or localized failure feedback through lib/toast;
  5. refresh the affected list after success.

Use a Modal for review and data entry. Do not place a full edit form in a table cell. Never introduce a side drawer in the admin panel.

RTL and accessibility

  • Keep the document and admin shell RTL; use logical start/end utilities.
  • Add an accessible name to icon-only buttons.
  • Preserve visible focus rings; do not remove outlines without a focus-visible replacement.
  • Use role="status"/aria-live for non-critical updates and role="alert" for errors.
  • Confirm keyboard and focus behavior when changing dialogs, modals, dropdowns, tables, or search fields.

Prefer compact spacing utilities (p-2 not px-2 py-2). Do not add breakpoint padding that only changes by one Tailwind step (p-4 md:p-5). Keep text-xs at every breakpoint; do not add sm:text-sm. Use integer spacing only (py-3 not py-2.5).

HeroUI MCP workflow

Before using or changing a HeroUI component:

  1. retrieve the current quick-start requirements;
  2. list available v3 components;
  3. retrieve the component documentation;
  4. consult source styles only when semantic tokens or documented classes are insufficient;
  5. validate against the installed package types.

The repository currently uses HeroUI 3.2.2. MCP version labels may lag the installed package, so TypeScript, focused tests, and the installed package types remain mandatory validation gates.

Required checks

For a focused UI change, run:

pnpm typecheck
pnpm exec eslint <changed-files> --max-warnings 0
pnpm exec vitest run <related-tests>
git diff --check

Before release, also run the complete test suite, architecture check, bundle budget check, and relevant Playwright accessibility scenarios.