UI breadcrumb active link

Signed-off-by: Émile Ré <nemile.re@gmail.com>
This commit is contained in:
Émile Ré
2025-03-14 15:27:33 +04:00
parent 1f0e8316b4
commit fdb247b813
2 changed files with 80 additions and 65 deletions

View File

@@ -1,6 +1,6 @@
import * as React from "react"; import * as React from "react";
import { Slot } from "@radix-ui/react-slot"; import { Slot } from "@radix-ui/react-slot";
import { ChevronRight, MoreHorizontal } from "lucide-react"; import { MoreHorizontal } from "lucide-react";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
@@ -19,8 +19,8 @@ const BreadcrumbList = React.forwardRef<
<ol <ol
ref={ref} ref={ref}
className={cn( className={cn(
"flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5", "flex flex-wrap items-center gap-3 break-words text-sm text-gray-500 sm:gap-2.5",
className, className
)} )}
{...props} {...props}
/> />
@@ -50,7 +50,7 @@ const BreadcrumbLink = React.forwardRef<
return ( return (
<Comp <Comp
ref={ref} ref={ref}
className={cn("transition-colors hover:text-foreground", className)} className={cn("transition-colors hover:text-primary", className)}
{...props} {...props}
/> />
); );
@@ -66,7 +66,7 @@ const BreadcrumbPage = React.forwardRef<
role="link" role="link"
aria-disabled="true" aria-disabled="true"
aria-current="page" aria-current="page"
className={cn("font-normal text-foreground", className)} className={cn("font-normal text-gray-700", className)}
{...props} {...props}
/> />
)); ));
@@ -80,10 +80,10 @@ const BreadcrumbSeparator = ({
<li <li
role="presentation" role="presentation"
aria-hidden="true" aria-hidden="true"
className={cn("[&>svg]:w-3.5 [&>svg]:h-3.5", className)} className={cn("[&>svg]:w-3.5 [&>svg]:h-3.5 text-gray-300", className)}
{...props} {...props}
> >
{children ?? <ChevronRight />} {children ?? "/"}
</li> </li>
); );
BreadcrumbSeparator.displayName = "BreadcrumbSeparator"; BreadcrumbSeparator.displayName = "BreadcrumbSeparator";

View File

