Component
Button
A versatile button with three variants — defaultoutlineghost.
Preview
Rendered from Storybook storiesDefault
Outline
Ghost
Code
button.tsx
import * as React from "react";
type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
variant?: "default" | "outline" | "ghost";
};
export function Button({
variant = "default",
className = "",
children,
...props
}: ButtonProps) {
const base =
"inline-flex items-center hover:cursor-pointer justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50 px-4 py-2";
const variants: Record<NonNullable<ButtonProps["variant"]>, string> = {
default:
"bg-zinc-900 text-white hover:bg-zinc-700 dark:bg-zinc-100 dark:text-zinc-900 dark:hover:bg-zinc-300",
outline:
"border border-zinc-200 bg-white text-zinc-900 hover:bg-zinc-100 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-100 dark:hover:bg-zinc-800",
ghost: "text-zinc-900 hover:bg-zinc-100 dark:text-zinc-100 dark:hover:bg-zinc-800",
};
return (
<button
className={[base, variants[variant], className].filter(Boolean).join(" ")}
{...props}
>
{children}
</button>
);
}
Tests
Powered by Vitestbutton.test.tsxPassed
Ran at build time✓ Button renders children 138ms ✓ Button applies default variant by default 15ms ✓ Button applies outline variant styles 9ms ✓ Button calls onClick when clicked 41ms ✓ Button is disabled when the disabled prop is set 11ms ✓ Button dark mode applies dark mode styles for default variant 25ms ✓ Button dark mode applies dark mode styles for outline variant 9ms ✓ Button dark mode applies dark mode styles for ghost variant 21ms ✓ Button dark mode respects disabled opacity in dark mode 9ms Tests 9 passed (9)