@campxdev/react-blueprint 2.3.8 → 2.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/types/src/components/Layout/AppLayout/components/AppBar.d.ts +4 -3
- package/dist/cjs/types/src/components/Layout/AppLayout/components/PersistentSidebar.d.ts +14 -0
- package/dist/cjs/types/src/components/Layout/AppLayout/components/Sidebar/interfaces.d.ts +2 -0
- package/dist/cjs/types/src/components/Layout/AppLayout/components/UserProfilePopup.d.ts +3 -2
- package/dist/cjs/types/src/components/Layout/AppLayout/types.d.ts +7 -0
- package/dist/esm/index.js +2 -2
- package/dist/esm/types/src/components/Layout/AppLayout/components/AppBar.d.ts +4 -3
- package/dist/esm/types/src/components/Layout/AppLayout/components/PersistentSidebar.d.ts +14 -0
- package/dist/esm/types/src/components/Layout/AppLayout/components/Sidebar/interfaces.d.ts +2 -0
- package/dist/esm/types/src/components/Layout/AppLayout/components/UserProfilePopup.d.ts +3 -2
- package/dist/esm/types/src/components/Layout/AppLayout/types.d.ts +7 -0
- package/dist/index.d.ts +48 -40
- package/package.json +1 -1
- package/src/App.tsx +9 -37
- package/src/components/Layout/AppLayout/AppLayout.tsx +61 -20
- package/src/components/Layout/AppLayout/components/AppBar.tsx +35 -49
- package/src/components/Layout/AppLayout/components/PersistentSidebar.tsx +171 -0
- package/src/components/Layout/AppLayout/components/Sidebar/MenuBar.tsx +8 -4
- package/src/components/Layout/AppLayout/components/Sidebar/MenuItem.tsx +123 -46
- package/src/components/Layout/AppLayout/components/Sidebar/interfaces.ts +2 -0
- package/src/components/Layout/AppLayout/components/Sidebar/styles.ts +0 -2
- package/src/components/Layout/AppLayout/components/UserProfilePopup.tsx +42 -12
- package/src/components/Layout/AppLayout/types.ts +9 -0
- package/src/components/Layout/PageHeader/components/Views/Views.tsx +3 -2
- package/src/components/Navigation/Breadcrumbs/Breadcrumbs.tsx +1 -1
- package/src/components/Navigation/Sidebar/SidebarV2.tsx +1 -1
- package/src/themes/colorTokens/darkColorTokens.tsx +1 -1
- package/src/themes/colorTokens/lightColorTokens.ts +1 -1
- package/src/themes/commonTheme.ts +1 -1
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { SideMenuItemProps } from './Sidebar/interfaces';
|
|
3
2
|
interface AppBarProps {
|
|
4
3
|
/** Right section component (actions, profile, etc.) */
|
|
5
4
|
rightSection?: React.ReactNode;
|
|
6
5
|
/** Center section component (workspace switcher, etc.) */
|
|
7
6
|
centerSection?: React.ReactNode;
|
|
8
|
-
/** Menu items for mobile drawer */
|
|
9
|
-
menu?: SideMenuItemProps[];
|
|
10
7
|
/** Custom className for the AppBar */
|
|
11
8
|
className?: string;
|
|
12
9
|
/** Custom styles for the AppBar */
|
|
13
10
|
sx?: any;
|
|
11
|
+
/** Hide hamburger menu (for persistent sidebar mode) */
|
|
12
|
+
hideHamburger?: boolean;
|
|
13
|
+
/** Callback to toggle sidebar (for persistent sidebar mode on mobile) */
|
|
14
|
+
onToggleSidebar?: () => void;
|
|
14
15
|
}
|
|
15
16
|
export declare const AppBar: React.FC<AppBarProps>;
|
|
16
17
|
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SideMenuItemProps } from './Sidebar/interfaces';
|
|
3
|
+
import { UserProfilePopupProps } from './UserProfilePopup';
|
|
4
|
+
interface PersistentSidebarProps {
|
|
5
|
+
/** Menu items for navigation */
|
|
6
|
+
menu: SideMenuItemProps[];
|
|
7
|
+
userProfileParams: UserProfilePopupProps;
|
|
8
|
+
/** Whether the sidebar is collapsed */
|
|
9
|
+
collapsed: boolean;
|
|
10
|
+
/** Function to toggle sidebar collapse state */
|
|
11
|
+
onToggle: () => void;
|
|
12
|
+
}
|
|
13
|
+
export declare const PersistentSidebar: React.FC<PersistentSidebarProps>;
|
|
14
|
+
export {};
|
|
@@ -40,6 +40,7 @@ export interface MenuItemProps {
|
|
|
40
40
|
currentMenuPath: string | null;
|
|
41
41
|
internalMenuClickHandler: (params: InternalMenuClickHandlerProps) => void;
|
|
42
42
|
onClose?: () => void;
|
|
43
|
+
collapsed?: boolean;
|
|
43
44
|
}
|
|
44
45
|
export interface SubMenuItemProps {
|
|
45
46
|
index: number;
|
|
@@ -52,4 +53,5 @@ export interface MenuBarProps {
|
|
|
52
53
|
internalMenuClickHandler: (params: InternalMenuClickHandlerProps) => void;
|
|
53
54
|
previousMenuClickHandler: () => void;
|
|
54
55
|
onClose?: () => void;
|
|
56
|
+
collapsed?: boolean;
|
|
55
57
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
interface UserProfilePopupProps {
|
|
2
|
+
export interface UserProfilePopupProps {
|
|
3
3
|
/** User's full name */
|
|
4
4
|
userFullName: string;
|
|
5
5
|
/** User's designation/role */
|
|
@@ -18,6 +18,8 @@ interface UserProfilePopupProps {
|
|
|
18
18
|
onActiveDevicesClick?: () => void;
|
|
19
19
|
/** Account section click handler */
|
|
20
20
|
onAccountClick?: () => void;
|
|
21
|
+
/**Persistant Side bar collapsed - boolean */
|
|
22
|
+
collapsed?: boolean;
|
|
21
23
|
}
|
|
22
24
|
/**
|
|
23
25
|
* Independent User Profile popup component for AppLayout right section
|
|
@@ -38,4 +40,3 @@ interface UserProfilePopupProps {
|
|
|
38
40
|
* />
|
|
39
41
|
*/
|
|
40
42
|
export declare const UserProfilePopup: React.FC<UserProfilePopupProps>;
|
|
41
|
-
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
2
|
import { SideMenuItemProps } from './components/Sidebar/interfaces';
|
|
3
|
+
import { UserProfilePopupProps } from './components/UserProfilePopup';
|
|
3
4
|
export interface HelpDocsAction {
|
|
4
5
|
name: string;
|
|
5
6
|
onClick: () => void;
|
|
@@ -15,6 +16,8 @@ export interface AppLayoutProps {
|
|
|
15
16
|
children: ReactNode;
|
|
16
17
|
/** Navigation menu items */
|
|
17
18
|
menu: SideMenuItemProps[];
|
|
19
|
+
/**User profile parameters */
|
|
20
|
+
userProfileParams: UserProfilePopupProps;
|
|
18
21
|
/** AppBar customization - Primary approach */
|
|
19
22
|
rightSection?: ReactNode;
|
|
20
23
|
/** AppBar center section customization */
|
|
@@ -23,4 +26,8 @@ export interface AppLayoutProps {
|
|
|
23
26
|
mainContainerSx?: any;
|
|
24
27
|
/** Help documentation configuration for route-based contextual help */
|
|
25
28
|
helpDocsConfig?: HelpDocsConfig;
|
|
29
|
+
/**
|
|
30
|
+
* Initial collapsed state for persistent sidebar
|
|
31
|
+
*/
|
|
32
|
+
initialCollapsed?: boolean;
|
|
26
33
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -956,6 +956,48 @@ interface SubMenuData {
|
|
|
956
956
|
permissionKey?: string;
|
|
957
957
|
}
|
|
958
958
|
|
|
959
|
+
interface UserProfilePopupProps {
|
|
960
|
+
/** User's full name */
|
|
961
|
+
userFullName: string;
|
|
962
|
+
/** User's designation/role */
|
|
963
|
+
designation?: string;
|
|
964
|
+
/** Profile dropdown actions (custom menu items) */
|
|
965
|
+
profileActions?: react__default.ReactNode[];
|
|
966
|
+
/** Logout click handler */
|
|
967
|
+
onLogout?: () => void;
|
|
968
|
+
/** Profile image URL */
|
|
969
|
+
profileUrl?: string;
|
|
970
|
+
/** Custom styles for the avatar */
|
|
971
|
+
avatarSx?: any;
|
|
972
|
+
/** Whether to show active devices option */
|
|
973
|
+
showActiveDevices?: boolean;
|
|
974
|
+
/** Active devices click handler */
|
|
975
|
+
onActiveDevicesClick?: () => void;
|
|
976
|
+
/** Account section click handler */
|
|
977
|
+
onAccountClick?: () => void;
|
|
978
|
+
/**Persistant Side bar collapsed - boolean */
|
|
979
|
+
collapsed?: boolean;
|
|
980
|
+
}
|
|
981
|
+
/**
|
|
982
|
+
* Independent User Profile popup component for AppLayout right section
|
|
983
|
+
* No longer depends on UserBox - contains its own implementation
|
|
984
|
+
* Provides clean, flexible props interface
|
|
985
|
+
*
|
|
986
|
+
* @example
|
|
987
|
+
* <UserProfilePopup
|
|
988
|
+
* userFullName="John Doe"
|
|
989
|
+
* designation="Administrator"
|
|
990
|
+
* profileActions={[
|
|
991
|
+
* <SwitchInstitutionPopup key="switch" />,
|
|
992
|
+
* <DropdownMenuItem key="settings" label="Settings" onClick={() => {}} />
|
|
993
|
+
* ]}
|
|
994
|
+
* onLogout={handleLogout}
|
|
995
|
+
* showActiveDevices={true}
|
|
996
|
+
* onActiveDevicesClick={() => console.log('Active devices')}
|
|
997
|
+
* />
|
|
998
|
+
*/
|
|
999
|
+
declare const UserProfilePopup: react__default.FC<UserProfilePopupProps>;
|
|
1000
|
+
|
|
959
1001
|
interface HelpDocsAction {
|
|
960
1002
|
name: string;
|
|
961
1003
|
onClick: () => void;
|
|
@@ -971,6 +1013,8 @@ interface AppLayoutProps {
|
|
|
971
1013
|
children: ReactNode;
|
|
972
1014
|
/** Navigation menu items */
|
|
973
1015
|
menu: SideMenuItemProps$1[];
|
|
1016
|
+
/**User profile parameters */
|
|
1017
|
+
userProfileParams: UserProfilePopupProps;
|
|
974
1018
|
/** AppBar customization - Primary approach */
|
|
975
1019
|
rightSection?: ReactNode;
|
|
976
1020
|
/** AppBar center section customization */
|
|
@@ -979,6 +1023,10 @@ interface AppLayoutProps {
|
|
|
979
1023
|
mainContainerSx?: any;
|
|
980
1024
|
/** Help documentation configuration for route-based contextual help */
|
|
981
1025
|
helpDocsConfig?: HelpDocsConfig;
|
|
1026
|
+
/**
|
|
1027
|
+
* Initial collapsed state for persistent sidebar
|
|
1028
|
+
*/
|
|
1029
|
+
initialCollapsed?: boolean;
|
|
982
1030
|
}
|
|
983
1031
|
|
|
984
1032
|
declare const AppLayout: react__default.FC<AppLayoutProps>;
|
|
@@ -1046,46 +1094,6 @@ interface SwitchInstitutionPopupProps {
|
|
|
1046
1094
|
*/
|
|
1047
1095
|
declare const SwitchInstitutionPopup: react__default.FC<SwitchInstitutionPopupProps>;
|
|
1048
1096
|
|
|
1049
|
-
interface UserProfilePopupProps {
|
|
1050
|
-
/** User's full name */
|
|
1051
|
-
userFullName: string;
|
|
1052
|
-
/** User's designation/role */
|
|
1053
|
-
designation?: string;
|
|
1054
|
-
/** Profile dropdown actions (custom menu items) */
|
|
1055
|
-
profileActions?: react__default.ReactNode[];
|
|
1056
|
-
/** Logout click handler */
|
|
1057
|
-
onLogout?: () => void;
|
|
1058
|
-
/** Profile image URL */
|
|
1059
|
-
profileUrl?: string;
|
|
1060
|
-
/** Custom styles for the avatar */
|
|
1061
|
-
avatarSx?: any;
|
|
1062
|
-
/** Whether to show active devices option */
|
|
1063
|
-
showActiveDevices?: boolean;
|
|
1064
|
-
/** Active devices click handler */
|
|
1065
|
-
onActiveDevicesClick?: () => void;
|
|
1066
|
-
/** Account section click handler */
|
|
1067
|
-
onAccountClick?: () => void;
|
|
1068
|
-
}
|
|
1069
|
-
/**
|
|
1070
|
-
* Independent User Profile popup component for AppLayout right section
|
|
1071
|
-
* No longer depends on UserBox - contains its own implementation
|
|
1072
|
-
* Provides clean, flexible props interface
|
|
1073
|
-
*
|
|
1074
|
-
* @example
|
|
1075
|
-
* <UserProfilePopup
|
|
1076
|
-
* userFullName="John Doe"
|
|
1077
|
-
* designation="Administrator"
|
|
1078
|
-
* profileActions={[
|
|
1079
|
-
* <SwitchInstitutionPopup key="switch" />,
|
|
1080
|
-
* <DropdownMenuItem key="settings" label="Settings" onClick={() => {}} />
|
|
1081
|
-
* ]}
|
|
1082
|
-
* onLogout={handleLogout}
|
|
1083
|
-
* showActiveDevices={true}
|
|
1084
|
-
* onActiveDevicesClick={() => console.log('Active devices')}
|
|
1085
|
-
* />
|
|
1086
|
-
*/
|
|
1087
|
-
declare const UserProfilePopup: react__default.FC<UserProfilePopupProps>;
|
|
1088
|
-
|
|
1089
1097
|
type AppHeaderProps = {
|
|
1090
1098
|
actions?: ReactNode[];
|
|
1091
1099
|
profileActions?: ReactNode[];
|
package/package.json
CHANGED
package/src/App.tsx
CHANGED
|
@@ -6,13 +6,8 @@ import {
|
|
|
6
6
|
} from 'react-router-dom';
|
|
7
7
|
import './App.css';
|
|
8
8
|
|
|
9
|
-
import { Stack } from '@mui/material';
|
|
10
9
|
import { Icons } from './components/export';
|
|
11
|
-
import {
|
|
12
|
-
AppLayout,
|
|
13
|
-
SwitchInstitutionPopup,
|
|
14
|
-
UserProfilePopup,
|
|
15
|
-
} from './components/Layout/AppLayout';
|
|
10
|
+
import { AppLayout } from './components/Layout/AppLayout';
|
|
16
11
|
|
|
17
12
|
// Sample Pages
|
|
18
13
|
import { Dashboard } from './pages/Dashboard';
|
|
@@ -269,39 +264,16 @@ function App() {
|
|
|
269
264
|
// In a real app, you would handle logout logic here
|
|
270
265
|
};
|
|
271
266
|
|
|
267
|
+
const userProfileParams = {
|
|
268
|
+
userFullName: 'User',
|
|
269
|
+
designation: 'Admin',
|
|
270
|
+
onLogout: () => {},
|
|
271
|
+
onAccountClick: () => {},
|
|
272
|
+
profileActions: [],
|
|
273
|
+
};
|
|
272
274
|
return (
|
|
273
275
|
<Router>
|
|
274
|
-
<AppLayout
|
|
275
|
-
menu={sampleMenu}
|
|
276
|
-
rightSection={
|
|
277
|
-
<Stack direction="row" alignItems="center" gap={1}>
|
|
278
|
-
<Icons.AdminIcon size={24} />
|
|
279
|
-
<UserProfilePopup
|
|
280
|
-
userFullName="John Doe"
|
|
281
|
-
designation="Administrator"
|
|
282
|
-
onLogout={handleLogout}
|
|
283
|
-
showActiveDevices={true}
|
|
284
|
-
profileActions={[
|
|
285
|
-
<SwitchInstitutionPopup
|
|
286
|
-
key="switch-institution"
|
|
287
|
-
institutionsData={[
|
|
288
|
-
{
|
|
289
|
-
name: 'Demo University',
|
|
290
|
-
code: 'demo',
|
|
291
|
-
imageSquare: { url: '' },
|
|
292
|
-
},
|
|
293
|
-
{
|
|
294
|
-
name: 'Test College',
|
|
295
|
-
code: 'test',
|
|
296
|
-
imageSquare: { url: '' },
|
|
297
|
-
},
|
|
298
|
-
]}
|
|
299
|
-
/>,
|
|
300
|
-
]}
|
|
301
|
-
/>
|
|
302
|
-
</Stack>
|
|
303
|
-
}
|
|
304
|
-
>
|
|
276
|
+
<AppLayout menu={sampleMenu} userProfileParams={userProfileParams}>
|
|
305
277
|
<Routes>
|
|
306
278
|
<Route path="/" element={<Navigate to="/dashboard" replace />} />
|
|
307
279
|
<Route path="/dashboard" element={<Dashboard />} />
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { Box, Stack, styled, useTheme } from '@mui/material';
|
|
2
|
-
import
|
|
1
|
+
import { Box, Stack, styled, useMediaQuery, useTheme } from '@mui/material';
|
|
2
|
+
import { motion } from 'framer-motion';
|
|
3
|
+
import React, { useState } from 'react';
|
|
3
4
|
import { AppBar } from './components/AppBar';
|
|
4
5
|
import { FloatingHelpDocs } from './components/FloatingHelpDocs';
|
|
6
|
+
import { PersistentSidebar } from './components/PersistentSidebar';
|
|
5
7
|
import { AppLayoutProps } from './types';
|
|
6
8
|
|
|
7
9
|
export const AppLayout: React.FC<AppLayoutProps> = ({
|
|
@@ -11,8 +13,14 @@ export const AppLayout: React.FC<AppLayoutProps> = ({
|
|
|
11
13
|
centerSection,
|
|
12
14
|
mainContainerSx = {},
|
|
13
15
|
helpDocsConfig,
|
|
16
|
+
initialCollapsed,
|
|
17
|
+
userProfileParams,
|
|
14
18
|
}) => {
|
|
15
19
|
const theme = useTheme();
|
|
20
|
+
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
|
21
|
+
|
|
22
|
+
// State for persistent sidebar
|
|
23
|
+
const [collapsed, setCollapsed] = useState(isSmallScreen ?? initialCollapsed);
|
|
16
24
|
|
|
17
25
|
// Get help docs actions for current route
|
|
18
26
|
const getCurrentRouteHelpActions = () => {
|
|
@@ -28,41 +36,74 @@ export const AppLayout: React.FC<AppLayoutProps> = ({
|
|
|
28
36
|
|
|
29
37
|
const helpDocsActions = getCurrentRouteHelpActions();
|
|
30
38
|
|
|
39
|
+
const toggleSidebar = () => {
|
|
40
|
+
setCollapsed(!collapsed);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// Calculate main content width for persistent sidebar
|
|
44
|
+
const getMainWidth = () => {
|
|
45
|
+
if (isSmallScreen) return '100%';
|
|
46
|
+
return collapsed ? 'calc(100% - 64px)' : 'calc(100% - 250px)';
|
|
47
|
+
};
|
|
48
|
+
|
|
31
49
|
return (
|
|
32
50
|
<AppLayoutContainer>
|
|
33
|
-
{/*
|
|
34
|
-
<
|
|
35
|
-
rightSection={rightSection}
|
|
36
|
-
centerSection={centerSection}
|
|
51
|
+
{/* Persistent Sidebar */}
|
|
52
|
+
<PersistentSidebar
|
|
37
53
|
menu={menu}
|
|
54
|
+
collapsed={collapsed}
|
|
55
|
+
onToggle={toggleSidebar}
|
|
56
|
+
userProfileParams={userProfileParams}
|
|
38
57
|
/>
|
|
39
58
|
|
|
40
|
-
{/* Main Content
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
59
|
+
{/* Main Content Area with dynamic width */}
|
|
60
|
+
<motion.div
|
|
61
|
+
animate={{
|
|
62
|
+
width: getMainWidth(),
|
|
63
|
+
}}
|
|
64
|
+
transition={{ duration: 0.3, ease: [0.32, 0.72, 0, 1] }}
|
|
65
|
+
style={{
|
|
66
|
+
flexDirection: 'column',
|
|
67
|
+
height: '100vh',
|
|
68
|
+
overflow: 'hidden',
|
|
44
69
|
}}
|
|
45
70
|
>
|
|
46
|
-
{
|
|
47
|
-
|
|
71
|
+
{/* AppBar - Top of main content area */}
|
|
72
|
+
<AppBar
|
|
73
|
+
rightSection={rightSection}
|
|
74
|
+
centerSection={centerSection}
|
|
75
|
+
hideHamburger={!isSmallScreen}
|
|
76
|
+
onToggleSidebar={toggleSidebar}
|
|
77
|
+
/>
|
|
48
78
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
79
|
+
{/* Main Content */}
|
|
80
|
+
<MainContent
|
|
81
|
+
sx={{
|
|
82
|
+
...mainContainerSx,
|
|
83
|
+
height: `calc(100vh - 90px)`,
|
|
84
|
+
overflow: 'scroll',
|
|
85
|
+
}}
|
|
86
|
+
>
|
|
87
|
+
{children}
|
|
88
|
+
</MainContent>
|
|
89
|
+
|
|
90
|
+
{/* Floating Help Docs - Route-aware contextual help */}
|
|
91
|
+
{helpDocsActions.length > 0 && (
|
|
92
|
+
<FloatingHelpDocs actions={helpDocsActions} />
|
|
93
|
+
)}
|
|
94
|
+
</motion.div>
|
|
53
95
|
</AppLayoutContainer>
|
|
54
96
|
);
|
|
55
97
|
};
|
|
56
98
|
|
|
57
99
|
const AppLayoutContainer = styled(Stack)(({ theme }: { theme?: any }) => ({
|
|
58
|
-
flexDirection: '
|
|
59
|
-
backgroundColor: theme.palette.surface.
|
|
100
|
+
flexDirection: 'row',
|
|
101
|
+
backgroundColor: theme.palette.surface.paperBackground,
|
|
60
102
|
height: '100vh',
|
|
61
|
-
overflow: '
|
|
103
|
+
overflow: 'hidden',
|
|
62
104
|
}));
|
|
63
105
|
|
|
64
106
|
const MainContent = styled(Box)(({ theme }: { theme?: any }) => ({
|
|
65
|
-
borderRadius: '8px',
|
|
66
107
|
flex: 1,
|
|
67
108
|
maxWidth: '1440px', // Max width for content
|
|
68
109
|
width: '100%',
|
|
@@ -1,16 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
Stack,
|
|
4
|
-
styled,
|
|
5
|
-
useMediaQuery,
|
|
6
|
-
useTheme,
|
|
7
|
-
} from '@mui/material';
|
|
8
|
-
import React, { useState } from 'react';
|
|
9
|
-
import { CampxFullLogoIconV2 } from '../../../Assets/Icons/IconComponents/CampxFullLogoIconV2';
|
|
1
|
+
import { IconButton, Stack, styled, useTheme } from '@mui/material';
|
|
2
|
+
import React from 'react';
|
|
10
3
|
import { CampxIconV2 } from '../../../Assets/Icons/IconComponents/CampxIconV2';
|
|
11
4
|
import { HamburgerMenuIcon } from '../../../Assets/Icons/IconComponents/HamburgerMenuIcon';
|
|
12
|
-
import { SideDrawer } from './SideDrawer';
|
|
13
|
-
import { SideMenuItemProps } from './Sidebar/interfaces';
|
|
14
5
|
|
|
15
6
|
const AppBarContainer = styled('header')(({ theme }: { theme?: any }) => ({
|
|
16
7
|
display: 'flex',
|
|
@@ -19,12 +10,12 @@ const AppBarContainer = styled('header')(({ theme }: { theme?: any }) => ({
|
|
|
19
10
|
justifyContent: 'space-between',
|
|
20
11
|
position: 'relative', // Add relative positioning for absolute center positioning
|
|
21
12
|
width: '100%',
|
|
22
|
-
height: '
|
|
23
|
-
minHeight: '
|
|
13
|
+
height: '54px',
|
|
14
|
+
minHeight: '54px',
|
|
24
15
|
backgroundColor: theme.palette.surface.paperBackground,
|
|
25
16
|
padding: '0 24px 0 0',
|
|
26
17
|
flexShrink: 0, // Prevent AppBar from shrinking
|
|
27
|
-
|
|
18
|
+
borderBottom: `1px solid ${theme.palette.divider}`,
|
|
28
19
|
[theme.breakpoints.down('md')]: {
|
|
29
20
|
height: '54px',
|
|
30
21
|
minHeight: '54px',
|
|
@@ -43,49 +34,51 @@ interface AppBarProps {
|
|
|
43
34
|
rightSection?: React.ReactNode;
|
|
44
35
|
/** Center section component (workspace switcher, etc.) */
|
|
45
36
|
centerSection?: React.ReactNode;
|
|
46
|
-
/** Menu items for mobile drawer */
|
|
47
|
-
menu?: SideMenuItemProps[];
|
|
48
37
|
/** Custom className for the AppBar */
|
|
49
38
|
className?: string;
|
|
50
39
|
/** Custom styles for the AppBar */
|
|
51
40
|
sx?: any;
|
|
41
|
+
/** Hide hamburger menu (for persistent sidebar mode) */
|
|
42
|
+
hideHamburger?: boolean;
|
|
43
|
+
/** Callback to toggle sidebar (for persistent sidebar mode on mobile) */
|
|
44
|
+
onToggleSidebar?: () => void;
|
|
52
45
|
}
|
|
53
46
|
|
|
54
47
|
export const AppBar: React.FC<AppBarProps> = ({
|
|
55
48
|
rightSection,
|
|
56
49
|
centerSection,
|
|
57
|
-
menu = [],
|
|
58
50
|
className = 'appHeaderV2',
|
|
59
51
|
sx = {},
|
|
52
|
+
hideHamburger = false,
|
|
53
|
+
onToggleSidebar = () => {},
|
|
60
54
|
}) => {
|
|
61
55
|
const theme = useTheme();
|
|
62
|
-
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
|
63
|
-
const [drawerOpen, setDrawerOpen] = useState(false);
|
|
64
|
-
|
|
65
|
-
const toggleDrawer = () => {
|
|
66
|
-
setDrawerOpen(!drawerOpen);
|
|
67
|
-
};
|
|
68
56
|
|
|
69
57
|
return (
|
|
70
|
-
<AppBarContainer
|
|
71
|
-
{
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
58
|
+
<AppBarContainer
|
|
59
|
+
className={className}
|
|
60
|
+
sx={{
|
|
61
|
+
...sx,
|
|
62
|
+
justifyContent: hideHamburger ? 'flex-end' : 'space-between',
|
|
63
|
+
}}
|
|
64
|
+
>
|
|
65
|
+
{/* Left section - Hamburger + Logo (only show if not hidden) */}
|
|
66
|
+
{!hideHamburger && (
|
|
67
|
+
<Stack gap={'4px'} direction={'row'} alignItems={'center'}>
|
|
68
|
+
<IconButton
|
|
69
|
+
onClick={onToggleSidebar}
|
|
70
|
+
sx={{
|
|
71
|
+
padding: '24px',
|
|
72
|
+
[theme.breakpoints.down('md')]: {
|
|
73
|
+
padding: '20px',
|
|
74
|
+
},
|
|
75
|
+
}}
|
|
76
|
+
>
|
|
77
|
+
<HamburgerMenuIcon />
|
|
78
|
+
</IconButton>
|
|
79
|
+
<CampxIconV2 />
|
|
80
|
+
</Stack>
|
|
81
|
+
)}
|
|
89
82
|
|
|
90
83
|
{/* Center section - Custom content from props */}
|
|
91
84
|
{centerSection && (
|
|
@@ -115,13 +108,6 @@ export const AppBar: React.FC<AppBarProps> = ({
|
|
|
115
108
|
{rightSection}
|
|
116
109
|
</Stack>
|
|
117
110
|
)}
|
|
118
|
-
|
|
119
|
-
{/* Side Drawer */}
|
|
120
|
-
<SideDrawer
|
|
121
|
-
open={drawerOpen}
|
|
122
|
-
onClose={() => setDrawerOpen(false)}
|
|
123
|
-
menu={menu}
|
|
124
|
-
/>
|
|
125
111
|
</AppBarContainer>
|
|
126
112
|
);
|
|
127
113
|
};
|