Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
202 changes: 202 additions & 0 deletions packages/graph-explorer/src/components/AlertDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
"use client";

import { AlertDialog as AlertDialogPrimitive } from "radix-ui";
import * as React from "react";

import { cn } from "@/utils";

import { Button } from "./Button";

function AlertDialog({
...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {
return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />;
}

function AlertDialogTrigger({
...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {
return (
<AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />
);
}

function AlertDialogPortal({
...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) {
return (
<AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />
);
}

function AlertDialogOverlay({
className,
...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) {
return (
<AlertDialogPrimitive.Overlay
data-slot="alert-dialog-overlay"
className={cn(
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 fixed inset-0 z-50 bg-black/30 duration-100 supports-backdrop-filter:backdrop-blur-xs",
className,
)}
{...props}
/>
);
}

function AlertDialogContent({
className,
size = "default",
...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Content> & {
size?: "default" | "sm";
}) {
return (
<AlertDialogPortal>
<AlertDialogOverlay />
<div className="fixed inset-0 z-50 flex h-full w-full items-center justify-center p-20">
<AlertDialogPrimitive.Content
data-slot="alert-dialog-content"
data-size={size}
className={cn(
"group/alert-dialog-content bg-popover text-popover-foreground ring-foreground/10 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 grid max-h-full w-full gap-6 overflow-y-auto rounded-xl p-6 shadow-lg ring-1 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-lg",
className,
)}
{...props}
/>
</div>
</AlertDialogPortal>
);
}

function AlertDialogHeader({
className,
...props
}: React.ComponentProps<"div">) {
return (
<div
data-slot="alert-dialog-header"
className={cn(
"grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-cols-[auto_1fr] sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]",
className,
)}
{...props}
/>
);
}

function AlertDialogFooter({
className,
...props
}: React.ComponentProps<"div">) {
return (
<div
data-slot="alert-dialog-footer"
className={cn(
"bg-muted/50 -mx-4 -mb-4 flex flex-col-reverse gap-3 rounded-b-xl border-t p-4 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end",
className,
)}
{...props}
/>
);
}

function AlertDialogMedia({
className,
...props
}: React.ComponentProps<"div">) {
return (
<div
data-slot="alert-dialog-media"
className={cn(
"bg-muted mb-2 inline-flex size-10 items-center justify-center rounded-md sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-6",
className,
)}
{...props}
/>
);
}

function AlertDialogTitle({
className,
...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {
return (
<AlertDialogPrimitive.Title
data-slot="alert-dialog-title"
className={cn(
"cn-font-heading text-base font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2",
className,
)}
{...props}
/>
);
}

function AlertDialogDescription({
className,
...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {
return (
<AlertDialogPrimitive.Description
data-slot="alert-dialog-description"
className={cn(
"text-muted-foreground *:[a]:hover:text-foreground text-sm text-balance md:text-pretty *:[a]:underline *:[a]:underline-offset-3 *:[p]:not-first:mbs-4",
className,
)}
{...props}
/>
);
}

function AlertDialogAction({
className,
variant = "outline",
size = "default",
...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Action> &
Pick<React.ComponentProps<typeof Button>, "variant" | "size">) {
return (
<Button variant={variant} size={size} asChild>
<AlertDialogPrimitive.Action
data-slot="alert-dialog-action"
className={cn(className)}
{...props}
/>
</Button>
);
}

function AlertDialogCancel({
className,
variant = "outline",
size = "default",
...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Cancel> &
Pick<React.ComponentProps<typeof Button>, "variant" | "size">) {
return (
<Button variant={variant} size={size} asChild>
<AlertDialogPrimitive.Cancel
data-slot="alert-dialog-cancel"
className={cn(className)}
{...props}
/>
</Button>
);
}

export {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogMedia,
AlertDialogOverlay,
AlertDialogPortal,
AlertDialogTitle,
AlertDialogTrigger,
};
2 changes: 2 additions & 0 deletions packages/graph-explorer/src/components/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ const buttonStyles = cva({
"text-primary-foreground hover:bg-primary-subtle data-open:bg-primary-subtle",
outline:
"text-text-primary border-input hover:bg-muted data-open:border-primary-main border bg-transparent shadow-xs",
"primary-danger":
"bg-danger hover:bg-danger-hover data-open:bg-danger-hover text-white",
danger:
"bg-danger-subtle text-danger hover:bg-danger-subtle-hover data-open:bg-danger-subtle-hover",
"danger-ghost":
Expand Down
89 changes: 89 additions & 0 deletions packages/graph-explorer/src/components/Group.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { cva, type VariantProps } from "cva";

import { cn } from "@/utils";

const groupVariants = cva({
base: "group/group divide-y rounded-xl border",
variants: {
variant: {
default: "border-border divide-border",
danger: "border-danger-foreground/25 divide-danger-foreground/25",
success: "border-success-foreground/25 divide-success-foreground/25",
warning: "border-warning-foreground/25 divide-warning-foreground/25",
},
},
defaultVariants: {
variant: "default",
},
});

function Group({
className,
variant = "default",
size = "default",
...props
}: React.ComponentProps<"div"> &
VariantProps<typeof groupVariants> & { size?: "default" | "small" }) {
return (
<div
data-variant={variant}
data-size={size}
className={cn(groupVariants({ variant }), className)}
{...props}
/>
);
}

function GroupHeader({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
className={cn(
"bg-neutral-subtle/50 text-text-secondary group-data-[variant=danger]/group:bg-danger-subtle/50 group-data-[variant=danger]/group:text-danger group-data-[variant=success]/group:bg-success-subtle/50 group-data-[variant=success]/group:text-success-main group-data-[variant=warning]/group:bg-warning-subtle/50 group-data-[variant=warning]/group:text-warning-main flex items-center gap-2 px-5 py-3 group-data-[size=small]/group:px-3 group-data-[size=small]/group:py-2",
className,
)}
{...props}
/>
);
}

function GroupMedia({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
className={cn("flex shrink-0 items-center [&>svg]:size-4", className)}
{...props}
/>
);
}

function GroupTitle({
className,
children,
...props
}: React.ComponentProps<"h2">) {
return (
<h2
className={cn(
"flex-1 text-xs font-medium tracking-wide uppercase",
className,
)}
{...props}
>
{children}
</h2>
);
}

function GroupItem({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
className={cn(
"space-y-4 px-5 py-4 group-data-[size=small]/group:px-3 group-data-[size=small]/group:py-2",
className,
)}
{...props}
/>
);
}

export { Group, GroupHeader, GroupMedia, GroupTitle, GroupItem };
export type { VariantProps };
31 changes: 31 additions & 0 deletions packages/graph-explorer/src/components/LabelledSetting.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { PropsWithChildren } from "react";

export function LabelledSetting({
label,
description,
htmlFor,
children,
}: PropsWithChildren<{
label: string;
description?: string;
htmlFor?: string;
}>) {
return (
<div className="group/labelled-setting flex flex-row items-center gap-8">
<label
htmlFor={htmlFor}
className="block flex-1 space-y-1 group-has-disabled/labelled-setting:cursor-not-allowed group-has-disabled/labelled-setting:opacity-70"
>
<p className="text-text-primary text-base leading-none font-medium text-pretty">
{label}
</p>
{description ? (
<p className="font-base text-text-secondary text-sm leading-normal text-pretty">
{description}
</p>
) : null}
</label>
{children}
</div>
);
}
5 changes: 4 additions & 1 deletion packages/graph-explorer/src/components/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ export function NavBarActions({
);
}

function NavBarLogo({ className, ...rest }: ComponentPropsWithRef<"div">) {
export function NavBarLogo({
className,
...rest
}: ComponentPropsWithRef<"div">) {
return (
<div
data-slot="nav-bar-logo"
Expand Down
Loading
Loading