# 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`](./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: ```bash pnpm typecheck pnpm exec eslint --max-warnings 0 pnpm exec vitest run git diff --check ``` Before release, also run the complete test suite, architecture check, bundle budget check, and relevant Playwright accessibility scenarios.