@abpjs/theme-basic
Basic layout components for ABP Framework in React

Overview
@abpjs/theme-basic provides the foundational layout system for ABP-based React applications. It includes multiple pre-built layouts for different sections of your application - from full application layouts with navigation to minimal account page layouts.
This package is a React translation of the original @abp/ng.theme.basic Angular package, bringing the same flexible layout system to React developers.
Features
- Multiple Layouts - Application, Account, and Empty layouts
- Dynamic Layout System - Switch layouts based on routes
- Navigation Management - Configurable navigation elements with icons and badges
- User Profile - Built-in profile and password change components
- Responsive Design - Mobile-friendly layouts with sidebar and drawer navigation
- RTL Support - Full right-to-left support for Arabic, Hebrew, Persian, and other RTL languages
- Search - Built-in navigation search to filter menu items
- Logo Customization - Customize logo via props without modifying source code
- Chakra UI v3 - Beautiful, accessible components with modern patterns
- Color Mode - Built-in light/dark theme support (opt-in)
- TypeScript - Full type safety with comprehensive definitions
Installation
npm install @abpjs/theme-basic
yarn add @abpjs/theme-basic
pnpm add @abpjs/theme-basic
Required Dependencies
This package requires the following peer dependencies:
npm install @abpjs/core @abpjs/theme-shared @chakra-ui/react @emotion/react lucide-react react-router-dom react-hook-form
Note: Chakra UI v3 no longer requires @chakra-ui/icons, @emotion/styled, or framer-motion as peer dependencies.
Quick Start
1. Setup the Theme Provider
Wrap your application with the ThemeBasicProvider:
import { ThemeBasicProvider } from '@abpjs/theme-basic';
import { CoreProvider } from '@abpjs/core';
function App() {
return (
<CoreProvider environment={environment}>
<ThemeBasicProvider>
<Router>
<AppRoutes />
</Router>
</ThemeBasicProvider>
</CoreProvider>
);
}
Note: ThemeBasicProvider includes Chakra's provider internally (via ThemeSharedProvider), so you don't need to wrap with ChakraProvider separately.
2. Use Layouts in Routes
import {
LayoutApplication,
LayoutAccount,
LayoutEmpty
} from '@abpjs/theme-basic';
import { Routes, Route, Outlet } from 'react-router-dom';
function AppRoutes() {
return (
<Routes>
{/* Application layout for main pages */}
<Route element={<LayoutApplication><Outlet /></LayoutApplication>}>
<Route path="/" element={<HomePage />} />
<Route path="/dashboard" element={<DashboardPage />} />
<Route path="/users" element={<UsersPage />} />
</Route>
{/* Account layout for auth pages */}
<Route element={<LayoutAccount><Outlet /></LayoutAccount>}>
<Route path="/login" element={<LoginPage />} />
<Route path="/register" element={<RegisterPage />} />
</Route>
{/* Empty layout for minimal pages */}
<Route element={<LayoutEmpty><Outlet /></LayoutEmpty>}>
<Route path="/print/:id" element={<PrintPage />} />
</Route>
</Routes>
);
}
3. Dynamic Layout Selection
Use the LAYOUTS constant for dynamic layout selection:
import { LAYOUTS, Layout } from '@abpjs/theme-basic';
function DynamicLayoutWrapper() {
const { pathname } = useLocation();
const getLayout = () => {
if (pathname.startsWith('/account')) return 'account';
if (pathname.startsWith('/print')) return 'empty';
return 'application';
};
const SelectedLayout = LAYOUTS.find(l => l.key === getLayout())?.component || Layout;
return (
<SelectedLayout>
<Outlet />
</SelectedLayout>
);
}
Layouts
LayoutApplication
The main application layout with navigation, header, and footer.
import { LayoutApplication } from '@abpjs/theme-basic';
function MainApp() {
return (
<LayoutApplication>
<YourContent />
</LayoutApplication>
);
}
Features:
- Side navigation menu
- Top header with user menu
- Breadcrumbs
- Footer
- Responsive sidebar (collapsible on mobile)
LayoutAccount
Centered layout for authentication pages.
import { LayoutAccount } from '@abpjs/theme-basic';
function AuthPages() {
return (
<LayoutAccount>
<LoginForm />
</LayoutAccount>
);
}
Features:
- Centered content
- Clean, minimal design
- Logo display
- Language selector
LayoutEmpty
Minimal layout with no chrome.
import { LayoutEmpty } from '@abpjs/theme-basic';
function PrintablePage() {
return (
<LayoutEmpty>
<PrintableContent />
</LayoutEmpty>
);
}
Features:
- No header or footer
- Full-width content
- Ideal for printing or embedded views
Components
Profile
User profile management component (modal-based).
import { Profile } from '@abpjs/theme-basic';
import { useState } from 'react';
function ProfileButton() {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<button onClick={() => setIsOpen(true)}>My Profile</button>
<Profile visible={isOpen} onVisibleChange={setIsOpen} />
</>
);
}
ChangePassword
Password change form component (modal-based).
import { ChangePassword } from '@abpjs/theme-basic';
import { useState } from 'react';
function SecurityButton() {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<button onClick={() => setIsOpen(true)}>Change Password</button>
<ChangePassword visible={isOpen} onVisibleChange={setIsOpen} />
</>
);
}
Hooks
useLayoutContext
Access and modify layout state.
import { useLayoutContext } from '@abpjs/theme-basic';
function SidebarToggle() {
const { isSidebarOpen, toggleSidebar } = useLayoutContext();
return (
<button onClick={toggleSidebar}>
{isSidebarOpen ? 'Close' : 'Open'} Sidebar
</button>
);
}
useLayoutService
Access layout service for programmatic control.
import { useLayoutService } from '@abpjs/theme-basic';
function LayoutController() {
const layoutService = useLayoutService();
const handleCollapse = () => {
layoutService.collapseSidebar();
};
return <button onClick={handleCollapse}>Collapse</button>;
}
useNavigationElements
Access and manage navigation items.
import { useNavigationElements } from '@abpjs/theme-basic';
function NavigationMenu() {
const elements = useNavigationElements();
return (
<nav>
{elements.map(item => (
<NavLink key={item.name} to={item.path}>
{item.name}
</NavLink>
))}
</nav>
);
}
Navigation Configuration
Adding Navigation Items
import { useLayoutService } from '@abpjs/theme-basic';
function ConfigureNavigation() {
const layoutService = useLayoutService();
useEffect(() => {
layoutService.addNavigationElement({
name: 'Dashboard',
element: <DashboardLink />,
order: 1,
});
layoutService.addNavigationElement({
name: 'Users',
element: <UsersLink />,
order: 2,
});
}, []);
return null;
}
Navigation Element Structure
interface NavigationElement {
name: string;
element: ReactNode;
order?: number;
}
LAYOUTS Constant
The package exports a LAYOUTS constant for dynamic layout selection:
import { LAYOUTS } from '@abpjs/theme-basic';
function getLayoutByKey(key: string) {
return LAYOUTS.find(l => l.key === key)?.component;
}
Customization
Theme Customization with Chakra v3
Customize layouts using defineConfig:
import { ThemeBasicProvider, defineConfig } from '@abpjs/theme-basic';
const customTheme = defineConfig({
theme: {
tokens: {
colors: {
brand: {
50: { value: '#e3f2fd' },
100: { value: '#bbdefb' },
500: { value: '#2196f3' },
600: { value: '#1e88e5' },
},
},
},
semanticTokens: {
colors: {
brand: {
solid: { value: '{colors.brand.500}' },
contrast: { value: 'white' },
},
},
},
},
});
function App() {
return (
<ThemeBasicProvider themeOverrides={customTheme}>
{/* Your app */}
</ThemeBasicProvider>
);
}
Color Mode (Dark/Light Theme)
Enable color mode support:
import { ThemeBasicProvider } from '@abpjs/theme-basic';
function App() {
return (
<ThemeBasicProvider
enableColorMode={true}
defaultColorMode="light" // 'light' | 'dark' | 'system'
>
{/* Your app */}
</ThemeBasicProvider>
);
}
Custom Layout Components
Create your own layouts extending the base:
import { LayoutBase } from '@abpjs/theme-basic';
import { Box, Flex } from '@chakra-ui/react';
function CustomLayout({ children }) {
return (
<LayoutBase>
<Flex direction="column" minH="100vh">
<CustomHeader />
<Box flex="1" p={4}>
{children}
</Box>
<CustomFooter />
</Flex>
</LayoutBase>
);
}
ThemeBasicProvider Props
children | ReactNode | - | Child components |
renderToasts | boolean | true | Render ToastContainer |
renderConfirmation | boolean | true | Render ConfirmationDialog |
themeOverrides | ThemeOverride | - | Custom theme configuration |
toastPosition | string | 'bottom-right' | Toast position |
enableColorMode | boolean | false | Enable dark/light mode |
defaultColorMode | 'light' | 'dark' | 'system' | 'light' | Default color mode |
logo | ReactNode | - | Custom logo component |
logoIcon | ReactNode | - | Custom logo icon (for collapsed states) |
appName | string | - | Application name for logo text |
logoLink | string | '/' | Link destination when clicking logo |
Logo Customization
Customize the application logo via ThemeBasicProvider props:
import { ThemeBasicProvider } from '@abpjs/theme-basic';
function App() {
return (
<ThemeBasicProvider
logo={<img src="/my-logo.svg" alt="My App" />}
logoIcon={<img src="/my-icon.svg" alt="Icon" />}
appName="My Application"
logoLink="/"
>
{/* Your app */}
</ThemeBasicProvider>
);
}
Route Icons and Badges
Define icons and badges directly on your routes:
import { LuHome, LuUsers, LuSettings, LuListTodo } from 'react-icons/lu';
const routes = [
{
name: 'Home',
path: '/',
icon: <LuHome />,
},
{
name: 'Tasks',
path: '/tasks',
icon: <LuListTodo />,
badge: 5,
badgeColorPalette: 'red',
},
{
name: 'Messages',
path: '/messages',
badge: '50+',
badgeColorPalette: 'blue',
},
{
name: 'Admin',
path: '/admin',
icon: <LuSettings />,
children: [
{
name: 'Users',
path: '/admin/users',
icon: <LuUsers />,
badge: 'New',
},
],
},
];
RTL (Right-to-Left) Support
The layout automatically supports RTL languages. When a user switches to Arabic, Hebrew, Persian, or other RTL languages:
- Sidebar moves to the right side
- Text alignment flips
- Icons and navigation elements reposition correctly
- Menus open in the appropriate direction
No additional configuration needed - RTL is detected automatically from the selected language.
Complete Example
Full application setup:
import { BrowserRouter, Routes, Route, Outlet } from 'react-router-dom';
import { CoreProvider } from '@abpjs/core';
import {
ThemeBasicProvider,
LayoutApplication,
LayoutAccount,
Profile,
ChangePassword,
defineConfig,
} from '@abpjs/theme-basic';
import { LoginPage, RegisterPage } from '@abpjs/account';
const environment = {
};
const customTheme = defineConfig({
theme: {
tokens: {
colors: {
brand: {
500: { value: '#6366f1' },
},
},
},
},
});
function App() {
return (
<CoreProvider environment={environment}>
<ThemeBasicProvider
themeOverrides={customTheme}
enableColorMode={true}
>
<BrowserRouter>
<Routes>
{/* Main application routes */}
<Route element={<LayoutApplication><Outlet /></LayoutApplication>}>
<Route path="/" element={<HomePage />} />
<Route path="/dashboard" element={<DashboardPage />} />
</Route>
{/* Auth routes */}
<Route element={<LayoutAccount><Outlet /></LayoutAccount>}>
<Route path="/login" element={<LoginPage />} />
<Route path="/register" element={<RegisterPage />} />
</Route>
</Routes>
</BrowserRouter>
</ThemeBasicProvider>
</CoreProvider>
);
}
export default App;
Migration from Chakra UI v2
If you're upgrading from a previous version that used Chakra UI v2:
Key Changes
- No separate ChakraProvider -
ThemeBasicProvider now includes it
- Theme configuration - Use
defineConfig() instead of extendTheme()
- Dependencies - Remove
@chakra-ui/icons, @emotion/styled, framer-motion; add lucide-react
- Color tokens - Use
{ value: '#color' } format in theme tokens
- Boolean props -
isDisabled → disabled, isLoading → loading
- Color scheme -
colorScheme → colorPalette
- Icons - Use
lucide-react instead of @chakra-ui/icons
Example Migration
import { ChakraProvider, extendTheme } from '@chakra-ui/react';
import { ThemeBasicProvider } from '@abpjs/theme-basic';
const theme = extendTheme({
colors: { brand: { 500: '#2196f3' } },
});
<ChakraProvider theme={theme}>
<ThemeBasicProvider>
<App />
</ThemeBasicProvider>
</ChakraProvider>
import { ThemeBasicProvider, defineConfig } from '@abpjs/theme-basic';
const customTheme = defineConfig({
theme: {
tokens: {
colors: { brand: { 500: { value: '#2196f3' } } },
},
},
});
<ThemeBasicProvider themeOverrides={customTheme}>
<App />
</ThemeBasicProvider>
Documentation
For comprehensive documentation, visit docs.abpjs.io:
Related Packages
Contributing
This package is part of the ABP React monorepo. Contributions are welcome!
License
LGPL-3.0 - See LICENSE for details.
View Full Documentation | Report Issues | View Source