forked from
slices.network/slices
Highly ambitious ATProtocol AppView service and sdks
1import type { JSX } from "preact";
2import { cn } from "../../utils/cn.ts";
3import { ComponentChildren } from "preact";
4
5type ButtonVariant =
6 | "primary" // zinc-900 background
7 | "secondary" // zinc-200/800 background
8 | "outline" // transparent with border
9 | "success" // green
10 | "danger" // red
11 | "blue"; // blue
12
13type ButtonSize = "sm" | "md" | "lg";
14
15export interface ButtonProps
16 extends Omit<JSX.IntrinsicElements["button"], "size"> {
17 variant?: ButtonVariant;
18 size?: ButtonSize;
19 children: ComponentChildren;
20 href?: string; // If provided, renders as a link styled like a button
21}
22
23const variantClasses = {
24 primary:
25 "bg-zinc-50 hover:bg-zinc-50/90 dark:bg-zinc-600 dark:hover:bg-zinc-600/90 text-zinc-900 dark:text-zinc-100 border border-zinc-200 dark:border-zinc-500/70",
26 secondary:
27 "bg-zinc-100 hover:bg-zinc-100/90 dark:bg-zinc-700 dark:hover:bg-zinc-700/90 text-zinc-900 dark:text-zinc-100 border border-zinc-200/70 dark:border-zinc-600/70",
28 outline:
29 "bg-transparent border border-zinc-300/70 hover:bg-zinc-50 dark:border-zinc-600/70 dark:hover:bg-zinc-600/10 text-zinc-900 dark:text-zinc-100",
30 success:
31 "bg-green-600 hover:bg-green-600/90 dark:bg-green-600 dark:hover:bg-green-600/90 text-white border border-green-700 dark:border-green-500",
32 danger:
33 "bg-red-600 hover:bg-red-600/90 dark:bg-red-600 dark:hover:bg-red-600/90 text-white border border-red-700 dark:border-red-500",
34 blue: "bg-blue-600 hover:bg-blue-700 dark:bg-blue-600 dark:hover:bg-blue-700 text-white border border-blue-700 dark:border-blue-500",
35};
36
37const sizeClasses = {
38 sm: "px-2.5 py-0.5 text-xs",
39 md: "px-3 py-1 text-sm",
40 lg: "px-4 py-2 text-sm font-medium",
41};
42
43export function Button(props: ButtonProps): JSX.Element {
44 const {
45 variant = "primary",
46 size = "lg",
47 children,
48 href,
49 className,
50 ...rest
51 } = props;
52
53 const classes = cn(
54 "rounded transition-colors inline-flex items-center font-medium",
55 variantClasses[variant],
56 sizeClasses[size],
57 className
58 );
59
60 if (href) {
61 return (
62 <a href={href} class={classes}>
63 {children}
64 </a>
65 );
66 }
67
68 return (
69 <button class={classes} {...rest}>
70 {children}
71 </button>
72 );
73}