@campxdev/react-blueprint 0.1.14 → 0.1.16

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.
Files changed (63) hide show
  1. package/.storybook/preview.tsx +3 -3
  2. package/package.json +15 -14
  3. package/src/components/DataDisplay/DataTable/DataTable.stories.tsx +34 -17
  4. package/src/components/DataDisplay/DataTable/DataTable.tsx +32 -7
  5. package/src/components/DataDisplay/DataTable/TablePagination.tsx +60 -6
  6. package/src/components/DataDisplay/styles.tsx +2 -0
  7. package/src/components/DropDownMenu/DropDownButton.tsx +3 -25
  8. package/src/components/DropDownMenu/DropDownMenu.stories.tsx +34 -31
  9. package/src/components/DropDownMenu/DropDownMenu.tsx +4 -4
  10. package/src/components/DropDownMenu/DropdownMenuItem.tsx +25 -0
  11. package/src/components/DropDownMenu/styles.tsx +1 -7
  12. package/src/components/Icons/IconComponents/AppsIcon.tsx +36 -0
  13. package/src/components/Icons/IconComponents/CareerIcon.tsx +24 -0
  14. package/src/components/Icons/IconComponents/ClogWheelIcon.tsx +38 -0
  15. package/src/components/Icons/IconComponents/DashBoardIcon.tsx +65 -0
  16. package/src/components/Icons/IconComponents/ExamResultIcon.tsx +26 -0
  17. package/src/components/Icons/IconComponents/HelpIcon.tsx +57 -0
  18. package/src/components/Icons/IconComponents/HomeIcon.tsx +52 -0
  19. package/src/components/Icons/IconComponents/LeftIcon.tsx +72 -0
  20. package/src/components/Icons/IconComponents/LogoutIcon.tsx +66 -0
  21. package/src/components/Icons/IconComponents/NotificationIcon.tsx +29 -0
  22. package/src/components/Icons/IconComponents/RightIcon.tsx +65 -0
  23. package/src/components/Icons/IconComponents/TicketsIcon.tsx +74 -0
  24. package/src/components/Icons/Icons.stories.tsx +21 -0
  25. package/src/components/Icons/Icons.tsx +14 -0
  26. package/src/components/Icons/export.ts +26 -0
  27. package/src/components/Input/Button/Button.tsx +10 -8
  28. package/src/components/Input/LabelWrapper/LabelWrapper.tsx +35 -0
  29. package/src/components/Input/SingleSelect/SingleSelect.stories.tsx +85 -36
  30. package/src/components/Input/SingleSelect/SingleSelect.tsx +17 -69
  31. package/src/components/Input/TextField/TextField.tsx +9 -5
  32. package/src/components/Input/components/FetchingOptionsLoader.tsx +16 -4
  33. package/src/components/Input/styles.tsx +9 -1
  34. package/src/components/Layout/Header/AppHeader.stories.tsx +5 -5
  35. package/src/components/Layout/Header/AppsMenu.tsx +2 -2
  36. package/src/components/Layout/Header/HeaderActions/CogWheelMenu.tsx +4 -4
  37. package/src/components/Layout/Header/HeaderActions/HeaderActions.tsx +2 -2
  38. package/src/components/Layout/Header/HeaderActions/UserBox.tsx +33 -18
  39. package/src/components/Layout/LayoutWrapper/LayoutWrapper.stories.tsx +55 -37
  40. package/src/components/Layout/LayoutWrapper/LayoutWrapper.tsx +49 -68
  41. package/src/components/Layout/LayoutWrapper/styles.tsx +52 -0
  42. package/src/components/Layout/PageContent/PageContent.stories.tsx +26 -0
  43. package/src/components/Layout/PageContent/PageContent.tsx +32 -0
  44. package/src/components/Layout/SideNavigation/SideNavigation.stories.tsx +57 -0
  45. package/src/components/Layout/SideNavigation/SideNavigation.tsx +29 -23
  46. package/src/components/Layout/SideNavigation/styles/styles.tsx +7 -59
  47. package/src/components/Layout/Spinner/Spinner.css +1 -1
  48. package/src/components/Layout/Spinner/Spinner.stories.tsx +1 -1
  49. package/src/components/Layout/Spinner/Spinner.tsx +1 -1
  50. package/src/components/Modals/DialogButton.tsx +1 -1
  51. package/src/components/TabsContainer/TabsContainer.stories.tsx +48 -0
  52. package/src/components/TabsContainer/TabsContainer.tsx +58 -0
  53. package/src/components/export.ts +3 -0
  54. package/src/store/activeStore.ts +1 -0
  55. package/src/themes/commonTheme.ts +60 -19
  56. package/src/themes/darkTheme.ts +2 -3
  57. package/src/themes/lightTheme.ts +2 -3
  58. package/src/utils/campxAxios.ts +1 -1
  59. package/tsconfig.json +1 -3
  60. package/types/theme.d.ts +38 -0
  61. package/src/assets/images/icons.tsx +0 -427
  62. package/src/components/DropDownMenu/MenuItemButton.tsx +0 -24
  63. package/src/components/Input/Label/Label.tsx +0 -11
