Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add Left Menu component
Browse files Browse the repository at this point in the history
Adds left lateral menu component to project
Import Label, NavigationMenu, Separator components
Closes #17
rfgvieira committed Jun 28, 2024
1 parent c0c61b4 commit e1923ce
Showing 10 changed files with 646 additions and 42 deletions.
10 changes: 5 additions & 5 deletions dashboard/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ module.exports = {
"plugin:react-hooks/recommended",
"plugin:storybook/recommended",
],
ignorePatterns: [".eslintrc.cjs", "*.config.js"],
ignorePatterns: [".eslintrc.cjs", "*.config.js", "/src/components/ui/*"],
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaFeatures: {
@@ -76,10 +76,10 @@ module.exports = {
"error",
"ignorePackages",
{
js: "never",
jsx: "never",
ts: "never",
tsx: "never",
"js": "never",
"jsx": "never",
"ts": "never",
"tsx": "never",
},
],
"import/no-cycle": ["error", { ignoreExternal: true }],
2 changes: 1 addition & 1 deletion dashboard/README.md
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ To add a new component to projet use the following command on terminal:
```
pnpm dlx shadcn-ui@latest add <component-name>
```

- [Docs](https://ui.shadcn.com/docs/cli)
## Expanding the ESLint configuration

If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
13 changes: 9 additions & 4 deletions dashboard/package.json
Original file line number Diff line number Diff line change
@@ -19,14 +19,21 @@
"@emotion/styled": "^11.11.5",
"@mui/material": "^5.15.20",
"@mui/x-charts": "^7.7.1",
"@radix-ui/react-dropdown-menu": "^2.1.1",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-navigation-menu": "^1.2.0",
"@radix-ui/react-separator": "^1.1.0",
"@tanstack/react-query": "^5.45.1",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"lucide-react": "^0.396.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-icons": "^5.2.1",
"tailwind-merge": "^2.3.0",
"tailwindcss-animate": "^1.0.7"
"tailwindcss-animate": "^1.0.7",
"vite": "^5.3.1",
"@vitejs/plugin-react": "^4.3.1"
},
"devDependencies": {
"@chromatic-com/storybook": "^1.5.0",
@@ -43,7 +50,6 @@
"@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^7.13.1",
"@typescript-eslint/parser": "^7.13.1",
"@vitejs/plugin-react": "^4.3.1",
"autoprefixer": "^10.4.19",
"eslint": "^8.57.0",
"eslint-plugin-import": "^2.29.1",
@@ -55,7 +61,6 @@
"postcss": "^8.4.38",
"storybook": "^8.1.10",
"tailwindcss": "^3.4.4",
"typescript": "^5.2.2",
"vite": "^5.3.1"
"typescript": "^5.2.2"
}
}
379 changes: 373 additions & 6 deletions dashboard/pnpm-lock.yaml

Large diffs are not rendered by default.

29 changes: 3 additions & 26 deletions dashboard/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,12 @@
import { useState } from "react";

import reactLogo from "./assets/react.svg";

import viteLogo from "/vite.svg";
import "./App.css";
import LateralMenu from "./components/LateralMenu/LateralMenu";

function App(): JSX.Element {
const [countState, setCount] = useState(0);

return (
<>
<div>
<a href="https://vitejs.dev" target="_blank" rel="noreferrer">
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="https://react.dev" target="_blank" rel="noreferrer">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<h1>Vite + React</h1>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {countState}
</button>
<p>
Edit <code>src/App.tsx</code> and save to test HMR
</p>
<div className="w-screen h-screen">
<LateralMenu />
</div>
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
</>
);
}
Binary file added dashboard/src/assets/kernelCI_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
91 changes: 91 additions & 0 deletions dashboard/src/components/LateralMenu/LateralMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { MdOutlineMonitorHeart, MdOutlineDashboard } from "react-icons/md";

import { ImTree, ImImages } from "react-icons/im";

import {
NavigationMenu,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
} from "../ui/navigation-menu";

import { Separator } from "../ui/separator";

type MenuItems = {
onClick: () => void;
text: string;
icon: JSX.Element;
selected: boolean;
};

const items: MenuItems[] = [
{
onClick: () : void => {},
text: "Dashboard",
icon: <MdOutlineDashboard className="size-5" />,
selected: false,
},
{
onClick: () : void => {},
text: "Tree Monitor",
icon: <ImTree className="size-5" />,
selected: true,
},
{
onClick: () : void => {},
text: "Device Monitor",
icon: <MdOutlineMonitorHeart className="size-5" />,
selected: false,
},
{
onClick: () : void => {},
text: "Labs Monitor",
icon: <ImImages className="size-5" />,
selected: false,
},
];

const NavLink = ({
icon,
text,
}: Pick<MenuItems, "icon" | "text">): JSX.Element => (
<NavigationMenuLink asChild>
<a className="flex items-center no-underline hover:text-sky-500">
<span className="mr-3">{icon}</span>
<span className="text-sm text-center">{text}</span>
</a>
</NavigationMenuLink>
);

