grain.social is a photo sharing platform built on atproto.
1import { cn } from "@bigmoves/bff/components";
2import { cloneElement, type JSX } from "preact";
3
4export type ButtonProps =
5 & JSX.ButtonHTMLAttributes<HTMLButtonElement>
6 & Readonly<{
7 variant?: "primary" | "secondary" | "ghost" | "destructive" | "tab";
8 asChild?: boolean;
9 }>;
10
11export function Button(props: ButtonProps): JSX.Element {
12 const { variant, class: classProp, asChild, children, ...rest } = props;
13 const className = cn(
14 "grain-btn",
15 variant === "primary" && "grain-btn-primary",
16 variant === "secondary" && "grain-btn-secondary",
17 variant === "ghost" && "grain-btn-ghost",
18 variant === "destructive" && "grain-btn-destructive",
19 variant === "tab" && "grain-btn-tab",
20 classProp,
21 );
22 if (
23 asChild && children && typeof children === "object" && children !== null &&
24 "type" in children
25 ) {
26 return cloneElement(children, {
27 ...rest,
28 ...children.props,
29 class: cn(className, children.props.class),
30 });
31 }
32 return <button class={className} {...rest}>{children}</button>;
33}