feat: initial @jason/ui-kit — tokens, preset, components, motion, blocks, Impeccable
ci / build-and-design (push) Failing after 15s
ci / build-and-design (push) Failing after 15s
This commit is contained in:
Executable
+29
@@ -0,0 +1,29 @@
|
||||
import * as React from "react";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { cn } from "../lib/cn";
|
||||
|
||||
const badgeVariants = cva(
|
||||
"inline-flex items-center gap-1 rounded-sm px-2 py-0.5 text-xs font-medium",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
brand: "bg-brand/15 text-brand",
|
||||
neutral: "bg-surface-2 text-muted",
|
||||
success: "bg-success/15 text-success",
|
||||
warning: "bg-warning/15 text-warning",
|
||||
danger: "bg-danger/15 text-danger",
|
||||
outline: "border border-border text-text",
|
||||
},
|
||||
},
|
||||
defaultVariants: { variant: "neutral" },
|
||||
}
|
||||
);
|
||||
|
||||
export interface BadgeProps
|
||||
extends React.HTMLAttributes<HTMLSpanElement>,
|
||||
VariantProps<typeof badgeVariants> {}
|
||||
|
||||
export const Badge = ({ className, variant, ...props }: BadgeProps) => (
|
||||
<span className={cn(badgeVariants({ variant }), className)} {...props} />
|
||||
);
|
||||
export { badgeVariants };
|
||||
Executable
+45
@@ -0,0 +1,45 @@
|
||||
import * as React from "react";
|
||||
import { Slot } from "@radix-ui/react-slot";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { cn } from "../lib/cn";
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded font-display font-semibold " +
|
||||
"transition-[background-color,box-shadow,transform,color] duration-base ease-out " +
|
||||
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/60 focus-visible:ring-offset-2 focus-visible:ring-offset-bg " +
|
||||
"active:scale-[0.98] disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
primary: "bg-brand text-bg hover:bg-brand-bright shadow-sm hover:shadow-glow",
|
||||
secondary: "bg-surface-2 text-text hover:bg-surface-2/70 shadow-sm",
|
||||
outline: "border border-border bg-transparent text-text hover:bg-surface-2/60",
|
||||
ghost: "bg-transparent text-text hover:bg-surface-2/60",
|
||||
danger: "bg-danger text-white hover:bg-danger/90 shadow-sm",
|
||||
link: "text-brand underline-offset-4 hover:underline",
|
||||
},
|
||||
size: {
|
||||
sm: "h-8 px-3 text-sm",
|
||||
md: "h-10 px-4 text-sm",
|
||||
lg: "h-12 px-6 text-base",
|
||||
icon: "size-10",
|
||||
},
|
||||
},
|
||||
defaultVariants: { variant: "primary", size: "md" },
|
||||
}
|
||||
);
|
||||
|
||||
export interface ButtonProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
VariantProps<typeof buttonVariants> {
|
||||
asChild?: boolean;
|
||||
}
|
||||
|
||||
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
({ className, variant, size, asChild = false, ...props }, ref) => {
|
||||
const Comp = asChild ? Slot : "button";
|
||||
return <Comp ref={ref} className={cn(buttonVariants({ variant, size }), className)} {...props} />;
|
||||
}
|
||||
);
|
||||
Button.displayName = "Button";
|
||||
export { buttonVariants };
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
import * as React from "react";
|
||||
import { cn } from "../lib/cn";
|
||||
|
||||
export const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
||||
({ className, ...props }, ref) => (
|
||||
<div ref={ref} className={cn("rounded-lg border border-border bg-surface shadow-sm", className)} {...props} />
|
||||
)
|
||||
);
|
||||
Card.displayName = "Card";
|
||||
|
||||
export const CardHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div className={cn("flex flex-col gap-1 p-5", className)} {...props} />
|
||||
);
|
||||
export const CardTitle = ({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>) => (
|
||||
<h3 className={cn("font-display text-lg font-semibold leading-tight", className)} {...props} />
|
||||
);
|
||||
export const CardDescription = ({ className, ...props }: React.HTMLAttributes<HTMLParagraphElement>) => (
|
||||
<p className={cn("text-sm text-muted", className)} {...props} />
|
||||
);
|
||||
export const CardContent = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div className={cn("p-5 pt-0", className)} {...props} />
|
||||
);
|
||||
export const CardFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div className={cn("flex items-center gap-2 p-5 pt-0", className)} {...props} />
|
||||
);
|
||||
Executable
+68
@@ -0,0 +1,68 @@
|
||||
import * as React from "react";
|
||||
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
||||
import { X } from "lucide-react";
|
||||
import { cn } from "../lib/cn";
|
||||
|
||||
export const Dialog = DialogPrimitive.Root;
|
||||
export const DialogTrigger = DialogPrimitive.Trigger;
|
||||
export const DialogClose = DialogPrimitive.Close;
|
||||
|
||||
const DialogOverlay = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Overlay>,
|
||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DialogPrimitive.Overlay
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed inset-0 z-50 bg-black/60 backdrop-blur-sm",
|
||||
"data-[state=open]:animate-fade-in data-[state=closed]:opacity-0",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
DialogOverlay.displayName = "DialogOverlay";
|
||||
|
||||
export const DialogContent = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Content>,
|
||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
|
||||
>(({ className, children, ...props }, ref) => (
|
||||
<DialogPrimitive.Portal>
|
||||
<DialogOverlay />
|
||||
<DialogPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"fixed left-1/2 top-1/2 z-50 w-full max-w-lg -translate-x-1/2 -translate-y-1/2",
|
||||
"rounded-lg border border-border bg-surface p-6 shadow-lg",
|
||||
"data-[state=open]:animate-scale-in",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm text-muted transition-colors hover:text-text focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/60">
|
||||
<X className="size-4" />
|
||||
<span className="sr-only">Close</span>
|
||||
</DialogPrimitive.Close>
|
||||
</DialogPrimitive.Content>
|
||||
</DialogPrimitive.Portal>
|
||||
));
|
||||
DialogContent.displayName = "DialogContent";
|
||||
|
||||
export const DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
||||
<div className={cn("flex flex-col gap-1.5 pb-4", className)} {...props} />
|
||||
);
|
||||
export const DialogTitle = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Title>,
|
||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DialogPrimitive.Title ref={ref} className={cn("font-display text-lg font-semibold", className)} {...props} />
|
||||
));
|
||||
DialogTitle.displayName = "DialogTitle";
|
||||
export const DialogDescription = React.forwardRef<
|
||||
React.ElementRef<typeof DialogPrimitive.Description>,
|
||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DialogPrimitive.Description ref={ref} className={cn("text-sm text-muted", className)} {...props} />
|
||||
));
|
||||
DialogDescription.displayName = "DialogDescription";
|
||||
Executable
+66
@@ -0,0 +1,66 @@
|
||||
import * as React from "react";
|
||||
import * as Menu from "@radix-ui/react-dropdown-menu";
|
||||
import { Check } from "lucide-react";
|
||||
import { cn } from "../lib/cn";
|
||||
|
||||
export const DropdownMenu = Menu.Root;
|
||||
export const DropdownMenuTrigger = Menu.Trigger;
|
||||
export const DropdownMenuGroup = Menu.Group;
|
||||
export const DropdownMenuSeparator = ({ className, ...props }: React.ComponentPropsWithoutRef<typeof Menu.Separator>) => (
|
||||
<Menu.Separator className={cn("-mx-1 my-1 h-px bg-border", className)} {...props} />
|
||||
);
|
||||
|
||||
export const DropdownMenuContent = React.forwardRef<
|
||||
React.ElementRef<typeof Menu.Content>,
|
||||
React.ComponentPropsWithoutRef<typeof Menu.Content>
|
||||
>(({ className, sideOffset = 6, ...props }, ref) => (
|
||||
<Menu.Portal>
|
||||
<Menu.Content
|
||||
ref={ref}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"z-50 min-w-[10rem] overflow-hidden rounded-md border border-border bg-surface p-1 shadow-lg",
|
||||
"data-[state=open]:animate-scale-in",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</Menu.Portal>
|
||||
));
|
||||
DropdownMenuContent.displayName = "DropdownMenuContent";
|
||||
|
||||
export const DropdownMenuItem = React.forwardRef<
|
||||
React.ElementRef<typeof Menu.Item>,
|
||||
React.ComponentPropsWithoutRef<typeof Menu.Item>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<Menu.Item
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex cursor-pointer select-none items-center gap-2 rounded px-2 py-1.5 text-sm text-text outline-none",
|
||||
"transition-colors focus:bg-surface-2 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:size-4",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
DropdownMenuItem.displayName = "DropdownMenuItem";
|
||||
|
||||
export const DropdownMenuLabel = ({ className, ...props }: React.ComponentPropsWithoutRef<typeof Menu.Label>) => (
|
||||
<Menu.Label className={cn("px-2 py-1.5 text-xs font-semibold uppercase tracking-wide text-muted", className)} {...props} />
|
||||
);
|
||||
export const DropdownMenuCheckboxItem = React.forwardRef<
|
||||
React.ElementRef<typeof Menu.CheckboxItem>,
|
||||
React.ComponentPropsWithoutRef<typeof Menu.CheckboxItem>
|
||||
>(({ className, children, ...props }, ref) => (
|
||||
<Menu.CheckboxItem
|
||||
ref={ref}
|
||||
className={cn("relative flex cursor-pointer select-none items-center rounded py-1.5 pl-7 pr-2 text-sm outline-none focus:bg-surface-2", className)}
|
||||
{...props}
|
||||
>
|
||||
<span className="absolute left-2 flex size-3.5 items-center justify-center">
|
||||
<Menu.ItemIndicator><Check className="size-3.5" /></Menu.ItemIndicator>
|
||||
</span>
|
||||
{children}
|
||||
</Menu.CheckboxItem>
|
||||
));
|
||||
DropdownMenuCheckboxItem.displayName = "DropdownMenuCheckboxItem";
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
import * as React from "react";
|
||||
import { cn } from "../lib/cn";
|
||||
|
||||
export const Input = React.forwardRef<HTMLInputElement, React.InputHTMLAttributes<HTMLInputElement>>(
|
||||
({ className, type, ...props }, ref) => (
|
||||
<input
|
||||
type={type}
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"flex h-10 w-full rounded border border-border bg-bg/40 px-3 py-2 text-sm text-text",
|
||||
"placeholder:text-muted transition-shadow duration-base ease-out",
|
||||
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/60 focus-visible:border-brand/60",
|
||||
"disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
);
|
||||
Input.displayName = "Input";
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
import * as React from "react";
|
||||
import { cn } from "../lib/cn";
|
||||
|
||||
export const Table = ({ className, ...props }: React.HTMLAttributes<HTMLTableElement>) => (
|
||||
<div className="relative w-full overflow-auto rounded-lg border border-border">
|
||||
<table className={cn("w-full caption-bottom text-sm", className)} {...props} />
|
||||
</div>
|
||||
);
|
||||
export const TableHeader = ({ className, ...props }: React.HTMLAttributes<HTMLTableSectionElement>) => (
|
||||
<thead className={cn("[&_tr]:border-b [&_tr]:border-border", className)} {...props} />
|
||||
);
|
||||
export const TableBody = ({ className, ...props }: React.HTMLAttributes<HTMLTableSectionElement>) => (
|
||||
<tbody className={cn("[&_tr:last-child]:border-0", className)} {...props} />
|
||||
);
|
||||
export const TableRow = ({ className, ...props }: React.HTMLAttributes<HTMLTableRowElement>) => (
|
||||
<tr className={cn("border-b border-border transition-colors hover:bg-surface-2/50 data-[state=selected]:bg-surface-2", className)} {...props} />
|
||||
);
|
||||
export const TableHead = ({ className, ...props }: React.ThHTMLAttributes<HTMLTableCellElement>) => (
|
||||
<th className={cn("sticky top-0 z-10 bg-surface px-4 py-3 text-left font-display text-xs font-semibold uppercase tracking-wide text-muted", className)} {...props} />
|
||||
);
|
||||
export const TableCell = ({ className, ...props }: React.TdHTMLAttributes<HTMLTableCellElement>) => (
|
||||
<td className={cn("px-4 py-3 align-middle", className)} {...props} />
|
||||
);
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
import { Toaster as Sonner, toast } from "sonner";
|
||||
|
||||
/** Pre-themed sonner Toaster. Drop <Toaster /> once near your app root. */
|
||||
export const Toaster = (props: React.ComponentProps<typeof Sonner>) => (
|
||||
<Sonner
|
||||
theme="dark"
|
||||
position="bottom-right"
|
||||
toastOptions={{
|
||||
classNames: {
|
||||
toast: "!bg-surface !border-border !text-text !rounded-lg !shadow-lg",
|
||||
description: "!text-muted",
|
||||
actionButton: "!bg-brand !text-bg",
|
||||
cancelButton: "!bg-surface-2 !text-muted",
|
||||
},
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
export { toast };
|
||||
Reference in New Issue
Block a user