const LateralMenu = (): JSX.Element => {
const selectedItemClassName = "w-full flex pl-5 py-4 cursor-pointer text-sky-500 bg-black border-l-4 border-sky-500";
const notSelectedItemClassName = "w-full flex pl-5 py-4 cursor-pointer text-white";

return (
<NavigationMenu
className="sticky bg-bgSecondary pt-6 flex-col"
orientation="vertical"
>
<div className="w-full px-4">
<img src="./src/assets/kernelCI_logo.png"className="size-14 text-onSecondary" />
</div>

<Separator className="my-4 bg-onSecondary-10" />

<NavigationMenuList className="flex-col h-screen justify-start w-52 space-y-4 space-x-0 ">
{items.map((item) =>

<NavigationMenuItem
className={item.selected ? selectedItemClassName : notSelectedItemClassName}
key={item.text}
>
<NavLink icon={item.icon} text={item.text} />
</NavigationMenuItem>

)}
</NavigationMenuList>
</NavigationMenu>
);
};

export default LateralMenu;
128 changes: 128 additions & 0 deletions dashboard/src/components/ui/navigation-menu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import * as React from "react"
import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu"
import { cva } from "class-variance-authority"
import { ChevronDown } from "lucide-react"

import { cn } from "../../lib/utils"

const NavigationMenu = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root>
>(({ className, children, ...props }, ref) => (
<NavigationMenuPrimitive.Root
ref={ref}
className={cn(
"relative z-10 flex max-w-max flex-1 items-center justify-center",
className
)}
{...props}
>
{children}
<NavigationMenuViewport />
</NavigationMenuPrimitive.Root>
))
NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName

const NavigationMenuList = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.List>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List>
>(({ className, ...props }, ref) => (
<NavigationMenuPrimitive.List
ref={ref}
className={cn(
"group flex flex-1 list-none items-center justify-center space-x-1",
className
)}
{...props}
/>
))
NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName

const NavigationMenuItem = NavigationMenuPrimitive.Item

const navigationMenuTriggerStyle = cva(
"group inline-flex h-10 w-max items-center justify-center rounded-md bg-white px-4 py-2 text-sm font-medium transition-colors hover:bg-slate-100 hover:text-slate-900 focus:bg-slate-100 focus:text-slate-900 focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-slate-100/50 data-[state=open]:bg-slate-100/50 dark:bg-slate-950 dark:hover:bg-slate-800 dark:hover:text-slate-50 dark:focus:bg-slate-800 dark:focus:text-slate-50 dark:data-[active]:bg-slate-800/50 dark:data-[state=open]:bg-slate-800/50"
)

const NavigationMenuTrigger = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
<NavigationMenuPrimitive.Trigger
ref={ref}
className={cn(navigationMenuTriggerStyle(), "group", className)}
{...props}
>
{children}{""}
<ChevronDown
className="relative top-[1px] ml-1 h-3 w-3 transition duration-200 group-data-[state=open]:rotate-180"
aria-hidden="true"
/>
</NavigationMenuPrimitive.Trigger>
))
NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName

const NavigationMenuContent = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content>
>(({ className, ...props }, ref) => (
<NavigationMenuPrimitive.Content
ref={ref}
className={cn(
"left-0 top-0 w-full data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 md:absolute md:w-auto",
className
)}
{...props}
/>
))
NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName

const NavigationMenuLink = NavigationMenuPrimitive.Link

const NavigationMenuViewport = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Viewport>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport>
>(({ className, ...props }, ref) => (
<div className={cn("absolute left-0 top-full flex justify-center")}>
<NavigationMenuPrimitive.Viewport
className={cn(
"origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border border-slate-200 bg-white text-slate-950 shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 md:w-[var(--radix-navigation-menu-viewport-width)] dark:border-slate-800 dark:bg-slate-950 dark:text-slate-50",
className
)}
ref={ref}
{...props}
/>
</div>
))
NavigationMenuViewport.displayName =
NavigationMenuPrimitive.Viewport.displayName

const NavigationMenuIndicator = React.forwardRef<
React.ElementRef<typeof NavigationMenuPrimitive.Indicator>,
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Indicator>
>(({ className, ...props }, ref) => (
<NavigationMenuPrimitive.Indicator
ref={ref}
className={cn(
"top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in",
className
)}
{...props}
>
<div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-slate-200 shadow-md dark:bg-slate-800" />
</NavigationMenuPrimitive.Indicator>
))
NavigationMenuIndicator.displayName =
NavigationMenuPrimitive.Indicator.displayName

export {
navigationMenuTriggerStyle,
NavigationMenu,
NavigationMenuList,
NavigationMenuItem,
NavigationMenuContent,
NavigationMenuTrigger,
NavigationMenuLink,
NavigationMenuIndicator,
NavigationMenuViewport,
}
29 changes: 29 additions & 0 deletions dashboard/src/components/ui/separator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import * as React from "react"
import * as SeparatorPrimitive from "@radix-ui/react-separator"

import { cn } from "../../lib/utils"

const Separator = React.forwardRef<
React.ElementRef<typeof SeparatorPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
>(
(
{ className, orientation = "horizontal", decorative = true, ...props },
ref
) => (
<SeparatorPrimitive.Root
ref={ref}
decorative={decorative}
orientation={orientation}
className={cn(
"shrink-0 bg-slate-200 dark:bg-slate-800",
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
className
)}
{...props}
/>
)
)
Separator.displayName = SeparatorPrimitive.Root.displayName

export { Separator }
7 changes: 7 additions & 0 deletions dashboard/tailwind.config.js
Original file line number Diff line number Diff line change
@@ -31,6 +31,13 @@ module.exports = {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
},
colors: {
'bgSecondary' : '#343638',
'onSecondary' : '#FFFFFF',
'lightBlue': '#11B3E6',
'onSecondary-10': '#FFFFFF1A',
'dark': '#000'
}
},
},
plugins: [require("tailwindcss-animate")],

0 comments on commit e1923ce

Please sign in to comment.