app sidebar UI polishing

Signed-off-by: Émile Ré <nemile.re@gmail.com>
This commit is contained in:
Émile Ré
2025-03-07 13:52:32 +04:00
parent dbc7711f98
commit a388c8cb96
11 changed files with 261 additions and 99 deletions

1
apps/console/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
dist/

View File

@@ -1,4 +1,5 @@
@import "tailwindcss"; @import "tailwindcss";
@import "./styles/colors.css";
@plugin 'tailwindcss-animate'; @plugin 'tailwindcss-animate';
@@ -40,10 +41,6 @@
--color-sidebar-accent-foreground: hsl(var(--sidebar-accent-foreground)); --color-sidebar-accent-foreground: hsl(var(--sidebar-accent-foreground));
--color-sidebar-border: hsl(var(--sidebar-border)); --color-sidebar-border: hsl(var(--sidebar-border));
--color-sidebar-ring: hsl(var(--sidebar-ring)); --color-sidebar-ring: hsl(var(--sidebar-ring));
--radius-lg: `var(--radius) `;
--radius-md: `calc(var(--radius) - 2px) `;
--radius-sm: calc(var(--radius) - 4px);
} }
/* /*
@@ -85,7 +82,6 @@
--destructive: 0 100% 50%; --destructive: 0 100% 50%;
--destructive-foreground: 210 40% 98%; --destructive-foreground: 210 40% 98%;
--ring: 215 20.2% 65.1%; --ring: 215 20.2% 65.1%;
--radius: 0.5rem;
--sidebar-background: 0 0% 98%; --sidebar-background: 0 0% 98%;
--sidebar-foreground: 240 5.3% 26.1%; --sidebar-foreground: 240 5.3% 26.1%;
--sidebar-primary: 240 5.9% 10%; --sidebar-primary: 240 5.9% 10%;

View File

@@ -93,7 +93,7 @@ export function NavMain({
if (item.items?.length) { if (item.items?.length) {
return item.items.some((subItem) => return item.items.some((subItem) =>
location.pathname.startsWith(subItem.url), location.pathname.startsWith(subItem.url)
); );
} }
@@ -102,7 +102,9 @@ export function NavMain({
return ( return (
<SidebarGroup> <SidebarGroup>
<SidebarGroupLabel>Compliance</SidebarGroupLabel> <SidebarGroupLabel className="text-gray-500 pl-3">
Compliance
</SidebarGroupLabel>
<SidebarMenu> <SidebarMenu>
{items.map((item) => { {items.map((item) => {
const active = isItemActive(item) || item.isActive; const active = isItemActive(item) || item.isActive;
@@ -114,11 +116,12 @@ export function NavMain({
asChild asChild
tooltip={item.title} tooltip={item.title}
data-active={active ? "true" : undefined} data-active={active ? "true" : undefined}
className={active ? "text-primary font-medium" : ""}
> >
<Link to={item.url ?? "#"}> <Link to={item.url ?? "#"}>
<item.icon /> <item.icon
<span>{item.title}</span> className={active ? "text-lime-9" : "text-lime-6"}
/>
<span className="font-medium">{item.title}</span>
</Link> </Link>
</SidebarMenuButton> </SidebarMenuButton>
{item.items?.length ? ( {item.items?.length ? (
@@ -133,7 +136,7 @@ export function NavMain({
<SidebarMenuSub> <SidebarMenuSub>
{item.items?.map((subItem) => { {item.items?.map((subItem) => {
const subItemActive = location.pathname.startsWith( const subItemActive = location.pathname.startsWith(
subItem.url, subItem.url
); );
return ( return (
@@ -143,12 +146,14 @@ export function NavMain({
data-active={subItemActive ? "true" : undefined} data-active={subItemActive ? "true" : undefined}
className={ className={
subItemActive subItemActive
? "text-primary font-medium" ? "text-primary"
: "" : "text-gray-600"
} }
> >
<Link to={subItem.url}> <Link to={subItem.url}>
<span>{subItem.title}</span> <span className="font-medium">
{subItem.title}
</span>
</Link> </Link>
</SidebarMenuSubButton> </SidebarMenuSubButton>
</SidebarMenuSubItem> </SidebarMenuSubItem>

View File

@@ -59,12 +59,12 @@ export function NavSecondary({
{item.url !== "#" ? ( {item.url !== "#" ? (
<a href={item.url}> <a href={item.url}>
<item.icon /> <item.icon />
<span>{item.title}</span> <span className="font-medium">{item.title}</span>
</a> </a>
) : ( ) : (
<> <>
<item.icon /> <item.icon />
<span>{item.title}</span> <span className="font-medium">{item.title}</span>
</> </>
)} )}
</SidebarMenuButton> </SidebarMenuButton>

View File

@@ -74,14 +74,12 @@ export function NavUser({ viewer }: { viewer: NavUser_viewer$key }) {
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<SidebarMenuButton <SidebarMenuButton
isActive
size="lg" size="lg"
className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground" className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
> >
<Avatar className="h-8 w-8 rounded-lg"> <Avatar className="h-9 w-9">
<AvatarFallback className="rounded-lg"> <AvatarFallback className="bg-slate-400 text-gray-100">
{currentUser.fullName.substring(0, 2).toUpperCase()}
</AvatarFallback>
<AvatarFallback className="rounded-lg">
{currentUser.fullName.substring(0, 2).toUpperCase()} {currentUser.fullName.substring(0, 2).toUpperCase()}
</AvatarFallback> </AvatarFallback>
</Avatar> </Avatar>
@@ -89,7 +87,9 @@ export function NavUser({ viewer }: { viewer: NavUser_viewer$key }) {
<span className="truncate font-semibold"> <span className="truncate font-semibold">
{currentUser.fullName} {currentUser.fullName}
</span> </span>
<span className="truncate text-xs">{currentUser.email}</span> <span className="truncate text-xs text-sidebar-foreground/70">
{currentUser.email}
</span>
</div> </div>
<ChevronsUpDown className="ml-auto size-4" /> <ChevronsUpDown className="ml-auto size-4" />
</SidebarMenuButton> </SidebarMenuButton>
@@ -102,11 +102,8 @@ export function NavUser({ viewer }: { viewer: NavUser_viewer$key }) {
> >
<DropdownMenuLabel className="p-0 font-normal"> <DropdownMenuLabel className="p-0 font-normal">
<div className="flex items-center gap-2 px-1 py-1.5 text-left text-sm"> <div className="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
<Avatar className="h-8 w-8 rounded-lg"> <Avatar className="h-8 w-8">
<AvatarFallback className="rounded-lg"> <AvatarFallback>
{currentUser.fullName.substring(0, 2).toUpperCase()}
</AvatarFallback>
<AvatarFallback className="rounded-lg">
{currentUser.fullName.substring(0, 2).toUpperCase()} {currentUser.fullName.substring(0, 2).toUpperCase()}
</AvatarFallback> </AvatarFallback>
</Avatar> </Avatar>

View File

@@ -24,6 +24,7 @@ import {
OrganizationSwitcher_organizations$key, OrganizationSwitcher_organizations$key,
OrganizationSwitcher_organizations$data, OrganizationSwitcher_organizations$data,
} from "./__generated__/OrganizationSwitcher_organizations.graphql"; } from "./__generated__/OrganizationSwitcher_organizations.graphql";
import { cn } from "@/lib/utils";
export const organizationSwitcherFragment = graphql` export const organizationSwitcherFragment = graphql`
fragment OrganizationSwitcher_organizations on User { fragment OrganizationSwitcher_organizations on User {
@@ -52,9 +53,15 @@ const LogoComponent = ({
className?: string; className?: string;
}) => { }) => {
if (org.logoUrl) { if (org.logoUrl) {
return <img src={org.logoUrl} alt={org.name} className={className} />; return (
<img
src={org.logoUrl}
alt={org.name}
className={cn("rounded-md", className)}
/>
);
} }
return null; return org.name.substring(0, 2).toUpperCase();
}; };
export function OrganizationSwitcher({ export function OrganizationSwitcher({
@@ -74,7 +81,7 @@ export function OrganizationSwitcher({
useEffect(() => { useEffect(() => {
if (hasOrganizations) { if (hasOrganizations) {
const org = data.organizations.edges.find( const org = data.organizations.edges.find(
(edge) => edge.node.id === organizationId, (edge) => edge.node.id === organizationId
); );
if (org) { if (org) {
setCurrentOrganization(org.node); setCurrentOrganization(org.node);
@@ -110,34 +117,30 @@ export function OrganizationSwitcher({
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<SidebarMenuButton <SidebarMenuButton
size="lg" size="lg"
className={`data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground ${ className={`data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground gap-2.5 ${
!currentOrganization !currentOrganization
? "border border-dashed border-gray-400" ? "border border-dashed border-gray-400"
: "" : ""
}`} }`}
> >
<div className="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground"> <div className="flex aspect-square size-8 items-center justify-center rounded-sm bg-slate-400 text-sidebar-primary-foreground overflow-hidden">
{currentOrganization ? ( {currentOrganization ? (
<LogoComponent org={currentOrganization} className="size-4" /> <LogoComponent org={currentOrganization} className="size-8" />
) : ( ) : (
<Building className="size-4 text-gray-400" /> <Building className="size-8 text-gray-400" />
)} )}
</div> </div>
<div className="grid flex-1 text-left text-sm leading-tight"> <div className="grid text-left leading-tight">
<span <span
className={`truncate font-semibold ${ className={`truncate font-medium text-lg leading-5 ${
!currentOrganization ? "text-gray-500" : "" !currentOrganization ? "text-gray-500" : "text-gray-900"
}`} }`}
> >
{currentOrganization {currentOrganization
? currentOrganization.name ? currentOrganization.name
: "Select Organization"} : "Select Organization"}
</span> </span>
<span <span className="truncate text-xs text-gray-500 font-medium">
className={`truncate text-xs ${
!currentOrganization ? "text-gray-400" : ""
}`}
>
{currentOrganization ? "Free" : "No organization selected"} {currentOrganization ? "Free" : "No organization selected"}
</span> </span>
</div> </div>
@@ -166,7 +169,7 @@ export function OrganizationSwitcher({
edge.node.id === organizationId ? "bg-muted" : "" edge.node.id === organizationId ? "bg-muted" : ""
}`} }`}
> >
<div className="flex size-6 items-center justify-center rounded-sm border"> <div className="flex size-6 items-center justify-center rounded-sm">
<LogoComponent <LogoComponent
org={edge.node} org={edge.node}
className="size-4 shrink-0" className="size-4 shrink-0"

View File

@@ -11,7 +11,7 @@ const Avatar = React.forwardRef<
ref={ref} ref={ref}
className={cn( className={cn(
"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", "relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
className, className
)} )}
{...props} {...props}
/> />
@@ -38,7 +38,7 @@ const AvatarFallback = React.forwardRef<
ref={ref} ref={ref}
className={cn( className={cn(
"flex h-full w-full items-center justify-center rounded-full bg-muted", "flex h-full w-full items-center justify-center rounded-full bg-muted",
className, className
)} )}
{...props} {...props}
/> />

View File

@@ -63,7 +63,7 @@ const SidebarProvider = React.forwardRef<
children, children,
...props ...props
}, },
ref, ref
) => { ) => {
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const [openMobile, setOpenMobile] = React.useState(false); const [openMobile, setOpenMobile] = React.useState(false);
@@ -84,7 +84,7 @@ const SidebarProvider = React.forwardRef<
// This sets the cookie to keep the sidebar state. // This sets the cookie to keep the sidebar state.
document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`; document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
}, },
[setOpenProp, open], [setOpenProp, open]
); );
// Helper to toggle the sidebar. // Helper to toggle the sidebar.
@@ -124,15 +124,7 @@ const SidebarProvider = React.forwardRef<
setOpenMobile, setOpenMobile,
toggleSidebar, toggleSidebar,
}), }),
[ [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]
state,
open,
setOpen,
isMobile,
openMobile,
setOpenMobile,
toggleSidebar,
],
); );
return ( return (
@@ -148,7 +140,7 @@ const SidebarProvider = React.forwardRef<
} }
className={cn( className={cn(
"group/sidebar-wrapper flex min-h-svh w-full has-data-[variant=inset]:bg-sidebar", "group/sidebar-wrapper flex min-h-svh w-full has-data-[variant=inset]:bg-sidebar",
className, className
)} )}
ref={ref} ref={ref}
{...props} {...props}
@@ -158,7 +150,7 @@ const SidebarProvider = React.forwardRef<
</TooltipProvider> </TooltipProvider>
</SidebarContext.Provider> </SidebarContext.Provider>
); );
}, }
); );
SidebarProvider.displayName = "SidebarProvider"; SidebarProvider.displayName = "SidebarProvider";
@@ -179,7 +171,7 @@ const Sidebar = React.forwardRef<
children, children,
...props ...props
}, },
ref, ref
) => { ) => {
const { isMobile, state, openMobile, setOpenMobile } = useSidebar(); const { isMobile, state, openMobile, setOpenMobile } = useSidebar();
@@ -188,7 +180,7 @@ const Sidebar = React.forwardRef<
<div <div
className={cn( className={cn(
"flex h-full w-(--sidebar-width) flex-col bg-sidebar text-sidebar-foreground", "flex h-full w-(--sidebar-width) flex-col bg-sidebar text-sidebar-foreground",
className, className
)} )}
ref={ref} ref={ref}
{...props} {...props}
@@ -235,7 +227,7 @@ const Sidebar = React.forwardRef<
"group-data-[side=right]:rotate-180", "group-data-[side=right]:rotate-180",
variant === "floating" || variant === "inset" variant === "floating" || variant === "inset"
? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]" ? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]"
: "group-data-[collapsible=icon]:w-(--sidebar-width-icon)", : "group-data-[collapsible=icon]:w-(--sidebar-width-icon)"
)} )}
/> />
<div <div
@@ -246,22 +238,22 @@ const Sidebar = React.forwardRef<
: "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]", : "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",
// Adjust the padding for floating and inset variants. // Adjust the padding for floating and inset variants.
variant === "floating" || variant === "inset" variant === "floating" || variant === "inset"
? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]" ? "p-4 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]"
: "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l", : "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l",
className, className
)} )}
{...props} {...props}
> >
<div <div
data-sidebar="sidebar" data-sidebar="sidebar"
className="flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow-sm" className="flex gap-2 h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow-sm"
> >
{children} {children}
</div> </div>
</div> </div>
</div> </div>
); );
}, }
); );
Sidebar.displayName = "Sidebar"; Sidebar.displayName = "Sidebar";
@@ -312,7 +304,7 @@ const SidebarRail = React.forwardRef<
"group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full hover:group-data-[collapsible=offcanvas]:bg-sidebar", "group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full hover:group-data-[collapsible=offcanvas]:bg-sidebar",
"[[data-side=left][data-collapsible=offcanvas]_&]:-right-2", "[[data-side=left][data-collapsible=offcanvas]_&]:-right-2",
"[[data-side=right][data-collapsible=offcanvas]_&]:-left-2", "[[data-side=right][data-collapsible=offcanvas]_&]:-left-2",
className, className
)} )}
{...props} {...props}
/> />
@@ -330,7 +322,7 @@ const SidebarInset = React.forwardRef<
className={cn( className={cn(
"relative flex min-h-svh flex-1 flex-col bg-background", "relative flex min-h-svh flex-1 flex-col bg-background",
"peer-data-[variant=inset]:min-h-[calc(100svh-(--spacing(4)))] md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm", "peer-data-[variant=inset]:min-h-[calc(100svh-(--spacing(4)))] md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm",
className, className
)} )}
{...props} {...props}
/> />
@@ -348,7 +340,7 @@ const SidebarInput = React.forwardRef<
data-sidebar="input" data-sidebar="input"
className={cn( className={cn(
"h-8 w-full bg-background shadow-none focus-visible:ring-2 focus-visible:ring-sidebar-ring", "h-8 w-full bg-background shadow-none focus-visible:ring-2 focus-visible:ring-sidebar-ring",
className, className
)} )}
{...props} {...props}
/> />
@@ -364,7 +356,7 @@ const SidebarHeader = React.forwardRef<
<div <div
ref={ref} ref={ref}
data-sidebar="header" data-sidebar="header"
className={cn("flex flex-col gap-2 p-2", className)} className={cn("flex flex-col gap-2", className)}
{...props} {...props}
/> />
); );
@@ -379,7 +371,7 @@ const SidebarFooter = React.forwardRef<
<div <div
ref={ref} ref={ref}
data-sidebar="footer" data-sidebar="footer"
className={cn("flex flex-col gap-2 p-2", className)} className={cn("flex flex-col gap-2", className)}
{...props} {...props}
/> />
); );
@@ -411,7 +403,7 @@ const SidebarContent = React.forwardRef<
data-sidebar="content" data-sidebar="content"
className={cn( className={cn(
"flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden", "flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden",
className, className
)} )}
{...props} {...props}
/> />
@@ -427,7 +419,7 @@ const SidebarGroup = React.forwardRef<
<div <div
ref={ref} ref={ref}
data-sidebar="group" data-sidebar="group"
className={cn("relative flex w-full min-w-0 flex-col p-2", className)} className={cn("relative flex w-full min-w-0 flex-col p-0", className)}
{...props} {...props}
/> />
); );
@@ -447,7 +439,7 @@ const SidebarGroupLabel = React.forwardRef<
className={cn( className={cn(
"flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 outline-hidden ring-sidebar-ring transition-[margin,opa] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0", "flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 outline-hidden ring-sidebar-ring transition-[margin,opa] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
"group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0", "group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0",
className, className
)} )}
{...props} {...props}
/> />
@@ -470,7 +462,7 @@ const SidebarGroupAction = React.forwardRef<
// Increases the hit area of the button on mobile. // Increases the hit area of the button on mobile.
"after:absolute after:-inset-2 md:after:hidden", "after:absolute after:-inset-2 md:after:hidden",
"group-data-[collapsible=icon]:hidden", "group-data-[collapsible=icon]:hidden",
className, className
)} )}
{...props} {...props}
/> />
@@ -518,25 +510,25 @@ const SidebarMenuItem = React.forwardRef<
SidebarMenuItem.displayName = "SidebarMenuItem"; SidebarMenuItem.displayName = "SidebarMenuItem";
const sidebarMenuButtonVariants = cva( const sidebarMenuButtonVariants = cva(
"peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0", "text-gray-600 peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-primary focus-visible:ring-2 active:bg-sidebar-accent active:text-primary disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-primary data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-primary group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 hover:cursor-pointer",
{ {
variants: { variants: {
variant: { variant: {
default: "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground", default: "hover:bg-sidebar-accent hover:text-primary",
outline: outline:
"bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]", "bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-primary hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]",
}, },
size: { size: {
default: "h-8 text-sm", default: "h-10 py-2 px-3 gap-3",
sm: "h-7 text-xs", sm: "h-8 text-sm",
lg: "h-12 text-sm group-data-[collapsible=icon]:p-0!", lg: "h-12 py-2 px-3 gap-3 group-data-[collapsible=icon]:p-0!",
}, },
}, },
defaultVariants: { defaultVariants: {
variant: "default", variant: "default",
size: "default", size: "default",
}, },
}, }
); );
const SidebarMenuButton = React.forwardRef< const SidebarMenuButton = React.forwardRef<
@@ -557,7 +549,7 @@ const SidebarMenuButton = React.forwardRef<
className, className,
...props ...props
}, },
ref, ref
) => { ) => {
const Comp = asChild ? Slot : "button"; const Comp = asChild ? Slot : "button";
const { isMobile, state } = useSidebar(); const { isMobile, state } = useSidebar();
@@ -594,7 +586,7 @@ const SidebarMenuButton = React.forwardRef<
/> />
</Tooltip> </Tooltip>
); );
}, }
); );
SidebarMenuButton.displayName = "SidebarMenuButton"; SidebarMenuButton.displayName = "SidebarMenuButton";
@@ -612,16 +604,16 @@ const SidebarMenuAction = React.forwardRef<
ref={ref} ref={ref}
data-sidebar="menu-action" data-sidebar="menu-action"
className={cn( className={cn(
"absolute right-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-hidden ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 peer-hover/menu-button:text-sidebar-accent-foreground [&>svg]:size-4 [&>svg]:shrink-0", "absolute right-1 top-1.5 flex aspect-square w-6 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-hidden ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 peer-hover/menu-button:text-sidebar-accent-foreground [&>svg]:size-4 [&>svg]:shrink-0 hover:cursor-pointer",
// Increases the hit area of the button on mobile. // Increases the hit area of the button on mobile.
"after:absolute after:-inset-2 md:after:hidden", "after:absolute after:-inset-2 md:after:hidden",
"peer-data-[size=sm]/menu-button:top-1", "peer-data-[size=sm]/menu-button:top-1",
"peer-data-[size=default]/menu-button:top-1.5", "peer-data-[size=default]/menu-button:top-2 peer-data-[size=default]/menu-button:right-2",
"peer-data-[size=lg]/menu-button:top-2.5", "peer-data-[size=lg]/menu-button:top-2.5",
"group-data-[collapsible=icon]:hidden", "group-data-[collapsible=icon]:hidden",
showOnHover && showOnHover &&
"group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 peer-data-[active=true]/menu-button:text-sidebar-accent-foreground md:opacity-0", "group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 peer-data-[active=true]/menu-button:text-sidebar-accent-foreground md:opacity-0",
className, className
)} )}
{...props} {...props}
/> />
@@ -643,7 +635,7 @@ const SidebarMenuBadge = React.forwardRef<
"peer-data-[size=default]/menu-button:top-1.5", "peer-data-[size=default]/menu-button:top-1.5",
"peer-data-[size=lg]/menu-button:top-2.5", "peer-data-[size=lg]/menu-button:top-2.5",
"group-data-[collapsible=icon]:hidden", "group-data-[collapsible=icon]:hidden",
className, className
)} )}
{...props} {...props}
/> />
@@ -696,9 +688,9 @@ const SidebarMenuSub = React.forwardRef<
ref={ref} ref={ref}
data-sidebar="menu-sub" data-sidebar="menu-sub"
className={cn( className={cn(
"mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5", "ml-5 flex min-w-0 flex-col gap-1 border-l border-sidebar-border px-2.5 py-1",
"group-data-[collapsible=icon]:hidden", "group-data-[collapsible=icon]:hidden",
className, className
)} )}
{...props} {...props}
/> />
@@ -728,12 +720,12 @@ const SidebarMenuSubButton = React.forwardRef<
data-size={size} data-size={size}
data-active={isActive} data-active={isActive}
className={cn( className={cn(
"flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground outline-hidden ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground", "flex h-7 min-w-0 items-center gap-2 overflow-hidden rounded-md px-4 text-sidebar-foreground outline-hidden ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground",
"data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground", "data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground",
size === "sm" && "text-xs", size === "sm" && "text-xs",
size === "md" && "text-sm", size === "md" && "text-sm",
"group-data-[collapsible=icon]:hidden", "group-data-[collapsible=icon]:hidden",
className, className
)} )}
{...props} {...props}
/> />

View File

@@ -134,7 +134,7 @@ function PeopleListContent({
}) { }) {
const data = usePreloadedQuery<PeopleListPageQueryType>( const data = usePreloadedQuery<PeopleListPageQueryType>(
peopleListPageQuery, peopleListPageQuery,
queryRef, queryRef
); );
const [, setSearchParams] = useSearchParams(); const [, setSearchParams] = useSearchParams();
const [, startTransition] = useTransition(); const [, startTransition] = useTransition();
@@ -211,7 +211,7 @@ function PeopleListContent({
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Badge <Badge
variant="secondary" variant="secondary"
className="bg-[#8BB563] text-white rounded-full px-3 py-0.5 text-xs font-medium" className="bg-lime-9 text-white rounded-full px-3 py-0.5 text-xs font-medium"
> >
{person?.kind === "EMPLOYEE" {person?.kind === "EMPLOYEE"
? "Employee" ? "Employee"
@@ -227,7 +227,7 @@ function PeopleListContent({
e.preventDefault(); e.preventDefault();
if ( if (
window.confirm( window.confirm(
"Are you sure you want to delete this person?", "Are you sure you want to delete this person?"
) )
) { ) {
deletePeople({ deletePeople({

View File

@@ -188,7 +188,7 @@ function VendorListContent({
const { toast } = useToast(); const { toast } = useToast();
const data = usePreloadedQuery<VendorListPageQueryType>( const data = usePreloadedQuery<VendorListPageQueryType>(
vendorListPageQuery, vendorListPageQuery,
queryRef, queryRef
); );
const [, setSearchParams] = useSearchParams(); const [, setSearchParams] = useSearchParams();
const [, startTransition] = useTransition(); const [, startTransition] = useTransition();
@@ -323,7 +323,7 @@ function VendorListContent({
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Badge <Badge
variant="secondary" variant="secondary"
className="bg-[#8BB563] text-white rounded-full px-3 py-0.5 text-xs font-medium" className="bg-lime-9 text-white rounded-full px-3 py-0.5 text-xs font-medium"
> >
Low Risk Low Risk
</Badge> </Badge>
@@ -335,7 +335,7 @@ function VendorListContent({
e.preventDefault(); // Prevent navigation e.preventDefault(); // Prevent navigation
if ( if (
window.confirm( window.confirm(
"Are you sure you want to delete this vendor?", "Are you sure you want to delete this vendor?"
) )
) { ) {
deleteVendor({ deleteVendor({

View File

@@ -0,0 +1,168 @@
@theme {
--color-lime-1: var(--lime-1);
--color-lime-2: var(--lime-2);
--color-lime-3: var(--lime-3);
--color-lime-4: var(--lime-4);
--color-lime-5: var(--lime-5);
--color-lime-6: var(--lime-6);
--color-lime-7: var(--lime-7);
--color-lime-8: var(--lime-8);
--color-lime-9: var(--lime-9);
--color-lime-10: var(--lime-10);
--color-lime-11: var(--lime-11);
--color-lime-12: var(--lime-12);
--color-lime-a1: var(--lime-a1);
--color-lime-a2: var(--lime-a2);
--color-lime-a3: var(--lime-a3);
--color-lime-a4: var(--lime-a4);
--color-lime-a5: var(--lime-a5);
--color-lime-a6: var(--lime-a6);
--color-lime-a7: var(--lime-a7);
--color-lime-a8: var(--lime-a8);
--color-lime-a9: var(--lime-a9);
--color-lime-a10: var(--lime-a10);
--color-lime-a11: var(--lime-a11);
--color-lime-a12: var(--lime-a12);
--color-lime-contrast: var(--lime-contrast);
--color-lime-surface: var(--lime-surface);
--color-lime-indicator: var(--lime-indicator);
--color-lime-track: var(--lime-track);
}
@layer base {
:root {
--lime-1: #fcfdfa;
--lime-2: #f7faf4;
--lime-3: #e9f7de;
--lime-4: #dbf1c9;
--lime-5: #cce8b5;
--lime-6: #bbdba0;
--lime-7: #a6ca87;
--lime-8: #8ab562;
--lime-9: #8bb663;
--lime-10: #80aa58;
--lime-11: #597b38;
--lime-12: #314023;
--lime-a1: #66990005;
--lime-a2: #468c000b;
--lime-a3: #55c20021;
--lime-a4: #55bd0036;
--lime-a5: #50b0014a;
--lime-a6: #499f005f;
--lime-a7: #428f0078;
--lime-a8: #4187009d;
--lime-a9: #4288009c;
--lime-a10: #3d7d00a7;
--lime-a11: #2a5600c7;
--lime-a12: #102200dc;
--lime-contrast: #fff;
--lime-surface: #f5f9f1cc;
--lime-indicator: #8bb663;
--lime-track: #8bb663;
@supports (color: color(display-p3 1 1 1)) {
@media (color-gamut: p3) {
--lime-1: oklch(99.3% 0.0039 131.3);
--lime-2: oklch(98.2% 0.0087 131.3);
--lime-3: oklch(96% 0.0366 131.3);
--lime-4: oklch(93.2% 0.0583 131.3);
--lime-5: oklch(89.8% 0.0744 131.3);
--lime-6: oklch(85.4% 0.0862 131.3);
--lime-7: oklch(79.5% 0.0979 131.3);
--lime-8: oklch(72.3% 0.121 131.3);
--lime-9: oklch(72.6% 0.121 131.3);
--lime-10: oklch(68.9% 0.121 131.3);
--lime-11: oklch(54.2% 0.1026 131.3);
--lime-12: oklch(35% 0.0511 131.3);
--lime-a1: color(display-p3 0.4118 0.6078 0.0196 / 0.02);
--lime-a2: color(display-p3 0.3765 0.5569 0.0196 / 0.044);
--lime-a3: color(display-p3 0.3922 0.7451 0.0039 / 0.122);
--lime-a4: color(display-p3 0.3647 0.702 0.0078 / 0.197);
--lime-a5: color(display-p3 0.3373 0.6549 0.0039 / 0.271);
--lime-a6: color(display-p3 0.3059 0.5843 0.0039 / 0.35);
--lime-a7: color(display-p3 0.2745 0.5255 0.0039 / 0.444);
--lime-a8: color(display-p3 0.2667 0.4902 0 / 0.577);
--lime-a9: color(display-p3 0.2667 0.4941 0 / 0.573);
--lime-a10: color(display-p3 0.251 0.4549 0 / 0.616);
--lime-a11: color(display-p3 0.1686 0.302 0 / 0.75);
--lime-a12: color(display-p3 0.0667 0.1216 0 / 0.851);
--lime-contrast: #fff;
--lime-surface: color(display-p3 0.9647 0.9765 0.9529 / 0.8);
--lime-indicator: oklch(72.6% 0.121 131.3);
--lime-track: oklch(72.6% 0.121 131.3);
}
}
}
.dark {
--lime-1: #0f120d;
--lime-2: #161914;
--lime-3: #21281b;
--lime-4: #2b371f;
--lime-5: #354527;
--lime-6: #405330;
--lime-7: #4c6238;
--lime-8: #597441;
--lime-9: #8bb663;
--lime-10: #80aa58;
--lime-11: #9cc775;
--lime-12: #d2ebbf;
--lime-a1: #00910002;
--lime-a2: #9ff46709;
--lime-a3: #b5fc7719;
--lime-a4: #b3fe6929;
--lime-a5: #b5fe7638;
--lime-a6: #baff8147;
--lime-a7: #beff8457;
--lime-a8: #bdfd846b;
--lime-a9: #c1ff88b1;
--lime-a10: #beff80a4;
--lime-a11: #c7ff94c3;
--lime-a12: #e4ffcfea;
--lime-contrast: #fff;
--lime-surface: #1b211780;
--lime-indicator: #8bb663;
--lime-track: #8bb663;
@supports (color: color(display-p3 1 1 1)) {
@media (color-gamut: p3) {
--lime-1: oklch(17.8% 0.0117 131.3);
--lime-2: oklch(20.9% 0.0117 131.3);
--lime-3: oklch(26.6% 0.025 131.3);
--lime-4: oklch(31.9% 0.0435 131.3);
--lime-5: oklch(36.7% 0.0515 131.3);
--lime-6: oklch(41.6% 0.06 131.3);
--lime-7: oklch(46.8% 0.0695 131.3);
--lime-8: oklch(52.4% 0.081 131.3);
--lime-9: oklch(72.6% 0.121 131.3);
--lime-10: oklch(68.9% 0.121 131.3);
--lime-11: oklch(78% 0.1182 131.3);
--lime-12: oklch(91.1% 0.0649 131.3);
--lime-a1: color(display-p3 0 0.8549 0 / 0.005);
--lime-a2: color(display-p3 0.7608 0.9922 0.4157 / 0.034);
--lime-a3: color(display-p3 0.7569 1 0.5137 / 0.097);
--lime-a4: color(display-p3 0.7529 1 0.4863 / 0.16);
--lime-a5: color(display-p3 0.7686 1 0.5176 / 0.219);
--lime-a6: color(display-p3 0.8 1 0.5686 / 0.274);
--lime-a7: color(display-p3 0.8 1 0.5804 / 0.337);
--lime-a8: color(display-p3 0.8 1 0.5843 / 0.412);
--lime-a9: color(display-p3 0.8118 1 0.5922 / 0.69);
--lime-a10: color(display-p3 0.8039 1 0.5647 / 0.639);
--lime-a11: color(display-p3 0.8314 1 0.6275 / 0.761);
--lime-a12: color(display-p3 0.9216 1 0.8353 / 0.912);
--lime-contrast: #fff;
--lime-surface: color(display-p3 0.1098 0.1255 0.0863 / 0.5);
--lime-indicator: oklch(72.6% 0.121 131.3);
--lime-track: oklch(72.6% 0.121 131.3);
}
}
}
}