A button component in neobrutalism style.
1import { Slot } from "@radix-ui/react-slot"
2import { cva, type VariantProps } from "class-variance-authority"
3
4import * as React from "react"
5
6import { cn } from "@/lib/utils"
7
8const buttonVariants = cva(
9 "inline-flex items-center justify-center whitespace-nowrap rounded-base text-sm font-base ring-offset-white transition-all gap-2 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-black focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
10 {
11 variants: {
12 variant: {
13 default:
14 "text-main-foreground bg-main border-2 border-border shadow-shadow hover:translate-x-boxShadowX hover:translate-y-boxShadowY hover:shadow-none",
15 noShadow: "text-main-foreground bg-main border-2 border-border",
16 neutral:
17 "bg-secondary-background text-foreground border-2 border-border shadow-shadow hover:translate-x-boxShadowX hover:translate-y-boxShadowY hover:shadow-none",
18 reverse:
19 "text-main-foreground bg-main border-2 border-border hover:translate-x-reverseBoxShadowX hover:translate-y-reverseBoxShadowY hover:shadow-shadow",
20 },
21 size: {
22 default: "h-10 px-4 py-2",
23 sm: "h-9 px-3",
24 lg: "h-11 px-8",
25 icon: "size-10",
26 },
27 },
28 defaultVariants: {
29 variant: "default",
30 size: "default",
31 },
32 },
33)
34
35function Button({
36 className,
37 variant,
38 size,
39 asChild = false,
40 ...props
41}: React.ComponentProps<"button"> &
42 VariantProps<typeof buttonVariants> & {
43 asChild?: boolean
44 }) {
45 const Comp = asChild ? Slot : "button"
46
47 return (
48 <Comp
49 data-slot="button"
50 className={cn(buttonVariants({ variant, size, className }))}
51 {...props}
52 />
53 )
54}
55
56export { Button, buttonVariants }
57