@@ -1,6 +1,6 @@
import { Link, Outlet, Route, Routes, useParams } from "react-router"; import { NavLink, Outlet, Route, Routes, To, useParams } from "react-router";
import { AppSidebar } from "@/components/AppSidebar"; import { AppSidebar } from "@/components/AppSidebar";
import React, { Suspense } from "react"; import { ReactNode, Suspense } from "react";
import { import {
Breadcrumb, Breadcrumb,
BreadcrumbItem, BreadcrumbItem,
@@ -23,15 +23,42 @@ import { ConsoleLayoutBreadcrumbVendorOverviewQuery } from "./__generated__/Cons
import { ConsoleLayoutBreadcrumbControlOverviewQuery } from "./__generated__/ConsoleLayoutBreadcrumbControlOverviewQuery.graphql"; import { ConsoleLayoutBreadcrumbControlOverviewQuery } from "./__generated__/ConsoleLayoutBreadcrumbControlOverviewQuery.graphql";
import { ConsoleLayoutOrganizationQuery } from "./__generated__/ConsoleLayoutOrganizationQuery.graphql"; import { ConsoleLayoutOrganizationQuery } from "./__generated__/ConsoleLayoutOrganizationQuery.graphql";
import { ConsoleLayoutBreadcrumbPolicyOverviewQuery } from "./__generated__/ConsoleLayoutBreadcrumbPolicyOverviewQuery.graphql"; import { ConsoleLayoutBreadcrumbPolicyOverviewQuery } from "./__generated__/ConsoleLayoutBreadcrumbPolicyOverviewQuery.graphql";
import { cn } from "@/lib/utils";
const BreadCrumbNavLink = ({
to,
children,
className,
}: {
to: To;
children?: ReactNode;
className?: string;
}) => {
return (
<BreadcrumbLink asChild>
<NavLink to={to} end>
{({ isActive }) => (
<BreadcrumbPage
className={cn(
"text-gray-300",
isActive && "text-gray-700",
className
)}
>
{children}
</BreadcrumbPage>
)}
</NavLink>
</BreadcrumbLink>
);
};
function BreadcrumbHome() { function BreadcrumbHome() {
return ( return (
<Breadcrumb> <Breadcrumb>
<BreadcrumbList> <BreadcrumbList>
<BreadcrumbItem> <BreadcrumbItem>
<BreadcrumbLink asChild> <BreadCrumbNavLink to="/">Home</BreadCrumbNavLink>
<Link to="/">Home</Link>
</BreadcrumbLink>
</BreadcrumbItem> </BreadcrumbItem>
<Outlet /> <Outlet />
</BreadcrumbList> </BreadcrumbList>
@@ -57,14 +84,12 @@ function BreadCrumbOrganization() {
); );
return ( return (
<Breadcrumb> <Breadcrumb className="select-none">
<BreadcrumbList> <BreadcrumbList>
<BreadcrumbItem> <BreadcrumbItem>
<BreadcrumbLink asChild> <BreadCrumbNavLink to={`/organizations/${organizationId}`}>
<Link to={`/organizations/${organizationId}`}>
{data.organization?.name || "Home"} {data.organization?.name || "Home"}
</Link> </BreadCrumbNavLink>
</BreadcrumbLink>
</BreadcrumbItem> </BreadcrumbItem>
<Outlet /> <Outlet />
</BreadcrumbList> </BreadcrumbList>
@@ -78,11 +103,9 @@ function BreadcrumbFrameworkList() {
<> <>
<BreadcrumbSeparator /> <BreadcrumbSeparator />
<BreadcrumbItem> <BreadcrumbItem>
<BreadcrumbLink asChild> <BreadCrumbNavLink to={`/organizations/${organizationId}/frameworks`}>
<Link to={`/organizations/${organizationId}/frameworks`}>
Frameworks Frameworks
</Link> </BreadCrumbNavLink>
</BreadcrumbLink>
</BreadcrumbItem> </BreadcrumbItem>
<Outlet /> <Outlet />
</> </>
@@ -120,13 +143,11 @@ function BreadcrumbFrameworkOverview() {
<> <>
<BreadcrumbSeparator /> <BreadcrumbSeparator />
<BreadcrumbItem> <BreadcrumbItem>
<BreadcrumbLink asChild> <BreadCrumbNavLink
<Link
to={`/organizations/${organizationId}/frameworks/${frameworkId}`} to={`/organizations/${organizationId}/frameworks/${frameworkId}`}
> >
{data.framework?.name} {data.framework?.name}
</Link> </BreadCrumbNavLink>
</BreadcrumbLink>
</BreadcrumbItem> </BreadcrumbItem>
<Outlet /> <Outlet />
</> </>
@@ -150,9 +171,9 @@ function BreadcrumbVendorList() {
<> <>
<BreadcrumbSeparator /> <BreadcrumbSeparator />
<BreadcrumbItem> <BreadcrumbItem>
<BreadcrumbLink asChild> <BreadCrumbNavLink to={`/organizations/${organizationId}/vendors`}>
<Link to={`/organizations/${organizationId}/vendors`}>Vendors</Link> Vendors
</BreadcrumbLink> </BreadCrumbNavLink>
</BreadcrumbItem> </BreadcrumbItem>
<Outlet /> <Outlet />
</> </>
@@ -180,13 +201,11 @@ function BreadcrumbVendorOverview() {
<> <>
<BreadcrumbSeparator /> <BreadcrumbSeparator />
<BreadcrumbItem> <BreadcrumbItem>
<BreadcrumbLink asChild> <BreadCrumbNavLink
<Link
to={`/organizations/${organizationId}/vendors/${data.vendor.id}`} to={`/organizations/${organizationId}/vendors/${data.vendor.id}`}
> >
{data.vendor.name} {data.vendor.name}
</Link> </BreadCrumbNavLink>
</BreadcrumbLink>
</BreadcrumbItem> </BreadcrumbItem>
<Outlet /> <Outlet />
</> </>
@@ -199,9 +218,9 @@ function BreadcrumbPeopleList() {
<> <>
<BreadcrumbSeparator /> <BreadcrumbSeparator />
<BreadcrumbItem> <BreadcrumbItem>
<BreadcrumbLink asChild> <BreadCrumbNavLink to={`/organizations/${organizationId}/people`}>
<Link to={`/organizations/${organizationId}/people`}>People</Link> People
</BreadcrumbLink> </BreadCrumbNavLink>
</BreadcrumbItem> </BreadcrumbItem>
<Outlet /> <Outlet />
</> </>
@@ -240,13 +259,11 @@ function BreadcrumbPeopleOverview() {
<> <>
<BreadcrumbSeparator /> <BreadcrumbSeparator />
<BreadcrumbItem> <BreadcrumbItem>
<BreadcrumbLink asChild> <BreadCrumbNavLink
<Link
to={`/organizations/${organizationId}/people/${data.people.id}`} to={`/organizations/${organizationId}/people/${data.people.id}`}
> >
{data.people.fullName} {data.people.fullName}
</Link> </BreadCrumbNavLink>
</BreadcrumbLink>
</BreadcrumbItem> </BreadcrumbItem>
<Outlet /> <Outlet />
</> </>
@@ -273,13 +290,11 @@ function BreadcrumbControlOverview() {
<> <>
<BreadcrumbSeparator /> <BreadcrumbSeparator />
<BreadcrumbItem> <BreadcrumbItem>
<BreadcrumbLink asChild> <BreadCrumbNavLink
<Link
to={`/organizations/${organizationId}/frameworks/${frameworkId}/controls/${controlId}`} to={`/organizations/${organizationId}/frameworks/${frameworkId}/controls/${controlId}`}
> >
{data.control?.name} {data.control?.name}
</Link> </BreadCrumbNavLink>
</BreadcrumbLink>
</BreadcrumbItem> </BreadcrumbItem>
</> </>
); );
@@ -302,9 +317,9 @@ function BreadcrumbPolicyList() {
<> <>
<BreadcrumbSeparator /> <BreadcrumbSeparator />
<BreadcrumbItem> <BreadcrumbItem>
<BreadcrumbLink asChild> <BreadCrumbNavLink to={`/organizations/${organizationId}/policies`}>
<Link to={`/organizations/${organizationId}/policies`}>Policies</Link> Policies
</BreadcrumbLink> </BreadCrumbNavLink>
</BreadcrumbItem> </BreadcrumbItem>
<Outlet /> <Outlet />
</> </>
@@ -343,11 +358,11 @@ function BreadcrumbPolicyOverview() {
<> <>
<BreadcrumbSeparator /> <BreadcrumbSeparator />
<BreadcrumbItem> <BreadcrumbItem>
<BreadcrumbLink asChild> <BreadCrumbNavLink
<Link to={`/organizations/${organizationId}/policies/${policyId}`}> to={`/organizations/${organizationId}/policies/${policyId}`}
>
{data.policy?.name} {data.policy?.name}
</Link> </BreadCrumbNavLink>
</BreadcrumbLink>
</BreadcrumbItem> </BreadcrumbItem>
<Outlet /> <Outlet />
</> </>