@@ -1,91 +1,72 @@
1
- import { Box, IconButton, Stack, Toolbar, Typography } from "@mui/material";
1
+ import { Box, IconButton, Stack, Typography } from "@mui/material";
2
2
 
3
3
  import MenuIcon from "@mui/icons-material/Menu";
4
- import { useState } from "react";
5
- import { LeftIcon, RightIcon } from "../../../assets/images/icons";
4
+ import { ReactNode, useState } from "react";
6
5
  import { activeStore } from "../../../store/activeStore";
7
- import { SideNavigation } from "../SideNavigation/SideNavigation";
8
- import {
9
- StyledLayoutContainer,
10
- StyledMainContainer,
11
- } from "../SideNavigation/styles/styles";
6
+ import { Icons } from "../../export";
7
+ import { Main, StyledLayoutContainer, StyledMainContainer } from "./styles";
12
8
 
13
9
  export interface LayoutWrapperProps {
14
10
  title?: string;
15
- actionButtons?: React.ReactNode[];
16
- children: React.ReactNode;
17
- showIcon?: boolean;
18
- menu?: any;
11
+ actionButtons?: ReactNode[];
12
+ children: ReactNode;
13
+ sideBar: (props: {
14
+ open: boolean;
15
+ handleClick: (e: any) => void;
16
+ }) => ReactNode;
19
17
  }
