Skip to content

Commit

Permalink
feat: added expandable dropdown in side bar
Browse files Browse the repository at this point in the history
  • Loading branch information
snehasharma1111 committed Jan 3, 2025
1 parent 617f743 commit 6f015a0
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 29 deletions.
90 changes: 71 additions & 19 deletions components/Side/index.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,85 @@
import { useStore } from "@/hooks";
import { MaterialIcon, Typography } from "@/library";
import { Navigation } from "@/types";
import { stylesConfig } from "@/utils";
import Link from "next/link";
import { useRouter } from "next/router";
import React from "react";
import React, { useState } from "react";
import styles from "./styles.module.scss";

interface ISideBarProps {}

const classes = stylesConfig(styles, "side-bar");

const SideBar: React.FC<ISideBarProps> = () => {
const SideBarItem: React.FC<Navigation> = ({ title, icon, route, options }) => {
const router = useRouter();
const { isSidebarExpanded } = useStore();
const [expanded, setExpanded] = useState(false);

return (
<>
<li className={classes("-list__item")}>
<Link
href={route}
className={classes("-link", {
"-link--active": route === router.pathname,
})}
>
{isSidebarExpanded && options && options.length > 0 ? (
<button
onClick={(e: any) => {
e.preventDefault();
e.stopPropagation();
setExpanded((p) => !p);
}}
className={classes("-list__arrow", {
"-list__arrow--expanded": expanded,
})}
>
<MaterialIcon icon="arrow_right" />
</button>
) : null}
<MaterialIcon
className={classes("-link__icon")}
icon={icon}
/>
<Typography className={classes("-link__title")} size="md">
{title}
</Typography>
</Link>
</li>
{isSidebarExpanded && expanded && options && options.length > 0 ? (
<ul className={classes("-list", "-sub-list")}>
{options.map((option, index) => (
<li
className={classes(
"-list__item",
"-sub-list__item"
)}
key={index}
>
<Link
href={option.route}
className={classes("-link", "-sub-list__link", {
"-link--active":
option.route === router.asPath,
})}
>
<MaterialIcon
className={classes("-link__icon")}
icon={option.icon}
/>
{option.title}
</Link>
</li>
))}
</ul>
) : null}
</>
);
};

const SideBar: React.FC<ISideBarProps> = () => {
const { closeSideBar, sideBarLinks, isSidebarExpanded } = useStore();
return (
<>
Expand All @@ -24,23 +92,7 @@ const SideBar: React.FC<ISideBarProps> = () => {
<nav className={classes("-nav")}>
<ul className={classes("-list")}>
{sideBarLinks.map((item, index) => (
<li className={classes("-list__item")} key={index}>
<Link
href={item.route}
className={classes("-link", {
"-link--active":
item.route === router.pathname,
})}
>
<MaterialIcon icon={item.icon} />
<Typography
className={classes("-link__title")}
size="md"
>
{item.title}
</Typography>
</Link>
</li>
<SideBarItem key={index} {...item} />
))}
</ul>
</nav>
Expand Down
24 changes: 23 additions & 1 deletion components/Side/styles.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
}

&-list {
width: 100%;
display: flex;
flex-flow: column;
justify-content: flex-start;
Expand All @@ -47,7 +48,27 @@
display: flex;
justify-content: center;
align-items: center;
position: relative;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

&__arrow {
@include init-button;
position: absolute;
font-size: 1rem;
transform: translateX(-40%);

&--expanded {
transform: translateX(-40%) rotate(90deg);
}
}
}

&-sub-list {
width: 95%;
margin-left: 5%;
}

&-link {
Expand All @@ -61,6 +82,7 @@
color: inherit;
text-decoration: none;
cursor: pointer;
overflow: hidden;

&:hover,
&:active,
Expand Down Expand Up @@ -93,7 +115,7 @@
align-items: center;
}

span:first-child {
&__icon {
width: 1.5rem;
height: 1.5rem;
margin: 0.25rem 0.5rem;
Expand Down
21 changes: 16 additions & 5 deletions constants/navigation.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Navigation } from "@/types";
import { IGroup, Navigation } from "@/types";
import { routes } from "./routes";

const loggedOutSideBarLinks: Array<Navigation> = [
Expand Down Expand Up @@ -34,11 +34,16 @@ const loggedOutSideBarLinks: Array<Navigation> = [
},
];

const loggedInSideBarLinks: Array<Navigation> = [
const loggedInSideBarLinks = (groups: Array<IGroup>): Array<Navigation> => [
{
title: "My Groups",
icon: "group",
icon: "groups",
route: routes.HOME,
options: groups.map((group) => ({
title: group.name,
icon: "group",
route: routes.GROUP(group.id),
})),
},
{
title: "Your Profile",
Expand Down Expand Up @@ -67,5 +72,11 @@ const loggedInSideBarLinks: Array<Navigation> = [
},
];

export const getSideBarLinks = (loggedIn: boolean) =>
loggedIn ? loggedInSideBarLinks : loggedOutSideBarLinks;
export const getSideBarLinks = ({
loggedIn,
groups,
}: {
loggedIn: boolean;
groups?: Array<IGroup>;
}) =>
loggedIn && groups ? loggedInSideBarLinks(groups) : loggedOutSideBarLinks;
2 changes: 1 addition & 1 deletion context/slices/ui.slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const initialState: UiSlice = {
networkStatus: "online",
isLoggedIn: false,
isSyncing: false,
sideBarLinks: getSideBarLinks(false),
sideBarLinks: getSideBarLinks({ loggedIn: false }),
};

export const uiSlice = createSlice({
Expand Down
19 changes: 18 additions & 1 deletion hooks/store.hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from "@/context/slices";
import { AppTheme, IUser } from "@/types";
import { hexToRgb, notify } from "@/utils";
import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";

export const useStore = () => {
Expand Down Expand Up @@ -52,7 +53,6 @@ export const useStore = () => {
const syncUserState = (user: IUser) => {
dispatch(userSlice.actions.setUser(user));
dispatch(uiSlice.actions.setIsLoggedIn(true));
dispatch(uiSlice.actions.setSideBarLinks(getSideBarLinks(true)));
};

const syncEverything = async () => {
Expand Down Expand Up @@ -91,6 +91,23 @@ export const useStore = () => {
}
};

useEffect(() => {
if (user) {
dispatch(
uiSlice.actions.setSideBarLinks(
getSideBarLinks({ loggedIn: true, groups })
)
);
} else {
dispatch(
uiSlice.actions.setSideBarLinks(
getSideBarLinks({ loggedIn: false })
)
);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [groups, user]);

return {
// dispatch takes an action object and sends it to the store
dispatch,
Expand Down
3 changes: 2 additions & 1 deletion library/icons/material.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ type MaterialIconProps = React.HTMLAttributes<HTMLSpanElement> &

export const MaterialIcon: React.FC<MaterialIconProps> = ({
icon,
className,
...rest
}) => (
<span className="material-symbols-outlined" {...rest}>
<span className={`material-symbols-outlined ${className}`} {...rest}>
{icon}
</span>
);
2 changes: 1 addition & 1 deletion pages/group/[id]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ const GroupPage: React.FC<GroupPageProps> = (props) => {
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
}, [props.group.id]);

if (!props.group)
return <PageNotFound description={(props as any).error} />;
Expand Down
1 change: 1 addition & 0 deletions types/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ export type Navigation = {
title: string;
icon: string;
route: string;
options?: Array<Omit<Navigation, "options">>;
};

0 comments on commit 6f015a0

Please sign in to comment.