Add new colors and wip use them all instead of tailwind ones
Signed-off-by: Émile Ré <nemile.re@gmail.com>
This commit is contained in:
@@ -1,5 +1,18 @@
|
||||
@import "tailwindcss";
|
||||
@import "./styles/colors.css";
|
||||
@import "@radix-ui/colors/blue.css";
|
||||
@import "@radix-ui/colors/blue-dark.css";
|
||||
@import "@radix-ui/colors/olive.css";
|
||||
@import "@radix-ui/colors/olive-alpha.css";
|
||||
@import "@radix-ui/colors/olive-dark.css";
|
||||
@import "@radix-ui/colors/olive-dark-alpha.css";
|
||||
@import "@radix-ui/colors/lime.css";
|
||||
@import "@radix-ui/colors/lime-dark.css";
|
||||
@import "@radix-ui/colors/red.css";
|
||||
@import "@radix-ui/colors/red-dark.css";
|
||||
@import "@radix-ui/colors/red-dark-alpha.css";
|
||||
@import "@radix-ui/colors/orange.css";
|
||||
@import "@radix-ui/colors/orange-dark.css";
|
||||
|
||||
@import "./styles/policy-content.css";
|
||||
|
||||
@plugin 'tailwindcss-animate';
|
||||
@@ -8,41 +21,107 @@
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
|
||||
@theme {
|
||||
--color-border: hsl(var(--border));
|
||||
--color-input: hsl(var(--input));
|
||||
--color-ring: hsl(var(--ring));
|
||||
--color-background: hsl(var(--background));
|
||||
--color-foreground: hsl(var(--foreground));
|
||||
/* Legacy */
|
||||
/* --color-border: hsl(var(--border)); -> solid-b
|
||||
--color-input: hsl(var(--input)); -> solid-b
|
||||
--color-ring: hsl(var(--ring)); -> active-b
|
||||
--color-background: hsl(var(--background)); -> level-0
|
||||
--color-foreground: hsl(var(--foreground)); -> primary
|
||||
|
||||
--color-primary: hsl(var(--primary));
|
||||
--color-primary-foreground: hsl(var(--primary-foreground));
|
||||
--color-primary: hsl(var(--primary)); -> primary
|
||||
--color-primary-foreground: hsl(var(--primary-foreground)); -> invert
|
||||
|
||||
--color-secondary: hsl(var(--secondary));
|
||||
--color-secondary-foreground: hsl(var(--secondary-foreground));
|
||||
--color-secondary: hsl(var(--secondary)); -> invert
|
||||
--color-secondary-foreground: hsl(var(--secondary-foreground)); -> secondary
|
||||
|
||||
--color-destructive: hsl(var(--destructive));
|
||||
--color-destructive-foreground: hsl(var(--destructive-foreground));
|
||||
--color-destructive: hsl(var(--destructive)); -> danger-bg
|
||||
--color-destructive-foreground: hsl(var(--destructive-foreground)); -> danger
|
||||
|
||||
--color-muted: hsl(var(--muted));
|
||||
--color-muted-foreground: hsl(var(--muted-foreground));
|
||||
--color-muted: hsl(var(--muted)); -> invert-bg
|
||||
--color-muted-foreground: hsl(var(--muted-foreground)); -> tertiary
|
||||
|
||||
--color-accent: hsl(var(--accent));
|
||||
--color-accent-foreground: hsl(var(--accent-foreground));
|
||||
--color-accent: hsl(var(--accent)); -> accent-bg
|
||||
--color-accent-foreground: hsl(var(--accent-foreground)); -> accent
|
||||
|
||||
--color-popover: hsl(var(--popover));
|
||||
--color-popover-foreground: hsl(var(--popover-foreground));
|
||||
--color-popover: hsl(var(--popover)); -> level-0
|
||||
--color-popover-foreground: hsl(var(--popover-foreground)); -> primary
|
||||
|
||||
--color-card: hsl(var(--card));
|
||||
--color-card-foreground: hsl(var(--card-foreground));
|
||||
--color-card: hsl(var(--card)); -> level-0
|
||||
--color-card-foreground: hsl(var(--card-foreground)); -> primary
|
||||
|
||||
--color-sidebar: hsl(var(--sidebar-background));
|
||||
--color-sidebar-foreground: hsl(var(--sidebar-foreground));
|
||||
--color-sidebar-primary: hsl(var(--sidebar-primary));
|
||||
--color-sidebar: hsl(var(--sidebar-background)); -> level-0
|
||||
--color-sidebar-foreground: hsl(var(--sidebar-foreground)); -> secondary
|
||||
--color-sidebar-primary: hsl(var(--sidebar-primary)); -> not used
|
||||
--color-sidebar-primary-foreground: hsl(var(--sidebar-primary-foreground));
|
||||
--color-sidebar-accent: hsl(var(--sidebar-accent));
|
||||
--color-sidebar-accent-foreground: hsl(var(--sidebar-accent-foreground));
|
||||
--color-sidebar-border: hsl(var(--sidebar-border));
|
||||
--color-sidebar-ring: hsl(var(--sidebar-ring));
|
||||
--color-sidebar-border: hsl(var(--sidebar-border)); -> solid-b
|
||||
--color-sidebar-ring: hsl(var(--sidebar-ring)); -> active-b */
|
||||
|
||||
/* New */
|
||||
/* Surfaces */
|
||||
--color-level-0: var(--level-0);
|
||||
--color-level-1: var(--level-1);
|
||||
--color-level-2: var(--level-2);
|
||||
--color-level-3: var(--level-3);
|
||||
|
||||
/* Text colors */
|
||||
--color-primary: var(--primary);
|
||||
--color-invert: var(--invert);
|
||||
--color-secondary: var(--secondary);
|
||||
--color-tertiary: var(--tertiary);
|
||||
--color-quaternary: var(--quaternary);
|
||||
--color-disabled: var(--disabled);
|
||||
--color-accent: var(--accent);
|
||||
--color-danger: var(--danger);
|
||||
--color-success: var(--success);
|
||||
--color-info: var(--info);
|
||||
--color-warning: var(--warning);
|
||||
|
||||
/* Background colors */
|
||||
--color-primary-bg: var(--primary-bg);
|
||||
--color-invert-bg: var(--invert-bg);
|
||||
--color-secondary-bg: var(--secondary-bg);
|
||||
--color-tertiary-bg: var(--tertiary-bg);
|
||||
--color-subtle-bg: var(--subtle-bg);
|
||||
--color-highlight-bg: var(--highlight-bg);
|
||||
--color-accent-bg: var(--accent-bg);
|
||||
--color-active-bg: var(--active-bg);
|
||||
--color-danger-bg: var(--danger-bg);
|
||||
--color-danger-plain-bg: var(--danger-plain-bg);
|
||||
--color-success-bg: var(--success-bg);
|
||||
--color-info-bg: var(--info-bg);
|
||||
--color-warning-bg: var(--warning-bg);
|
||||
/* Hover */
|
||||
--color-h-primary-bg: var(--h-primary-bg);
|
||||
--color-h-invert-bg: var(--h-invert-bg);
|
||||
--color-h-secondary-bg: var(--h-secondary-bg);
|
||||
--color-h-tertiary-bg: var(--h-tertiary-bg);
|
||||
--color-h-subtle-bg: var(--h-subtle-bg);
|
||||
--color-h-highlight-bg: var(--h-highlight-bg);
|
||||
--color-h-accent-bg: var(--h-accent-bg);
|
||||
--color-h-active-bg: var(--h-active-bg);
|
||||
/* Pressed */
|
||||
--color-p-primary-bg: var(--p-primary-bg);
|
||||
--color-p-invert-bg: var(--p-invert-bg);
|
||||
--color-p-secondary-bg: var(--p-secondary-bg);
|
||||
--color-p-tertiary-bg: var(--p-tertiary-bg);
|
||||
--color-p-subtle-bg: var(--p-subtle-bg);
|
||||
--color-p-highlight-bg: var(--p-highlight-bg);
|
||||
--color-p-accent-bg: var(--p-accent-bg);
|
||||
--color-p-active-bg: var(--p-active-bg);
|
||||
|
||||
/* Borders */
|
||||
--color-solid-b: var(--solid-b);
|
||||
--color-low-b: var(--low-b);
|
||||
--color-mid-b: var(--mid-b);
|
||||
--color-strong-b: var(--strong-b);
|
||||
--color-active-b: var(--active-b);
|
||||
--color-accent-b: var(--accent-b);
|
||||
--color-danger-b: var(--danger-b);
|
||||
--color-success-b: var(--success-b);
|
||||
--color-warning-b: var(--warning-b);
|
||||
--color-info-b: var(--info-b);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -59,12 +138,13 @@
|
||||
::before,
|
||||
::backdrop,
|
||||
::file-selector-button {
|
||||
border-color: var(--color-gray-200, currentColor);
|
||||
border-color: var(--color-mid-b, currentColor);
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
/* Legacy */
|
||||
/* :root {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 222.2 47.4% 11.2%;
|
||||
--muted: 210 40% 96.1%;
|
||||
@@ -122,14 +202,122 @@
|
||||
--sidebar-accent-foreground: 240 4.8% 95.9%;
|
||||
--sidebar-border: 240 3.7% 15.9%;
|
||||
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||
} */
|
||||
|
||||
/* New */
|
||||
:root {
|
||||
/* Surfaces */
|
||||
--level-0: #FAFAF5;
|
||||
--level-1: #FFFFFF;
|
||||
--level-2: #FFFFFF;
|
||||
--level-3: var(--olive-12);
|
||||
|
||||
/* Text colors */
|
||||
--primary: var(--olive-12);
|
||||
--invert: var(--olive-1);
|
||||
--secondary: var(--olive-11);
|
||||
--tertiary: var(--olive-10);
|
||||
--quaternary: var(--olive-8);
|
||||
--disabled: var(--olive-7);
|
||||
--accent: var(--lime-10);
|
||||
--danger: var(--red-11);
|
||||
--success: var(--lime-11);
|
||||
--info: var(--blue-11);
|
||||
--warning: var(--orange-11);
|
||||
|
||||
/* Background colors */
|
||||
--primary-bg: var(--olive-12);
|
||||
--invert-bg: #ffffff;
|
||||
--secondary-bg: var(--olive-1);
|
||||
--tertiary-bg: transparent;
|
||||
--subtle-bg: var(--olive-a2);
|
||||
--highlight-bg: var(--olive-a3);
|
||||
--accent-bg: var(--olive-12);
|
||||
--active-bg: var(--lime-4);
|
||||
--danger-bg: var(--red-3);
|
||||
--danger-plain-bg: var(--red-10);
|
||||
--success-bg: var(--lime-3);
|
||||
--info-bg: var(--blue-3);
|
||||
--warning-bg: var(--orange-3);
|
||||
/* Hover */
|
||||
--h-primary-bg: #273025;
|
||||
--h-invert-bg: var(--olive-2);
|
||||
--h-secondary-bg: var(--olive-2);
|
||||
--h-tertiary-bg: var(--olive-a2);
|
||||
--h-subtle-bg: var(--olive-a3);
|
||||
--h-highlight-bg: var(--olive-a4);
|
||||
--h-accent-bg: #1E2C1C;
|
||||
--h-active-bg: var(--lime-5);
|
||||
/* Pressed */
|
||||
--p-primary-bg: #30392E;
|
||||
--p-invert-bg: var(--olive-3);
|
||||
--p-secondary-bg: var(--olive-3);
|
||||
--p-tertiary-bg: var(--olive-a3);
|
||||
--p-subtle-bg: var(--olive-a4);
|
||||
--p-highlight-bg: var(--olive-a5);
|
||||
--p-accent-bg: #293A25;
|
||||
--p-active-bg: var(--lime-6);
|
||||
|
||||
/* Borders */
|
||||
--solid-b: var(--olive-4);
|
||||
--low-b: var(--olive-a4);
|
||||
--mid-b: var(--olive-a7);
|
||||
--strong-b: var(--olive-a8);
|
||||
--active-b: var(--olive-12);
|
||||
--accent-b: var(--lime-11);
|
||||
--danger-b: var(--red-10);
|
||||
--success-b: var(--lime-10);
|
||||
--warning-b: var(--orange-10);
|
||||
--info-b: var(--blue-10);
|
||||
}
|
||||
|
||||
.dark {
|
||||
/* Surfaces */
|
||||
--level-0: var(--olive-1);
|
||||
--level-1: var(--olive-2);
|
||||
--level-2: var(--olive-3);
|
||||
--level-3: var(--olive-7);
|
||||
|
||||
/* Text colors */
|
||||
--success: var(--lime-a11);
|
||||
|
||||
/* Background colors */
|
||||
--primary-bg: var(--lime-10);
|
||||
--invert-bg: var(--olive-1);
|
||||
--secondary-bg: var(--olive-a3);
|
||||
--active-bg: var(--olive-a4);
|
||||
--accent-bg: var(--lime-10);
|
||||
--danger-bg: var(--red-a3);
|
||||
--danger-plain-bg: var(--red-a10);
|
||||
--success-bg: var(--lime-a3);
|
||||
--info-bg: var(--blue-a3);
|
||||
--warning-bg: var(--orange-a3);
|
||||
/* Hover */
|
||||
--h-primary-bg: #C4F042E1;
|
||||
--h-secondary-bg: var(--olive-a3);
|
||||
--h-highlight-bg: var(--olive-a5);
|
||||
--h-accent-bg: var(--lime-a9);
|
||||
--h-active-bg: var(--olive-a5);
|
||||
/* Pressed */
|
||||
--p-primary-bg: #C4F042D7;
|
||||
--p-secondary-bg: var(--olive-a4);
|
||||
--p-highlight-bg: var(--olive-a6);
|
||||
--p-accent-bg: var(--lime-a10);
|
||||
--p-active-bg: var(--olive-a6);
|
||||
|
||||
/* Borders */
|
||||
--solid-b: var(--olive-5);
|
||||
--mid-b: var(--olive-a5);
|
||||
--active-b: var(--olive-a12);
|
||||
--warning-b: var(--orange-a10);
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border;
|
||||
@apply border-solid-b;
|
||||
}
|
||||
body {
|
||||
@apply font-sans antialiased bg-background text-foreground;
|
||||
@apply font-sans antialiased bg-level-0 text-primary;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ export function EditableField({
|
||||
</Label>
|
||||
{helpText && (
|
||||
<div className="relative flex items-center">
|
||||
<HelpCircle className="h-4 w-4 text-muted-foreground" />
|
||||
<HelpCircle className="h-4 w-4 text-tertiary" />
|
||||
<span className="sr-only">{helpText}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
} from "@/components/ui/collapsible";
|
||||
import {
|
||||
SidebarGroup,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuAction,
|
||||
SidebarMenuButton,
|
||||
@@ -63,9 +62,6 @@ export function NavMain() {
|
||||
|
||||
return (
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel className="text-gray-500 pl-3">
|
||||
Compliance
|
||||
</SidebarGroupLabel>
|
||||
<SidebarMenu>
|
||||
{items.map((item) => {
|
||||
const active = isItemActive(item) || item.isActive;
|
||||
|
||||
@@ -13,7 +13,7 @@ export function NavMainSkeleton() {
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel className="pl-3">
|
||||
<div className="py-0.5">
|
||||
<div className="h-3 w-24 rounded-sm bg-gray-300 animate-pulse" />
|
||||
<div className="h-3 w-24 rounded-sm bg-subtle-bg animate-pulse" />
|
||||
</div>
|
||||
</SidebarGroupLabel>
|
||||
<SidebarMenu className="space-y-1.5">
|
||||
@@ -21,7 +21,7 @@ export function NavMainSkeleton() {
|
||||
<SidebarMenuButton className="animate-pulse">
|
||||
<div className="h-4 w-4 rounded-md bg-lime-5" />
|
||||
<div className="py-[3px]">
|
||||
<div className="h-3.5 w-32 rounded-md bg-gray-300" />
|
||||
<div className="h-3.5 w-32 rounded-md bg-subtle-bg" />
|
||||
</div>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
@@ -29,7 +29,7 @@ export function NavMainSkeleton() {
|
||||
<SidebarMenuButton className="animate-pulse">
|
||||
<div className="h-4 w-4 rounded-md bg-lime-6" />
|
||||
<div className="py-[3px]">
|
||||
<div className="h-3.5 w-32 rounded-md bg-gray-300" />
|
||||
<div className="h-3.5 w-32 rounded-md bg-subtle-bg" />
|
||||
</div>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
@@ -37,7 +37,7 @@ export function NavMainSkeleton() {
|
||||
<SidebarMenuButton className="animate-pulse">
|
||||
<div className="h-4 w-4 rounded-md bg-lime-6" />
|
||||
<div className="py-[3px]">
|
||||
<div className="h-3.5 w-32 rounded-md bg-gray-300" />
|
||||
<div className="h-3.5 w-32 rounded-md bg-subtle-bg" />
|
||||
</div>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
@@ -45,7 +45,7 @@ export function NavMainSkeleton() {
|
||||
<SidebarMenuButton className="animate-pulse">
|
||||
<div className="h-4 w-4 rounded-md bg-lime-6" />
|
||||
<div className="py-[3px]">
|
||||
<div className="h-3.5 w-32 rounded-md bg-gray-300" />
|
||||
<div className="h-3.5 w-32 rounded-md bg-subtle-bg" />
|
||||
</div>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
|
||||
@@ -49,13 +49,9 @@ export function NavUser({ viewer }: { viewer: NavUser_viewer$key }) {
|
||||
<SidebarMenuItem>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<SidebarMenuButton
|
||||
isActive
|
||||
size="lg"
|
||||
className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
|
||||
>
|
||||
<SidebarMenuButton size="lg" variant="outline">
|
||||
<Avatar className="h-9 w-9">
|
||||
<AvatarFallback className="bg-slate-400 text-gray-100">
|
||||
<AvatarFallback className="bg-highlight-bg">
|
||||
{currentUser.fullName.substring(0, 2).toUpperCase()}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
@@ -63,7 +59,7 @@ export function NavUser({ viewer }: { viewer: NavUser_viewer$key }) {
|
||||
<span className="truncate font-semibold">
|
||||
{currentUser.fullName}
|
||||
</span>
|
||||
<span className="truncate text-xs text-sidebar-foreground/70">
|
||||
<span className="truncate text-xs text-secondary/70">
|
||||
{currentUser.email}
|
||||
</span>
|
||||
</div>
|
||||
@@ -78,7 +74,7 @@ export function NavUser({ viewer }: { viewer: NavUser_viewer$key }) {
|
||||
>
|
||||
<DropdownMenuLabel className="p-0 font-normal">
|
||||
<div className="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
|
||||
<Avatar className="h-8 w-8">
|
||||
<Avatar className="h-8 w-8 bg-highlight-bg">
|
||||
<AvatarFallback>
|
||||
{currentUser.fullName.substring(0, 2).toUpperCase()}
|
||||
</AvatarFallback>
|
||||
|
||||
@@ -14,14 +14,14 @@ export function NavUserSkeleton() {
|
||||
isActive
|
||||
disabled
|
||||
size="lg"
|
||||
className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground animate-pulse"
|
||||
className="data-[state=open]:bg-accent data-[state=open]:text-accent animate-pulse"
|
||||
>
|
||||
<div className="bg-gray-400 size-9 rounded-full animate-pulse" />
|
||||
<div className="bg-subtle-bg size-9 rounded-full animate-pulse" />
|
||||
<div className="flex-1 space-y-[3px] animate-pulse">
|
||||
<div className="h-3.5 w-20 rounded-sm bg-gray-400" />
|
||||
<div className="h-3.5 w-30 rounded-sm bg-gray-400" />
|
||||
<div className="h-3.5 w-20 rounded-sm bg-subtle-bg" />
|
||||
<div className="h-3.5 w-30 rounded-sm bg-subtle-bg" />
|
||||
</div>
|
||||
<div className="ml-auto size-4 rounded-lg bg-gray-400" />
|
||||
<div className="ml-auto size-4 rounded-lg bg-subtle-bg" />
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
</SidebarMenu>
|
||||
|
||||
@@ -101,27 +101,28 @@ export function OrganizationSwitcher({
|
||||
<DropdownMenuTrigger asChild>
|
||||
<SidebarMenuButton
|
||||
size="lg"
|
||||
variant="ghost"
|
||||
className={cn(
|
||||
"data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground gap-2.5",
|
||||
!currentOrganization && "border border-dashed border-gray-300"
|
||||
"gap-2.5",
|
||||
!currentOrganization && "border border-dashed"
|
||||
)}
|
||||
>
|
||||
<div className="flex aspect-square size-8 items-center justify-center rounded-sm bg-slate-400 text-gray-100">
|
||||
<div className="flex aspect-square size-8 items-center justify-center rounded-sm bg-highlight-bg">
|
||||
{currentOrganization ? (
|
||||
<LogoComponent org={currentOrganization} className="size-8" />
|
||||
) : (
|
||||
<div className="size-8 bg-slate-400 rounded-sm" />
|
||||
<div className="size-8 bg-highlight-bg rounded-sm" />
|
||||
)}
|
||||
</div>
|
||||
<div className="grid text-left leading-tight">
|
||||
<div className="grid text-left leading-tight text-primary">
|
||||
{currentOrganization ? (
|
||||
<>
|
||||
<span className="truncate font-medium text-lg leading-5 text-gray-900">
|
||||
<span className="truncate font-medium text-lg leading-5">
|
||||
{currentOrganization.name}
|
||||
</span>
|
||||
</>
|
||||
) : (
|
||||
<span className="truncate text-gray-500 font-medium">
|
||||
<span className="truncate text-secondary font-medium">
|
||||
Select Organization
|
||||
</span>
|
||||
)}
|
||||
@@ -135,7 +136,7 @@ export function OrganizationSwitcher({
|
||||
side={isMobile ? "bottom" : "right"}
|
||||
sideOffset={4}
|
||||
>
|
||||
<DropdownMenuLabel className="text-xs text-muted-foreground">
|
||||
<DropdownMenuLabel className="text-xs text-tertiary">
|
||||
Organizations
|
||||
</DropdownMenuLabel>
|
||||
{hasOrganizations &&
|
||||
@@ -144,10 +145,10 @@ export function OrganizationSwitcher({
|
||||
key={edge.node.id}
|
||||
onClick={() => handleOrganizationSwitch(edge.node)}
|
||||
className={`gap-2 p-2 ${
|
||||
edge.node.id === organizationId ? "bg-muted" : ""
|
||||
edge.node.id === organizationId ? "bg-subtle-bg" : ""
|
||||
}`}
|
||||
>
|
||||
<div className="flex size-6 items-center justify-center rounded-sm">
|
||||
<div className="flex size-6 items-center justify-center rounded-sm bg-highlight-bg">
|
||||
<LogoComponent
|
||||
org={edge.node}
|
||||
className="size-4 shrink-0"
|
||||
@@ -163,10 +164,10 @@ export function OrganizationSwitcher({
|
||||
to="/organizations/new"
|
||||
className="gap-2 p-2 cursor-pointer"
|
||||
>
|
||||
<div className="flex size-6 items-center justify-center rounded-md border bg-background">
|
||||
<div className="flex size-6 items-center justify-center rounded-md border bg-secondary-bg">
|
||||
<Plus className="size-4" />
|
||||
</div>
|
||||
<div className="font-medium text-muted-foreground">
|
||||
<div className="font-medium text-tertiary">
|
||||
Add organization
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
@@ -12,18 +12,18 @@ export function OrganizationSwitcherSkeleton() {
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton
|
||||
size="lg"
|
||||
className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground gap-2.5"
|
||||
className="data-[state=open]:bg-accent-bg data-[state=open]:text-accent gap-2.5"
|
||||
>
|
||||
<div className="size-8 items-center justify-center rounded-md bg-gray-300 animate-pulse" />
|
||||
<div className="size-8 items-center justify-center rounded-md bg-subtle-bg animate-pulse" />
|
||||
<div className="flex flex-col items-start">
|
||||
<div className="py-[1px]">
|
||||
<div className="h-4.5 animate-pulse w-16 rounded-sm bg-gray-300" />
|
||||
<div className="h-4.5 animate-pulse w-16 rounded-sm bg-subtle-bg" />
|
||||
</div>
|
||||
<div className="py-0.5">
|
||||
<div className="h-3 animate-pulse w-8 rounded-sm bg-gray-300" />
|
||||
<div className="h-3 animate-pulse w-8 rounded-sm bg-subtle-bg" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="ml-auto size-4 rounded-lg bg-gray-300 animate-pulse" />
|
||||
<div className="ml-auto size-4 rounded-lg bg-subtle-bg animate-pulse" />
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
</SidebarMenu>
|
||||
|
||||
@@ -57,7 +57,7 @@ export function PageHeading({
|
||||
const PageHeadingSkeleton: FC = () => {
|
||||
return (
|
||||
<div className="py-[3px] w-2/5">
|
||||
<div className="bg-muted animate rounded-lg h-7.5" />
|
||||
<div className="bg-subtle-bg animate rounded-lg h-7.5" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -70,12 +70,7 @@ export function PageDescription({
|
||||
children: ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"text-md text-muted-foreground whitespace-pre-wrap",
|
||||
className
|
||||
)}
|
||||
>
|
||||
<div className={cn("text-md text-tertiary text-left", className)}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
@@ -84,7 +79,7 @@ export function PageDescription({
|
||||
export function PageDescriptionSkeleton() {
|
||||
return (
|
||||
<div className="py-[5px]">
|
||||
<div className="bg-muted animate rounded-md w-100 h-4.5" />
|
||||
<div className="bg-subtle-bg animate rounded-md w-100 h-4.5" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
line-height: 1.5;
|
||||
font-weight: 400;
|
||||
margin-top: 0.5rem;
|
||||
border: 1px solid hsl(var(--border));
|
||||
border: 1px solid var(--solid-b);
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.policy-editor {
|
||||
background: #fff;
|
||||
background: var(--bg-invert-bg);
|
||||
position: relative;
|
||||
border-radius: 0.5rem;
|
||||
display: flex;
|
||||
@@ -63,8 +63,8 @@
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 8px;
|
||||
border-bottom: 1px solid hsl(var(--border));
|
||||
background-color: hsl(var(--muted));
|
||||
border-bottom: 1px solid hsl(var(--solid-b));
|
||||
background-color: hsl(var(--invert-bg));
|
||||
border-radius: 0.5rem 0.5rem 0 0;
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
|
||||
.policy-editor .toolbar .divider {
|
||||
width: 1px;
|
||||
background-color: hsl(var(--border));
|
||||
background-color: hsl(var(--solid-b));
|
||||
margin: 0 8px;
|
||||
height: 24px;
|
||||
}
|
||||
@@ -130,8 +130,8 @@
|
||||
margin: 0;
|
||||
margin-left: 20px;
|
||||
padding-left: 16px;
|
||||
border-left: 4px solid hsl(var(--border));
|
||||
color: hsl(var(--muted-foreground));
|
||||
border-left: 4px solid hsl(var(--solid-b));
|
||||
color: hsl(var(--tertiary));
|
||||
}
|
||||
|
||||
.editor-list-ol {
|
||||
@@ -174,7 +174,7 @@
|
||||
}
|
||||
|
||||
.editor-text-code {
|
||||
background-color: hsl(var(--muted));
|
||||
background-color: hsl(var(--invert-bg));
|
||||
padding: 1px 4px;
|
||||
border-radius: 4px;
|
||||
font-family: monospace;
|
||||
@@ -186,7 +186,7 @@
|
||||
}
|
||||
|
||||
.editor-code {
|
||||
background-color: hsl(var(--muted));
|
||||
background-color: hsl(var(--invert-bg));
|
||||
font-family: monospace;
|
||||
display: block;
|
||||
padding: 8px 16px;
|
||||
@@ -227,4 +227,4 @@
|
||||
|
||||
.editor-tokenFunction {
|
||||
color: #dd4a68;
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ const AvatarFallback = React.forwardRef<
|
||||
<AvatarPrimitive.Fallback
|
||||
ref={ref}
|
||||
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-subtle-bg",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -4,23 +4,23 @@ import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const badgeVariants = cva(
|
||||
"inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
||||
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-hidden focus:ring-2 focus:ring-active-b focus:ring-offset-2",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
"border-transparent bg-primary text-primary-foreground shadow-sm hover:bg-primary/80",
|
||||
secondary:
|
||||
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
||||
destructive:
|
||||
"border-transparent bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/80",
|
||||
outline: "text-foreground",
|
||||
default: "bg-primary-bg text-invert",
|
||||
secondary: "bg-secondary-bg border border-low-b",
|
||||
info: "bg-info-bg text-info border-info-b",
|
||||
success: "bg-success-bg text-success border-success-b",
|
||||
warning: "bg-warning-bg text-warning border-warning-b",
|
||||
destructive: "bg-danger-bg text-danger border-danger-b",
|
||||
outline: "",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
export interface BadgeProps
|
||||
|
||||
@@ -19,7 +19,7 @@ const BreadcrumbList = React.forwardRef<
|
||||
<ol
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"flex flex-wrap items-center gap-3 break-words text-sm text-gray-500 sm:gap-2.5",
|
||||
"flex flex-wrap items-center gap-3 break-words text-sm text-secondary sm:gap-2.5",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
@@ -66,7 +66,7 @@ const BreadcrumbPage = React.forwardRef<
|
||||
role="link"
|
||||
aria-disabled="true"
|
||||
aria-current="page"
|
||||
className={cn("font-normal text-gray-700", className)}
|
||||
className={cn("font-normal text-primary", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
@@ -80,7 +80,7 @@ const BreadcrumbSeparator = ({
|
||||
<li
|
||||
role="presentation"
|
||||
aria-hidden="true"
|
||||
className={cn("[&>svg]:w-3.5 [&>svg]:h-3.5 text-gray-300", className)}
|
||||
className={cn("[&>svg]:w-3.5 [&>svg]:h-3.5 text-quaternary", className)}
|
||||
{...props}
|
||||
>
|
||||
{children ?? "/"}
|
||||
|
||||
@@ -5,25 +5,25 @@ import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const buttonVariants = cva(
|
||||
"cursor-pointer inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||
"rounded-full cursor-pointer inline-flex items-center justify-center gap-2 whitespace-nowrap text-sm font-medium transition-colors focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-active-b disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
"bg-primary text-primary-foreground shadow-sm hover:bg-primary/90",
|
||||
default: "bg-primary-bg text-invert shadow-sm hover:bg-h-primary-bg",
|
||||
destructive:
|
||||
"bg-destructive text-destructive-foreground shadow-xs hover:bg-destructive/90",
|
||||
"bg-danger-plain-bg text-invert shadow-xs hover:bg-danger-plain-bg/90",
|
||||
outline:
|
||||
"border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground",
|
||||
"border border-low-b hover:bg-h-tertiary-bg active:bg-p-tertiary-bg focus:bg-tertiary-bg shadow-xs",
|
||||
secondary:
|
||||
"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
|
||||
ghost: "hover:bg-accent hover:text-accent-foreground",
|
||||
"bg-secondary-bg border border-low-b shadow-sm hover:bg-h-secondary-bg",
|
||||
ghost:
|
||||
"hover:bg-h-tertiary-bg active:bg-p-tertiary-bg focus:bg-tertiary-bg",
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
},
|
||||
size: {
|
||||
default: "h-9 px-4 py-2",
|
||||
sm: "h-8 rounded-md px-3 text-xs",
|
||||
lg: "h-10 rounded-md px-8",
|
||||
sm: "h-8 px-3 text-xs",
|
||||
lg: "h-10 px-8",
|
||||
icon: "h-9 w-9",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -8,10 +8,7 @@ const Card = React.forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"rounded-xl border bg-card text-card-foreground shadow-sm",
|
||||
className,
|
||||
)}
|
||||
className={cn("rounded-xl border bg-level-1", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
@@ -47,7 +44,7 @@ const CardDescription = React.forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn("text-sm text-muted-foreground", className)}
|
||||
className={cn("text-sm text-tertiary", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
||||
@@ -11,8 +11,8 @@ const Checkbox = React.forwardRef<
|
||||
<CheckboxPrimitive.Root
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
|
||||
className,
|
||||
"peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-level-0 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-active-b focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-invert",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
|
||||
@@ -18,7 +18,7 @@ const Command = React.forwardRef<
|
||||
<CommandPrimitive
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
|
||||
"flex h-full w-full flex-col overflow-hidden rounded-md bg-level-0 text-primary",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
@@ -30,7 +30,7 @@ const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
|
||||
return (
|
||||
<Dialog {...props}>
|
||||
<DialogContent className="overflow-hidden p-0 shadow-lg">
|
||||
<Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
|
||||
<Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-tertiary [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
|
||||
{children}
|
||||
</Command>
|
||||
</DialogContent>
|
||||
@@ -47,7 +47,7 @@ const CommandInput = React.forwardRef<
|
||||
<CommandPrimitive.Input
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
||||
"flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-tertiary disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
@@ -90,7 +90,7 @@ const CommandGroup = React.forwardRef<
|
||||
<CommandPrimitive.Group
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
|
||||
"overflow-hidden p-1 text-primary [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-tertiary",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
@@ -105,7 +105,7 @@ const CommandSeparator = React.forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<CommandPrimitive.Separator
|
||||
ref={ref}
|
||||
className={cn("-mx-1 h-px bg-border", className)}
|
||||
className={cn("-mx-1 h-px bg-solid-b", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
@@ -118,7 +118,7 @@ const CommandItem = React.forwardRef<
|
||||
<CommandPrimitive.Item
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 hover:bg-gray-100 transition-colors",
|
||||
"relative flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none aria-selected:bg-accent-bg aria-selected:text-accent data-[disabled]:pointer-events-none data-[disabled]:opacity-50 hover:bg-secondary-bg transition-colors",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
@@ -133,10 +133,7 @@ const CommandShortcut = ({
|
||||
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
||||
return (
|
||||
<span
|
||||
className={cn(
|
||||
"ml-auto text-xs tracking-widest text-muted-foreground",
|
||||
className
|
||||
)}
|
||||
className={cn("ml-auto text-xs tracking-widest text-tertiary", className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -19,7 +19,7 @@ const DialogOverlay = React.forwardRef<
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed inset-0 z-50 bg-black/50 backdrop-blur-xs data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
||||
className,
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
@@ -35,13 +35,13 @@ const DialogContent = React.forwardRef<
|
||||
<DialogPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-gray-200 bg-white p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
|
||||
className,
|
||||
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-mid-b bg-white p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-white transition-opacity hover:opacity-100 focus:outline-hidden focus:ring-2 focus:ring-gray-950 focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-gray-100 data-[state=open]:text-gray-500">
|
||||
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-white transition-opacity hover:opacity-100 focus:outline-hidden focus:ring-2 focus:ring-active focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary-bg data-[state=open]:text-secondary">
|
||||
<X className="h-4 w-4" />
|
||||
<span className="sr-only">Close</span>
|
||||
</DialogPrimitive.Close>
|
||||
@@ -57,7 +57,7 @@ const DialogHeader = ({
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col space-y-1.5 text-center sm:text-left",
|
||||
className,
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
@@ -71,7 +71,7 @@ const DialogFooter = ({
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
|
||||
className,
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
@@ -86,7 +86,7 @@ const DialogTitle = React.forwardRef<
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"text-lg font-semibold leading-none tracking-tight",
|
||||
className,
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
@@ -99,7 +99,7 @@ const DialogDescription = React.forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DialogPrimitive.Description
|
||||
ref={ref}
|
||||
className={cn("text-sm text-gray-500", className)}
|
||||
className={cn("text-sm text-secondary", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
||||
@@ -27,9 +27,9 @@ const DropdownMenuSubTrigger = React.forwardRef<
|
||||
<DropdownMenuPrimitive.SubTrigger
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-hidden focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||
"flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-hidden focus:bg-accent-bg data-[state=open]:bg-accent-bg [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||
inset && "pl-8",
|
||||
className,
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
@@ -47,8 +47,8 @@ const DropdownMenuSubContent = React.forwardRef<
|
||||
<DropdownMenuPrimitive.SubContent
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
className,
|
||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-level-1 p-1 shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
@@ -65,9 +65,9 @@ const DropdownMenuContent = React.forwardRef<
|
||||
ref={ref}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md",
|
||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-level-1 p-1 shadow-md",
|
||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
className,
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
@@ -84,9 +84,9 @@ const DropdownMenuItem = React.forwardRef<
|
||||
<DropdownMenuPrimitive.Item
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0",
|
||||
"relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden transition-colors focus:bg-active-bg focus:text-active data-disabled:pointer-events-none data-disabled:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0",
|
||||
inset && "pl-8",
|
||||
className,
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
@@ -100,8 +100,8 @@ const DropdownMenuCheckboxItem = React.forwardRef<
|
||||
<DropdownMenuPrimitive.CheckboxItem
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
|
||||
className,
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden transition-colors focus:bg-accent-bg focus:text-accent data-disabled:pointer-events-none data-disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
checked={checked}
|
||||
{...props}
|
||||
@@ -124,8 +124,8 @@ const DropdownMenuRadioItem = React.forwardRef<
|
||||
<DropdownMenuPrimitive.RadioItem
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
|
||||
className,
|
||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden transition-colors focus:bg-accent-bg focus:text-accent data-disabled:pointer-events-none data-disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
@@ -150,7 +150,7 @@ const DropdownMenuLabel = React.forwardRef<
|
||||
className={cn(
|
||||
"px-2 py-1.5 text-sm font-semibold",
|
||||
inset && "pl-8",
|
||||
className,
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
@@ -163,7 +163,7 @@ const DropdownMenuSeparator = React.forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DropdownMenuPrimitive.Separator
|
||||
ref={ref}
|
||||
className={cn("-mx-1 my-1 h-px bg-muted", className)}
|
||||
className={cn("-mx-1 my-1 h-px bg-subtle-bg", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
||||
@@ -8,14 +8,14 @@ const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
|
||||
<input
|
||||
type={type}
|
||||
className={cn(
|
||||
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-xs transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
||||
className,
|
||||
"flex h-9 w-full rounded-md border border-solid-b bg-invert-bg px-3 py-1 text-base shadow-xs transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-primary placeholder:text-tertiary focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-active-b disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
||||
className
|
||||
)}
|
||||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
},
|
||||
}
|
||||
);
|
||||
Input.displayName = "Input";
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ const PopoverContent = React.forwardRef<
|
||||
align={align}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
"z-50 w-72 rounded-md border bg-level-0 p-4 text-primary shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -26,8 +26,8 @@ const RadioGroupItem = React.forwardRef<
|
||||
<RadioGroupPrimitive.Item
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className,
|
||||
"aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-level-0 focus:outline-hidden focus-visible:ring-2 focus-visible:ring-active-b focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
|
||||
@@ -17,8 +17,8 @@ const SelectTrigger = React.forwardRef<
|
||||
<SelectPrimitive.Trigger
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className,
|
||||
"flex h-10 w-full items-center justify-between rounded-md border border-solid-b bg-invert-bg px-3 py-2 text-sm ring-offset-level-0 placeholder:text-tertiary focus:outline-hidden focus:ring focus:ring-active-b disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
@@ -36,10 +36,10 @@ const SelectContent = React.forwardRef<
|
||||
<SelectPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
"relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-invert-bg text-primary shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
position === "popper" &&
|
||||
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
||||
className,
|
||||
className
|
||||
)}
|
||||
position={position}
|
||||
{...props}
|
||||
@@ -48,7 +48,7 @@ const SelectContent = React.forwardRef<
|
||||
className={cn(
|
||||
"p-1",
|
||||
position === "popper" &&
|
||||
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]",
|
||||
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
@@ -65,8 +65,8 @@ const SelectItem = React.forwardRef<
|
||||
<SelectPrimitive.Item
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
|
||||
className,
|
||||
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-hidden focus:bg-active-bg focus:text-active data-disabled:pointer-events-none data-disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
|
||||
@@ -9,20 +9,20 @@ const Separator = React.forwardRef<
|
||||
>(
|
||||
(
|
||||
{ className, orientation = "horizontal", decorative = true, ...props },
|
||||
ref,
|
||||
ref
|
||||
) => (
|
||||
<SeparatorPrimitive.Root
|
||||
ref={ref}
|
||||
decorative={decorative}
|
||||
orientation={orientation}
|
||||
className={cn(
|
||||
"shrink-0 bg-border",
|
||||
"shrink-0 bg-solid-b",
|
||||
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
|
||||
className,
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
)
|
||||
);
|
||||
Separator.displayName = SeparatorPrimitive.Root.displayName;
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ const SheetOverlay = React.forwardRef<
|
||||
<SheetPrimitive.Overlay
|
||||
className={cn(
|
||||
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
||||
className,
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
ref={ref}
|
||||
@@ -31,7 +31,7 @@ const SheetOverlay = React.forwardRef<
|
||||
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
|
||||
|
||||
const sheetVariants = cva(
|
||||
"fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out",
|
||||
"fixed z-50 gap-4 bg-level-0 p-6 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out",
|
||||
{
|
||||
variants: {
|
||||
side: {
|
||||
@@ -46,7 +46,7 @@ const sheetVariants = cva(
|
||||
defaultVariants: {
|
||||
side: "right",
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
interface SheetContentProps
|
||||
@@ -64,7 +64,7 @@ const SheetContent = React.forwardRef<
|
||||
className={cn(sheetVariants({ side }), className)}
|
||||
{...props}
|
||||
>
|
||||
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
|
||||
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-level-0 transition-opacity hover:opacity-100 focus:outline-hidden focus:ring-2 focus:ring-active-b focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-invert">
|
||||
<X className="h-4 w-4" />
|
||||
<span className="sr-only">Close</span>
|
||||
</SheetPrimitive.Close>
|
||||
@@ -81,7 +81,7 @@ const SheetHeader = ({
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col space-y-2 text-center sm:text-left",
|
||||
className,
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
@@ -95,7 +95,7 @@ const SheetFooter = ({
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
|
||||
className,
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
@@ -108,7 +108,7 @@ const SheetTitle = React.forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SheetPrimitive.Title
|
||||
ref={ref}
|
||||
className={cn("text-lg font-semibold text-foreground", className)}
|
||||
className={cn("text-lg font-semibold text-primary", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
@@ -120,7 +120,7 @@ const SheetDescription = React.forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SheetPrimitive.Description
|
||||
ref={ref}
|
||||
className={cn("text-sm text-muted-foreground", className)}
|
||||
className={cn("text-sm text-tertiary", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
||||
@@ -139,7 +139,7 @@ const SidebarProvider = React.forwardRef<
|
||||
} as React.CSSProperties
|
||||
}
|
||||
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-level-0",
|
||||
className
|
||||
)}
|
||||
ref={ref}
|
||||
@@ -179,7 +179,7 @@ const Sidebar = React.forwardRef<
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"flex h-full w-(--sidebar-width) flex-col bg-sidebar text-sidebar-foreground",
|
||||
"flex h-full w-(--sidebar-width) flex-col bg-level-0 text-secondary",
|
||||
className
|
||||
)}
|
||||
ref={ref}
|
||||
@@ -196,7 +196,7 @@ const Sidebar = React.forwardRef<
|
||||
<SheetContent
|
||||
data-sidebar="sidebar"
|
||||
data-mobile="true"
|
||||
className="w-(--sidebar-width) bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden"
|
||||
className="w-(--sidebar-width) bg-level-0 p-0 text-secondary [&>button]:hidden"
|
||||
style={
|
||||
{
|
||||
"--sidebar-width": SIDEBAR_WIDTH_MOBILE,
|
||||
@@ -213,7 +213,7 @@ const Sidebar = React.forwardRef<
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className="group peer hidden text-sidebar-foreground md:block"
|
||||
className="group peer hidden text-secondary md:block"
|
||||
data-state={state}
|
||||
data-collapsible={state === "collapsed" ? collapsible : ""}
|
||||
data-variant={variant}
|
||||
@@ -246,7 +246,7 @@ const Sidebar = React.forwardRef<
|
||||
>
|
||||
<div
|
||||
data-sidebar="sidebar"
|
||||
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"
|
||||
className="flex gap-2 h-full w-full flex-col bg-level-0 group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-solid-b group-data-[variant=floating]:shadow-sm"
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
@@ -298,10 +298,10 @@ const SidebarRail = React.forwardRef<
|
||||
onClick={toggleSidebar}
|
||||
title="Toggle Sidebar"
|
||||
className={cn(
|
||||
"absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex",
|
||||
"absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-solid-b group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex",
|
||||
"in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize",
|
||||
"[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize",
|
||||
"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-level-0",
|
||||
"[[data-side=left][data-collapsible=offcanvas]_&]:-right-2",
|
||||
"[[data-side=right][data-collapsible=offcanvas]_&]:-left-2",
|
||||
className
|
||||
@@ -320,7 +320,7 @@ const SidebarInset = React.forwardRef<
|
||||
<main
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex min-h-svh flex-1 flex-col bg-background",
|
||||
"relative flex min-h-svh flex-1 flex-col bg-level-0",
|
||||
"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
|
||||
)}
|
||||
@@ -339,7 +339,7 @@ const SidebarInput = React.forwardRef<
|
||||
ref={ref}
|
||||
data-sidebar="input"
|
||||
className={cn(
|
||||
"h-8 w-full bg-background shadow-none focus-visible:ring-2 focus-visible:ring-sidebar-ring",
|
||||
"h-8 w-full bg-level-0 shadow-none focus-visible:ring-2 focus-visible:ring-active-b",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
@@ -386,7 +386,7 @@ const SidebarSeparator = React.forwardRef<
|
||||
<Separator
|
||||
ref={ref}
|
||||
data-sidebar="separator"
|
||||
className={cn("mx-2 w-auto bg-sidebar-border", className)}
|
||||
className={cn("mx-2 w-auto bg-solid-b", className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
@@ -437,7 +437,7 @@ const SidebarGroupLabel = React.forwardRef<
|
||||
ref={ref}
|
||||
data-sidebar="group-label"
|
||||
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-secondary/70 outline-hidden ring-active-b 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",
|
||||
className
|
||||
)}
|
||||
@@ -458,7 +458,7 @@ const SidebarGroupAction = React.forwardRef<
|
||||
ref={ref}
|
||||
data-sidebar="group-action"
|
||||
className={cn(
|
||||
"absolute right-3 top-3.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 [&>svg]:size-4 [&>svg]:shrink-0",
|
||||
"absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-secondary outline-hidden ring-active-b transition-transform hover:bg-accent-bg hover:text-accent focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
|
||||
// Increases the hit area of the button on mobile.
|
||||
"after:absolute after:-inset-2 md:after:hidden",
|
||||
"group-data-[collapsible=icon]:hidden",
|
||||
@@ -510,13 +510,16 @@ const SidebarMenuItem = React.forwardRef<
|
||||
SidebarMenuItem.displayName = "SidebarMenuItem";
|
||||
|
||||
const sidebarMenuButtonVariants = cva(
|
||||
"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",
|
||||
"rounded-full text-tertiary active:text-primary data-[active=true]:text-primary peer/menu-button flex w-full items-center gap-2 overflow-hidden p-2 text-left text-sm outline-hidden ring-active-b transition-[width,height,padding] focus-visible:ring 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]:font-medium 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: {
|
||||
variant: {
|
||||
default: "hover:bg-sidebar-accent hover:text-primary",
|
||||
default:
|
||||
"hover:bg-h-active-bg data-[state=open]:bg-active-bg data-[state=open]:hover:bg-h-active-bg active:bg-active-bg data-[active=true]:bg-active-bg",
|
||||
outline:
|
||||
"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))]",
|
||||
"border border-low-b shadow-[0_0_0_1px_hsl(var(--solid-b))] hover:bg-h-tertiary-bg data-[state=open]:hover:bg-h-tertiary-bg hover:shadow-[0_0_0_1px_hsl(var(--accent))] active:bg-tertiary-bg ata-[active=true]:bg-h-tertiary-bg",
|
||||
ghost:
|
||||
"shadow-[0_0_0_1px_hsl(var(--solid-b))] hover:bg-h-tertiary-bg data-[state=open]:hover:bg-h-tertiary-bg hover:shadow-[0_0_0_1px_hsl(var(--accent))] active:bg-tertiary-bg ata-[active=true]:bg-h-tertiary-bg",
|
||||
},
|
||||
size: {
|
||||
default: "h-10 py-2 px-3 gap-3",
|
||||
@@ -604,7 +607,7 @@ const SidebarMenuAction = React.forwardRef<
|
||||
ref={ref}
|
||||
data-sidebar="menu-action"
|
||||
className={cn(
|
||||
"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",
|
||||
"absolute right-1 top-1.5 flex aspect-square w-6 items-center justify-center rounded-md p-0 text-secondary outline-hidden ring-active-b transition-transform hover:bg-accent-bg hover:text-accent focus-visible:ring-2 peer-hover/menu-button:text-accent [&>svg]:size-4 [&>svg]:shrink-0 hover:cursor-pointer",
|
||||
// Increases the hit area of the button on mobile.
|
||||
"after:absolute after:-inset-2 md:after:hidden",
|
||||
"peer-data-[size=sm]/menu-button:top-1",
|
||||
@@ -612,7 +615,7 @@ const SidebarMenuAction = React.forwardRef<
|
||||
"peer-data-[size=lg]/menu-button:top-2.5",
|
||||
"group-data-[collapsible=icon]:hidden",
|
||||
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-accent md:opacity-0",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
@@ -629,8 +632,8 @@ const SidebarMenuBadge = React.forwardRef<
|
||||
ref={ref}
|
||||
data-sidebar="menu-badge"
|
||||
className={cn(
|
||||
"pointer-events-none absolute right-1 flex h-5 min-w-5 select-none items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums text-sidebar-foreground",
|
||||
"peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground",
|
||||
"pointer-events-none absolute right-1 flex h-5 min-w-5 select-none items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums text-secondary",
|
||||
"peer-hover/menu-button:text-accent peer-data-[active=true]/menu-button:text-accent",
|
||||
"peer-data-[size=sm]/menu-button:top-1",
|
||||
"peer-data-[size=default]/menu-button:top-1.5",
|
||||
"peer-data-[size=lg]/menu-button:top-2.5",
|
||||
@@ -688,7 +691,7 @@ const SidebarMenuSub = React.forwardRef<
|
||||
ref={ref}
|
||||
data-sidebar="menu-sub"
|
||||
className={cn(
|
||||
"ml-5 flex min-w-0 flex-col gap-1 border-l border-sidebar-border px-2.5 py-1",
|
||||
"ml-5 flex min-w-0 flex-col gap-1 border-l border-solid-b px-2.5 py-1",
|
||||
"group-data-[collapsible=icon]:hidden",
|
||||
className
|
||||
)}
|
||||
@@ -720,8 +723,8 @@ const SidebarMenuSubButton = React.forwardRef<
|
||||
data-size={size}
|
||||
data-active={isActive}
|
||||
className={cn(
|
||||
"text-gray-600 flex h-7 min-w-0 items-center gap-2 overflow-hidden rounded-md px-4 outline-hidden ring-sidebar-ring 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 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
|
||||
"data-[active=true]:bg-sidebar-accent data-[active=true]:text-primary",
|
||||
"text-secondary flex h-7 min-w-0 items-center gap-2 overflow-hidden rounded-md px-4 outline-hidden ring-active-b hover:bg-accent-bg hover:text-primary focus-visible:ring-2 active:bg-accent-bg active:text-primary 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",
|
||||
"data-[active=true]:bg-accent-bg data-[active=true]:text-primary",
|
||||
size === "sm" && "text-xs",
|
||||
size === "md" && "text-sm",
|
||||
"group-data-[collapsible=icon]:hidden",
|
||||
|
||||
@@ -42,7 +42,7 @@ const TableFooter = React.forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<tfoot
|
||||
ref={ref}
|
||||
className={cn("bg-primary font-medium text-primary-foreground", className)}
|
||||
className={cn("bg-primary font-medium text-invert", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
@@ -55,7 +55,7 @@ const TableRow = React.forwardRef<
|
||||
<tr
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
|
||||
"border-b transition-colors hover:bg-h-subtle-bg data-[state=selected]:bg-subtle-bg",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
@@ -70,7 +70,7 @@ const TableHead = React.forwardRef<
|
||||
<th
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
|
||||
"h-12 px-4 text-left align-middle font-medium text-tertiary [&:has([role=checkbox])]:pr-0",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
@@ -96,7 +96,7 @@ const TableCaption = React.forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<caption
|
||||
ref={ref}
|
||||
className={cn("mt-4 text-sm text-muted-foreground", className)}
|
||||
className={cn("mt-4 text-sm text-tertiary", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
||||
@@ -11,7 +11,7 @@ const TabsList = React.forwardRef<
|
||||
<TabsPrimitive.List
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
|
||||
"inline-flex h-10 items-center rounded-md p-1 text-tertiary",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
@@ -26,7 +26,7 @@ const TabsTrigger = React.forwardRef<
|
||||
<TabsPrimitive.Trigger
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
|
||||
"border-b-2 border-transparent cursor-pointer inline-flex items-center justify-center whitespace-nowrap px-3 py-1.5 text-sm font-medium ring-offset-level-0 transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-active-b focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:text-active data-[state=active]:border-primary",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
@@ -41,7 +41,7 @@ const TabsContent = React.forwardRef<
|
||||
<TabsPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
||||
"mt-2 ring-offset-level-0 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-active-b focus-visible:ring-offset-2",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -11,8 +11,8 @@ const Textarea = React.forwardRef<
|
||||
return (
|
||||
<textarea
|
||||
className={cn(
|
||||
"flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className,
|
||||
"flex min-h-[80px] w-full rounded-md border border-solid-b bg-invert-bg px-3 py-2 text-sm ring-offset-level-0 placeholder:text-tertiary focus-visible:outline-hidden focus-visible:ring focus-visible:ring-active-b disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
ref={ref}
|
||||
{...props}
|
||||
|
||||
@@ -15,7 +15,7 @@ const ToastViewport = React.forwardRef<
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed top-0 z-100 flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]",
|
||||
className,
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
@@ -27,15 +27,15 @@ const toastVariants = cva(
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "border bg-background text-foreground",
|
||||
default: "border bg-level-0 text-primary",
|
||||
destructive:
|
||||
"destructive group border-destructive bg-destructive text-destructive-foreground",
|
||||
"destructive group border-danger-b bg-danger-bg text-danger",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const Toast = React.forwardRef<
|
||||
@@ -60,8 +60,8 @@ const ToastAction = React.forwardRef<
|
||||
<ToastPrimitives.Action
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium transition-colors hover:bg-secondary focus:outline-hidden focus:ring-1 focus:ring-ring disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 hover:group-[.destructive]:border-destructive/30 hover:group-[.destructive]:bg-destructive hover:group-[.destructive]:text-destructive-foreground focus:group-[.destructive]:ring-destructive",
|
||||
className,
|
||||
"inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium transition-colors hover:bg-invert focus:outline-hidden focus:ring-1 focus:ring-active-b disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-solid-b/40 hover:group-[.destructive]:border-danger-b/30 hover:group-[.destructive]:bg-danger-bg hover:group-[.destructive]:text-danger focus:group-[.destructive]:ring-danger-b",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
@@ -75,8 +75,8 @@ const ToastClose = React.forwardRef<
|
||||
<ToastPrimitives.Close
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"absolute right-1 top-1 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-hidden focus:ring-1 group-hover:opacity-100 group-[.destructive]:text-red-300 hover:group-[.destructive]:text-red-50 focus:group-[.destructive]:ring-red-400 focus:group-[.destructive]:ring-offset-red-600",
|
||||
className,
|
||||
"absolute right-1 top-1 rounded-md p-1 text-primary/50 opacity-0 transition-opacity hover:text-primary focus:opacity-100 focus:outline-hidden focus:ring-1 group-hover:opacity-100 group-[.destructive]:text-red-300 hover:group-[.destructive]:text-red-50 focus:group-[.destructive]:ring-red-400 focus:group-[.destructive]:ring-offset-red-600",
|
||||
className
|
||||
)}
|
||||
toast-close=""
|
||||
{...props}
|
||||
|
||||
@@ -18,8 +18,8 @@ const TooltipContent = React.forwardRef<
|
||||
ref={ref}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
className,
|
||||
"z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-invert animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
|
||||
@@ -5,7 +5,7 @@ export default function AuthLayout({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<div className="flex min-h-screen flex-col">
|
||||
<div className="flex flex-1">
|
||||
<div className="flex flex-1 flex-col bg-muted/40">
|
||||
<div className="flex flex-1 flex-col bg-subtle-bg/40">
|
||||
<div className="flex flex-1 items-center justify-center">
|
||||
<main className="w-full max-w-md p-6">{children}</main>
|
||||
</div>
|
||||
@@ -25,7 +25,7 @@ export default function AuthLayout({ children }: { children: ReactNode }) {
|
||||
Navigate compliance with
|
||||
<br />
|
||||
confidence thanks to{" "}
|
||||
<span className="text-lime-400">probo</span>
|
||||
<span className="text-accent">probo</span>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -14,19 +14,19 @@ export function ErrorPage({
|
||||
}: ErrorPageProps) {
|
||||
return (
|
||||
<div className="flex h-full flex-1 flex-col items-center justify-center p-8 text-center">
|
||||
<div className="mb-4 rounded-full bg-destructive/10 p-3 text-destructive">
|
||||
<div className="mb-4 rounded-full bg-danger-bg/10 p-3 text-danger">
|
||||
<AlertCircle className="size-6" />
|
||||
</div>
|
||||
<h1 className="mb-2 text-2xl font-semibold">{title}</h1>
|
||||
<p className="mb-6 max-w-md text-muted-foreground">{description}</p>
|
||||
<p className="mb-6 max-w-md text-tertiary">{description}</p>
|
||||
{error?.message && (
|
||||
<pre className="mb-8 max-w-2xl overflow-auto rounded-lg bg-muted/50 p-4 text-sm">
|
||||
<pre className="mb-8 max-w-2xl overflow-auto rounded-lg bg-danger-bg/50 p-4 text-sm">
|
||||
{error.message}
|
||||
</pre>
|
||||
)}
|
||||
<Link
|
||||
to="/"
|
||||
className="inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90 focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50"
|
||||
className="inline-flex items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-invert transition-colors hover:bg-primary/90 focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-active-b disabled:pointer-events-none disabled:opacity-50"
|
||||
>
|
||||
Return Home
|
||||
</Link>
|
||||
|
||||
@@ -140,7 +140,7 @@ export default function ConfirmEmailPage() {
|
||||
disabled={isLoading}
|
||||
required
|
||||
/>
|
||||
<p className="text-xs text-gray-500 dark:text-gray-400">
|
||||
<p className="text-xs text-secondary dark:text-tertiary">
|
||||
The token has been automatically filled from the URL if
|
||||
available
|
||||
</p>
|
||||
@@ -157,7 +157,7 @@ export default function ConfirmEmailPage() {
|
||||
{!isConfirmed && (
|
||||
<Link
|
||||
to="/login"
|
||||
className="text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300"
|
||||
className="text-sm text-secondary hover:text-primary dark:text-tertiary dark:hover:text-quaternary"
|
||||
>
|
||||
Back to Login
|
||||
</Link>
|
||||
|
||||
@@ -151,7 +151,7 @@ export default function ConfirmInvitationPage() {
|
||||
required
|
||||
autoComplete="off"
|
||||
/>
|
||||
<p className="text-xs text-gray-500 dark:text-gray-400">
|
||||
<p className="text-xs text-secondary dark:text-tertiary">
|
||||
The token has been automatically filled from the URL if
|
||||
available
|
||||
</p>
|
||||
@@ -196,7 +196,7 @@ export default function ConfirmInvitationPage() {
|
||||
{!isConfirmed && (
|
||||
<Link
|
||||
to="/login"
|
||||
className="text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300"
|
||||
className="text-sm text-secondary hover:text-primary dark:text-tertiary dark:hover:text-quaternary"
|
||||
>
|
||||
Back to Login
|
||||
</Link>
|
||||
|
||||
@@ -113,7 +113,7 @@ export default function ForgotPasswordPage() {
|
||||
<CardFooter className="flex justify-center">
|
||||
<Link
|
||||
to="/login"
|
||||
className="text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300"
|
||||
className="text-sm text-secondary hover:text-primary dark:text-tertiary dark:hover:text-quaternary"
|
||||
>
|
||||
Back to Login
|
||||
</Link>
|
||||
|
||||
@@ -63,7 +63,7 @@ export default function LoginPage() {
|
||||
<h1 className="text-2xl font-semibold tracking-tight">
|
||||
Login to your account
|
||||
</h1>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
<p className="text-sm text-tertiary">
|
||||
Enter your email below to login to your account
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -74,7 +74,7 @@ export default function RegisterPage() {
|
||||
<div className="space-y-6">
|
||||
<div className="space-y-2 text-center">
|
||||
<h1 className="text-3xl font-bold">Sign up</h1>
|
||||
<p className="text-gray-500 dark:text-gray-400">
|
||||
<p className="text-secondary dark:text-tertiary">
|
||||
Enter your information to create an account
|
||||
</p>
|
||||
</div>
|
||||
@@ -122,7 +122,7 @@ export default function RegisterPage() {
|
||||
</form>
|
||||
|
||||
<div className="text-center">
|
||||
<p className="text-sm text-gray-500 dark:text-gray-400">
|
||||
<p className="text-sm text-secondary dark:text-tertiary">
|
||||
Already have an account?{" "}
|
||||
<Link to="/login" className="underline">
|
||||
Log in here
|
||||
|
||||
@@ -150,7 +150,7 @@ export default function ResetPasswordPage() {
|
||||
required
|
||||
autoComplete="off"
|
||||
/>
|
||||
<p className="text-xs text-gray-500 dark:text-gray-400">
|
||||
<p className="text-xs text-secondary dark:text-tertiary">
|
||||
The token has been automatically filled from the URL if
|
||||
available
|
||||
</p>
|
||||
@@ -195,7 +195,7 @@ export default function ResetPasswordPage() {
|
||||
{!isReset && (
|
||||
<Link
|
||||
to="/login"
|
||||
className="text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300"
|
||||
className="text-sm text-secondary hover:text-primary dark:text-tertiary dark:hover:text-quaternary"
|
||||
>
|
||||
Back to Login
|
||||
</Link>
|
||||
|
||||
@@ -10,7 +10,7 @@ export function CreateOrganizationViewSkeleton() {
|
||||
title="Create Organization"
|
||||
description="Create a new organization to manage your compliance and security needs."
|
||||
>
|
||||
<div className="max-w-2xl aspect-square bg-muted rounded-xl animate-pulse" />
|
||||
<div className="max-w-2xl aspect-square bg-subtle-bg rounded-xl animate-pulse" />
|
||||
</PageTemplateSkeleton>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ function EditableField({
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<HelpCircle className="h-4 w-4 text-gray-400" />
|
||||
<HelpCircle className="h-4 w-4 text-tertiary" />
|
||||
<Label className="text-sm">{label}</Label>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
@@ -75,7 +75,7 @@ function EditableField({
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
required={required}
|
||||
/>
|
||||
{helpText && <p className="text-sm text-gray-500">{helpText}</p>}
|
||||
{helpText && <p className="text-sm text-secondary">{helpText}</p>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -29,8 +29,8 @@ const BreadCrumbNavLink = ({
|
||||
{({ isActive }) => (
|
||||
<BreadcrumbPage
|
||||
className={cn(
|
||||
"text-gray-300",
|
||||
isActive && "text-gray-700",
|
||||
"text-quaternary",
|
||||
isActive && "text-primary",
|
||||
className
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -57,8 +57,8 @@ const BreadcrumbNavLink = ({
|
||||
{({ isActive }) => (
|
||||
<BreadcrumbPage
|
||||
className={cn(
|
||||
"text-gray-300",
|
||||
isActive && "text-gray-700",
|
||||
"text-quaternary",
|
||||
isActive && "text-primary",
|
||||
className
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -15,7 +15,10 @@ export function SettingsViewSkeleton() {
|
||||
<div className="space-y-6">
|
||||
<div className="space-y-2">
|
||||
{[1, 2].map((i) => (
|
||||
<div key={i} className="h-64 bg-muted animate-pulse rounded-lg" />
|
||||
<div
|
||||
key={i}
|
||||
className="h-64 bg-subtle-bg animate-pulse rounded-lg"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -313,10 +313,10 @@ function SettingsViewContent({
|
||||
/>
|
||||
) : (
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-lg border">
|
||||
<Upload className="h-5 w-5 text-muted-foreground" />
|
||||
<Upload className="h-5 w-5 text-tertiary" />
|
||||
</div>
|
||||
)}
|
||||
<span className="text-muted-foreground">
|
||||
<span className="text-tertiary">
|
||||
Upload a logo to be displayed at the top of your trust page
|
||||
</span>
|
||||
</div>
|
||||
@@ -344,8 +344,8 @@ function SettingsViewContent({
|
||||
<label className="text-sm font-medium">Organization name</label>
|
||||
<div className="flex items-center justify-between rounded-lg border p-3 shadow-xs">
|
||||
<div className="flex items-center gap-2">
|
||||
<Building2 className="h-5 w-5 text-muted-foreground" />
|
||||
<span className="text-muted-foreground">
|
||||
<Building2 className="h-5 w-5 text-tertiary" />
|
||||
<span className="text-tertiary">
|
||||
Set the name of the organization
|
||||
</span>
|
||||
</div>
|
||||
@@ -389,11 +389,11 @@ function SettingsViewContent({
|
||||
<div className="space-y-4">
|
||||
{users.length === 0 ? (
|
||||
<div className="flex flex-col items-center justify-center p-8 text-center">
|
||||
<div className="rounded-full bg-muted p-3">
|
||||
<Building2 className="h-6 w-6 text-muted-foreground" />
|
||||
<div className="rounded-full bg-subtle-bg p-3">
|
||||
<Building2 className="h-6 w-6 text-tertiary" />
|
||||
</div>
|
||||
<h3 className="mt-4 text-lg font-medium">No members found</h3>
|
||||
<p className="mt-2 text-sm text-muted-foreground">
|
||||
<p className="mt-2 text-sm text-tertiary">
|
||||
You haven't added any members to your workspace yet.
|
||||
</p>
|
||||
</div>
|
||||
@@ -413,15 +413,13 @@ function SettingsViewContent({
|
||||
<span className="text-sm font-medium">
|
||||
{user.fullName}
|
||||
</span>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
<span className="text-sm text-tertiary">
|
||||
{user.email}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm text-muted-foreground">
|
||||
Owner
|
||||
</span>
|
||||
<span className="text-sm text-tertiary">Owner</span>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" size="icon">
|
||||
|
||||
@@ -12,7 +12,7 @@ export function EditFrameworkViewSkeleton() {
|
||||
title="Update Framework"
|
||||
description="Update the framework details"
|
||||
>
|
||||
<div className="max-w-2xl aspect-square bg-muted rounded-xl animate-pulse" />
|
||||
<div className="max-w-2xl aspect-square bg-subtle-bg rounded-xl animate-pulse" />
|
||||
</PageTemplateSkeleton>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ function EditableField({
|
||||
</Label>
|
||||
{helpText && (
|
||||
<div className="relative flex items-center">
|
||||
<HelpCircle className="h-4 w-4 text-muted-foreground" />
|
||||
<HelpCircle className="h-4 w-4 text-tertiary" />
|
||||
<span className="sr-only">{helpText}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -12,8 +12,8 @@ export function FrameworkLayoutViewSkeleton() {
|
||||
<PageTemplateSkeleton
|
||||
actions={
|
||||
<div className="flex gap-4 w-1/3">
|
||||
<div className="bg-muted animate-pulse h-9 w-1/2 rounded-lg" />
|
||||
<div className="bg-muted animate-pulse h-9 w-1/2 rounded-lg" />
|
||||
<div className="bg-subtle-bg animate-pulse h-9 w-1/2 rounded-lg" />
|
||||
<div className="bg-subtle-bg animate-pulse h-9 w-1/2 rounded-lg" />
|
||||
</div>
|
||||
}
|
||||
>
|
||||
@@ -22,11 +22,11 @@ export function FrameworkLayoutViewSkeleton() {
|
||||
<Card key={i}>
|
||||
<CardContent className="p-6">
|
||||
<div className="relative mb-6">
|
||||
<div className="bg-muted w-24 h-24 rounded-full animate-pulse mb-4" />
|
||||
<div className="h-6 w-48 bg-muted animate-pulse rounded mb-2" />
|
||||
<div className="h-20 w-full bg-muted animate-pulse rounded" />
|
||||
<div className="bg-subtle-bg w-24 h-24 rounded-full animate-pulse mb-4" />
|
||||
<div className="h-6 w-48 bg-subtle-bg animate-pulse rounded mb-2" />
|
||||
<div className="h-20 w-full bg-subtle-bg animate-pulse rounded" />
|
||||
</div>
|
||||
<div className="h-4 w-32 bg-muted animate-pulse rounded" />
|
||||
<div className="h-4 w-32 bg-subtle-bg animate-pulse rounded" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
|
||||
@@ -133,7 +133,7 @@ function FrameworkLayoutViewContent({
|
||||
description={framework.description || ""}
|
||||
actions={
|
||||
<div className="flex gap-4">
|
||||
<Button variant="outline" asChild>
|
||||
<Button variant="secondary" asChild>
|
||||
<Link
|
||||
to={`/organizations/${organizationId}/frameworks/${framework.id}/edit`}
|
||||
>
|
||||
|
||||
@@ -22,6 +22,7 @@ export const controlListFragment = graphql`
|
||||
|
||||
interface ControlListProps {
|
||||
fragmentKey: ControlList_List$key;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function ControlList(props: ControlListProps) {
|
||||
@@ -30,7 +31,7 @@ export function ControlList(props: ControlListProps) {
|
||||
frameworkId: string;
|
||||
controlId?: string;
|
||||
}>();
|
||||
const { fragmentKey } = props;
|
||||
const { className, fragmentKey } = props;
|
||||
const { controls } = useFragment<ControlList_List$key>(
|
||||
controlListFragment,
|
||||
fragmentKey
|
||||
@@ -41,15 +42,20 @@ export function ControlList(props: ControlListProps) {
|
||||
}
|
||||
|
||||
return (
|
||||
<aside className="shrink-0 w-70 border-r border-gray-100 h-full overflow-x-hidden overflow-y-auto [&::-webkit-scrollbar]:w-1.5 [&::-webkit-scrollbar-track]:bg-gray-100 [&::-webkit-scrollbar-thumb]:bg-gray-300 [&::-webkit-scrollbar-thumb]:rounded-xs">
|
||||
<aside
|
||||
className={cn(
|
||||
"shrink-0 w-70 border-r h-full overflow-x-hidden overflow-y-auto [&::-webkit-scrollbar]:w-1.5 [&::-webkit-scrollbar-track]:bg-level-0 [&::-webkit-scrollbar-thumb]:bg-highlight-bg [&::-webkit-scrollbar-thumb]:rounded-xs",
|
||||
className
|
||||
)}
|
||||
>
|
||||
{controls.edges.map(({ node: control }, i) => (
|
||||
<NavLink
|
||||
key={control.id}
|
||||
to={`/organizations/${organizationId}/frameworks/${frameworkId}/controls/${control.id}`}
|
||||
className={({ isActive }) =>
|
||||
cn(
|
||||
"block pl-8 pr-4 py-4 hover:bg-gray-50 border-b border-gray-100",
|
||||
(isActive || (i === 0 && !controlId)) && "bg-gray-50"
|
||||
"block pl-8 pr-4 py-4 border-b hover:bg-h-subtle-bg",
|
||||
(isActive || (i === 0 && !controlId)) && "bg-subtle-bg"
|
||||
)
|
||||
}
|
||||
>
|
||||
@@ -58,8 +64,8 @@ export function ControlList(props: ControlListProps) {
|
||||
<>
|
||||
<div
|
||||
className={cn(
|
||||
"inline-block font-mono text-sm px-1 py-0.25 rounded-sm bg-lime-2 border border-lime-4 text-lime-9 font-semibold",
|
||||
isActive && "font-bold bg-lime-3 border-lime-6 text-lime-11"
|
||||
"inline-block font-mono text-sm px-1 py-0.25 rounded-sm bg-highlight-bg border font-semibold",
|
||||
isActive && "font-bold bg-active-bg border-mid-b"
|
||||
)}
|
||||
>
|
||||
{control.referenceId}
|
||||
|
||||
@@ -14,21 +14,21 @@ export function FrameworkListViewSkeleton() {
|
||||
description="Manage your compliance frameworks"
|
||||
actions={
|
||||
<div className="flex gap-4 w-1/3">
|
||||
<div className="bg-muted animate-pulse h-9 w-1/2 rounded-lg" />
|
||||
<div className="bg-muted animate-pulse h-9 w-1/2 rounded-lg" />
|
||||
<div className="bg-subtle-bg animate-pulse h-9 w-1/2 rounded-lg" />
|
||||
<div className="bg-subtle-bg animate-pulse h-9 w-1/2 rounded-lg" />
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className="grid gap-6 md:grid-cols-2">
|
||||
{[1, 2].map((i) => (
|
||||
<Card key={i} className="bg-card/50">
|
||||
<Card key={i}>
|
||||
<CardContent className="p-6">
|
||||
<div className="relative mb-6">
|
||||
<div className="bg-muted w-24 h-24 rounded-full animate-pulse mb-4" />
|
||||
<div className="h-6 w-48 bg-muted animate-pulse rounded mb-2" />
|
||||
<div className="h-20 w-full bg-muted animate-pulse rounded" />
|
||||
<div className="bg-subtle-bg w-24 h-24 rounded-full animate-pulse mb-4" />
|
||||
<div className="h-6 w-48 bg-subtle-bg animate-pulse rounded mb-2" />
|
||||
<div className="h-20 w-full bg-subtle-bg animate-pulse rounded" />
|
||||
</div>
|
||||
<div className="h-4 w-32 bg-muted animate-pulse rounded" />
|
||||
<div className="h-4 w-32 bg-subtle-bg animate-pulse rounded" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
|
||||
@@ -139,12 +139,12 @@ function FrameworkListViewContent({
|
||||
className="hidden"
|
||||
/>
|
||||
<Button
|
||||
variant="outline"
|
||||
variant="secondary"
|
||||
onClick={handleImportClick}
|
||||
disabled={isUploading}
|
||||
>
|
||||
<Upload className="mr-2 h-4 w-4" />
|
||||
Import Framework
|
||||
Import
|
||||
</Button>
|
||||
<Button asChild>
|
||||
<Link to={`/organizations/${organizationId}/frameworks/new`}>
|
||||
@@ -161,10 +161,10 @@ function FrameworkListViewContent({
|
||||
<table className="w-full caption-bottom text-sm">
|
||||
<tbody className="[&_tr:last-child]:border-0">
|
||||
{frameworks.length === 0 ? (
|
||||
<tr className="border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted">
|
||||
<tr className="border-b transition-colors hover:bg-h-subte-bg/50 data-[state=selected]:bg-subtle-bg">
|
||||
<td
|
||||
colSpan={4}
|
||||
className="text-center p-4 align-middle text-muted-foreground"
|
||||
className="text-center p-4 align-middle text-tertiary"
|
||||
>
|
||||
No frameworks found. Create or import one to get started.
|
||||
</td>
|
||||
@@ -173,7 +173,7 @@ function FrameworkListViewContent({
|
||||
frameworks.map((framework) => (
|
||||
<tr
|
||||
key={framework.id}
|
||||
className="border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted cursor-pointer"
|
||||
className="border-b transition-colors hover:bg-h-subtle-bg/50 data-[state=selected]:bg-subtle-bg cursor-pointer"
|
||||
>
|
||||
<td className="p-4 align-middle">
|
||||
<Link
|
||||
|
||||
@@ -13,11 +13,11 @@ export function FrameworkViewSkeleton() {
|
||||
<Card key={i}>
|
||||
<CardContent className="p-6">
|
||||
<div className="relative mb-6">
|
||||
<div className="bg-muted w-24 h-24 rounded-full animate-pulse mb-4" />
|
||||
<div className="h-6 w-48 bg-muted animate-pulse rounded mb-2" />
|
||||
<div className="h-20 w-full bg-muted animate-pulse rounded" />
|
||||
<div className="bg-subtle-bg w-24 h-24 rounded-full animate-pulse mb-4" />
|
||||
<div className="h-6 w-48 bg-subtle-bg animate-pulse rounded mb-2" />
|
||||
<div className="h-20 w-full bg-subtle-bg animate-pulse rounded" />
|
||||
</div>
|
||||
<div className="h-4 w-32 bg-muted animate-pulse rounded" />
|
||||
<div className="h-4 w-32 bg-subtle-bg animate-pulse rounded" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
|
||||
@@ -12,7 +12,7 @@ export function NewFrameworkViewSkeleton() {
|
||||
title="Create Framework"
|
||||
description="Create a new framework to organize your mitigations"
|
||||
>
|
||||
<div className="max-w-2xl aspect-square bg-muted rounded-xl animate-pulse" />
|
||||
<div className="max-w-2xl aspect-square bg-subtle-bg rounded-xl animate-pulse" />
|
||||
</PageTemplateSkeleton>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ function EditableField({
|
||||
</Label>
|
||||
{helpText && (
|
||||
<div className="relative flex items-center">
|
||||
<HelpCircle className="h-4 w-4 text-muted-foreground" />
|
||||
<HelpCircle className="h-4 w-4 text-tertiary" />
|
||||
<span className="sr-only">{helpText}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -451,42 +451,42 @@ export function Control({
|
||||
};
|
||||
|
||||
const getImportanceColor = (importance: string | undefined): string => {
|
||||
if (!importance) return "bg-gray-100 text-gray-800";
|
||||
if (!importance) return "bg-secondary-bg text-secondary";
|
||||
|
||||
switch (importance) {
|
||||
case "LOW":
|
||||
return "bg-blue-100 text-blue-800";
|
||||
return "bg-success-bg text-success";
|
||||
case "MEDIUM":
|
||||
return "bg-yellow-100 text-yellow-800";
|
||||
return "bg-info-bg text-info";
|
||||
case "HIGH":
|
||||
return "bg-orange-100 text-orange-800";
|
||||
return "bg-warning-bg text-warning";
|
||||
case "CRITICAL":
|
||||
return "bg-red-100 text-red-800";
|
||||
return "bg-danger-bg text-danger";
|
||||
default:
|
||||
return "bg-gray-100 text-gray-800";
|
||||
return "bg-secondary-bg text-secondary";
|
||||
}
|
||||
};
|
||||
|
||||
const getStateColor = (state: string | undefined): string => {
|
||||
if (!state) return "bg-gray-100 text-gray-800";
|
||||
if (!state) return "bg-secondary-bg text-secondary";
|
||||
|
||||
switch (state) {
|
||||
case "NOT_STARTED":
|
||||
return "bg-gray-100 text-gray-800";
|
||||
return "bg-secondary-bg text-secondary";
|
||||
case "IN_PROGRESS":
|
||||
return "bg-blue-100 text-blue-800";
|
||||
return "bg-info-bg text-info";
|
||||
case "IMPLEMENTED":
|
||||
return "bg-green-100 text-green-800";
|
||||
return "bg-success-bg text-success";
|
||||
case "NOT_APPLICABLE":
|
||||
return "bg-purple-100 text-purple-800";
|
||||
return "bg-warning-bg text-warning";
|
||||
default:
|
||||
return "bg-gray-100 text-gray-800";
|
||||
return "bg-secondary-bg text-secondary";
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-auto p-5 flex items-start gap-5">
|
||||
<div className="font-mono text-lg px-1 py-0.25 rounded-sm bg-lime-3 border border-lime-6 text-lime-11 font-bold">
|
||||
<div className="font-mono text-lg px-1 py-0.25 rounded-sm bg-active-bg border-mid-b border font-bold">
|
||||
{control.referenceId}
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
@@ -494,7 +494,7 @@ export function Control({
|
||||
|
||||
{/* Control Description */}
|
||||
{control.description && (
|
||||
<div className="mt-4 text-gray-600">{control.description}</div>
|
||||
<div className="mt-4 text-tertiary">{control.description}</div>
|
||||
)}
|
||||
|
||||
{/* Security Measures Section */}
|
||||
@@ -516,7 +516,7 @@ export function Control({
|
||||
<div className="flex items-center space-x-4 mb-4">
|
||||
<div className="flex-1">
|
||||
<div className="relative">
|
||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" />
|
||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-tertiary" />
|
||||
<Input
|
||||
placeholder="Search security measures by name or description..."
|
||||
value={mitigationSearchQuery}
|
||||
@@ -550,20 +550,20 @@ export function Control({
|
||||
<div className="flex-1 overflow-hidden">
|
||||
{isLoadingMitigations ? (
|
||||
<div className="flex items-center justify-center h-full">
|
||||
<Loader2 className="w-8 h-8 animate-spin text-blue-500" />
|
||||
<Loader2 className="w-8 h-8 animate-spin text-info" />
|
||||
<span className="ml-2">Loading security measures...</span>
|
||||
</div>
|
||||
) : (
|
||||
<div className="max-h-[50vh] overflow-y-auto pr-2">
|
||||
{filteredMitigations().length === 0 ? (
|
||||
<div className="text-center py-8 text-gray-500">
|
||||
<div className="text-center py-8 text-secondary">
|
||||
No security measures found. Try adjusting your search or
|
||||
select a different category.
|
||||
</div>
|
||||
) : (
|
||||
<table className="w-full">
|
||||
<table className="w-full bg-level-1">
|
||||
<thead className="sticky top-0 bg-white">
|
||||
<tr className="border-b text-left text-sm text-gray-500 bg-gray-50">
|
||||
<tr className="border-b text-left text-sm text-secondary bg-invert-bg">
|
||||
<th className="py-3 px-4 font-medium">Name</th>
|
||||
<th className="py-3 px-4 font-medium">
|
||||
Importance
|
||||
@@ -580,14 +580,14 @@ export function Control({
|
||||
return (
|
||||
<tr
|
||||
key={mitigation.id}
|
||||
className="border-b hover:bg-gray-50"
|
||||
className="border-b hover:bg-invert-bg"
|
||||
>
|
||||
<td className="py-3 px-4">
|
||||
<div className="font-medium">
|
||||
{mitigation.name}
|
||||
</div>
|
||||
{mitigation.description && (
|
||||
<div className="text-xs text-gray-500 line-clamp-1 mt-0.5">
|
||||
<div className="text-xs text-secondary line-clamp-1 mt-0.5">
|
||||
{mitigation.description}
|
||||
</div>
|
||||
)}
|
||||
@@ -619,7 +619,7 @@ export function Control({
|
||||
handleUnlinkMitigation(mitigation.id)
|
||||
}
|
||||
disabled={isUnlinkingMitigation}
|
||||
className="text-xs h-7 text-red-500 border-red-200 hover:bg-red-50"
|
||||
className="text-xs h-7 text-danger border-danger-b hover:bg-h-danger-bg"
|
||||
>
|
||||
{isUnlinkingMitigation ? (
|
||||
<Loader2 className="w-4 h-4 animate-spin" />
|
||||
@@ -630,13 +630,13 @@ export function Control({
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
variant="outline"
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
onClick={() =>
|
||||
handleLinkMitigation(mitigation.id)
|
||||
}
|
||||
disabled={isLinkingMitigation}
|
||||
className="text-xs h-7 text-blue-500 border-blue-200 hover:bg-blue-50"
|
||||
className="text-xs h-7 text-info border-info-b hover:bg-h-info-bg"
|
||||
>
|
||||
{isLinkingMitigation ? (
|
||||
<Loader2 className="w-4 h-4 animate-spin" />
|
||||
@@ -668,7 +668,7 @@ export function Control({
|
||||
{/* Linked Mitigations List */}
|
||||
<div>
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<h3 className="text-xl font-medium text-gray-600">
|
||||
<h3 className="text-xl font-medium text-secondary">
|
||||
Security measures
|
||||
</h3>
|
||||
<Button
|
||||
@@ -684,7 +684,7 @@ export function Control({
|
||||
|
||||
{isLoadingMitigations ? (
|
||||
<div className="flex items-center justify-center h-24">
|
||||
<Loader2 className="w-6 h-6 animate-spin text-blue-500" />
|
||||
<Loader2 className="w-6 h-6 animate-spin text-info" />
|
||||
<span className="ml-2">Loading security measures...</span>
|
||||
</div>
|
||||
) : linkedMitigationsData?.control?.mitigations?.edges &&
|
||||
@@ -692,7 +692,7 @@ export function Control({
|
||||
<div className="overflow-x-auto border rounded-md">
|
||||
<table className="w-full">
|
||||
<thead>
|
||||
<tr className="border-b text-left text-sm text-gray-500 bg-gray-50">
|
||||
<tr className="border-b text-left text-sm text-secondary bg-invert-bg">
|
||||
<th className="py-3 px-4 font-medium">Name</th>
|
||||
<th className="py-3 px-4 font-medium">Importance</th>
|
||||
<th className="py-3 px-4 font-medium">State</th>
|
||||
@@ -705,12 +705,12 @@ export function Control({
|
||||
{getLinkedMitigations().map((mitigation) => (
|
||||
<tr
|
||||
key={mitigation.id}
|
||||
className="border-b hover:bg-gray-50"
|
||||
className="border-b hover:bg-invert-bg"
|
||||
>
|
||||
<td className="py-3 px-4">
|
||||
<div className="font-medium">{mitigation.name}</div>
|
||||
{mitigation.description && (
|
||||
<div className="text-xs text-gray-500 line-clamp-1 mt-0.5">
|
||||
<div className="text-xs text-secondary line-clamp-1 mt-0.5">
|
||||
{mitigation.description}
|
||||
</div>
|
||||
)}
|
||||
@@ -754,7 +754,7 @@ export function Control({
|
||||
handleUnlinkMitigation(mitigation.id)
|
||||
}
|
||||
disabled={isUnlinkingMitigation}
|
||||
className="text-xs h-7 text-red-500 border-red-200 hover:bg-red-50"
|
||||
className="text-xs h-7 text-danger border-danger-b hover:bg-h-danger-bg"
|
||||
>
|
||||
Unlink
|
||||
</Button>
|
||||
@@ -766,7 +766,7 @@ export function Control({
|
||||
</table>
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-center py-8 text-gray-500 border rounded-md">
|
||||
<div className="text-center py-8 text-secondary border rounded-md">
|
||||
No security measures linked to this control yet. Click
|
||||
"Link Security Measures" to connect some.
|
||||
</div>
|
||||
|
||||
@@ -13,11 +13,11 @@ export function ControlViewSkeleton() {
|
||||
<Card key={i}>
|
||||
<CardContent className="p-6">
|
||||
<div className="relative mb-6">
|
||||
<div className="bg-muted w-24 h-24 rounded-full animate-pulse mb-4" />
|
||||
<div className="h-6 w-48 bg-muted animate-pulse rounded mb-2" />
|
||||
<div className="h-20 w-full bg-muted animate-pulse rounded" />
|
||||
<div className="bg-subtle-bg w-24 h-24 rounded-full animate-pulse mb-4" />
|
||||
<div className="h-6 w-48 bg-subtle-bg animate-pulse rounded mb-2" />
|
||||
<div className="h-20 w-full bg-subtle-bg animate-pulse rounded" />
|
||||
</div>
|
||||
<div className="h-4 w-32 bg-muted animate-pulse rounded" />
|
||||
<div className="h-4 w-32 bg-subtle-bg animate-pulse rounded" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
|
||||
@@ -12,7 +12,7 @@ export function EditMitigationViewSkeleton() {
|
||||
title="Edit Mitigation"
|
||||
description="Edit a mitigation. You will be able to link it to control and risks"
|
||||
>
|
||||
<div className="max-w-2xl aspect-square bg-muted rounded-xl animate-pulse" />
|
||||
<div className="max-w-2xl aspect-square bg-subtle-bg rounded-xl animate-pulse" />
|
||||
</PageTemplateSkeleton>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -170,8 +170,8 @@ function EditMitigationViewContent({
|
||||
className={cn(
|
||||
"rounded-full cursor-pointer px-4 py-1 text-sm transition-colors",
|
||||
formData.importance === "MANDATORY"
|
||||
? "bg-red-100 text-red-900 ring-2 ring-red-600 ring-offset-2"
|
||||
: "bg-gray-100 text-gray-900 hover:bg-gray-200"
|
||||
? "bg-danger-bg text-danger ring ring-danger-b"
|
||||
: "bg-invert-bg hover:bg-h-invert-bg"
|
||||
)}
|
||||
>
|
||||
Mandatory
|
||||
@@ -182,8 +182,8 @@ function EditMitigationViewContent({
|
||||
className={cn(
|
||||
"rounded-full cursor-pointer px-4 py-1 text-sm transition-colors",
|
||||
formData.importance === "PREFERRED"
|
||||
? "bg-yellow-100 text-yellow-900 ring-2 ring-yellow-600 ring-offset-2"
|
||||
: "bg-gray-100 text-gray-900 hover:bg-gray-200"
|
||||
? "bg-warning-bg text-warning ring ring-warning-b"
|
||||
: "bg-invert-bg hover:bg-h-invert-bg"
|
||||
)}
|
||||
>
|
||||
Preferred
|
||||
@@ -194,8 +194,8 @@ function EditMitigationViewContent({
|
||||
className={cn(
|
||||
"rounded-full cursor-pointer px-4 py-1 text-sm transition-colors",
|
||||
formData.importance === "ADVANCED"
|
||||
? "bg-blue-100 text-blue-900 ring-2 ring-blue-600 ring-offset-2"
|
||||
: "bg-gray-100 text-gray-900 hover:bg-gray-200"
|
||||
? "bg-info-bg text-info ring ring-info-b"
|
||||
: "bg-invert-bg hover:bg-h-invert-bg"
|
||||
)}
|
||||
>
|
||||
Advanced
|
||||
|
||||
@@ -13,19 +13,17 @@ export function MitigationListViewSkeleton() {
|
||||
description="Mitigations are actions taken to reduce the risk of a risk."
|
||||
>
|
||||
<div className="space-y-6">
|
||||
<div className="rounded-xl border bg-card p-4 space-y-4">
|
||||
<div className="h-5 w-32 bg-muted animate-pulse rounded" />
|
||||
<div className="flex gap-2">
|
||||
<div className="h-10 flex-1 bg-muted animate-pulse rounded" />
|
||||
<div className="h-10 w-32 bg-muted animate-pulse rounded" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="h-[72px] bg-subtle-bg animate-pulse rounded-xl" />
|
||||
|
||||
<div className="space-y-2">
|
||||
{[1, 2, 3].map((i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="h-[72px] bg-muted animate-pulse rounded-xl"
|
||||
/>
|
||||
<div key={i} className="rounded-xl border bg-level-1 p-4 space-y-4">
|
||||
<div className="h-5 w-32 bg-subtle-bg animate-pulse rounded" />
|
||||
<div className="flex gap-2">
|
||||
<div className="h-10 flex-1 bg-subtle-bg animate-pulse rounded" />
|
||||
<div className="h-10 w-32 bg-subtle-bg animate-pulse rounded" />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -267,15 +267,15 @@ function MitigationListContent({
|
||||
const getStatusIcon = (status: string) => {
|
||||
switch (status) {
|
||||
case "complete":
|
||||
return <CheckCircle2 className="h-5 w-5 text-green-500" />;
|
||||
return <CheckCircle2 className="h-5 w-5 text-success" />;
|
||||
case "in-progress":
|
||||
return <Clock className="h-5 w-5 text-blue-500" />;
|
||||
return <Clock className="h-5 w-5 text-info" />;
|
||||
case "not-started":
|
||||
return <AlertCircle className="h-5 w-5 text-gray-200" />;
|
||||
return <AlertCircle className="h-5 w-5 text-disabled" />;
|
||||
case "incomplete":
|
||||
return <AlertCircle className="h-5 w-5 text-red-500" />;
|
||||
return <AlertCircle className="h-5 w-5 text-danger" />;
|
||||
case "not-applicable":
|
||||
return <X className="h-5 w-5 text-gray-300" />;
|
||||
return <X className="h-5 w-5 text-quaternary" />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
@@ -332,7 +332,7 @@ function MitigationListContent({
|
||||
actions={
|
||||
<div className="flex gap-4">
|
||||
<Button
|
||||
variant="outline"
|
||||
variant="secondary"
|
||||
onClick={() => fileInputRef.current?.click()}
|
||||
disabled={isImporting}
|
||||
>
|
||||
@@ -359,13 +359,13 @@ function MitigationListContent({
|
||||
<div className="mb-8">
|
||||
<div className="flex items-center justify-between mb-1">
|
||||
<h3 className="text-lg font-medium">Mitigation Implementation</h3>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
<span className="text-sm text-tertiary">
|
||||
{globalProgress}% complete
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Progress bar container */}
|
||||
<div className="w-full h-5 rounded-full overflow-hidden bg-muted mb-2">
|
||||
<div className="w-full h-5 rounded-full overflow-hidden bg-subtle-bg mb-2">
|
||||
{/* Segmented progress bar */}
|
||||
<div className="flex h-full">
|
||||
{/* Complete segment */}
|
||||
@@ -404,7 +404,7 @@ function MitigationListContent({
|
||||
{/* Not applicable segment */}
|
||||
{globalStatusCounts["not-applicable"] > 0 && (
|
||||
<div
|
||||
className="bg-gray-600 h-full"
|
||||
className="bg-primary-bg h-full"
|
||||
style={{
|
||||
width: `${
|
||||
(globalStatusCounts["not-applicable"] / totalMitigations) *
|
||||
@@ -416,7 +416,7 @@ function MitigationListContent({
|
||||
{/* Not started segment */}
|
||||
{globalStatusCounts["not-started"] > 0 && (
|
||||
<div
|
||||
className="bg-gray-200 h-full"
|
||||
className="bg-secondary h-full"
|
||||
style={{
|
||||
width: `${
|
||||
(globalStatusCounts["not-started"] / totalMitigations) * 100
|
||||
@@ -448,16 +448,16 @@ function MitigationListContent({
|
||||
</div>
|
||||
)}
|
||||
{globalStatusCounts["not-applicable"] > 0 && (
|
||||
<div className="flex items-center gap-1.5 text-muted-foreground">
|
||||
<div className="w-3 h-3 rounded-full bg-gray-600"></div>
|
||||
<div className="flex items-center gap-1.5 text-tertiary">
|
||||
<div className="w-3 h-3 rounded-full bg-primary"></div>
|
||||
<span>
|
||||
Not Applicable ({globalStatusCounts["not-applicable"]})
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{globalStatusCounts["not-started"] > 0 && (
|
||||
<div className="flex items-center gap-1.5 text-muted-foreground">
|
||||
<div className="w-3 h-3 rounded-full bg-gray-200"></div>
|
||||
<div className="flex items-center gap-1.5 text-tertiary">
|
||||
<div className="w-3 h-3 rounded-full bg-secondary"></div>
|
||||
<span>Not Started ({globalStatusCounts["not-started"]})</span>
|
||||
</div>
|
||||
)}
|
||||
@@ -476,14 +476,14 @@ function MitigationListContent({
|
||||
>
|
||||
<Card className="border-0 shadow-none">
|
||||
<CardHeader
|
||||
className="bg-muted/50 cursor-pointer"
|
||||
className="bg-subtle-bg/50 cursor-pointer"
|
||||
onClick={() => toggleCategory(category.id)}
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<CardTitle>{category.name}</CardTitle>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<div className="flex items-center gap-2 text-sm text-tertiary">
|
||||
<span>
|
||||
{category.doneCount} / {category.totalCount}
|
||||
</span>
|
||||
@@ -502,7 +502,7 @@ function MitigationListContent({
|
||||
<div className="w-full">
|
||||
<table className="w-full">
|
||||
<thead>
|
||||
<tr className="bg-muted/30 text-sm font-medium text-muted-foreground">
|
||||
<tr className="bg-subtle-bg/30 text-sm font-medium text-tertiary">
|
||||
<th className="w-24 px-4 py-2 text-left">
|
||||
Importance
|
||||
</th>
|
||||
@@ -518,7 +518,7 @@ function MitigationListContent({
|
||||
{category.mitigations.map((mitigation) => (
|
||||
<tr
|
||||
key={mitigation.id || Math.random().toString()}
|
||||
className="hover:bg-muted/50 cursor-pointer"
|
||||
className="hover:bg-h-subtle-bg cursor-pointer"
|
||||
onClick={() => {
|
||||
if (mitigation?.id) {
|
||||
// Store this category in the hash
|
||||
@@ -570,7 +570,7 @@ function MitigationListContent({
|
||||
</table>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center justify-center p-6 text-center text-muted-foreground">
|
||||
<div className="flex items-center justify-center p-6 text-center text-tertiary">
|
||||
No mitigations in this category
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -12,9 +12,9 @@ export function MitigationViewSkeleton() {
|
||||
<PageTemplateSkeleton
|
||||
actions={
|
||||
<div className="flex items-center gap-2 w-1/3">
|
||||
<div className="bg-muted animate-pulse h-8 w-1/3 rounded-lg" />
|
||||
<div className="bg-muted animate-pulse h-8 w-1/3 rounded-lg" />
|
||||
<div className="bg-muted animate-pulse h-8 w-1/3 rounded-full" />
|
||||
<div className="bg-subtle-bg animate-pulse h-8 w-1/3 rounded-lg" />
|
||||
<div className="bg-subtle-bg animate-pulse h-8 w-1/3 rounded-lg" />
|
||||
<div className="bg-subtle-bg animate-pulse h-8 w-1/3 rounded-full" />
|
||||
</div>
|
||||
}
|
||||
>
|
||||
@@ -22,8 +22,8 @@ export function MitigationViewSkeleton() {
|
||||
{[1, 2, 3].map((i) => (
|
||||
<Card key={i}>
|
||||
<CardContent className="p-6">
|
||||
<div className="h-6 w-48 bg-muted animate-pulse rounded mb-2" />
|
||||
<div className="h-4 w-full bg-muted animate-pulse rounded" />
|
||||
<div className="h-6 w-48 bg-subtle-bg animate-pulse rounded mb-2" />
|
||||
<div className="h-4 w-full bg-subtle-bg animate-pulse rounded" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
|
||||
@@ -631,20 +631,20 @@ function MitigationViewContent({
|
||||
};
|
||||
|
||||
const getStateColor = (state: string | undefined): string => {
|
||||
if (!state) return "bg-gray-100 text-gray-800";
|
||||
if (!state) return "bg-secondary-bg text-primary";
|
||||
|
||||
const upperState = state.toUpperCase();
|
||||
|
||||
if (upperState === "NOT_STARTED") return "bg-gray-100 text-gray-800";
|
||||
if (upperState === "NOT_STARTED") return "bg-secondary-bg text-primary";
|
||||
if (upperState === "IN_PROGRESS") return "bg-blue-100 text-blue-800";
|
||||
if (upperState === "NOT_APPLICABLE") return "bg-purple-100 text-purple-800";
|
||||
if (upperState === "IMPLEMENTED") return "bg-green-100 text-green-800";
|
||||
|
||||
return "bg-gray-100 text-gray-800";
|
||||
return "bg-secondary-bg text-primary";
|
||||
};
|
||||
|
||||
const getImportanceColor = (importance: string | undefined): string => {
|
||||
if (!importance) return "bg-gray-100 text-gray-800";
|
||||
if (!importance) return "bg-secondary-bg text-primary";
|
||||
|
||||
const upperImportance = importance.toUpperCase();
|
||||
|
||||
@@ -652,7 +652,7 @@ function MitigationViewContent({
|
||||
if (upperImportance === "PREFERRED") return "bg-orange-100 text-orange-800";
|
||||
if (upperImportance === "ADVANCED") return "bg-blue-100 text-blue-800";
|
||||
|
||||
return "bg-gray-100 text-gray-800";
|
||||
return "bg-secondary-bg text-primary";
|
||||
};
|
||||
|
||||
const [updateTask] = useMutation<MitigationViewUpdateTaskStateMutationType>(
|
||||
@@ -1214,7 +1214,7 @@ function MitigationViewContent({
|
||||
} else if (mimeType.includes("excel") || mimeType.includes("spreadsheet")) {
|
||||
return <FileText className="w-4 h-4 text-green-600" />;
|
||||
} else {
|
||||
return <FileGeneric className="w-4 h-4 text-gray-500" />;
|
||||
return <FileGeneric className="w-4 h-4 text-secondary" />;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1891,18 +1891,16 @@ function MitigationViewContent({
|
||||
title={data.mitigation.name ?? ""}
|
||||
actions={
|
||||
<div className="flex items-center gap-2">
|
||||
<Button variant="outline" size="sm" onClick={handleEditMitigation}>
|
||||
Edit Mitigation
|
||||
</Button>
|
||||
<Button onClick={handleEditMitigation}>Edit Mitigation</Button>
|
||||
<Select
|
||||
defaultValue={data.mitigation.state}
|
||||
onValueChange={handleMitigationStateChange}
|
||||
>
|
||||
<SelectTrigger className="w-[160px] h-8 text-sm">
|
||||
<SelectTrigger className="w-[160px] h-10 text-sm">
|
||||
<div
|
||||
className={`${getStateColor(
|
||||
data.mitigation.state
|
||||
)} px-2 py-0.5 rounded-full text-sm w-full text-center`}
|
||||
)} px-2 py-0.5 rounded-sm text-sm w-full text-center`}
|
||||
>
|
||||
{formatState(data.mitigation.state)}
|
||||
</div>
|
||||
@@ -1927,7 +1925,7 @@ function MitigationViewContent({
|
||||
<div className="space-y-4 mb-8">
|
||||
<Card className="mt-4">
|
||||
<CardContent className="pt-6">
|
||||
<div className="prose prose-gray prose-sm md:prose-base text-gray-600 max-w-3xl">
|
||||
<div className="prose prose-gray prose-sm md:prose-base text-secondary max-w-3xl">
|
||||
<ReactMarkdown>{data.mitigation.description}</ReactMarkdown>
|
||||
</div>
|
||||
</CardContent>
|
||||
@@ -1939,8 +1937,9 @@ function MitigationViewContent({
|
||||
defaultValue="tasks"
|
||||
value={mainContentTab}
|
||||
onValueChange={setMainContentTab}
|
||||
className="mb-4"
|
||||
>
|
||||
<TabsList className="mb-4">
|
||||
<TabsList className="border-b w-full p-0 h-auto">
|
||||
<TabsTrigger value="tasks" className="flex items-center gap-2">
|
||||
<Check className="w-4 h-4" />
|
||||
Tasks
|
||||
@@ -2005,7 +2004,7 @@ function MitigationViewContent({
|
||||
<div className="flex items-center space-x-4 mb-4">
|
||||
<div className="flex-1">
|
||||
<div className="relative">
|
||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" />
|
||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-tertiary" />
|
||||
<Input
|
||||
placeholder="Search controls by ID, name, or description..."
|
||||
value={controlSearchQuery}
|
||||
@@ -2048,7 +2047,7 @@ function MitigationViewContent({
|
||||
) : (
|
||||
<div className="grid grid-cols-1 gap-2 max-h-[50vh] overflow-y-auto pr-2">
|
||||
{filteredControls().length === 0 ? (
|
||||
<div className="text-center py-8 text-gray-500">
|
||||
<div className="text-center py-8 text-secondary">
|
||||
No controls found. Try adjusting your search or select
|
||||
a different framework.
|
||||
</div>
|
||||
@@ -2084,7 +2083,7 @@ function MitigationViewContent({
|
||||
{control.name}
|
||||
</h3>
|
||||
{control.description && (
|
||||
<p className="text-sm text-gray-500 mt-1 line-clamp-2">
|
||||
<p className="text-sm text-secondary mt-1 line-clamp-2">
|
||||
{control.description}
|
||||
</p>
|
||||
)}
|
||||
@@ -2168,7 +2167,7 @@ function MitigationViewContent({
|
||||
{getLinkedControls().map((control: ControlNode) => (
|
||||
<tr
|
||||
key={control.id}
|
||||
className="border-b hover:bg-gray-50"
|
||||
className="border-b hover:bg-invert-bg"
|
||||
>
|
||||
<td className="py-3 px-4">
|
||||
<div className="font-mono text-sm px-1.5 py-0.5 rounded-sm bg-lime-100 border border-lime-200 text-lime-800 font-bold inline-block">
|
||||
@@ -2195,7 +2194,7 @@ function MitigationViewContent({
|
||||
</table>
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-center py-8 text-gray-500">
|
||||
<div className="text-center py-8 text-secondary">
|
||||
No controls linked to this mitigation yet. Click "Map
|
||||
to Controls" to link controls.
|
||||
</div>
|
||||
@@ -2211,7 +2210,7 @@ function MitigationViewContent({
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<h2 className="text-xl font-semibold">Tasks</h2>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="text-sm text-gray-500 flex items-center bg-gray-50 px-3 py-1.5 rounded-md border border-gray-200">
|
||||
<div className="text-sm text-secondary flex items-center bg-invert-bg px-3 py-1.5 rounded-md border border-mid-b">
|
||||
<FileIcon className="w-4 h-4 mr-2 text-blue-500" />
|
||||
<span>Drag & drop files onto tasks to add evidence</span>
|
||||
</div>
|
||||
@@ -2269,7 +2268,7 @@ function MitigationViewContent({
|
||||
}
|
||||
placeholder="Days"
|
||||
/>
|
||||
<p className="text-xs text-gray-500 mt-1">Days</p>
|
||||
<p className="text-xs text-secondary mt-1">Days</p>
|
||||
</div>
|
||||
<div className="w-full">
|
||||
<Input
|
||||
@@ -2282,7 +2281,7 @@ function MitigationViewContent({
|
||||
}
|
||||
placeholder="Hours"
|
||||
/>
|
||||
<p className="text-xs text-gray-500 mt-1">Hours</p>
|
||||
<p className="text-xs text-secondary mt-1">Hours</p>
|
||||
</div>
|
||||
<div className="w-full">
|
||||
<Input
|
||||
@@ -2295,7 +2294,7 @@ function MitigationViewContent({
|
||||
}
|
||||
placeholder="Minutes"
|
||||
/>
|
||||
<p className="text-xs text-gray-500 mt-1">
|
||||
<p className="text-xs text-secondary mt-1">
|
||||
Minutes
|
||||
</p>
|
||||
</div>
|
||||
@@ -2319,10 +2318,10 @@ function MitigationViewContent({
|
||||
{tasks.map((task) => (
|
||||
<div
|
||||
key={task?.id}
|
||||
className="rounded-md overflow-hidden border border-gray-200"
|
||||
className="rounded-md overflow-hidden border border-mid-b"
|
||||
>
|
||||
<div
|
||||
className={`flex items-center gap-3 py-4 px-2 hover:bg-gray-50 group relative transition-all duration-200 ${
|
||||
className={`flex items-center gap-3 py-4 px-2 hover:bg-invert-bg group relative transition-all duration-200 ${
|
||||
isDraggingFile && draggedOverTaskId !== task?.id
|
||||
? "border-dashed border-blue-300 bg-blue-50 bg-opacity-30"
|
||||
: ""
|
||||
@@ -2365,16 +2364,14 @@ function MitigationViewContent({
|
||||
<div className="flex flex-col items-center gap-3 text-blue-600">
|
||||
<Loader2 className="w-10 h-10 animate-spin text-blue-500" />
|
||||
<p className="font-medium">Adding document...</p>
|
||||
<p className="text-sm text-gray-500">Please wait</p>
|
||||
<p className="text-sm text-secondary">Please wait</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div
|
||||
className={`w-5 h-5 rounded border flex items-center justify-center cursor-pointer ${
|
||||
task?.state === "DONE"
|
||||
? "border-gray-400 bg-gray-100"
|
||||
: "border-gray-300"
|
||||
task?.state === "DONE" && "border-strong-b"
|
||||
} ${isDraggingFile ? "opacity-50" : ""}`}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation(); // Prevent task selection when checkbox is clicked
|
||||
@@ -2384,7 +2381,7 @@ function MitigationViewContent({
|
||||
}}
|
||||
>
|
||||
{task?.state === "DONE" && (
|
||||
<CheckCircle2 className="w-4 h-4 text-gray-500" />
|
||||
<CheckCircle2 className="w-4 h-4 text-secondary" />
|
||||
)}
|
||||
</div>
|
||||
<div
|
||||
@@ -2395,9 +2392,8 @@ function MitigationViewContent({
|
||||
<div>
|
||||
<h3
|
||||
className={`text-sm ${
|
||||
task?.state === "DONE"
|
||||
? "text-gray-500 line-through"
|
||||
: "text-gray-900"
|
||||
task?.state === "DONE" &&
|
||||
"text-secondary line-through"
|
||||
}`}
|
||||
>
|
||||
{task?.name}
|
||||
@@ -2406,7 +2402,7 @@ function MitigationViewContent({
|
||||
<p
|
||||
className={`text-xs mt-1 flex items-center ${
|
||||
task?.state === "DONE"
|
||||
? "text-gray-400 line-through"
|
||||
? "text-tertiary line-through"
|
||||
: "text-blue-500"
|
||||
}`}
|
||||
>
|
||||
@@ -2417,7 +2413,7 @@ function MitigationViewContent({
|
||||
</p>
|
||||
)}
|
||||
{task?.assignedTo && (
|
||||
<p className="text-xs mt-1 flex items-center text-gray-600">
|
||||
<p className="text-xs mt-1 flex items-center text-secondary">
|
||||
<User className="w-3 h-3 mr-1" />
|
||||
<span>{task.assignedTo.fullName}</span>
|
||||
</p>
|
||||
@@ -2439,7 +2435,7 @@ function MitigationViewContent({
|
||||
<PopoverTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
className="text-gray-400 hover:text-blue-600"
|
||||
className="text-tertiary hover:text-blue-600"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
if (task?.id) {
|
||||
@@ -2461,12 +2457,12 @@ function MitigationViewContent({
|
||||
{task?.assignedTo ? (
|
||||
<div className="p-4 space-y-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<User className="w-4 h-4 text-gray-500" />
|
||||
<User className="w-4 h-4 text-secondary" />
|
||||
<div className="text-sm">
|
||||
<p className="font-medium">
|
||||
{task.assignedTo.fullName}
|
||||
</p>
|
||||
<p className="text-xs text-gray-500">
|
||||
<p className="text-xs text-secondary">
|
||||
{task.assignedTo.primaryEmailAddress}
|
||||
</p>
|
||||
</div>
|
||||
@@ -2505,7 +2501,7 @@ function MitigationViewContent({
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="px-3 py-2 text-xs text-gray-500">
|
||||
<div className="px-3 py-2 text-xs text-secondary">
|
||||
Click on a person to assign them to this task
|
||||
</div>
|
||||
<div className="py-1">
|
||||
@@ -2574,7 +2570,7 @@ function MitigationViewContent({
|
||||
<p className="font-medium">
|
||||
{edge.node.fullName}
|
||||
</p>
|
||||
<p className="text-xs text-gray-500">
|
||||
<p className="text-xs text-secondary">
|
||||
{edge.node.primaryEmailAddress}
|
||||
</p>
|
||||
</div>
|
||||
@@ -2591,7 +2587,7 @@ function MitigationViewContent({
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="text-gray-400 hover:text-blue-600"
|
||||
className="text-tertiary hover:text-blue-600"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
if (task?.id && task?.name) {
|
||||
@@ -2604,7 +2600,7 @@ function MitigationViewContent({
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="text-gray-400 hover:text-red-600"
|
||||
className="text-tertiary hover:text-red-600"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
if (task?.id && task?.name) {
|
||||
@@ -2623,7 +2619,7 @@ function MitigationViewContent({
|
||||
task.evidences.edges.length > 0 && (
|
||||
<>
|
||||
<div
|
||||
className="flex items-center justify-between px-4 py-2 border-t border-gray-200 bg-gray-50 cursor-pointer hover:bg-gray-100"
|
||||
className="flex items-center justify-between px-4 py-2 border-t border-mid-b bg-invert-bg cursor-pointer hover:bg-secondary-bg"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation(); // Prevent task selection
|
||||
if (task.id) toggleEvidenceList(task.id);
|
||||
@@ -2631,7 +2627,7 @@ function MitigationViewContent({
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<FileText className="w-4 h-4 text-blue-500" />
|
||||
<span className="text-xs text-gray-600">
|
||||
<span className="text-xs text-secondary">
|
||||
{task.evidences.edges.length}{" "}
|
||||
{task.evidences.edges.length === 1
|
||||
? "Evidence"
|
||||
@@ -2639,14 +2635,14 @@ function MitigationViewContent({
|
||||
</span>
|
||||
</div>
|
||||
{expandedEvidenceTaskId === task.id ? (
|
||||
<ChevronUp className="w-4 h-4 text-gray-500" />
|
||||
<ChevronUp className="w-4 h-4 text-secondary" />
|
||||
) : (
|
||||
<ChevronDown className="w-4 h-4 text-gray-500" />
|
||||
<ChevronDown className="w-4 h-4 text-secondary" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
{expandedEvidenceTaskId === task.id && (
|
||||
<div className="bg-white border-t border-gray-200 p-3 space-y-2.5">
|
||||
<div className="bg-white border-t border-mid-b p-3 space-y-2.5">
|
||||
{task.evidences.edges.map((edge) => {
|
||||
if (!edge) return null;
|
||||
const evidence = edge.node;
|
||||
@@ -2655,17 +2651,17 @@ function MitigationViewContent({
|
||||
return (
|
||||
<div
|
||||
key={evidence.id}
|
||||
className="flex items-center justify-between p-3 rounded-md border border-gray-200 hover:border-blue-300 hover:shadow-sm transition-all bg-gray-50"
|
||||
className="flex items-center justify-between p-3 rounded-md border border-mid-b hover:border-blue-300 hover:shadow-sm transition-all bg-invert-bg"
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="bg-white p-2 rounded-md border border-gray-200">
|
||||
<div className="bg-white p-2 rounded-md border border-mid-b">
|
||||
{getFileIcon(
|
||||
evidence.mimeType,
|
||||
evidence.type
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-sm font-medium text-gray-800 flex items-center gap-2">
|
||||
<div className="text-sm font-medium text-primary flex items-center gap-2">
|
||||
{evidence.filename}
|
||||
{evidence.state === "REQUESTED" && (
|
||||
<Badge
|
||||
@@ -2676,14 +2672,14 @@ function MitigationViewContent({
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
<div className="text-xs text-gray-500 flex items-center gap-2 mt-0.5">
|
||||
<div className="text-xs text-secondary flex items-center gap-2 mt-0.5">
|
||||
{evidence.state === "REQUESTED" ? (
|
||||
<span className="italic text-yellow-600">
|
||||
Waiting for fulfillment
|
||||
{evidence.description && (
|
||||
<>
|
||||
<span className="mx-1">•</span>
|
||||
<span className="text-gray-600 not-italic">
|
||||
<span className="text-secondary not-italic">
|
||||
{evidence.description}
|
||||
</span>
|
||||
</>
|
||||
@@ -2691,7 +2687,7 @@ function MitigationViewContent({
|
||||
</span>
|
||||
) : evidence.type === "FILE" ? (
|
||||
<>
|
||||
<span className="font-medium text-gray-600">
|
||||
<span className="font-medium text-secondary">
|
||||
{formatFileSize(evidence.size)}
|
||||
</span>
|
||||
<span>•</span>
|
||||
@@ -2802,7 +2798,7 @@ function MitigationViewContent({
|
||||
))}
|
||||
|
||||
{tasks.length === 0 && (
|
||||
<div className="text-center py-12 bg-gray-50 rounded-lg border border-gray-200">
|
||||
<div className="text-center py-12 bg-invert-bg rounded-lg border border-mid-b">
|
||||
<p>No tasks yet. Click "Add Task" to create one.</p>
|
||||
</div>
|
||||
)}
|
||||
@@ -2843,7 +2839,7 @@ function MitigationViewContent({
|
||||
{risksData.mitigation.risks.edges.map(({ node }) => (
|
||||
<tr
|
||||
key={node.id}
|
||||
className="border-b hover:bg-gray-50"
|
||||
className="border-b hover:bg-invert-bg"
|
||||
onClick={() =>
|
||||
navigate(
|
||||
`/organizations/${organizationId}/risks/${node.id}`
|
||||
@@ -2883,7 +2879,7 @@ function MitigationViewContent({
|
||||
</table>
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-center py-8 text-gray-500">
|
||||
<div className="text-center py-8 text-secondary">
|
||||
No risks linked to this mitigation yet.
|
||||
</div>
|
||||
)}
|
||||
@@ -2906,7 +2902,7 @@ function MitigationViewContent({
|
||||
<SheetTitle className="text-xl font-semibold">
|
||||
{selectedTask.name}
|
||||
</SheetTitle>
|
||||
<SheetClose className="rounded-full p-1 hover:bg-gray-100">
|
||||
<SheetClose className="rounded-full p-1 hover:bg-secondary-bg">
|
||||
<X className="h-5 w-5" />
|
||||
</SheetClose>
|
||||
</div>
|
||||
@@ -2929,7 +2925,7 @@ function MitigationViewContent({
|
||||
</div>
|
||||
{!isEditingDuration ? (
|
||||
<div
|
||||
className="text-sm text-gray-500 flex items-center hover:bg-gray-100 px-2 py-1 rounded-md cursor-pointer"
|
||||
className="text-sm text-secondary flex items-center hover:bg-secondary-bg px-2 py-1 rounded-md cursor-pointer"
|
||||
onClick={() =>
|
||||
startEditingDuration(selectedTask.timeEstimate)
|
||||
}
|
||||
@@ -2954,7 +2950,7 @@ function MitigationViewContent({
|
||||
className="w-12 p-1 text-xs border rounded"
|
||||
placeholder="0"
|
||||
/>
|
||||
<span className="text-xs text-gray-500">d</span>
|
||||
<span className="text-xs text-secondary">d</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<input
|
||||
@@ -2968,7 +2964,7 @@ function MitigationViewContent({
|
||||
className="w-12 p-1 text-xs border rounded"
|
||||
placeholder="0"
|
||||
/>
|
||||
<span className="text-xs text-gray-500">h</span>
|
||||
<span className="text-xs text-secondary">h</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<input
|
||||
@@ -2982,7 +2978,7 @@ function MitigationViewContent({
|
||||
className="w-12 p-1 text-xs border rounded"
|
||||
placeholder="0"
|
||||
/>
|
||||
<span className="text-xs text-gray-500">m</span>
|
||||
<span className="text-xs text-secondary">m</span>
|
||||
</div>
|
||||
<button
|
||||
className="p-1 text-sm text-blue-600 hover:text-blue-800"
|
||||
@@ -2991,7 +2987,7 @@ function MitigationViewContent({
|
||||
Save
|
||||
</button>
|
||||
<button
|
||||
className="p-1 text-sm text-gray-500 hover:text-gray-700"
|
||||
className="p-1 text-sm text-secondary hover:text-primary"
|
||||
onClick={() => setIsEditingDuration(false)}
|
||||
>
|
||||
Cancel
|
||||
@@ -3004,10 +3000,10 @@ function MitigationViewContent({
|
||||
{/* Task description */}
|
||||
{selectedTask.description && (
|
||||
<div className="space-y-2">
|
||||
<h3 className="text-sm font-medium text-gray-600">
|
||||
<h3 className="text-sm font-medium text-secondary">
|
||||
Description
|
||||
</h3>
|
||||
<div className="prose prose-sm max-w-none p-3 bg-gray-50 rounded-md border border-gray-100">
|
||||
<div className="prose prose-sm max-w-none p-3 bg-invert-bg rounded-md border border-low-b">
|
||||
<ReactMarkdown>{selectedTask.description}</ReactMarkdown>
|
||||
</div>
|
||||
</div>
|
||||
@@ -3015,11 +3011,11 @@ function MitigationViewContent({
|
||||
|
||||
{/* Assigned person */}
|
||||
<div className="space-y-2">
|
||||
<h3 className="text-sm font-medium text-gray-600">
|
||||
<h3 className="text-sm font-medium text-secondary">
|
||||
Assignment
|
||||
</h3>
|
||||
{selectedTask.assignedTo ? (
|
||||
<div className="flex items-center justify-between p-3 bg-gray-50 rounded-md border border-gray-100">
|
||||
<div className="flex items-center justify-between p-3 bg-invert-bg rounded-md border border-low-b">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="bg-blue-100 text-blue-700 rounded-full p-2">
|
||||
<User className="w-5 h-5" />
|
||||
@@ -3028,7 +3024,7 @@ function MitigationViewContent({
|
||||
<p className="font-medium">
|
||||
{selectedTask.assignedTo.fullName}
|
||||
</p>
|
||||
<p className="text-xs text-gray-500">
|
||||
<p className="text-xs text-secondary">
|
||||
{selectedTask.assignedTo.primaryEmailAddress}
|
||||
</p>
|
||||
</div>
|
||||
@@ -3044,8 +3040,8 @@ function MitigationViewContent({
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center justify-between p-3 bg-gray-50 rounded-md border border-gray-100">
|
||||
<p className="text-gray-500">
|
||||
<div className="flex items-center justify-between p-3 bg-invert-bg rounded-md border border-low-b">
|
||||
<p className="text-secondary">
|
||||
No one is assigned to this task
|
||||
</p>
|
||||
<Popover>
|
||||
@@ -3115,7 +3111,7 @@ function MitigationViewContent({
|
||||
<p className="font-medium">
|
||||
{edge.node.fullName}
|
||||
</p>
|
||||
<p className="text-xs text-gray-500">
|
||||
<p className="text-xs text-secondary">
|
||||
{edge.node.primaryEmailAddress}
|
||||
</p>
|
||||
</div>
|
||||
@@ -3134,7 +3130,7 @@ function MitigationViewContent({
|
||||
{/* Evidence section */}
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<h3 className="text-sm font-medium text-gray-600">
|
||||
<h3 className="text-sm font-medium text-secondary">
|
||||
Evidence
|
||||
</h3>
|
||||
<Button
|
||||
@@ -3161,14 +3157,14 @@ function MitigationViewContent({
|
||||
return (
|
||||
<div
|
||||
key={evidence.id}
|
||||
className="flex items-center justify-between p-3 rounded-md border border-gray-200 hover:border-blue-300 hover:shadow-sm transition-all bg-gray-50"
|
||||
className="flex items-center justify-between p-3 rounded-md border border-mid-b hover:border-blue-300 hover:shadow-sm transition-all bg-invert-bg"
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="bg-white p-2 rounded-md border border-gray-200">
|
||||
<div className="bg-white p-2 rounded-md border border-mid-b">
|
||||
{getFileIcon(evidence.mimeType, evidence.type)}
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-sm font-medium text-gray-800 flex items-center gap-2">
|
||||
<div className="text-sm font-medium text-primary flex items-center gap-2">
|
||||
{evidence.filename}
|
||||
{evidence.state === "REQUESTED" && (
|
||||
<Badge
|
||||
@@ -3179,14 +3175,14 @@ function MitigationViewContent({
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
<div className="text-xs text-gray-500 flex items-center gap-2 mt-0.5">
|
||||
<div className="text-xs text-secondary flex items-center gap-2 mt-0.5">
|
||||
{evidence.state === "REQUESTED" ? (
|
||||
<span className="italic text-yellow-600">
|
||||
Waiting for fulfillment
|
||||
{evidence.description && (
|
||||
<>
|
||||
<span className="mx-1">•</span>
|
||||
<span className="text-gray-600 not-italic">
|
||||
<span className="text-secondary not-italic">
|
||||
{evidence.description}
|
||||
</span>
|
||||
</>
|
||||
@@ -3194,7 +3190,7 @@ function MitigationViewContent({
|
||||
</span>
|
||||
) : evidence.type === "FILE" ? (
|
||||
<>
|
||||
<span className="font-medium text-gray-600">
|
||||
<span className="font-medium text-secondary">
|
||||
{formatFileSize(evidence.size)}
|
||||
</span>
|
||||
<span>•</span>
|
||||
@@ -3296,12 +3292,12 @@ function MitigationViewContent({
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<div className="text-center py-6 bg-gray-50 rounded-md border border-dashed border-gray-200">
|
||||
<FileIcon className="w-8 h-8 text-gray-400 mx-auto mb-2" />
|
||||
<p className="text-sm text-gray-500">
|
||||
<div className="text-center py-6 bg-invert-bg rounded-md border border-dashed border-mid-b">
|
||||
<FileIcon className="w-8 h-8 text-tertiary mx-auto mb-2" />
|
||||
<p className="text-sm text-secondary">
|
||||
No evidence attached yet
|
||||
</p>
|
||||
<p className="text-xs text-gray-400 mt-1">
|
||||
<p className="text-xs text-tertiary mt-1">
|
||||
Upload files or add links to provide evidence
|
||||
</p>
|
||||
</div>
|
||||
@@ -3492,7 +3488,7 @@ function MitigationViewContent({
|
||||
<span>{previewEvidence?.filename}</span>
|
||||
<button
|
||||
onClick={() => setIsPreviewModalOpen(false)}
|
||||
className="rounded-full p-1 hover:bg-gray-100"
|
||||
className="rounded-full p-1 hover:bg-secondary-bg"
|
||||
>
|
||||
<X className="w-5 h-5" />
|
||||
</button>
|
||||
@@ -3502,11 +3498,11 @@ function MitigationViewContent({
|
||||
from here.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="flex flex-col items-center justify-center min-h-[300px] bg-gray-50 rounded-md p-4">
|
||||
<div className="flex flex-col items-center justify-center min-h-[300px] bg-invert-bg rounded-md p-4">
|
||||
{isLoadingFileUrl ? (
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<Loader2 className="w-8 h-8 animate-spin text-blue-500" />
|
||||
<p className="text-gray-500">Loading preview...</p>
|
||||
<p className="text-secondary">Loading preview...</p>
|
||||
</div>
|
||||
) : previewEvidence?.fileUrl ? (
|
||||
previewEvidence.mimeType.startsWith("image/") ? (
|
||||
@@ -3523,8 +3519,8 @@ function MitigationViewContent({
|
||||
/>
|
||||
) : (
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<FileGeneric className="w-16 h-16 text-gray-400" />
|
||||
<p className="text-gray-600">
|
||||
<FileGeneric className="w-16 h-16 text-tertiary" />
|
||||
<p className="text-secondary">
|
||||
Preview not available for this file type
|
||||
</p>
|
||||
<Button
|
||||
@@ -3540,8 +3536,8 @@ function MitigationViewContent({
|
||||
)
|
||||
) : (
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<FileGeneric className="w-12 h-12 text-gray-400" />
|
||||
<p className="text-gray-500">Failed to load preview</p>
|
||||
<FileGeneric className="w-12 h-12 text-tertiary" />
|
||||
<p className="text-secondary">Failed to load preview</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -12,7 +12,7 @@ export function NewMitigationViewSkeleton() {
|
||||
title="New Mitigation"
|
||||
description="Add a new mitigation. You will be able to link it to control and risks"
|
||||
>
|
||||
<div className="max-w-2xl aspect-square bg-muted rounded-xl animate-pulse" />
|
||||
<div className="max-w-2xl aspect-square bg-subtle-bg rounded-xl animate-pulse" />
|
||||
</PageTemplateSkeleton>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ export default function NewMitigationView() {
|
||||
"rounded-full cursor-pointer px-4 py-1 text-sm transition-colors",
|
||||
formData.importance === "MANDATORY"
|
||||
? "bg-red-100 text-red-900 ring-2 ring-red-600 ring-offset-2"
|
||||
: "bg-gray-100 text-gray-900 hover:bg-gray-200"
|
||||
: "bg-secondary-bg text-primary hover:bg-h-secondary-bg"
|
||||
)}
|
||||
>
|
||||
Mandatory
|
||||
@@ -164,7 +164,7 @@ export default function NewMitigationView() {
|
||||
"rounded-full cursor-pointer px-4 py-1 text-sm transition-colors",
|
||||
formData.importance === "PREFERRED"
|
||||
? "bg-yellow-100 text-yellow-900 ring-2 ring-yellow-600 ring-offset-2"
|
||||
: "bg-gray-100 text-gray-900 hover:bg-gray-200"
|
||||
: "bg-secondary-bg text-primary hover:bg-h-secondary-bg"
|
||||
)}
|
||||
>
|
||||
Preferred
|
||||
@@ -176,7 +176,7 @@ export default function NewMitigationView() {
|
||||
"rounded-full cursor-pointer px-4 py-1 text-sm transition-colors",
|
||||
formData.importance === "ADVANCED"
|
||||
? "bg-blue-100 text-blue-900 ring-2 ring-blue-600 ring-offset-2"
|
||||
: "bg-gray-100 text-gray-900 hover:bg-gray-200"
|
||||
: "bg-secondary-bg text-primary hover:bg-h-secondary-bg"
|
||||
)}
|
||||
>
|
||||
Advanced
|
||||
|
||||
@@ -12,7 +12,7 @@ export function NewPeopleViewSkeleton() {
|
||||
title="New Person"
|
||||
description="Add a new person interacting with organization"
|
||||
>
|
||||
<div className="max-w-2xl aspect-square bg-muted rounded-xl animate-pulse" />
|
||||
<div className="max-w-2xl aspect-square bg-subtle-bg rounded-xl animate-pulse" />
|
||||
</PageTemplateSkeleton>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ function EditableField({
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<HelpCircle className="h-4 w-4 text-gray-400" />
|
||||
<HelpCircle className="h-4 w-4 text-tertiary" />
|
||||
<Label className="text-sm">{label}</Label>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
@@ -59,7 +59,7 @@ function EditableField({
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
required={required}
|
||||
/>
|
||||
{helpText && <p className="text-sm text-gray-500">{helpText}</p>}
|
||||
{helpText && <p className="text-sm text-secondary">{helpText}</p>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -175,7 +175,7 @@ function NewPeopleViewContent() {
|
||||
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<HelpCircle className="h-4 w-4 text-gray-400" />
|
||||
<HelpCircle className="h-4 w-4 text-tertiary" />
|
||||
<Label className="text-sm">Additional Email Addresses</Label>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
@@ -224,7 +224,7 @@ function NewPeopleViewContent() {
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<h2 className="text-lg font-medium">Additional Information</h2>
|
||||
<p className="text-sm text-gray-500">
|
||||
<p className="text-sm text-secondary">
|
||||
Additional details about the person
|
||||
</p>
|
||||
</div>
|
||||
@@ -232,7 +232,7 @@ function NewPeopleViewContent() {
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<HelpCircle className="h-4 w-4 text-gray-400" />
|
||||
<HelpCircle className="h-4 w-4 text-tertiary" />
|
||||
<Label className="text-sm">Kind</Label>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
@@ -243,7 +243,7 @@ function NewPeopleViewContent() {
|
||||
"rounded-full px-4 py-1 text-sm transition-colors",
|
||||
formData.kind === "EMPLOYEE"
|
||||
? "bg-blue-100 text-blue-900 ring-2 ring-blue-600 ring-offset-2"
|
||||
: "bg-gray-100 text-gray-900 hover:bg-gray-200"
|
||||
: "bg-secondary-bg text-primary hover:bg-h-secondary-bg"
|
||||
)}
|
||||
>
|
||||
Employee
|
||||
@@ -255,7 +255,7 @@ function NewPeopleViewContent() {
|
||||
"rounded-full px-4 py-1 text-sm transition-colors",
|
||||
formData.kind === "CONTRACTOR"
|
||||
? "bg-purple-100 text-purple-900 ring-2 ring-purple-600 ring-offset-2"
|
||||
: "bg-gray-100 text-gray-900 hover:bg-gray-200"
|
||||
: "bg-secondary-bg text-primary hover:bg-h-secondary-bg"
|
||||
)}
|
||||
>
|
||||
Contractor
|
||||
@@ -269,7 +269,7 @@ function NewPeopleViewContent() {
|
||||
"rounded-full px-4 py-1 text-sm transition-colors",
|
||||
formData.kind === "SERVICE_ACCOUNT"
|
||||
? "bg-green-100 text-green-900 ring-2 ring-green-600 ring-offset-2"
|
||||
: "bg-gray-100 text-gray-900 hover:bg-gray-200"
|
||||
: "bg-secondary-bg text-primary hover:bg-h-secondary-bg"
|
||||
)}
|
||||
>
|
||||
Service Account
|
||||
@@ -286,7 +286,7 @@ function NewPeopleViewContent() {
|
||||
</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
className="bg-primary text-primary-foreground hover:bg-primary/90"
|
||||
className="bg-primary text-invert hover:bg-primary/90"
|
||||
>
|
||||
Create Person
|
||||
</Button>
|
||||
|
||||
@@ -11,18 +11,20 @@ export function PeopleListViewSkeleton() {
|
||||
<PageTemplateSkeleton
|
||||
title="People"
|
||||
description="Keep track of your company's workforce and their progress towards completing tasks assigned to them."
|
||||
actions={<div className="bg-muted animate-pulse h-9 w-1/6 rounded-lg" />}
|
||||
actions={
|
||||
<div className="bg-subtle-bg animate-pulse h-9 w-1/6 rounded-lg" />
|
||||
}
|
||||
>
|
||||
<div className="space-y-6">
|
||||
<div className="rounded-xl border bg-card p-4 space-y-2">
|
||||
<div className="h-5 w-32 bg-muted animate-pulse rounded" />
|
||||
<div className="h-10 w-full bg-muted animate-pulse rounded" />
|
||||
<div className="rounded-xl border bg-level-1 p-4 space-y-2">
|
||||
<div className="h-5 w-32 bg-subtle-bg animate-pulse rounded" />
|
||||
<div className="h-10 w-full bg-subtle-bg animate-pulse rounded" />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
{[1, 2, 3].map((i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="h-[72px] bg-muted animate-pulse rounded-xl"
|
||||
className="h-[72px] bg-subtle-bg animate-pulse rounded-xl"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -179,12 +179,7 @@ function PeopleListContent({
|
||||
description="Keep track of your company's workforce and their progress
|
||||
towards completing tasks assigned to them."
|
||||
actions={
|
||||
<Button
|
||||
asChild
|
||||
variant="outline"
|
||||
style={{ borderRadius: "0.5rem" }}
|
||||
className="gap-2"
|
||||
>
|
||||
<Button asChild variant="secondary" className="gap-2">
|
||||
<Link to={`/organizations/${organizationId}/people/new`}>
|
||||
<UserPlus className="h-4 w-4" />
|
||||
Add a person
|
||||
@@ -200,7 +195,7 @@ function PeopleListContent({
|
||||
to={`/organizations/${organizationId}/people/${person?.id}`}
|
||||
className="block"
|
||||
>
|
||||
<div className="flex items-center justify-between p-4 rounded-xl border bg-card hover:bg-accent/5 transition-colors">
|
||||
<div className="flex items-center justify-between p-4 rounded-xl border bg-level-1 hover:bg-accent-bg/5 transition-colors">
|
||||
<div className="flex items-center gap-3">
|
||||
<Avatar className="h-8 w-8">
|
||||
<AvatarFallback>{person?.fullName?.[0]}</AvatarFallback>
|
||||
@@ -209,8 +204,8 @@ function PeopleListContent({
|
||||
<p className="font-medium">{person?.fullName}</p>
|
||||
{person?.primaryEmailAddress && (
|
||||
<>
|
||||
<span className="text-muted-foreground">•</span>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
<span className="text-tertiary">•</span>
|
||||
<p className="text-sm text-tertiary">
|
||||
{person.primaryEmailAddress}
|
||||
</p>
|
||||
</>
|
||||
@@ -218,10 +213,7 @@ function PeopleListContent({
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Badge
|
||||
variant="secondary"
|
||||
className="bg-lime-9 text-white rounded-full px-3 py-0.5 text-xs font-medium"
|
||||
>
|
||||
<Badge className="px-3 py-0.5 text-xs font-medium">
|
||||
{person?.kind === "EMPLOYEE"
|
||||
? "Employee"
|
||||
: person?.kind === "CONTRACTOR"
|
||||
@@ -233,7 +225,7 @@ function PeopleListContent({
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-8 w-8 text-muted-foreground hover:bg-transparent hover:[&>svg]:text-destructive"
|
||||
className="h-8 w-8 text-tertiary hover:bg-transparent hover:[&>svg]:text-danger"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
if (
|
||||
@@ -254,7 +246,7 @@ function PeopleListContent({
|
||||
>
|
||||
<Trash2 className="h-4 w-4 transition-colors" />
|
||||
</Button>
|
||||
<ChevronRight className="h-4 w-4 text-muted-foreground" />
|
||||
<ChevronRight className="h-4 w-4 text-tertiary" />
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
@@ -11,12 +11,15 @@ export function PeopleViewSkeleton() {
|
||||
<PageTemplateSkeleton>
|
||||
<div className="space-y-6">
|
||||
<div className="space-y-1">
|
||||
<div className="h-8 w-48 bg-muted animate-pulse rounded" />
|
||||
<div className="h-4 w-96 bg-muted animate-pulse rounded" />
|
||||
<div className="h-8 w-48 bg-subtle-bg animate-pulse rounded" />
|
||||
<div className="h-4 w-96 bg-subtle-bg animate-pulse rounded" />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
{[1, 2].map((i) => (
|
||||
<div key={i} className="h-20 bg-muted animate-pulse rounded-lg" />
|
||||
<div
|
||||
key={i}
|
||||
className="h-20 bg-subtle-bg animate-pulse rounded-lg"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -73,7 +73,7 @@ function EditableField({
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<HelpCircle className="h-4 w-4 text-gray-400" />
|
||||
<HelpCircle className="h-4 w-4 text-tertiary" />
|
||||
<Label className="text-sm">{label}</Label>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
@@ -82,7 +82,7 @@ function EditableField({
|
||||
value={value}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
/>
|
||||
{helpText && <p className="text-sm text-gray-500">{helpText}</p>}
|
||||
{helpText && <p className="text-sm text-secondary">{helpText}</p>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -164,7 +164,7 @@ function PeopleViewContent({
|
||||
return (
|
||||
<PageTemplate title={formData.fullName}>
|
||||
<div className="space-y-6">
|
||||
<div className="mx-auto max-w-4xl space-y-6">
|
||||
<div className="max-w-4xl space-y-6">
|
||||
<EditableField
|
||||
label="Full Name"
|
||||
value={formData.fullName}
|
||||
@@ -182,7 +182,7 @@ function PeopleViewContent({
|
||||
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<HelpCircle className="h-4 w-4 text-gray-400" />
|
||||
<HelpCircle className="h-4 w-4 text-tertiary" />
|
||||
<Label className="text-sm">Additional Email Addresses</Label>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
@@ -229,7 +229,7 @@ function PeopleViewContent({
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<h2 className="text-lg font-medium">Additional Information</h2>
|
||||
<p className="text-sm text-gray-500">
|
||||
<p className="text-sm text-secondary">
|
||||
Additional details about the person
|
||||
</p>
|
||||
</div>
|
||||
@@ -237,7 +237,7 @@ function PeopleViewContent({
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<HelpCircle className="h-4 w-4 text-gray-400" />
|
||||
<HelpCircle className="h-4 w-4 text-tertiary" />
|
||||
<Label className="text-sm">Kind</Label>
|
||||
</div>
|
||||
<Select
|
||||
@@ -266,7 +266,7 @@ function PeopleViewContent({
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleSave}
|
||||
className="bg-primary text-primary-foreground hover:bg-primary/90"
|
||||
className="bg-primary text-invert hover:bg-primary/90"
|
||||
disabled={!hasChanges}
|
||||
>
|
||||
Save Changes
|
||||
|
||||
@@ -12,7 +12,7 @@ export function EditPolicyViewSkeleton() {
|
||||
title="Edit Policy"
|
||||
description="Edit an existing policy"
|
||||
>
|
||||
<div className="bg-muted animate-pulse rounded-lg h-[600px]" />
|
||||
<div className="bg-subtle-bg animate-pulse rounded-lg h-[600px]" />
|
||||
</PageTemplateSkeleton>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ export function NewPolicyViewSkeleton() {
|
||||
title="New Policy"
|
||||
description="Add a new policy for your organization"
|
||||
>
|
||||
<div className="bg-muted animate-pulse rounded-lg h-[600px]" />
|
||||
<div className="bg-subtle-bg animate-pulse rounded-lg h-[600px]" />
|
||||
</PageTemplateSkeleton>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,43 +12,45 @@ export function PolicyListViewSkeleton() {
|
||||
<PageTemplateSkeleton
|
||||
title="Policies"
|
||||
description="Manage your organization's policies"
|
||||
actions={<div className="bg-muted animate-pulse h-9 w-1/6 rounded-lg" />}
|
||||
actions={
|
||||
<div className="bg-subtle-bg animate-pulse h-9 w-1/6 rounded-lg" />
|
||||
}
|
||||
>
|
||||
{/* Search and filter mitigations skeleton */}
|
||||
<div className="flex flex-col md:flex-row gap-4 mb-6">
|
||||
<div className="flex-1 h-10 bg-muted animate-pulse rounded" />
|
||||
<div className="flex-1 h-10 bg-subtle-bg animate-pulse rounded" />
|
||||
<div className="flex gap-2">
|
||||
<div className="h-10 w-[180px] bg-muted animate-pulse rounded" />
|
||||
<div className="h-10 w-24 bg-muted animate-pulse rounded" />
|
||||
<div className="h-10 w-[180px] bg-subtle-bg animate-pulse rounded" />
|
||||
<div className="h-10 w-24 bg-subtle-bg animate-pulse rounded" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Results summary skeleton */}
|
||||
<div className="mb-4 h-4 w-48 bg-muted animate-pulse rounded" />
|
||||
<div className="mb-4 h-4 w-48 bg-subtle-bg animate-pulse rounded" />
|
||||
|
||||
{/* Policy grid skeleton */}
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||
{[1, 2, 3, 4, 5, 6].map((i) => (
|
||||
<Card key={i} className="bg-card/50 h-full flex flex-col">
|
||||
<Card key={i} className="bg-level-1/50 h-full flex flex-col">
|
||||
<CardContent className="p-6 flex-grow">
|
||||
<div className="flex justify-between items-start mb-3">
|
||||
<div className="h-7 w-48 bg-muted animate-pulse rounded" />
|
||||
<div className="h-6 w-20 bg-muted animate-pulse rounded-full" />
|
||||
<div className="h-7 w-48 bg-subtle-bg animate-pulse rounded" />
|
||||
<div className="h-6 w-20 bg-subtle-bg animate-pulse rounded-full" />
|
||||
</div>
|
||||
<div className="space-y-2 mb-4">
|
||||
<div className="h-4 w-full bg-muted animate-pulse rounded" />
|
||||
<div className="h-4 w-full bg-muted animate-pulse rounded" />
|
||||
<div className="h-4 w-2/3 bg-muted animate-pulse rounded" />
|
||||
<div className="h-4 w-full bg-subtle-bg animate-pulse rounded" />
|
||||
<div className="h-4 w-full bg-subtle-bg animate-pulse rounded" />
|
||||
<div className="h-4 w-2/3 bg-subtle-bg animate-pulse rounded" />
|
||||
</div>
|
||||
<div className="mt-auto space-y-2">
|
||||
<div className="h-4 w-40 bg-muted animate-pulse rounded" />
|
||||
<div className="h-4 w-40 bg-muted animate-pulse rounded" />
|
||||
<div className="h-4 w-40 bg-subtle-bg animate-pulse rounded" />
|
||||
<div className="h-4 w-40 bg-subtle-bg animate-pulse rounded" />
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="p-0 border-t">
|
||||
<div className="w-full grid grid-cols-2">
|
||||
<div className="h-12 border-r bg-muted/20 animate-pulse" />
|
||||
<div className="h-12 bg-muted/20 animate-pulse" />
|
||||
<div className="h-12 border-r bg-subtle-bg/20 animate-pulse" />
|
||||
<div className="h-12 bg-subtle-bg/20 animate-pulse" />
|
||||
</div>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
|
||||
@@ -92,20 +92,20 @@ function PolicyCard({
|
||||
: "No description available";
|
||||
|
||||
return (
|
||||
<Card className="relative overflow-hidden border bg-card transition-all hover:shadow-md h-full flex flex-col">
|
||||
<Card className="relative overflow-hidden border transition-all hover:shadow-md h-full flex flex-col">
|
||||
<CardContent className="p-6 flex-grow">
|
||||
<div className="flex flex-col h-full">
|
||||
<div className="flex justify-between items-start mb-3">
|
||||
<h3 className="font-semibold text-xl">{title}</h3>
|
||||
{status && (
|
||||
<Badge
|
||||
className={`${
|
||||
variant={
|
||||
status === "ACTIVE"
|
||||
? "bg-green-100 text-green-700 hover:bg-green-200"
|
||||
? "success"
|
||||
: status === "DRAFT"
|
||||
? "bg-yellow-100 text-yellow-700 hover:bg-yellow-200"
|
||||
: "bg-gray-100 text-gray-700 hover:bg-gray-200"
|
||||
}`}
|
||||
? "warning"
|
||||
: "secondary"
|
||||
}
|
||||
>
|
||||
{status === "ACTIVE"
|
||||
? "Security"
|
||||
@@ -116,11 +116,11 @@ function PolicyCard({
|
||||
)}
|
||||
</div>
|
||||
|
||||
<p className="text-muted-foreground text-sm line-clamp-3 mb-4">
|
||||
<p className="text-tertiary text-sm line-clamp-3 mb-4">
|
||||
{description}
|
||||
</p>
|
||||
|
||||
<div className="flex items-center gap-2 text-sm text-muted-foreground mt-auto">
|
||||
<div className="flex items-center gap-2 text-sm text-tertiary mt-auto">
|
||||
<Clock className="h-4 w-4" />
|
||||
<span>
|
||||
Last updated: {format(formattedUpdatedAt, "yyyy-MM-dd")}
|
||||
@@ -235,7 +235,7 @@ function PolicyListViewContent({
|
||||
{/* Search and filter mitigations */}
|
||||
<div className="flex flex-col md:flex-row gap-4 mb-6">
|
||||
<div className="relative flex-1">
|
||||
<Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
|
||||
<Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-tertiary" />
|
||||
<Input
|
||||
placeholder="Search policies..."
|
||||
className="pl-10"
|
||||
@@ -261,7 +261,7 @@ function PolicyListViewContent({
|
||||
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="outline" className="flex items-center gap-2">
|
||||
<Button variant="secondary" className="flex items-center gap-2">
|
||||
<ArrowUpDown className="h-4 w-4" />
|
||||
Sort
|
||||
</Button>
|
||||
@@ -291,7 +291,7 @@ function PolicyListViewContent({
|
||||
</div>
|
||||
|
||||
{/* Results summary */}
|
||||
<div className="mb-4 text-sm text-muted-foreground">
|
||||
<div className="mb-4 text-sm text-tertiary">
|
||||
Showing {filteredPolicies.length} of {policies.length} policies
|
||||
</div>
|
||||
|
||||
@@ -315,10 +315,10 @@ function PolicyListViewContent({
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-center py-12 border rounded-lg bg-muted/20">
|
||||
<FileText className="mx-auto h-8 w-8 text-muted-foreground mb-3" />
|
||||
<div className="text-center py-12 border rounded-lg bg-subtle-bg/20">
|
||||
<FileText className="mx-auto h-8 w-8 text-tertiary mb-3" />
|
||||
<h3 className="text-lg font-medium">No policies found</h3>
|
||||
<p className="text-muted-foreground mb-4">
|
||||
<p className="text-tertiary mb-4">
|
||||
{searchQuery || statusFilter !== "ALL"
|
||||
? "Try adjusting your search or filters"
|
||||
: "Create your first policy to get started"}
|
||||
|
||||
@@ -13,8 +13,8 @@ export function PolicyViewSkeleton() {
|
||||
withDescription
|
||||
actions={
|
||||
<div className="flex gap-2 w-1/3">
|
||||
<div className="bg-muted animate-pulse h-8 w-1/2 rounded-lg" />
|
||||
<div className="bg-muted animate-pulse h-8 w-1/2 rounded-lg" />
|
||||
<div className="bg-subtle-bg animate-pulse h-8 w-1/2 rounded-lg" />
|
||||
<div className="bg-subtle-bg animate-pulse h-8 w-1/2 rounded-lg" />
|
||||
</div>
|
||||
}
|
||||
>
|
||||
@@ -25,35 +25,35 @@ export function PolicyViewSkeleton() {
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<div className="p-2 rounded-md bg-slate-100/50 h-10 w-10 animate-pulse" />
|
||||
<div className="flex gap-2">
|
||||
<div className="h-6 w-16 bg-muted animate-pulse rounded-md" />
|
||||
<div className="h-6 w-20 bg-muted animate-pulse rounded-md" />
|
||||
<div className="h-6 w-16 bg-muted animate-pulse rounded-md" />
|
||||
<div className="h-6 w-16 bg-subtle-bg animate-pulse rounded-md" />
|
||||
<div className="h-6 w-20 bg-subtle-bg animate-pulse rounded-md" />
|
||||
<div className="h-6 w-16 bg-subtle-bg animate-pulse rounded-md" />
|
||||
</div>
|
||||
<div className="ml-auto">
|
||||
<div className="h-9 w-9 bg-muted animate-pulse rounded-full" />
|
||||
<div className="h-9 w-9 bg-subtle-bg animate-pulse rounded-full" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="h-8 w-3/4 bg-muted animate-pulse rounded mb-3" />
|
||||
<div className="h-8 w-3/4 bg-subtle-bg animate-pulse rounded mb-3" />
|
||||
|
||||
<div className="space-y-2 mb-6">
|
||||
<div className="h-4 w-full bg-muted animate-pulse rounded" />
|
||||
<div className="h-4 w-full bg-muted animate-pulse rounded" />
|
||||
<div className="h-4 w-2/3 bg-muted animate-pulse rounded" />
|
||||
<div className="h-4 w-full bg-subtle-bg animate-pulse rounded" />
|
||||
<div className="h-4 w-full bg-subtle-bg animate-pulse rounded" />
|
||||
<div className="h-4 w-2/3 bg-subtle-bg animate-pulse rounded" />
|
||||
</div>
|
||||
|
||||
<div className="flex border-b mb-6">
|
||||
<div className="px-4 py-2 h-8 w-28 bg-muted animate-pulse rounded" />
|
||||
<div className="px-4 py-2 h-8 w-28 bg-muted animate-pulse rounded opacity-50" />
|
||||
<div className="px-4 py-2 h-8 w-28 bg-muted animate-pulse rounded opacity-50" />
|
||||
<div className="px-4 py-2 h-8 w-28 bg-subtle-bg animate-pulse rounded" />
|
||||
<div className="px-4 py-2 h-8 w-28 bg-subtle-bg animate-pulse rounded opacity-50" />
|
||||
<div className="px-4 py-2 h-8 w-28 bg-subtle-bg animate-pulse rounded opacity-50" />
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="h-4 w-full bg-muted animate-pulse rounded" />
|
||||
<div className="h-4 w-full bg-muted animate-pulse rounded" />
|
||||
<div className="h-4 w-full bg-muted animate-pulse rounded" />
|
||||
<div className="h-4 w-full bg-muted animate-pulse rounded" />
|
||||
<div className="h-4 w-3/4 bg-muted animate-pulse rounded" />
|
||||
<div className="h-4 w-full bg-subtle-bg animate-pulse rounded" />
|
||||
<div className="h-4 w-full bg-subtle-bg animate-pulse rounded" />
|
||||
<div className="h-4 w-full bg-subtle-bg animate-pulse rounded" />
|
||||
<div className="h-4 w-full bg-subtle-bg animate-pulse rounded" />
|
||||
<div className="h-4 w-3/4 bg-subtle-bg animate-pulse rounded" />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -62,44 +62,44 @@ export function PolicyViewSkeleton() {
|
||||
<div className="lg:col-span-1">
|
||||
<Card className="border shadow-sm mb-6">
|
||||
<CardContent className="p-6">
|
||||
<div className="h-6 w-32 bg-muted animate-pulse rounded mb-6" />
|
||||
<div className="h-6 w-32 bg-subtle-bg animate-pulse rounded mb-6" />
|
||||
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<div className="h-4 w-28 bg-muted animate-pulse rounded mb-1" />
|
||||
<div className="h-5 w-24 bg-muted animate-pulse rounded" />
|
||||
<div className="h-4 w-28 bg-subtle-bg animate-pulse rounded mb-1" />
|
||||
<div className="h-5 w-24 bg-subtle-bg animate-pulse rounded" />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="h-4 w-28 bg-muted animate-pulse rounded mb-1" />
|
||||
<div className="h-5 w-24 bg-muted animate-pulse rounded" />
|
||||
<div className="h-4 w-28 bg-subtle-bg animate-pulse rounded mb-1" />
|
||||
<div className="h-5 w-24 bg-subtle-bg animate-pulse rounded" />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="h-4 w-28 bg-muted animate-pulse rounded mb-1" />
|
||||
<div className="h-5 w-36 bg-muted animate-pulse rounded" />
|
||||
<div className="h-4 w-28 bg-subtle-bg animate-pulse rounded mb-1" />
|
||||
<div className="h-5 w-36 bg-subtle-bg animate-pulse rounded" />
|
||||
</div>
|
||||
|
||||
<hr className="my-4" />
|
||||
|
||||
<div>
|
||||
<div className="h-5 w-32 bg-muted animate-pulse rounded mb-3" />
|
||||
<div className="h-5 w-32 bg-subtle-bg animate-pulse rounded mb-3" />
|
||||
<div className="space-y-2">
|
||||
<div className="h-4 w-48 bg-muted animate-pulse rounded" />
|
||||
<div className="h-4 w-48 bg-muted animate-pulse rounded" />
|
||||
<div className="h-4 w-48 bg-subtle-bg animate-pulse rounded" />
|
||||
<div className="h-4 w-48 bg-subtle-bg animate-pulse rounded" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<div className="h-10 w-full bg-muted animate-pulse rounded mb-6" />
|
||||
<div className="h-10 w-full bg-subtle-bg animate-pulse rounded mb-6" />
|
||||
|
||||
<Card className="border shadow-sm bg-red-50/30">
|
||||
<CardContent className="p-6">
|
||||
<div className="h-5 w-28 bg-muted animate-pulse rounded mb-3" />
|
||||
<div className="h-16 w-full bg-muted animate-pulse rounded mb-4" />
|
||||
<div className="h-10 w-full bg-muted animate-pulse rounded" />
|
||||
<div className="h-5 w-28 bg-subtle-bg animate-pulse rounded mb-3" />
|
||||
<div className="h-16 w-full bg-subtle-bg animate-pulse rounded mb-4" />
|
||||
<div className="h-10 w-full bg-subtle-bg animate-pulse rounded" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
@@ -151,7 +151,7 @@ function PolicyViewContent({
|
||||
<PageTemplate
|
||||
title={policy.name ?? ""}
|
||||
description={
|
||||
<div className="flex items-center gap-2 text-muted-foreground">
|
||||
<div className="flex items-center gap-2 text-tertiary">
|
||||
<Badge variant={policy.status === "ACTIVE" ? "default" : "outline"}>
|
||||
{policy.status === "ACTIVE" ? "Active" : "Draft"}
|
||||
</Badge>
|
||||
@@ -176,7 +176,7 @@ function PolicyViewContent({
|
||||
}
|
||||
actions={
|
||||
<div className="flex gap-2">
|
||||
<Button variant="outline" size="sm" asChild>
|
||||
<Button variant="secondary" asChild>
|
||||
<Link
|
||||
to={`/organizations/${organizationId}/policies/${policy.id}/edit`}
|
||||
>
|
||||
@@ -185,8 +185,6 @@ function PolicyViewContent({
|
||||
</Link>
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
// Logic to download policy content as PDF or text
|
||||
const element = document.createElement("a");
|
||||
@@ -219,10 +217,10 @@ function PolicyViewContent({
|
||||
<Badge
|
||||
className={`px-3 py-1 rounded-md font-medium ${
|
||||
policy.status === "ACTIVE"
|
||||
? "bg-green-100 text-green-700 hover:bg-green-200"
|
||||
? "bg-success-bg text-success hover:bg-h-success-bg"
|
||||
: policy.status === "DRAFT"
|
||||
? "bg-yellow-100 text-yellow-700 hover:bg-yellow-200"
|
||||
: "bg-gray-100 text-gray-700 hover:bg-gray-200"
|
||||
? "bg-warning-bg text-warning hover:bg-h-warning-bg"
|
||||
: "bg-secondary-bg text-secondary hover:bg-h-secondary-bg"
|
||||
}`}
|
||||
>
|
||||
{policy.status === "ACTIVE"
|
||||
@@ -237,7 +235,7 @@ function PolicyViewContent({
|
||||
|
||||
<h1 className="text-3xl font-bold mb-3">{policy.name}</h1>
|
||||
|
||||
<p className="text-muted-foreground mb-6">
|
||||
<p className="text-tertiary mb-6">
|
||||
{getDescription(policy.content)}
|
||||
</p>
|
||||
|
||||
@@ -247,33 +245,33 @@ function PolicyViewContent({
|
||||
onValueChange={setActiveTab}
|
||||
className="mb-6"
|
||||
>
|
||||
<TabsList className="border-b w-full rounded-none bg-transparent p-0 h-auto">
|
||||
<TabsList className="border-b w-full rounded-none p-0 h-auto">
|
||||
<TabsTrigger
|
||||
value="content"
|
||||
className={`rounded-none border-b-2 border-transparent px-4 py-2 font-medium ${
|
||||
className={`px-4 py-2 font-medium ${
|
||||
activeTab === "content"
|
||||
? "border-primary text-primary"
|
||||
: "text-muted-foreground"
|
||||
: "text-tertiary"
|
||||
}`}
|
||||
>
|
||||
Policy Content
|
||||
</TabsTrigger>
|
||||
<TabsTrigger
|
||||
value="history"
|
||||
className={`rounded-none border-b-2 border-transparent px-4 py-2 font-medium ${
|
||||
className={`px-4 py-2 font-medium ${
|
||||
activeTab === "history"
|
||||
? "border-primary text-primary"
|
||||
: "text-muted-foreground"
|
||||
: "text-tertiary"
|
||||
}`}
|
||||
>
|
||||
Version History
|
||||
</TabsTrigger>
|
||||
<TabsTrigger
|
||||
value="approvals"
|
||||
className={`rounded-none border-b-2 border-transparent px-4 py-2 font-medium ${
|
||||
className={`px-4 py-2 font-medium ${
|
||||
activeTab === "approvals"
|
||||
? "border-primary text-primary"
|
||||
: "text-muted-foreground"
|
||||
: "text-tertiary"
|
||||
}`}
|
||||
>
|
||||
Approvals
|
||||
@@ -293,7 +291,7 @@ function PolicyViewContent({
|
||||
|
||||
<TabsContent value="history" className="pt-6">
|
||||
<div className="text-center py-12">
|
||||
<p className="text-muted-foreground">
|
||||
<p className="text-tertiary">
|
||||
Version history will be available soon.
|
||||
</p>
|
||||
</div>
|
||||
@@ -301,7 +299,7 @@ function PolicyViewContent({
|
||||
|
||||
<TabsContent value="approvals" className="pt-6">
|
||||
<div className="text-center py-12">
|
||||
<p className="text-muted-foreground">
|
||||
<p className="text-tertiary">
|
||||
Approval workflow will be available soon.
|
||||
</p>
|
||||
</div>
|
||||
@@ -318,7 +316,7 @@ function PolicyViewContent({
|
||||
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<div className="flex items-center gap-2 text-muted-foreground mb-1">
|
||||
<div className="flex items-center gap-2 text-tertiary mb-1">
|
||||
<FileText className="h-4 w-4" />
|
||||
<span className="text-sm">Last Updated</span>
|
||||
</div>
|
||||
@@ -326,7 +324,7 @@ function PolicyViewContent({
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="flex items-center gap-2 text-muted-foreground mb-1">
|
||||
<div className="flex items-center gap-2 text-tertiary mb-1">
|
||||
<FileText className="h-4 w-4" />
|
||||
<span className="text-sm">Review Due</span>
|
||||
</div>
|
||||
@@ -338,7 +336,7 @@ function PolicyViewContent({
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="flex items-center gap-2 text-muted-foreground mb-1">
|
||||
<div className="flex items-center gap-2 text-tertiary mb-1">
|
||||
<User className="h-4 w-4" />
|
||||
<span className="text-sm">Owner</span>
|
||||
</div>
|
||||
@@ -364,10 +362,10 @@ function PolicyViewContent({
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
<Card className="border shadow-sm mt-6 bg-red-50">
|
||||
<Card className="border shadow-sm mt-6 bg-danger-bg">
|
||||
<CardContent className="p-6">
|
||||
<h3 className="text-red-500 font-semibold mb-3">Danger Zone</h3>
|
||||
<p className="text-sm text-muted-foreground mb-4">
|
||||
<h3 className="text-danger font-semibold mb-3">Danger Zone</h3>
|
||||
<p className="text-sm text-tertiary mb-4">
|
||||
Permanently delete this policy and all of its data. This action
|
||||
cannot be undone.
|
||||
</p>
|
||||
|
||||
@@ -10,7 +10,7 @@ export function NewRiskViewSkeleton() {
|
||||
return (
|
||||
<PageTemplateSkeleton>
|
||||
<div className="space-y-2">
|
||||
<div className="h-96 bg-muted animate-pulse rounded-lg" />
|
||||
<div className="h-96 bg-subtle-bg animate-pulse rounded-lg" />
|
||||
</div>
|
||||
</PageTemplateSkeleton>
|
||||
);
|
||||
|
||||
@@ -277,7 +277,7 @@ export default function NewRiskView() {
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
<p className="text-sm text-tertiary">
|
||||
Select a template to prefill the form or create a custom risk.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -11,7 +11,10 @@ export function RiskViewSkeleton() {
|
||||
<PageTemplateSkeleton>
|
||||
<div className="space-y-2">
|
||||
{[1, 2].map((i) => (
|
||||
<div key={i} className="h-20 bg-muted animate-pulse rounded-lg" />
|
||||
<div key={i} className="h-20 bg-level-1 rounded-xl">
|
||||
<div className="h10 animate-pulse rounded-lg" />
|
||||
<div className="h10 animate-pulse rounded-lg" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</PageTemplateSkeleton>
|
||||
|
||||
@@ -287,27 +287,27 @@ function RiskListViewContent({
|
||||
<div className="w-full overflow-auto">
|
||||
<table className="w-full caption-bottom text-sm">
|
||||
<thead className="[&_tr]:border-b">
|
||||
<tr className="border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted">
|
||||
<th className="h-12 px-4 text-left align-middle font-medium text-muted-foreground w-1/2">
|
||||
<tr className="border-b transition-colors hover:bg-h-subtle-bg data-[state=selected]:bg-subtle-bg">
|
||||
<th className="h-12 px-4 text-left align-middle font-medium text-tertiary w-1/2">
|
||||
Name
|
||||
</th>
|
||||
<th className="h-12 px-4 text-left align-middle font-medium text-muted-foreground w-1/4">
|
||||
<th className="h-12 px-4 text-left align-middle font-medium text-tertiary w-1/4">
|
||||
Probability
|
||||
</th>
|
||||
<th className="h-12 px-4 text-left align-middle font-medium text-muted-foreground w-1/4">
|
||||
<th className="h-12 px-4 text-left align-middle font-medium text-tertiary w-1/4">
|
||||
Impact
|
||||
</th>
|
||||
<th className="h-12 px-4 text-left align-middle font-medium text-muted-foreground w-[80px]">
|
||||
<th className="h-12 px-4 text-left align-middle font-medium text-tertiary w-[80px]">
|
||||
Action
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="[&_tr:last-child]:border-0">
|
||||
{risks.length === 0 ? (
|
||||
<tr className="border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted">
|
||||
<tr className="border-b transition-colors hover:bg-h-subtle-bg data-[state=selected]:bg-subtle-bg">
|
||||
<td
|
||||
colSpan={4}
|
||||
className="text-center p-4 align-middle text-muted-foreground"
|
||||
className="text-center p-4 align-middle text-tertiary"
|
||||
>
|
||||
No risks found. Create a new risk to get started.
|
||||
</td>
|
||||
@@ -316,7 +316,7 @@ function RiskListViewContent({
|
||||
risks.map((risk) => (
|
||||
<tr
|
||||
key={risk.id}
|
||||
className="border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted cursor-pointer"
|
||||
className="border-b transition-colors hover:bg-h-subtle-bg data-[state=selected]:bg-subtle-bg cursor-pointer"
|
||||
>
|
||||
<td className="p-0 align-middle font-medium w-1/2">
|
||||
<Link
|
||||
@@ -350,7 +350,7 @@ function RiskListViewContent({
|
||||
setRiskToDelete({ id: risk.id, name: risk.name });
|
||||
}}
|
||||
>
|
||||
<Trash2 className="h-4 w-4 text-destructive" />
|
||||
<Trash2 className="h-4 w-4 text-danger" />
|
||||
</Button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -10,7 +10,7 @@ export function ShowRiskViewSkeleton() {
|
||||
return (
|
||||
<PageTemplateSkeleton>
|
||||
<div className="space-y-2">
|
||||
<div className="h-96 bg-muted animate-pulse rounded-lg" />
|
||||
<div className="h-96 subtle-bg animate-pulse rounded-lg" />
|
||||
</div>
|
||||
</PageTemplateSkeleton>
|
||||
);
|
||||
|
||||
@@ -415,7 +415,7 @@ function ShowRiskViewContent({
|
||||
<CardContent>
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
||||
<div>
|
||||
<h3 className="text-sm font-medium text-gray-500">
|
||||
<h3 className="text-sm font-medium text-secondary">
|
||||
Probability
|
||||
</h3>
|
||||
<p className="mt-1 text-lg">
|
||||
@@ -423,19 +423,19 @@ function ShowRiskViewContent({
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-sm font-medium text-gray-500">Impact</h3>
|
||||
<h3 className="text-sm font-medium text-secondary">Impact</h3>
|
||||
<p className="mt-1 text-lg">
|
||||
{(risk.impact! * 100).toFixed(0)}%
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-sm font-medium text-gray-500">Severity</h3>
|
||||
<h3 className="text-sm font-medium text-secondary">Severity</h3>
|
||||
<p className="mt-1">
|
||||
<Badge className={severity.class}>{severity.level}</Badge>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-sm font-medium text-gray-500">Created</h3>
|
||||
<h3 className="text-sm font-medium text-secondary">Created</h3>
|
||||
<p className="mt-1 text-sm">{formatDate(risk.createdAt!)}</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -490,7 +490,7 @@ function ShowRiskViewContent({
|
||||
disabled={isUnlinkingMitigation}
|
||||
title="Unlink mitigation"
|
||||
>
|
||||
<Trash2 className="h-4 w-4 text-destructive" />
|
||||
<Trash2 className="h-4 w-4 text-danger" />
|
||||
</Button>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
@@ -499,7 +499,7 @@ function ShowRiskViewContent({
|
||||
</Table>
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-center py-10 text-gray-500">
|
||||
<div className="text-center py-10 text-secondary">
|
||||
<p>No mitigations associated with this risk.</p>
|
||||
</div>
|
||||
)}
|
||||
@@ -510,13 +510,13 @@ function ShowRiskViewContent({
|
||||
<CardContent className="pt-6">
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<h3 className="text-sm font-medium text-gray-500">
|
||||
<h3 className="text-sm font-medium text-secondary">
|
||||
Full Description
|
||||
</h3>
|
||||
<p className="mt-1">{risk.description}</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-sm font-medium text-gray-500">
|
||||
<h3 className="text-sm font-medium text-secondary">
|
||||
Last Updated
|
||||
</h3>
|
||||
<p className="mt-1">{formatDate(risk.updatedAt!)}</p>
|
||||
@@ -578,7 +578,7 @@ function ShowRiskViewContent({
|
||||
<div className="flex flex-row space-x-2">
|
||||
<div className="flex-1">
|
||||
<div className="relative">
|
||||
<Search className="absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" />
|
||||
<Search className="absolute left-2 top-2.5 h-4 w-4 text-tertiary" />
|
||||
<Input
|
||||
placeholder="Search mitigations..."
|
||||
className="pl-8"
|
||||
@@ -629,7 +629,7 @@ function ShowRiskViewContent({
|
||||
return (
|
||||
<div
|
||||
key={mitigation.id}
|
||||
className="p-4 hover:bg-gray-50"
|
||||
className="p-4 hover:bg-invert-bg"
|
||||
>
|
||||
<div className="flex justify-between">
|
||||
<div>
|
||||
|
||||
@@ -14,18 +14,18 @@ export function VendorListViewSkeleton() {
|
||||
keep track of their risk and compliance status."
|
||||
>
|
||||
<div className="space-y-6">
|
||||
<div className="rounded-xl border bg-card p-4 space-y-4">
|
||||
<div className="h-5 w-32 bg-muted animate-pulse rounded" />
|
||||
<div className="rounded-xl border bg-level-1 p-4 space-y-4">
|
||||
<div className="h-5 w-32 subtle-bg animate-pulse rounded" />
|
||||
<div className="flex gap-2">
|
||||
<div className="h-10 flex-1 bg-muted animate-pulse rounded" />
|
||||
<div className="h-10 w-32 bg-muted animate-pulse rounded" />
|
||||
<div className="h-10 flex-1 subtle-bg animate-pulse rounded" />
|
||||
<div className="h-10 w-32 subtle-bg animate-pulse rounded" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
{[1, 2, 3].map((i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="h-[72px] bg-muted animate-pulse rounded-xl"
|
||||
className="h-[72px] subtle-bg animate-pulse rounded-xl"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -246,7 +246,7 @@ function VendorListContent({
|
||||
keep track of their risk and compliance status."
|
||||
>
|
||||
<div className="space-y-6">
|
||||
<div className="rounded-xl border bg-card p-4">
|
||||
<div className="rounded-xl border bg-level-1 p-4">
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<Store className="h-5 w-5" />
|
||||
<h3 className="font-medium">Add a vendor</h3>
|
||||
@@ -276,12 +276,12 @@ function VendorListContent({
|
||||
{filteredVendors.length > 0 ? (
|
||||
<div
|
||||
style={{ borderRadius: "0.3rem" }}
|
||||
className="absolute top-full left-0 mt-1 w-[calc(100%-100px)] max-h-48 overflow-y-auto border bg-popover shadow-md z-10"
|
||||
className="absolute top-full left-0 mt-1 w-[calc(100%-100px)] max-h-48 overflow-y-auto border bg-invert-bg shadow-md z-10"
|
||||
>
|
||||
{filteredVendors.map((vendor: VendorItem) => (
|
||||
<button
|
||||
key={vendor.id}
|
||||
className="w-full px-3 py-2 text-left hover:bg-accent"
|
||||
className="w-full px-3 py-2 text-left bg-invert-bg hover:bg-h-subtle-bg"
|
||||
onClick={() => {
|
||||
createVendor({
|
||||
variables: {
|
||||
@@ -314,10 +314,10 @@ function VendorListContent({
|
||||
) : (
|
||||
<div
|
||||
style={{ borderRadius: "0.3rem" }}
|
||||
className="absolute top-full left-0 mt-1 w-[calc(100%-100px)] border bg-popover shadow-md z-10"
|
||||
className="absolute top-full left-0 mt-1 w-[calc(100%-100px)] border bg-level-0 shadow-md z-10"
|
||||
>
|
||||
<button
|
||||
className="w-full px-3 py-2 text-left hover:bg-accent flex items-center gap-2"
|
||||
className="w-full px-3 py-2 text-left hover:bg-accent-bg flex items-center gap-2"
|
||||
onClick={() => {
|
||||
createVendor({
|
||||
variables: {
|
||||
@@ -360,7 +360,7 @@ function VendorListContent({
|
||||
to={`/organizations/${organizationId}/vendors/${vendor?.id}`}
|
||||
className="block"
|
||||
>
|
||||
<div className="flex items-center justify-between p-4 rounded-xl border bg-card hover:bg-accent/5 transition-colors">
|
||||
<div className="flex items-center justify-between p-4 rounded-xl border bg-level-1 hover:bg-accent-bg/5 transition-colors">
|
||||
<div className="flex items-center gap-3">
|
||||
<Avatar className="h-8 w-8">
|
||||
<AvatarFallback>{vendor?.name?.[0]}</AvatarFallback>
|
||||
@@ -369,8 +369,8 @@ function VendorListContent({
|
||||
<p className="font-medium">{vendor?.name}</p>
|
||||
{vendor?.description && (
|
||||
<>
|
||||
<span className="text-muted-foreground">•</span>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
<span className="text-tertiary">•</span>
|
||||
<p className="text-sm text-tertiary">
|
||||
{vendor.description}
|
||||
</p>
|
||||
</>
|
||||
@@ -382,10 +382,10 @@ function VendorListContent({
|
||||
variant="secondary"
|
||||
className={
|
||||
vendor.riskTier === "CRITICAL"
|
||||
? "bg-red-100 text-red-900 rounded-full px-3 py-0.5 text-xs font-medium"
|
||||
? "bg-danger-bg text-danger rounded-full px-3 py-0.5 text-xs font-medium"
|
||||
: vendor?.riskTier === "SIGNIFICANT"
|
||||
? "bg-yellow-100 text-yellow-900 rounded-full px-3 py-0.5 text-xs font-medium"
|
||||
: "bg-green-100 text-green-900 rounded-full px-3 py-0.5 text-xs font-medium"
|
||||
? "bg-warning-bg text-warning rounded-full px-3 py-0.5 text-xs font-medium"
|
||||
: "bg-success-bg text-success rounded-full px-3 py-0.5 text-xs font-medium"
|
||||
}
|
||||
>
|
||||
{vendor.riskTier}
|
||||
@@ -393,7 +393,7 @@ function VendorListContent({
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-8 w-8 text-muted-foreground hover:bg-transparent hover:[&>svg]:text-destructive"
|
||||
className="h-8 w-8 text-tertiary hover:bg-transparent hover:[&>svg]:text-danger"
|
||||
onClick={(e) => {
|
||||
e.preventDefault(); // Prevent navigation
|
||||
if (
|
||||
@@ -421,7 +421,7 @@ function VendorListContent({
|
||||
>
|
||||
<Trash2 className="h-4 w-4 transition-colors" />
|
||||
</Button>
|
||||
<ChevronRight className="h-4 w-4 text-muted-foreground" />
|
||||
<ChevronRight className="h-4 w-4 text-tertiary" />
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
@@ -11,7 +11,7 @@ export function VendorViewSkeleton() {
|
||||
<PageTemplateSkeleton>
|
||||
<div className="space-y-2">
|
||||
{[1, 2].map((i) => (
|
||||
<div key={i} className="h-20 bg-muted animate-pulse rounded-lg" />
|
||||
<div key={i} className="h-20 subtle-bg animate-pulse rounded-lg" />
|
||||
))}
|
||||
</div>
|
||||
</PageTemplateSkeleton>
|
||||
|
||||
@@ -77,7 +77,7 @@ function EditableField({
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<HelpCircle className="h-4 w-4 text-gray-400" />
|
||||
<HelpCircle className="h-4 w-4 text-tertiary" />
|
||||
<Label className="text-sm">{label}</Label>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
@@ -86,7 +86,7 @@ function EditableField({
|
||||
value={value}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
/>
|
||||
{helpText && <p className="text-sm text-gray-500">{helpText}</p>}
|
||||
{helpText && <p className="text-sm text-secondary">{helpText}</p>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -218,7 +218,7 @@ function VendorViewContent({
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<h2 className="text-lg font-medium">Service Information</h2>
|
||||
<p className="text-sm text-gray-500">
|
||||
<p className="text-sm text-secondary">
|
||||
Basic information about the vendor service
|
||||
</p>
|
||||
</div>
|
||||
@@ -242,7 +242,7 @@ function VendorViewContent({
|
||||
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<HelpCircle className="h-4 w-4 text-gray-400" />
|
||||
<HelpCircle className="h-4 w-4 text-tertiary" />
|
||||
<Label className="text-sm">Service Criticality</Label>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
@@ -253,8 +253,8 @@ function VendorViewContent({
|
||||
className={cn(
|
||||
"rounded-full px-4 py-1 text-sm transition-colors",
|
||||
formData.serviceCriticality === "LOW"
|
||||
? "bg-green-100 text-green-900 ring-2 ring-green-600 ring-offset-2"
|
||||
: "bg-gray-100 text-gray-900 hover:bg-gray-200"
|
||||
? "bg-success-bg text-success ring ring-success-b"
|
||||
: "bg-invert-bg"
|
||||
)}
|
||||
>
|
||||
Low
|
||||
@@ -266,8 +266,8 @@ function VendorViewContent({
|
||||
className={cn(
|
||||
"rounded-full px-4 py-1 text-sm transition-colors",
|
||||
formData.serviceCriticality === "MEDIUM"
|
||||
? "bg-yellow-100 text-yellow-900 ring-2 ring-yellow-600 ring-offset-2"
|
||||
: "bg-gray-100 text-gray-900 hover:bg-gray-200"
|
||||
? "bg-warning-bg text-warning ring ring-warning-b"
|
||||
: "bg-invert-bg"
|
||||
)}
|
||||
>
|
||||
Medium
|
||||
@@ -279,14 +279,14 @@ function VendorViewContent({
|
||||
className={cn(
|
||||
"rounded-full px-4 py-1 text-sm transition-colors",
|
||||
formData.serviceCriticality === "HIGH"
|
||||
? "bg-red-100 text-red-900 ring-2 ring-red-600 ring-offset-2"
|
||||
: "bg-gray-100 text-gray-900 hover:bg-gray-200"
|
||||
? "bg-danger-bg text-danger ring ring-danger-b"
|
||||
: "bg-invert-bg"
|
||||
)}
|
||||
>
|
||||
High
|
||||
</button>
|
||||
</div>
|
||||
<p className="text-sm text-gray-500">
|
||||
<p className="text-sm text-secondary">
|
||||
{formData.serviceCriticality === "HIGH" &&
|
||||
"Critical service - downtime severely impacts end-users"}
|
||||
{formData.serviceCriticality === "MEDIUM" &&
|
||||
@@ -298,7 +298,7 @@ function VendorViewContent({
|
||||
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<HelpCircle className="h-4 w-4 text-gray-400" />
|
||||
<HelpCircle className="h-4 w-4 text-tertiary" />
|
||||
<Label className="text-sm">Risk Tier</Label>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
@@ -307,8 +307,8 @@ function VendorViewContent({
|
||||
className={cn(
|
||||
"rounded-full px-4 py-1 text-sm transition-colors",
|
||||
formData.riskTier === "CRITICAL"
|
||||
? "bg-red-100 text-red-900 ring-2 ring-red-600 ring-offset-2"
|
||||
: "bg-gray-100 text-gray-900 hover:bg-gray-200"
|
||||
? "bg-danger-bg text-danger ring ring-danger-b"
|
||||
: "bg-invert-bg"
|
||||
)}
|
||||
>
|
||||
Critical
|
||||
@@ -318,8 +318,8 @@ function VendorViewContent({
|
||||
className={cn(
|
||||
"rounded-full px-4 py-1 text-sm transition-colors",
|
||||
formData.riskTier === "SIGNIFICANT"
|
||||
? "bg-yellow-100 text-yellow-900 ring-2 ring-yellow-600 ring-offset-2"
|
||||
: "bg-gray-100 text-gray-900 hover:bg-gray-200"
|
||||
? "bg-warning-bg text-warning ring ring-warning-b"
|
||||
: "bg-invert-bg"
|
||||
)}
|
||||
>
|
||||
Significant
|
||||
@@ -329,14 +329,14 @@ function VendorViewContent({
|
||||
className={cn(
|
||||
"rounded-full px-4 py-1 text-sm transition-colors",
|
||||
formData.riskTier === "GENERAL"
|
||||
? "bg-green-100 text-green-900 ring-2 ring-green-600 ring-offset-2"
|
||||
: "bg-gray-100 text-gray-900 hover:bg-gray-200"
|
||||
? "bg-info-bg text-info ring ring-info-b"
|
||||
: "bg-invert-bg"
|
||||
)}
|
||||
>
|
||||
General
|
||||
</button>
|
||||
</div>
|
||||
<p className="text-sm text-gray-500">
|
||||
<p className="text-sm text-secondary">
|
||||
{formData.riskTier === "CRITICAL" &&
|
||||
"Handles sensitive data, critical for platform operation"}
|
||||
{formData.riskTier === "SIGNIFICANT" &&
|
||||
@@ -376,7 +376,7 @@ function VendorViewContent({
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleSave}
|
||||
className="bg-primary text-primary-foreground hover:bg-primary/90"
|
||||
className="bg-primary text-invert hover:bg-primary/90"
|
||||
disabled={!hasChanges}
|
||||
>
|
||||
Save Changes
|
||||
|
||||
@@ -1,168 +0,0 @@
|
||||
@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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.policy-content ul,
|
||||
.policy-content ul,
|
||||
.policy-content ol {
|
||||
margin-left: 1.5rem;
|
||||
margin-bottom: 1rem;
|
||||
@@ -67,24 +67,24 @@
|
||||
}
|
||||
|
||||
.policy-content blockquote {
|
||||
border-left: 4px solid hsl(var(--border));
|
||||
border-left: 4px solid hsl(var(--solid-b));
|
||||
padding-left: 1rem;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
font-style: italic;
|
||||
color: hsl(var(--muted-foreground));
|
||||
color: hsl(var(--tertiary));
|
||||
}
|
||||
|
||||
.policy-content code {
|
||||
font-family: monospace;
|
||||
background-color: hsl(var(--muted));
|
||||
background-color: hsl(var(--invert-bg));
|
||||
padding: 0.2rem 0.4rem;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
.policy-content pre {
|
||||
background-color: hsl(var(--muted));
|
||||
background-color: hsl(var(--invert-bg));
|
||||
padding: 1rem;
|
||||
border-radius: 0.5rem;
|
||||
overflow-x: auto;
|
||||
@@ -105,12 +105,12 @@
|
||||
|
||||
.policy-content th,
|
||||
.policy-content td {
|
||||
border: 1px solid hsl(var(--border));
|
||||
border: 1px solid hsl(var(--solid-b));
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.policy-content th {
|
||||
background-color: hsl(var(--muted));
|
||||
background-color: hsl(var(--invert-bg));
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
@@ -122,6 +122,6 @@
|
||||
|
||||
.policy-content hr {
|
||||
border: 0;
|
||||
border-top: 1px solid hsl(var(--border));
|
||||
border-top: 1px solid hsl(var(--solid-b));
|
||||
margin: 1.5rem 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user