18
+
20
19
  export const LayoutWrapper = ({
21
20
  children,
22
21
  title,
23
- showIcon = true,
24
- menu,
25
- actionButtons,
22
+ sideBar,
26
23
  }: LayoutWrapperProps) => {
27
- const [open, setOpen] = useState<boolean>(
28
- window.innerWidth > 1024 ? true : false
29
- );
30
24
  const [isHovered, setIsHovered] = useState<boolean>(false);
25
+ const { open } = activeStore.useState((s) => s);
31
26
 
32
- const { active } = activeStore.useState((s) => s);
33
-
34
- const handleDrawer = () => {
35
- setOpen(!open);
27
+ const handleClick = () => {
28
+ activeStore.update((s) => {
29
+ s.open = !open;
30
+ });
36
31
  };
37
32
 
38
33
  return (
39
34
  <StyledLayoutContainer>
40
35
  <StyledMainContainer>
41
- <Toolbar
42
- sx={{
43
- padding: "0px !important",
44
- }}
45
- >
46
- {showIcon && (
47
- <>
48
- <Stack
49
- direction={"row"}
50
- width={"100%"}
51
- justifyContent={"space-between"}
36
+ <Box>
37
+ <Stack
38
+ direction={"row"}
39
+ width={"100%"}
40
+ justifyContent={"space-between"}
41
+ >
42
+ <Stack direction={"row"} alignItems={"center"}>
43
+ <IconButton
44
+ color="inherit"
45
+ aria-label="open drawer"
46
+ onClick={handleClick}
47
+ edge="start"
48
+ sx={{ mr: 0.5, padding: "6px", marginLeft: "0px" }}
49
+ onMouseEnter={() => setIsHovered(true)}
50
+ onMouseLeave={() => setIsHovered(false)}
52
51
  >
53
- <Stack direction={"row"}>
54
- <IconButton
55
- color="inherit"
56
- aria-label="open drawer"
57
- onClick={handleDrawer}
58
- edge="start"
59
- sx={{ mr: 0.5, padding: "6px", marginLeft: "0px" }}
60
- onMouseEnter={() => setIsHovered(true)}
61
- onMouseLeave={() => setIsHovered(false)}
62
- >
63
- {open && isHovered ? (
64
- <LeftIcon />
65
- ) : !open && isHovered ? (
66
- <RightIcon />
67
- ) : (
68
- <MenuIcon />
69
- )}
70
- </IconButton>
71
- <Typography variant="subtitle1" noWrap>
72
- {title ? title : menu[active].name}
73
- </Typography>
74
- </Stack>
75
- <Stack direction={"row"} alignItems={"flex-end"}>
76
- {actionButtons?.map((element) => element)}
77
- </Stack>
78
- </Stack>
79
- </>
80
- )}
81
- </Toolbar>
52
+ {open && isHovered ? (
53
+ <Icons.LeftIcon />
54
+ ) : !open && isHovered ? (
55
+ <Icons.RightIcon />
56
+ ) : (
57
+ <MenuIcon />
58
+ )}
59
+ </IconButton>
60
+ <Typography variant="subtitle1" noWrap>
61
+ {title ? title : ""}
62
+ </Typography>
63
+ </Stack>
64
+ </Stack>
65
+
66
+ {sideBar({ open: open, handleClick: handleClick })}
67
+ </Box>
82
68
 
83
- <SideNavigation
84
- menu={menu}
85
- children={children}
86
- open={open}
87
- handleDrawer={handleDrawer}
88
- />
69
+ <Main open={open}>{children}</Main>
89
70
  </StyledMainContainer>
90
71
  </StyledLayoutContainer>
91
72
  );
@@ -0,0 +1,52 @@
1
+ import { Box, styled } from "@mui/material";
2
+
3
+ const drawerWidth: number = 240;
4
+
5
+ export const Main = styled("main", {
6
+ shouldForwardProp: (prop) => prop !== "open",
7
+ })<{
8
+ open?: boolean;
9
+ }>(({ theme, open }) => ({
10
+ padding: "0px 25px",
11
+ transition: theme.transitions.create("margin", {
12
+ easing: theme.transitions.easing.sharp,
13
+ duration: theme.transitions.duration.leavingScreen,
14
+ }),
15
+ marginLeft: `-${drawerWidth}px`,
16
+ ...(open && {
17
+ transition: theme.transitions.create("margin", {
18
+ easing: theme.transitions.easing.easeOut,
19
+ duration: theme.transitions.duration.enteringScreen,
20
+ }),
21
+ marginLeft: 0,
22
+ }),
23
+ width: "100%",
24
+ overflowY: "auto",
25
+ borderRadius: "5px",
26
+ "&::-webkit-scrollbar": {
27
+ width: "0.4em",
28
+ height: "0.4em",
29
+ },
30
+
31
+ "&::-webkit-scrollbar-thumb": {
32
+ backgroundColor: "rgba(0, 0, 0, 0.2)",
33
+ borderRadius: "3px",
34
+ },
35
+ "@media (max-width: 1024px)": {
36
+ marginLeft: 0,
37
+ },
38
+ }));
39
+
40
+ export const StyledLayoutContainer = styled(Box)(({ theme }) => ({
41
+ width: "100%",
42
+ position: "fixed",
43
+ top: "80px",
44
+ backgroundColor: theme.palette.background.default,
45
+ }));
46
+
47
+ export const StyledMainContainer = styled("main")(() => ({
48
+ width: "90%",
49
+ margin: "auto",
50
+ overflowY: "auto",
51
+ display: "flex",
52
+ }));
@@ -0,0 +1,26 @@
1
+ import { Meta, StoryObj } from "@storybook/react";
2
+ import { PageContent } from "../../export";
3
+
4
+ // Define the default export with Meta type including the component type
5
+ const meta: Meta<typeof PageContent> = {
6
+ title: "Layout/PageContent",
7
+ component: PageContent,
8
+ tags: ["autodocs"],
9
+ argTypes: {
10
+ children: {
11
+ control: "object",
12
+ description: "The content of the component",
13
+ },
14
+ },
15
+ };
16
+
17
+ export default meta;
18
+ type Story = StoryObj<typeof PageContent>;
19
+
20
+ // Primary story
21
+ export const Primary: Story = {
22
+ render: (args: any) => <PageContent {...args} />,
23
+ args: {
24
+ children: <>Tickets</>,
25
+ },
26
+ };
@@ -0,0 +1,32 @@
1
+ import { Box, styled } from "@mui/material";
2
+
3
+ export const StyledContainer = styled(Box)(({ theme }) => ({
4
+ width: "100%",
5
+ height: "calc(100vh - 120px)",
6
+ overflowY: "auto",
7
+ backgroundColor: theme.palette.background.paper,
8
+ borderRadius: "5px",
9
+ "&::-webkit-scrollbar": {
10
+ width: "0.4em",
11
+ height: "0.4em",
12
+ },
13
+ "&::-webkit-scrollbar-thumb": {
14
+ backgroundColor: "rgba(0, 0, 0, 0.2)",
15
+ borderRadius: "3px",
16
+ },
17
+ "@media (max-width: 1024px)": {
18
+ marginLeft: 0,
19
+ },
20
+ padding: "25px",
21
+ marginTop: "10px",
22
+ }));
23
+
24
+ export const PageContent = ({
25
+ children,
26
+ sx,
27
+ }: {
28
+ children: React.ReactNode;
29
+ sx?: any;
30
+ }) => {
31
+ return <StyledContainer sx={sx}> {children}</StyledContainer>;
32
+ };
@@ -0,0 +1,57 @@
1
+ import { Typography } from "@mui/material";
2
+ import { Meta, StoryObj } from "@storybook/react";
3
+ import { Icons } from "../../export";
4
+ import {
5
+ SideNavigation,
6
+ SideNavigationProps,
7
+ } from "../SideNavigation/SideNavigation";
8
+
9
+ // Define the default export with Meta type including the component type
10
+ const meta: Meta<typeof SideNavigation> = {
11
+ title: "Layout/SideNavigation",
12
+ component: SideNavigation,
13
+ tags: ["autodocs"],
14
+ argTypes: {
15
+ menu: {
16
+ control: "object",
17
+ description: "Array of menu item props",
18
+ },
19
+ open: {
20
+ control: "boolean",
21
+ description: "State to control if the drawer is open",
22
+ },
23
+ handleDrawer: {
24
+ control: false,
25
+ description: "Function to handle drawer state",
26
+ type: { name: "function", required: false },
27
+ },
28
+ },
29
+ };
30
+
31
+ export default meta;
32
+ type Story = StoryObj<typeof SideNavigation>;
33
+
34
+ // Primary story
35
+ export const Primary: Story = {
36
+ render: (args: SideNavigationProps) => <SideNavigation {...args} />,
37
+ args: {
38
+ open: true,
39
+ menu: [
40
+ { name: "Tickets", path: "/home", icon: Icons.DashBoardIcon },
41
+ { name: "Item 2", path: "/item2" },
42
+ ],
43
+ },
44
+ };
45
+
46
+ export const WithoutMenu: Story = {
47
+ render: (args: SideNavigationProps) => <SideNavigation {...args} />,
48
+ args: {
49
+ open: true,
50
+ children: (
51
+ <Typography variant="body2">
52
+ Vestibulum blandit viverra conv allis. Pellentesque ligula urna,
53
+ fermentum ut semper in, tincidunt nec dui.
54
+ </Typography>
55
+ ),
56
+ },
57
+ };
@@ -1,61 +1,67 @@
1
1
  import { ListItemIcon, Stack } from "@mui/material";
2
+ import { ReactNode } from "react";
2
3
  import { useMatch, useResolvedPath } from "react-router-dom";
3
- import { HomeIcon } from "../../../assets/images/icons";
4
4
  import { activeStore } from "../../../store/activeStore";
5
5
  import { Typography } from "../../Typography/Typography";
6
+ import { Icons } from "../../export";
6
7
  import {
7
- Main,
8
+ StyledBox,
9
+ StyledContainer,
8
10
  StyledDrawer,
9
11
  StyledLinkButton,
10
- StyledList,
11
12
  StyledListItem,
12
13
  StyledListItemButton,
13
14
  } from "./styles/styles";
14
15
 
15
16
  export interface SideNavigationProps {
16
- menu?: any;
17
- children: React.ReactNode;
17
+ menu?: MenuItemProps[];
18
+ children?: ReactNode;
18
19
  open?: any;
19
20
  handleDrawer?: any;
20
21
  }
21
22
 
22
23
  export interface MenuItemProps {
23
- menuItem: {
24
- name: string;
25
- path: string;
26
- icon: any;
27
- permissionKey: string;
28
- iconType: string;
29
- };
30
- index: number;
24
+ name: string;
25
+ path: string;
26
+ icon?: any;
27
+ permissionKey?: string;
28
+ iconType?: string;
31
29
  }
32
30
 
33
31
  export const SideNavigation = ({
34
32
  menu,
35
- children,
36
33
  open,
37
34
  handleDrawer,
35
+ children,
38
36
  }: SideNavigationProps) => {
39
37
  return (
40
- <Stack gap="20px" direction={"row"}>
38
+ <Stack gap="20px" direction={"row"} marginTop={"10px"}>
41
39
  <StyledDrawer
42
40
  variant={window.innerWidth > 1024 ? "persistent" : "temporary"}
43
41
  anchor="left"
44
42
  open={open}
45
43
  onClose={handleDrawer}
46
44
  >
47
- <StyledList>
48
- {menu?.map((item: any, index: number) => (
49
- <MenuItem menuItem={item} index={index} key={index} />
50
- ))}
51
- </StyledList>
45
+ <StyledBox>
46
+ {menu &&
47
+ menu.length > 0 &&
48
+ menu?.map((item: any, index: number) => (
49
+ <MenuItem menuItem={item} index={index} key={index} />
50
+ ))}
51
+ <StyledContainer>{children}</StyledContainer>
52
+ </StyledBox>
52
53
  </StyledDrawer>
53
- <Main open={open}>{children}</Main>
54
54
  </Stack>
55
55
  );
56
56
  };
57
57
 
58
- const MenuItem = ({ menuItem, index }: MenuItemProps) => {
58
+ const MenuItem = ({
59
+ menuItem,
60
+ index,
61
+ }: {
62
+ menuItem: MenuItemProps;
63
+ index: number;
64
+ }) => {
59
65
  const { path, icon: Icon, name, permissionKey, iconType } = menuItem;
60
66
 
61
67
  let resolved = useResolvedPath(path);
@@ -84,7 +90,7 @@ const MenuItem = ({ menuItem, index }: MenuItemProps) => {
84
90
  marginRight: "8px",
85
91
  }}
86
92
  >
87
- {Icon ? <Icon /> : <HomeIcon />}
93
+ {Icon ? <Icon /> : <Icons.HomeIcon />}
88
94
  </ListItemIcon>
89
95
  <Typography variant="subtitle3">{name}</Typography>
90
96
  </StyledListItemButton>
@@ -1,11 +1,4 @@
1
- import {
2
- Box,
3
- Drawer,
4
- List,
5
- ListItem,
6
- ListItemButton,
7
- styled,
8
- } from "@mui/material";
1
+ import { Box, Drawer, ListItem, ListItemButton, styled } from "@mui/material";
9
2
  import { Link } from "react-router-dom";
10
3
  const drawerWidth: number = 240;
11
4
 
@@ -39,6 +32,11 @@ export const StyledListItem = styled(ListItem)<StyledListItemProps>(
39
32
  borderRadius: "5px",
40
33
  })
41
34
  );
35
+
36
+ export const StyledContainer = styled(Box)(({ theme }) => ({
37
+ width: "auto",
38
+ margin: "5px 10px",
39
+ }));
42
40
  export const StyledListItemButton = styled(ListItemButton)(() => ({
43
41
  alignItems: "center",
44
42
  display: "flex",
@@ -53,57 +51,7 @@ export const StyledLinkButton = styled(Link)({
53
51
  },
54
52
  });
55
53
 
56
- export const Main = styled("main", {
57
- shouldForwardProp: (prop) => prop !== "open",
58
- })<{
59
- open?: boolean;
60
- }>(({ theme, open }) => ({
61
- padding: "25px",
62
- transition: theme.transitions.create("margin", {
63
- easing: theme.transitions.easing.sharp,
64
- duration: theme.transitions.duration.leavingScreen,
65
- }),
66
- marginLeft: `-${drawerWidth}px`,
67
- ...(open && {
68
- transition: theme.transitions.create("margin", {
69
- easing: theme.transitions.easing.easeOut,
70
- duration: theme.transitions.duration.enteringScreen,
71
- }),
72
- marginLeft: 0,
73
- }),
74
- width: "100%",
75
- height: "calc(100vh - 120px)",
76
- overflowY: "auto",
77
- backgroundColor: theme.palette.background.paper,
78
- borderRadius: "5px",
79
- "&::-webkit-scrollbar": {
80
- width: "0.4em",
81
- height: "0.4em",
82
- },
83
-
84
- "&::-webkit-scrollbar-thumb": {
85
- backgroundColor: "rgba(0, 0, 0, 0.2)",
86
- borderRadius: "3px",
87
- },
88
- "@media (max-width: 1024px)": {
89
- marginLeft: 0,
90
- },
91
- }));
92
-
93
- export const StyledMainContainer = styled("main")(() => ({
94
- width: "90%",
95
- margin: "auto",
96
- overflowY: "auto",
97
- }));
98
-
99
- export const StyledLayoutContainer = styled(Box)(({ theme }) => ({
100
- width: "100%",
101
- position: "fixed",
102
- top: "60px",
103
- backgroundColor: theme.palette.background.default,
104
- }));
105
-
106
- export const StyledList = styled(List)(({ theme }) => ({
54
+ export const StyledBox = styled(Box)(({ theme }) => ({
107
55
  backgroundColor: theme.palette.background.paper,
108
56
  height: "calc(100vh - 120px)",
109
57
  paddingTop: "20px",
@@ -4,7 +4,7 @@
4
4
  border-radius: 50%;
5
5
  position: relative;
6
6
  animation: rotate 1s linear infinite;
7
- scale: 0.5;
7
+ scale: 0.4;
8
8
  }
9
9
  .spinner::before , .spinner::after {
10
10
  content: "";
@@ -7,7 +7,7 @@ import { Spinner } from "./Spinner";
7
7
 
8
8
  // Define the default export with Meta type including the component type
9
9
  export default {
10
- title: "Layout/Spinner",
10
+ title: "FeedBack/Spinner",
11
11
  component: Spinner,
12
12
  tags: ["autodocs"],
13
13
  argTypes: {},
@@ -1,5 +1,5 @@
1
1
  import "./Spinner.css";
2
2
 
3
3
  export const Spinner = () => {
4
- return <div className="spinner" style={{}}></div>;
4
+ return <div className="spinner"></div>;
5
5
  };
@@ -13,7 +13,7 @@ import { ReactNode, forwardRef, useState } from "react";
13
13
 
14
14
  const StyledDialogHeader = styled(Box)(({ theme }) => ({
15
15
  height: "60px",
16
- backgroundColor: theme.palette.grey[200],
16
+
17
17
  display: "flex",
18
18
  justifyContent: "space-between",
19
19
  alignItems: "center",
@@ -0,0 +1,48 @@
1
+ import { Box } from "@mui/material";
2
+ import { Meta, StoryObj } from "@storybook/react";
3
+ import { PageContent } from "../Layout/PageContent/PageContent";
4
+ import { TabsContainer, TabsContainerProps } from "./TabsContainer";
5
+
6
+ // Define the default export with Meta type including the component type
7
+ const meta: Meta<typeof TabsContainer> = {
8
+ title: "Navigation/TabsContainer",
9
+ component: TabsContainer,
10
+ tags: ["autodocs"],
11
+ // argTypes: {
12
+ // menu: {
13
+ // control: "object",
14
+ // description: "Menu items to be displayed in the side navigation.",
15
+ // },
16
+ // },
17
+ };
18
+
19
+ export default meta;
20
+ type Story = StoryObj<typeof TabsContainer>;
21
+
22
+ // Primary story
23
+ export const Primary: Story = {
24
+ render: (args: TabsContainerProps) => (
25
+ <PageContent sx={{ padding: "0px" }}>
26
+ <TabsContainer {...args} />{" "}
27
+ </PageContent>
28
+ ),
29
+ args: {
30
+ tabs: [
31
+ {
32
+ key: "1",
33
+ label: "Personal Details",
34
+ component: <Box>First Year</Box>,
35
+ },
36
+ {
37
+ key: "2",
38
+ label: "Overview",
39
+ component: <>Second Year</>,
40
+ },
41
+ {
42
+ key: "3",
43
+ label: "year 3",
44
+ component: <>Third Year</>,
45
+ },
46
+ ],
47
+ },
48
+ };
@@ -0,0 +1,58 @@
1
+ import { Box, Tab, TabProps, Tabs, TabsProps } from "@mui/material";
2
+ import { ChangeEvent, useEffect, useState } from "react";
3
+
4
+ interface CustomTabProps extends Omit<TabProps, "component"> {
5
+ component: React.ReactNode;
6
+ highlight?: boolean;
7
+ key: string | number;
8
+ }
9
+
10
+ export interface TabsContainerProps {
11
+ tabs: CustomTabProps[];
12
+ onTabChange?: (tabKey: string) => void;
13
+ currentTabIndex?: number;
14
+ tabsProps: TabsProps;
15
+ }
16
+
17
+ export const TabsContainer = ({
18
+ tabs,
19
+ onTabChange,
20
+ currentTabIndex = 0,
21
+ tabsProps,
22
+ }: TabsContainerProps) => {
23
+ const [currentTab, setCurrentTab] = useState(tabs[currentTabIndex]?.key);
24
+
25
+ const handleTabsChange = (_event: ChangeEvent<{}>, value: string): void => {
26
+ setCurrentTab(value);
27
+ onTabChange && onTabChange(value);
28
+ };
29
+ useEffect(() => {
30
+ setCurrentTab(tabs[currentTabIndex]?.key);
31
+ }, []);
32
+
33
+ return (
34
+ <>
35
+ <Tabs
36
+ onChange={handleTabsChange}
37
+ value={currentTab}
38
+ variant="scrollable"
39
+ scrollButtons="auto"
40
+ TabIndicatorProps={{
41
+ children: <span className="MuiTabs-indicatorSpan" />,
42
+ }}
43
+ {...tabsProps}
44
+ >
45
+ {tabs.map(({ component, ...tab }) => (
46
+ <Tab
47
+ label={tab.label}
48
+ value={tab?.key}
49
+ icon={tab.highlight ? <span>{"."}</span> : <></>}
50
+ iconPosition="end"
51
+ {...tab}
52
+ />
53
+ ))}
54
+ </Tabs>
55
+ <Box p={2}>{tabs.find((tab) => tab?.key === currentTab)?.component}</Box>
56
+ </>
57
+ );
58
+ };
@@ -1,5 +1,6 @@
1
1
  export * from "./DropDownMenu/DropDownButton";
2
2
  export * from "./DropDownMenu/DropDownMenu";
3
+ export * from "./Icons/export";
3
4
  export * from "./Input/Button/Button";
4
5
  export * from "./Input/SingleSelect/SingleSelect";
5
6
  export * from "./Input/Switch/Switch";
@@ -8,3 +9,5 @@ export * from "./Layout/Header/AppHeader";
8
9
  export * from "./Layout/Header/AppLogo";
9
10
  export * from "./Layout/Header/AppsMenu";
10
11
  export * from "./Layout/LayoutWrapper/LayoutWrapper";
12
+ export * from "./Layout/PageContent/PageContent";
13
+ export * from "./Layout/SideNavigation/SideNavigation";
@@ -2,4 +2,5 @@ import { Store } from "pullstate";
2
2
 
3
3
  export const activeStore = new Store({
4
4
  active: 0,
5
+ open: window.innerWidth > 1024 ? true : false,
5
6
  });