forked from jordanlambrecht/tracker-tracker
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathButton.tsx
More file actions
89 lines (83 loc) · 2.6 KB
/
Copy pathButton.tsx
File metadata and controls
89 lines (83 loc) · 2.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// src/components/ui/Button.tsx
import { cva } from "class-variance-authority"
import clsx from "clsx"
import type { ButtonHTMLAttributes, ReactNode, Ref } from "react"
import { SpinnerIcon } from "@/components/ui/Icons"
type ButtonVariant = "primary" | "secondary" | "ghost" | "danger" | "minimal"
type ButtonSize = "icon" | "sm" | "md" | "lg"
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
variant?: ButtonVariant
size?: ButtonSize
text?: string
leftIcon?: ReactNode
rightIcon?: ReactNode
loading?: boolean
ref?: Ref<HTMLButtonElement>
}
const button = cva(
[
"inline-flex items-center justify-center font-sans font-medium",
"transition-all duration-150 cursor-pointer select-none",
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color:var(--color-control-focus)] focus-visible:ring-offset-1 focus-visible:ring-offset-base",
"disabled:opacity-40 disabled:cursor-not-allowed disabled:pointer-events-none disabled:shadow-none",
],
{
variants: {
variant: {
primary:
"bg-accent-dim text-accent nm-raised-sm hover:nm-raised active:nm-pressed active:scale-[0.93]",
secondary:
"bg-raised text-primary nm-raised-sm hover:nm-raised active:nm-pressed active:scale-[0.93]",
ghost:
"bg-transparent text-secondary hover:bg-raised hover:text-primary hover:nm-raised-sm active:scale-[0.96]",
danger:
"bg-danger-dim text-danger nm-raised-sm hover:nm-raised active:nm-pressed active:scale-[0.93]",
minimal: "bg-transparent text-muted hover:text-secondary",
},
size: {
icon: "p-1.5 rounded-nm-sm",
sm: "px-4 py-2 text-xs gap-2 rounded-nm-sm",
md: "px-5 py-2 text-sm gap-2 rounded-nm-md",
lg: "px-6 py-3 text-base gap-3 rounded-nm-md",
},
},
defaultVariants: {
variant: "primary",
size: "md",
},
}
)
function Button({
variant = "primary",
size = "md",
text,
leftIcon,
rightIcon,
loading = false,
type = "button",
className,
disabled,
children,
style,
ref,
...props
}: ButtonProps) {
const content = children ?? text
return (
<button
ref={ref}
type={type}
disabled={disabled || loading}
aria-busy={loading || undefined}
className={clsx(button({ variant, size }), className)}
style={style}
{...props}
>
{loading ? <SpinnerIcon className="animate-spin h-4 w-4 shrink-0" /> : leftIcon}
{content}
{rightIcon}
</button>
)
}
export type { ButtonProps, ButtonSize, ButtonVariant }
export { Button, button as buttonVariants }