feat: functionnal sidebar

This commit is contained in:
Ruben 2025-03-25 20:52:21 +01:00
parent 3d944825ee
commit cc6341adb2
20 changed files with 2397 additions and 146 deletions

View File

@ -1,7 +1,13 @@
import type { NextConfig } from "next"; import type { NextConfig } from "next";
const nextConfig: NextConfig = { const nextConfig: NextConfig = {
/* config options here */ webpack(config) {
config.module.rules.push({
test: /\.svg$/,
use: ['@svgr/webpack'],
});
return config;
},
}; };
export default nextConfig; export default nextConfig;

View File

@ -24,6 +24,7 @@
}, },
"devDependencies": { "devDependencies": {
"@eslint/eslintrc": "^3", "@eslint/eslintrc": "^3",
"@svgr/webpack": "^8.1.0",
"@tailwindcss/postcss": "^4", "@tailwindcss/postcss": "^4",
"@types/node": "^20", "@types/node": "^20",
"@types/react": "^19", "@types/react": "^19",

1948
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

9
public/favicon.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

@ -0,0 +1,10 @@
export default function HomePage () {
return(
<>
</>
)
}

43
src/app/admin/layout.tsx Normal file
View File

@ -0,0 +1,43 @@
import { ReactNode } from "react";
import Image from "next/image";
import { icons } from "#/assets/icons"
import "../../assets/css/admin.css"
import Sidebar from "../components/sidebar";
export default function Dashboard({ children }: { children: ReactNode }) {
return (
<div className="r-flex-between">
<Sidebar/>
<main className="flex-grow-1 min-w-0 pt-md-1 pt-sm-5">
<div className="p-4">
{children}
</div>
</main>
</div >
)
}
/*
<div className="sidebar r-m-0 d-flex flex-column pt-[16px] max-w-[90px] h-[100vh] relative ">
<div className="logo r-flex-center pt-[13px] px-[20px] ">
<icons.Logo aria-label="Logo" className="scale-95" />
</div>
<div className="nav-menu r-column-center h-max pt-[160px] r-gap-40 ">
<Link href="#" className="nav-item r-flex-center ">
<icons.HomeIcon aria-label="Home" className="nav-home scale-100" />
</Link>
<Link href="#" className="nav-item border-none r-flex-center ">
<icons.CompaniesIcon aria-label="Companies" className="scale-100 " width={24} height={24} />
</Link>
<Link href="#" className="nav-item r-flex-center ">
<icons.UserGroup aria-label="Admins" className="scale-100" width={24} height={24} />
</Link>
</div>
</div>
<div className="logout absolute bottom-[60px] left-[22px]">
<icons.Logout aria-label="Logout" />
</div>
*/

6
src/app/admin/page.tsx Normal file
View File

@ -0,0 +1,6 @@
export default function Admin () {
return(
<>
</>
)
}

View File

@ -0,0 +1,21 @@
import Image from "next/image";
import Link from "next/link";
interface ItemProps {
link: string;
iconSrc: string;
label: string;
isActive: boolean;
isNavHome?: boolean;
onClick: () => void;
}
export default function NavItem({ link, iconSrc, label, isActive, isNavHome, onClick }: ItemProps) {
return (
<>
<Link href={link} onClick={onClick} className={`nav-item r-flex-center ${isActive ? "active" : ""}`} >
<Image src={iconSrc} alt={label} className={`scale-100 ${isNavHome ? "nav-home" : ""}`} />
</Link>
</>
);
}

View File

@ -0,0 +1,38 @@
"use client"
import Image from "next/image";
import { icons } from "#/assets/icons"
import NavItem from "./navItem";
import { useState } from "react";
export default function Sidebar() {
const [activeItem, setActiveItem] = useState("home")
const handleNavMenu = (item:string) => {
setActiveItem(item)
console.log("active: ", item);
}
return (
<>
<div className="sidebar r-m-0 d-flex flex-column pt-[16px] max-w-[90px] h-[100vh] relative ">
<div className="logo r-flex-center pt-[13px] px-[20px] ">
<Image src={icons.logo} alt="Logo" className="scale-95" />
</div>
<div className="nav-menu r-column-center h-max pt-[160px] r-gap-40 ">
<NavItem link="#" iconSrc={icons.homeIcon} label="Home" isNavHome={true} isActive={activeItem === "home"} onClick={() => handleNavMenu("home") } />
<NavItem link="#" iconSrc={icons.companiesIcon} label="Organizations" isActive={activeItem === "organizations"} onClick={() => handleNavMenu("organizations") } />
<NavItem link="#" iconSrc={icons.userGroup} label="Admins" isActive={activeItem === "admins"} onClick={() => handleNavMenu("admins") } />
</div>
<div className="logout absolute bottom-[40px] left-[28px]">
<button type="button" className="cursor-pointer">
<Image src={icons.logout} alt="Logout" />
</button>
</div>
</div>
</>
)
}

View File

@ -1,29 +1,28 @@
@import "tailwindcss"; @import "tailwindcss";
:root { :root {
--foreground: #000000;
--background: #ffffff; --background: #ffffff;
--foreground: #171717; --primary: #246BFD;
--cinder: #E7E5E4;
} }
@theme inline { [ data-theme="dark"] {
--color-background: var(--background); --foreground: #000000;
--color-foreground: var(--foreground); --background: #ffffff;
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
} }
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
:root { :root {
--background: #0a0a0a; --foreground: #000000;
--foreground: #ededed; --background: #ffffff;
} }
} }
body { body {
background: var(--background); background: var(--background);
color: var(--foreground); color: var(--foreground);
font-family: Arial, Helvetica, sans-serif; font-family: Inter, sans-serif;
} }
.input-form { .input-form {

View File

@ -1,21 +1,14 @@
import type { Metadata } from "next"; import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google"; import { Inter } from "next/font/google";
import "./globals.css"; import "./globals.css";
import NextTopLoader from "nextjs-toploader"; import NextTopLoader from "nextjs-toploader";
import "../assets/css/ruben-ui.css"
const geistSans = Geist({ const inter = Inter({ subsets: ["latin"] });
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Private Docs", title: "Private Docs",
description: "Un application de gestion de documents", description: "L'appli de gestion de documents par excellence !",
}; };
export default function RootLayout({ export default function RootLayout({
@ -25,10 +18,12 @@ export default function RootLayout({
}>) { }>) {
return ( return (
<html lang="en"> <html lang="en">
<body <head>
className={`${geistSans.variable} ${geistMono.variable} antialiased`} <link rel="icon" href="/favicon.svg" />
> <link rel="favicon.svg" href="/favicon.svg" />
<NextTopLoader /> </head>
<body className={inter.className}>
<NextTopLoader color="#246BFD" shadow="0" />
{children} {children}
</body> </body>
</html> </html>

View File

@ -1,103 +1,10 @@
import Image from "next/image"; import Image from "next/image";
import Link from "next/link";
export default function Home() { export default function Home() {
return ( return (
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]"> <div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
<main className="flex flex-col gap-[32px] row-start-2 items-center sm:items-start"> <Link href="/admin">See the admin page</Link>
<Image
className="dark:invert"
src="/next.svg"
alt="Next.js logo"
width={180}
height={38}
priority
/>
<ol className="list-inside list-decimal text-sm/6 text-center sm:text-left font-[family-name:var(--font-geist-mono)]">
<li className="mb-2 tracking-[-.01em]">
Get started by editing{" "}
<code className="bg-black/[.05] dark:bg-white/[.06] px-1 py-0.5 rounded font-[family-name:var(--font-geist-mono)] font-semibold">
src/app/page.tsx
</code>
.
</li>
<li className="tracking-[-.01em]">
Save and see your changes instantly.
</li>
</ol>
<div className="flex gap-4 items-center flex-col sm:flex-row">
<a
className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:w-auto"
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
className="dark:invert"
src="/vercel.svg"
alt="Vercel logomark"
width={20}
height={20}
/>
Deploy now
</a>
<a
className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 w-full sm:w-auto md:w-[158px]"
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Read our docs
</a>
</div>
</main>
<footer className="row-start-3 flex gap-[24px] flex-wrap items-center justify-center">
<a
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
aria-hidden
src="/file.svg"
alt="File icon"
width={16}
height={16}
/>
Learn
</a>
<a
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
aria-hidden
src="/window.svg"
alt="Window icon"
width={16}
height={16}
/>
Examples
</a>
<a
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
aria-hidden
src="/globe.svg"
alt="Globe icon"
width={16}
height={16}
/>
Go to nextjs.org
</a>
</footer>
</div> </div>
); );
} }

28
src/assets/css/admin.css Normal file
View File

@ -0,0 +1,28 @@
.sidebar{
border-right: 1px solid var(--cinder);
}
.nav-item .nav-home{
margin-bottom: -10px;
}
.nav-item{
width: 100%;
height: max-content;
}
.nav-item.active{
border-right: 2px solid var(--primary);
}
.nav-item svg{
color: var(--primary)!important;
background-color: var(--primary)!important;
fill: var(--primary)!important;
stroke: var(--primary)!important
}
.nav-home{
margin-top: -11px;
margin-bottom: -11px;
}

160
src/assets/css/ruben-ui.css Normal file
View File

@ -0,0 +1,160 @@
/* Extra Small (XS) */
.r-p-0 {
padding: 0;
}
.r-m-0 {
margin: 0;
}
.r-p-m-0{
padding: 0;
margin: 0;
}
.r-p-0auto {
padding: 0 auto;
}
.r-m-0auto {
margin: 0 auto;
}
.r-flex {
display: flex;
}
.r-flex-center {
display: flex;
justify-content: center;
}
.r-flex-between {
display: flex;
justify-content: space-between;
}
.r-flex-around {
display: flex;
justify-content: space-around;
}
.r-flex-evenly {
display: flex;
justify-content: space-evenly;
}
.r-flex-column {
display: flex;
flex-direction: column;
}
.r-column-center,.r-column-md-row, .r-column-lg-row, .r-column-xl-row {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.r-row-center, .r-row-md-column, .r-row-lg-column, .r-row-xl-column {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
.r-gap-2{
gap: 2px;
}
.r-gap-4{
gap: 4px;
}
.r-gap-6{
gap: 6px;
}
.r-gap-8{
gap: 8px;
}
.r-gap-10{
gap: 10px;
}
.r-gap-12{
gap: 12px;
}
.r-gap-14{
gap: 14px;
}
.r-gap-16{
gap: 16px;
}
.r-gap-18{
gap: 18px;
}
.r-gap-20{
gap: 20px;
}
.r-gap-22{
gap: 22px;
}
.r-gap-24{
gap: 24px;
}
.r-gap-32{
gap: 32px;
}
.r-gap-36{
gap: 36px;
}
.r-gap-40{
gap: 40px;
}
.r-gap-42{
gap: 42px;
}
.r-gap-50{
gap: 50px;
}
.r-gap-60{
gap: 60px;
}
.r-gap-70{
gap: 70px;
}
/* Small (SM) */
@media (min-width: 640px) {
/* Styles for small devices and up */
}
/* Medium (MD) */
@media (min-width: 768px) {
.r-column-md-row {
flex-direction: row;
}
.r-row-md-column{
flex-direction: column;
}
}
/* Large (LG) */
@media (min-width: 1024px) {
.r-column-lg-row {
flex-direction: row;
}
.r-row-lg-column{
flex-direction: column;
}
}
/* Extra Large (XL) */
@media (min-width: 1280px) {
.r-column-xl-row {
flex-direction: row;
}
.r-row-xl-column{
flex-direction: column;
}
}
/* 2XL (XXL) */
@media (min-width: 1536px) {
/* Styles for very large screens */
}

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 582 KiB

View File

@ -1,4 +1,4 @@
<svg width="48" height="49" viewBox="0 0 48 49" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 48 49" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M21.02 15.34L15.63 19.54C14.73 20.24 14 21.73 14 22.86V30.27C14 32.59 15.89 34.49 18.21 34.49H29.79C32.11 34.49 34 32.59 34 30.28V23C34 21.79 33.19 20.24 32.2 19.55L26.02 15.22C24.62 14.24 22.37 14.29 21.02 15.34Z" stroke="#246BFD" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M21.02 15.34L15.63 19.54C14.73 20.24 14 21.73 14 22.86V30.27C14 32.59 15.89 34.49 18.21 34.49H29.79C32.11 34.49 34 32.59 34 30.28V23C34 21.79 33.19 20.24 32.2 19.55L26.02 15.22C24.62 14.24 22.37 14.29 21.02 15.34Z" stroke="#246BFD" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M24 30.49V27.49" stroke="#246BFD" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M24 30.49V27.49" stroke="#246BFD" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 523 B

After

Width:  |  Height:  |  Size: 500 B

View File

@ -0,0 +1,9 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13 22H5C3 22 2 21 2 19V11C2 9 3 8 5 8H10V19C10 21 11 22 13 22Z" stroke="#9FA8BC" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10.11 4C10.03 4.3 10 4.63 10 5V8H5V6C5 4.9 5.9 4 7 4H10.11Z" stroke="#9FA8BC" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M14 8V13" stroke="#9FA8BC" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M18 8V13" stroke="#9FA8BC" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M17 17H15C14.45 17 14 17.45 14 18V22H18V18C18 17.45 17.55 17 17 17Z" stroke="#9FA8BC" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 13V17" stroke="#9FA8BC" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10 19V5C10 3 11 2 13 2H19C21 2 22 3 22 5V19C22 21 21 22 19 22H13C11 22 10 21 10 19Z" stroke="#9FA8BC" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -14,12 +14,14 @@ import addBlueIcon from "./icon-add.svg"
import archivesIcon from "./archives.svg" import archivesIcon from "./archives.svg"
import notificationsIcon from "./notifications.svg" import notificationsIcon from "./notifications.svg"
import timerIcon from "./Line Duotone.svg" import timerIcon from "./Line Duotone.svg"
import logo from "./Logo Private Docs@2x.svg" import logo from "./logo.svg"
import logoutRed from "./logout-red.svg" import logoutRed from "./logout-red.svg"
import logout from "./logout.svg"
import maximizeIcon from "./maximize-3.svg" import maximizeIcon from "./maximize-3.svg"
import menuIcon from "./Menu Dots.svg" import menuIcon from "./Menu Dots.svg"
import messagesIcon from "./message.svg" import messagesIcon from "./message.svg"
import homeIcon from "./NavItem.svg" import homeIcon from "./NavItem.svg"
import companiesIcon from "./buildings.svg"
import arrowLeft from "./arrowLeft.svg" import arrowLeft from "./arrowLeft.svg"
import arrowRight from "./arrowLeft.svg" import arrowRight from "./arrowLeft.svg"
import filesIcon from "./ph_files.svg" import filesIcon from "./ph_files.svg"
@ -55,6 +57,8 @@ export const icons = {
notificationsIcon, notificationsIcon,
timerIcon, timerIcon,
logo, logo,
companiesIcon,
logout,
logoutRed, logoutRed,
maximizeIcon, maximizeIcon,
menuIcon, menuIcon,
@ -75,4 +79,92 @@ export const icons = {
shareIcon, shareIcon,
starIcon, starIcon,
arrowUp arrowUp
} }
/*
import AddIcon from "./add.svg";
import CalendarIcon from "./Calendar Mark.svg";
import DocummentTextIcon from "./document-text.svg";
import FolderIcon from "./Document.svg";
import EditIcon from "./edit-2.svg";
import GridIcon from "./element-3-white.svg";
import GridBlueIcon from "./element-3.svg";
import ProfilePicture from "./Ellipse 2.svg";
import EyeIcon from "./eye.svg";
import EyeSlashIcon from "./eye-slash.svg";
import CheckboxchedIcon from "./checked.svg";
import CrossIcon from "./cross.svg";
import AddBlueIcon from "./icon-add.svg";
import ArchivesIcon from "./archives.svg";
import NotificationsIcon from "./notifications.svg";
import TimerIcon from "./Line Duotone.svg";
import Logo from "./logo.svg";
import LogoutRed from "./logout-red.svg";
import Logout from "./logout.svg";
import MaximizeIcon from "./maximize-3.svg";
import MenuIcon from "./Menu Dots.svg";
import MessagesIcon from "./message.svg";
import HomeIcon from "./NavItem.svg";
import CompaniesIcon from "./buildings.svg";
import ArrowLeft from "./arrowLeft.svg";
import ArrowRight from "./arrowLeft.svg";
import FilesIcon from "./ph_files.svg";
import PdfIcon from "./prime_file-pdf.svg";
import WordIcon from "./prime_file-word.svg";
import UserIcon from "./profile.svg";
import UserGroup from "./profile-2user.svg";
import UserGroupBlue from "./profile-2user-blue.svg";
import Rectanagle from "./Rectangle.svg";
import SearchIcon from "./Search.svg";
import SettingsIcon from "./setting-2.svg";
import FilterIcon from "./setting-3.svg";
import ShareIcon from "./share.svg";
import StarIcon from "./star.svg";
import ArrowUp from "./Vector.svg";
export const icons = {
AddIcon,
CalendarIcon,
DocummentTextIcon,
FolderIcon,
EditIcon,
GridIcon,
GridBlueIcon,
ProfilePicture,
EyeIcon,
EyeSlashIcon,
CheckboxchedIcon,
CrossIcon,
AddBlueIcon,
ArchivesIcon,
NotificationsIcon,
TimerIcon,
Logo,
CompaniesIcon,
Logout,
LogoutRed,
MaximizeIcon,
MenuIcon,
MessagesIcon,
HomeIcon,
ArrowLeft,
ArrowRight,
FilesIcon,
PdfIcon,
WordIcon,
UserIcon,
UserGroup,
UserGroupBlue,
Rectanagle,
SearchIcon,
SettingsIcon,
FilterIcon,
ShareIcon,
StarIcon,
ArrowUp
};
*/

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.8999 7.55999C9.2099 3.95999 11.0599 2.48999 15.1099 2.48999H15.2399C19.7099 2.48999 21.4999 4.27999 21.4999 8.74999V15.27C21.4999 19.74 19.7099 21.53 15.2399 21.53H15.1099C11.0899 21.53 9.2399 20.08 8.9099 16.54" stroke="#9FA8BC" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M15.0001 12H3.62012" stroke="#9FA8BC" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5.85 8.65002L2.5 12L5.85 15.35" stroke="#9FA8BC" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 655 B