because I got bored of customising my CV for every job
1import { cva, type VariantProps } from "class-variance-authority";
2import { cn } from "../lib/cn";
3
4const iconButtonVariants = cva(
5 "inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ctp-blue focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
6 {
7 variants: {
8 variant: {
9 primary: "",
10 secondary: "",
11 outline: "border border-ctp-surface1 bg-transparent",
12 ghost: "",
13 destructive: "",
14 },
15 size: {
16 xs: "h-6 w-6 text-xs",
17 sm: "h-8 w-8 text-sm",
18 md: "h-10 w-10",
19 lg: "h-12 w-12 text-lg",
20 },
21 showColorOnHover: {
22 true: "",
23 false: "",
24 },
25 },
26 compoundVariants: [
27 // Primary variants
28 {
29 variant: "primary",
30 showColorOnHover: true,
31 className: "text-ctp-text hover:bg-ctp-blue hover:text-ctp-base",
32 },
33 {
34 variant: "primary",
35 showColorOnHover: false,
36 className: "bg-ctp-blue text-ctp-base hover:bg-ctp-blue/90",
37 },
38 // Secondary variants
39 {
40 variant: "secondary",
41 showColorOnHover: true,
42 className: "text-ctp-text hover:bg-ctp-surface1",
43 },
44 {
45 variant: "secondary",
46 showColorOnHover: false,
47 className: "bg-ctp-surface1 text-ctp-text hover:bg-ctp-surface1/80",
48 },
49 // Outline variants
50 {
51 variant: "outline",
52 showColorOnHover: true,
53 className: "text-ctp-text hover:bg-ctp-surface0 hover:border-ctp-blue",
54 },
55 {
56 variant: "outline",
57 showColorOnHover: false,
58 className: "text-ctp-text hover:bg-ctp-surface0",
59 },
60 // Ghost variants
61 {
62 variant: "ghost",
63 showColorOnHover: true,
64 className: "text-ctp-text hover:bg-ctp-surface0",
65 },
66 {
67 variant: "ghost",
68 showColorOnHover: false,
69 className: "text-ctp-text hover:bg-ctp-surface0",
70 },
71 // Destructive variants
72 {
73 variant: "destructive",
74 showColorOnHover: true,
75 className: "text-ctp-text hover:bg-ctp-red hover:text-ctp-base",
76 },
77 {
78 variant: "destructive",
79 showColorOnHover: false,
80 className: "bg-ctp-red text-ctp-base hover:bg-ctp-red/90",
81 },
82 ],
83 defaultVariants: {
84 variant: "ghost",
85 size: "md",
86 showColorOnHover: true,
87 },
88 },
89);
90
91interface IconButtonProps extends VariantProps<typeof iconButtonVariants> {
92 icon: React.ReactNode;
93 label: string;
94 onClick?: () => void;
95 disabled?: boolean;
96 className?: string;
97}
98
99export const IconButton = ({
100 icon,
101 label,
102 onClick,
103 disabled = false,
104 variant = "ghost",
105 size = "md",
106 className = "",
107 showColorOnHover = true,
108}: IconButtonProps) => {
109 return (
110 <button
111 type="button"
112 onClick={onClick}
113 disabled={disabled}
114 aria-label={label}
115 className={cn(
116 iconButtonVariants({ variant, size, showColorOnHover }),
117 className,
118 )}
119 >
120 {icon}
121 </button>
122 );
123};