Add sidebar

This commit is contained in:
Philipinho
2023-08-29 00:15:48 +01:00
parent 54a748ced7
commit 5b6dbcc5bb
14 changed files with 275 additions and 11 deletions

View File

@ -0,0 +1,37 @@
import { ReactNode } from 'react';
import {
IconHome,
IconSearch,
IconSettings,
IconFilePlus,
} from '@tabler/icons-react';
export type NavigationMenuType = {
label: string;
path: string;
icon: ReactNode;
isActive?: boolean;
onClick?: React.MouseEventHandler<HTMLAnchorElement | HTMLButtonElement>;
};
export const navigationMenu: NavigationMenuType[] = [
{
label: 'Home',
path: '',
icon: <IconHome size={16} />,
},
{
label: 'Search',
path: '',
icon: <IconSearch size={16} />,
},
{
label: 'Settings',
path: '',
icon: <IconSettings size={16} />,
},
{
label: 'New Page',
path: '',
icon: <IconFilePlus size={16} />,
},
];

View File

@ -0,0 +1,5 @@
import { atomWithWebStorage } from "@/lib/jotai-helper";
import { atom } from "jotai";
export const desktopSidebarAtom = atomWithWebStorage('showSidebar',true);
export const mobileSidebarAtom = atom(false);

View File

@ -0,0 +1,8 @@
import { useAtom } from "jotai";
export function useToggleSidebar(sidebarAtom) {
const [sidebarState, setSidebarState] = useAtom(sidebarAtom);
return () => {
setSidebarState(!sidebarState);
}
}

View File

@ -0,0 +1,15 @@
import React, { ReactNode } from "react";
import { cn } from "@/lib/utils";
interface SidebarSectionProps {
className?: string;
children: ReactNode
}
export function SidebarSection({className, children}: SidebarSectionProps) {
return (
<div className={cn('flex-shrink-0 flex-grow-0 pb-0.5', className)}>
{children}
</div>
)
}

View File

@ -0,0 +1,62 @@
import { useIsMobile } from '@/hooks/use-is-mobile';
import { useAtom } from 'jotai';
import {
desktopSidebarAtom,
mobileSidebarAtom,
} from '@/components/sidebar/atoms/sidebar-atom';
import { ScrollArea } from '@/components/ui/scroll-area';
import { IconFileText } from '@tabler/icons-react';
import { SidebarSection } from '@/components/sidebar/sidebar-section';
import {
navigationMenu,
NavigationMenuType,
} from '@/components/sidebar/actions/sidebar-actions';
import ButtonWithIcon from '@/components/ui/button-with-icon';
export default function Sidebar() {
const isMobile = useIsMobile();
const [isSidebarOpen] = useAtom(
isMobile ? mobileSidebarAtom : desktopSidebarAtom
);
return (
<nav
className={`${
isSidebarOpen ? 'w-[270px]' : 'w-[0px]'
} flex-grow-0 flex-shrink-0 overflow-hidden border-r duration-300 ease-in-out`}
>
<div className="flex flex-col flex-shrink-0 gap-0.5 p-[10px]">
<div className="h-full">
<div className="mt-[20px]"></div>
<SidebarSection className="pb-2 mb-4 select-none border-b">
{navigationMenu.map((menu: NavigationMenuType, index: number) => (
<ButtonWithIcon
key={index}
icon={menu.icon}
variant={'ghost'}
className="w-full flex flex-1 justify-start items-center"
>
<span className="text-ellipsis overflow-hidden">
{menu.label}
</span>
</ButtonWithIcon>
))}
</SidebarSection>
<ScrollArea className="h-[70vh]">
<div className="space-y-1">
<ButtonWithIcon
variant="ghost"
className="w-full justify-start"
icon={<IconFileText size={16} />}
>
Welcome page
</ButtonWithIcon>
</div>
</ScrollArea>
</div>
</div>
</nav>
);
}

View File

@ -0,0 +1,38 @@
'use client';
import { ReactNode } from 'react';
import { useIsMobile } from '@/hooks/use-is-mobile';
import {
desktopSidebarAtom,
mobileSidebarAtom,
} from '@/components/sidebar/atoms/sidebar-atom';
import { useToggleSidebar } from './hooks/use-toggle-sidebar';
import ButtonWithIcon from '../ui/button-with-icon';
import { IconLayoutSidebarLeftCollapse } from '@tabler/icons-react';
export default function TopBar() {
const isMobile = useIsMobile();
const sidebarStateAtom = isMobile ? mobileSidebarAtom : desktopSidebarAtom;
const toggleSidebar = useToggleSidebar(sidebarStateAtom);
return (
<header className="max-w-full z-50 select-none">
<div
className="w-full max-w-full h-[50px] opacity-100 relative
transition-opacity duration-700 ease-in transition-color duration-700 ease-in"
>
<div className="flex justify-between items-center h-full overflow-hidden py-0 px-1 gap-2.5 border-b">
<div className="flex items-center leading-tight h-full flex-grow-0 mr-[8px] min-w-0 font-semibold text-sm">
<ButtonWithIcon
icon={<IconLayoutSidebarLeftCollapse size={20} />}
variant={'ghost'}
onClick={toggleSidebar}
></ButtonWithIcon>
</div>
</div>
</div>
</header>
);
}