Files
edr-platform/packages/ui-common/src/components/Layout/Sidebar.tsx
2026-05-18 23:23:51 +03:00

90 lines
2.7 KiB
TypeScript

import { ReactNode } from "react";
import clsx from "clsx";
export interface SidebarItem {
label: string;
href: string;
icon?: ReactNode;
}
export interface SidebarProps {
title?: string;
items: SidebarItem[];
activeHref?: string;
onNavigate?: (href: string) => void;
headerExtra?: ReactNode;
}
/**
* Brand palette
* #10B981 — dominant dark green → brand mark, active state, hover text
* #10B981 — secondary green → hover background tint
* #10B981 — muted green tone → sidebar canvas
*/
const Sidebar = ({
title,
items,
activeHref,
onNavigate,
headerExtra,
}: SidebarProps) => (
<aside className="flex h-full w-64 shrink-0 flex-col gap-1 overflow-y-auto border-r border-slate-200 bg-[#10B981]/10 px-3 py-5 dark:border-slate-800 dark:bg-slate-900">
{title ? (
<div className="flex items-center justify-between gap-2 px-3 pb-4">
<div className="flex items-center gap-2">
<div className="flex h-9 w-9 items-center justify-center rounded-xl bg-[#10B981] text-sm font-bold text-white">
{title.charAt(0)}
</div>
<div className="text-base font-semibold text-slate-800 dark:text-slate-100">
{title}
</div>
</div>
{headerExtra}
</div>
) : null}
<nav className="flex flex-col gap-1">
{items.map((item) => {
const isActive =
activeHref?.toLowerCase() === item.href.toLowerCase();
return (
<a
key={item.href}
href={item.href}
onClick={(event) => {
if (onNavigate) {
event.preventDefault();
onNavigate(item.href);
}
}}
aria-current={isActive ? "page" : undefined}
className={clsx(
"group flex items-center gap-3 rounded-xl px-3 py-2.5 text-sm font-medium transition",
isActive
? "bg-[#10B981] text-white shadow-sm shadow-[#10B981]/25"
: "text-slate-700 hover:bg-[#10B981]/10 hover:text-[#10B981] dark:text-slate-300 dark:hover:bg-[#10B981]/20 dark:hover:text-white",
)}
>
{item.icon ? (
<span
className={clsx(
"flex h-5 w-5 items-center justify-center [&_svg]:h-5 [&_svg]:w-5",
isActive
? "text-white"
: "text-slate-500 group-hover:text-[#10B981] dark:text-slate-400 dark:group-hover:text-white",
)}
>
{item.icon}
</span>
) : null}
<span>{item.label}</span>
</a>
);
})}
</nav>
</aside>
);
export default Sidebar;