Back to Abp

Customization

docs/en/framework/ui/react/customization.md

10.4.05.9 KB
Original Source
json
//[doc-seo]
{
    "Description": "Learn how to customize ABP React UI applications, including pages, themes, sidebar navigation, and the user menu."
}

Customization

The React app generated by ABP is fully owned by your solution. All source code is available, so you can change pages, components, routes, themes, menus, API calls, and layout behavior just like in any other React application.

This page focuses on the main developer-owned React app. The same general approach applies to the public-web React app if your solution includes one. The Admin Console is an ABP-managed administration surface; see Admin Console for details.

General Customization

Application pages live under src/pages/. The template includes practical references:

  • Users page: a simple page that lists users and links to the Admin Console for full user and role management.
  • Books page: a full CRUD sample when the sample CRUD option is selected during solution creation. It demonstrates TanStack Query, forms, Zod validation, dialogs, tables, permissions, and toast notifications.

Shared UI and infrastructure live under:

text
src/
├── components/
│   ├── layout/
│   └── ui/
├── lib/
│   ├── api/
│   ├── auth/
│   ├── i18n/
│   ├── routing/
│   └── theme/
└── pages/

Adding a Page

Create a page under src/pages/:

tsx
export function ReportsPage() {
  return (
    <div className="space-y-6">
      <h1 className="text-3xl font-bold tracking-tight">Reports</h1>
    </div>
  )
}

Register it with TanStack Router in src/routes/router.tsx:

tsx
const reportsRoute = createRoute({
  getParentRoute: () => rootRoute,
  path: '/reports',
  component: ReportsPage,
  beforeLoad: createPermissionGuard('MyProjectName.Reports'),
})

const routeTree = rootRoute.addChildren([
  indexRoute,
  reportsRoute,
])

Use authGuard for pages that only require authentication and createPermissionGuard for pages that require a permission.

Theming

The React template uses shadcn/ui-style components, Radix UI primitives, Tailwind CSS, and CSS variables.

Theme tokens are defined in src/styles/globals.css:

css
:root {
  --background: oklch(0.978 0.003 264);
  --foreground: oklch(0.205 0.008 264);
  --primary: oklch(0.48 0.10 278);
  --radius: 0.5rem;
}

.dark {
  --background: oklch(0.16 0.004 264);
  --foreground: oklch(0.92 0.005 264);
  --primary: oklch(0.62 0.12 278);
}

ABP Studio's modern wizard can generate different shadcn theme color presets and light/dark/system theme behavior.

Changing Theme Colors

To make a quick theme change, edit the CSS variables in src/styles/globals.css:

css
:root {
  --primary: oklch(0.623 0.188 259.6);
  --primary-foreground: oklch(1 0 0);
}

Because the generated shadcn/ui components consume these variables through Tailwind tokens, the change applies across buttons, links, active sidebar entries, focus rings, and other components that use the primary color.

Theme Mode Switcher

Theme mode is handled by src/lib/theme/ThemeProvider.tsx. It supports:

  • light
  • dark
  • system

The header cycles through the allowed modes:

tsx
const THEME_CYCLE: Theme[] = ['light', 'dark', 'system']

function ThemeToggle() {
  const { theme, resolvedTheme, setTheme } = useTheme()

  function cycleTheme() {
    const currentIndex = THEME_CYCLE.indexOf(theme)
    const nextIndex = currentIndex < 0 ? 0 : (currentIndex + 1) % THEME_CYCLE.length
    setTheme(THEME_CYCLE[nextIndex])
  }

  return <Button variant="ghost" size="icon" onClick={cycleTheme}>...</Button>
}

To remove the switcher or replace it with a dropdown, edit src/components/layout/Header.tsx.

Modifying the Sidebar Menu

Sidebar navigation is defined in src/lib/routing/route-config.ts.

Add a menu item:

ts
import { BarChart3 } from 'lucide-react'

export const routeConfig: RouteConfigItem[] = [
  {
    path: '/reports',
    nameKey: 'Menu:Reports',
    icon: BarChart3,
    order: 10,
    requiredPolicy: 'MyProjectName.Reports',
  },
]

Then add the localization key to src/locales/en.json:

json
{
  "Menu:Reports": "Reports"
}

Use these properties depending on the menu item:

PropertyUse
pathInternal route path or logical path for an external item.
nameKeyLocalization key shown in the sidebar.
iconOptional Lucide icon.
orderSorting order.
requiredPolicyHide the item unless the permission is granted.
requiresAuthHide the item unless the user is authenticated.
externalHrefOpen an external URL or another app, such as the Admin Console.
childrenAdd nested sidebar items.

Use the sidebar navigation for application pages and module entry points.

Use the user menu for account-specific actions, profile links, sessions, security logs, linked accounts, and logout. The user menu is implemented in src/components/layout/UserMenu.tsx.

Example user menu item:

tsx
<DropdownMenuItem asChild className="cursor-pointer">
  <a href="/account/preferences">
    <Settings className="size-4" />
    {t('MyAccount::Preferences')}
  </a>
</DropdownMenuItem>

Customizing UI Components

shadcn/ui components are copied into your project under src/components/ui/. They are not black-box components from a package. You can edit them directly.

For example:

  • Change button variants in src/components/ui/button.tsx.
  • Change dialog structure in src/components/ui/dialog.tsx.
  • Add a new reusable component under src/components/ui/.
  • Add feature-specific components under src/components/<feature>/.

Keep generic primitives in components/ui and business-specific components close to the feature or page that owns them.

See Also