
Security News
/Company News
Socket Is Sponsoring Composer and Packagist
Socket has joined the new Composer and Packagist sponsorship program as a launch sponsor, supporting the team that keeps PHP's package ecosystem secure.
@abpjs/theme-basic
Advanced tools
ABP Framework Theme Basic components for React - translated from @abp/ng.theme.basic
Basic layout components for ABP Framework in React
@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.
# Using npm
npm install @abpjs/theme-basic
# Using yarn
yarn add @abpjs/theme-basic
# Using pnpm
pnpm add @abpjs/theme-basic
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, orframer-motionas peer dependencies.
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:
ThemeBasicProviderincludes Chakra's provider internally (viaThemeSharedProvider), so you don't need to wrap withChakraProviderseparately.
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>
);
}
Use the LAYOUTS constant for dynamic layout selection:
import { LAYOUTS, Layout } from '@abpjs/theme-basic';
function DynamicLayoutWrapper() {
const { pathname } = useLocation();
// Determine layout based on route
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>
);
}
The main application layout with navigation, header, and footer.
import { LayoutApplication } from '@abpjs/theme-basic';
function MainApp() {
return (
<LayoutApplication>
<YourContent />
</LayoutApplication>
);
}
Features:
Centered layout for authentication pages.
import { LayoutAccount } from '@abpjs/theme-basic';
function AuthPages() {
return (
<LayoutAccount>
<LoginForm />
</LayoutAccount>
);
}
Features:
Minimal layout with no chrome.
import { LayoutEmpty } from '@abpjs/theme-basic';
function PrintablePage() {
return (
<LayoutEmpty>
<PrintableContent />
</LayoutEmpty>
);
}
Features:
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} />
</>
);
}
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} />
</>
);
}
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>
);
}
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>;
}
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>
);
}
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;
}
interface NavigationElement {
name: string;
element: ReactNode;
order?: number;
}
The package exports a LAYOUTS constant for dynamic layout selection:
import { LAYOUTS } from '@abpjs/theme-basic';
// LAYOUTS structure:
// [
// { key: 'application', component: LayoutApplication },
// { key: 'account', component: LayoutAccount },
// { key: 'empty', component: LayoutEmpty },
// ]
function getLayoutByKey(key: string) {
return LAYOUTS.find(l => l.key === key)?.component;
}
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' },
// ... more shades
},
},
},
semanticTokens: {
colors: {
brand: {
solid: { value: '{colors.brand.500}' },
contrast: { value: 'white' },
},
},
},
},
});
function App() {
return (
<ThemeBasicProvider themeOverrides={customTheme}>
{/* Your app */}
</ThemeBasicProvider>
);
}
Enable color mode support:
import { ThemeBasicProvider } from '@abpjs/theme-basic';
function App() {
return (
<ThemeBasicProvider
enableColorMode={true}
defaultColorMode="light" // 'light' | 'dark' | 'system'
>
{/* Your app */}
</ThemeBasicProvider>
);
}
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>
);
}
| Prop | Type | Default | Description |
|---|---|---|---|
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 |
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>
);
}
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, // Shows "5" badge
badgeColorPalette: 'red', // Badge color (default: 'gray')
},
{
name: 'Messages',
path: '/messages',
badge: '50+', // Can be string or number
badgeColorPalette: 'blue',
},
{
name: 'Admin',
path: '/admin',
icon: <LuSettings />,
children: [
{
name: 'Users',
path: '/admin/users',
icon: <LuUsers />,
badge: 'New',
},
],
},
];
The layout automatically supports RTL languages. When a user switches to Arabic, Hebrew, Persian, or other RTL languages:
No additional configuration needed - RTL is detected automatically from the selected language.
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 = {
// Your ABP configuration
};
// Optional: Custom theme
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;
If you're upgrading from a previous version that used Chakra UI v2:
ThemeBasicProvider now includes itdefineConfig() instead of extendTheme()@chakra-ui/icons, @emotion/styled, framer-motion; add lucide-react{ value: '#color' } format in theme tokensisDisabled → disabled, isLoading → loadingcolorScheme → colorPalettelucide-react instead of @chakra-ui/icons// Before (Chakra v2)
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>
// After (Chakra v3)
import { ThemeBasicProvider, defineConfig } from '@abpjs/theme-basic';
const customTheme = defineConfig({
theme: {
tokens: {
colors: { brand: { 500: { value: '#2196f3' } } },
},
},
});
<ThemeBasicProvider themeOverrides={customTheme}>
<App />
</ThemeBasicProvider>
For comprehensive documentation, visit docs.abpjs.io:
This package is part of the ABP React monorepo. Contributions are welcome!
LGPL-3.0 - See LICENSE for details.
FAQs
ABP Framework Theme Basic components for React - translated from @abp/ng.theme.basic
The npm package @abpjs/theme-basic receives a total of 43 weekly downloads. As such, @abpjs/theme-basic popularity was classified as not popular.
We found that @abpjs/theme-basic demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
/Company News
Socket has joined the new Composer and Packagist sponsorship program as a launch sponsor, supporting the team that keeps PHP's package ecosystem secure.

Research
/Security News
Benign-looking npm packages split malicious functionality across a dependency chain that deploys a cross-platform RAT targeting Alibaba developers.

Research
/Security News
Two Joyfill npm beta releases contain an import-time implant that uses blockchain transactions to retrieve a remote-access trojan.