/Components
buttons

Button

A versatile, minimalist button component with support for multiple aesthetic variants, sizes, and states.

buttonvariantsprimarysecondaryoutlineghostinteractive

Preview

Select Color & Active Theming
All variants pair and style dynamically matching the “zinc” color family:

Sizes
Inactive States

🖲Usage

example-usage.tsx
import { Button } from "@/components/kanso/button"

export default function ButtonDemo() {
  return (
    <div className="flex gap-4">
      <Button variant="primary">Primary</Button>
      <Button variant="secondary" color="blue">Secondary Blue</Button>
      <Button variant="outline">Outline</Button>
    </div>
  )
}

Installation

1

Create folder & copy source

Create a folder named kanso inside your project's components directory (i.e. components/kanso/). Copy the source code shown in the next section, and paste it into a file named button.tsx inside it.

2

Required helper files

Ensure your project has the following helper files configured:

  • lib/utils

<>Source Code

button.tsx
import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"

const buttonVariants = cva(
  "inline-flex shrink-0 items-center justify-center rounded-lg text-sm font-medium transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-40 disabled:cursor-not-allowed active:scale-[0.98]",
  {
    variants: {
      variant: {
        primary: "shadow-sm",
        secondary: "shadow-2xs",
        outline: "border bg-transparent shadow-3xs",
        ghost: "",
        link: "underline-offset-4 hover:underline p-0 h-auto rounded-none active:scale-100",
      },
      size: {
        default: "h-9.5 px-4 py-2",
        sm: "h-8.5 rounded-md px-3 text-xs",
        lg: "h-11 rounded-lg px-6 text-base",
        icon: "size-9.5",
      },
      color: {
        zinc: "",
        blue: "",
        emerald: "",
        violet: "",
        amber: "",
        rose: "",
      },
    },
    compoundVariants: [
      // Zinc
      {
        color: "zinc",
        variant: "primary",
        className: "bg-zinc-950 text-zinc-50 hover:bg-zinc-800 dark:bg-zinc-50 dark:text-zinc-950 dark:hover:bg-zinc-200 focus-visible:ring-zinc-400",
      },
      {
        color: "zinc",
        variant: "secondary",
        className: "bg-zinc-100 text-zinc-900 hover:bg-zinc-200/80 dark:bg-zinc-900 dark:text-zinc-50 dark:hover:bg-zinc-800/80 focus-visible:ring-zinc-400",
      },
      {
        color: "zinc",
        variant: "outline",
        className: "border-zinc-200 text-zinc-900 hover:bg-zinc-50 dark:border-zinc-800 dark:text-zinc-100 dark:hover:bg-zinc-900/60 focus-visible:ring-zinc-400",
      },
      {
        color: "zinc",
        variant: "ghost",
        className: "hover:bg-zinc-100 hover:text-zinc-900 dark:hover:bg-zinc-900 dark:hover:text-zinc-50 focus-visible:ring-zinc-400",
      },
      {
        color: "zinc",
        variant: "link",
        className: "text-zinc-900 dark:text-zinc-50 focus-visible:ring-zinc-400",
      },

      // Blue
      {
        color: "blue",
        variant: "primary",
        className: "bg-blue-600 text-white hover:bg-blue-500 dark:bg-blue-500 dark:hover:bg-blue-400 focus-visible:ring-blue-400",
      },
      {
        color: "blue",
        variant: "secondary",
        className: "bg-blue-50 text-blue-900 hover:bg-blue-100 dark:bg-blue-950/40 dark:text-blue-200 dark:hover:bg-blue-950/60 focus-visible:ring-blue-400",
      },
      {
        color: "blue",
        variant: "outline",
        className: "border-blue-200 text-blue-600 hover:bg-blue-50/50 dark:border-blue-900/60 dark:text-blue-400 dark:hover:bg-blue-950/20 focus-visible:ring-blue-400",
      },
      {
        color: "blue",
        variant: "ghost",
        className: "text-blue-600 hover:bg-blue-50 dark:text-blue-400 dark:hover:bg-blue-950/30 focus-visible:ring-blue-400",
      },
      {
        color: "blue",
        variant: "link",
        className: "text-blue-600 dark:text-blue-400 focus-visible:ring-blue-400",
      },

      // Emerald
      {
        color: "emerald",
        variant: "primary",
        className: "bg-emerald-600 text-white hover:bg-emerald-500 dark:bg-emerald-500 dark:hover:bg-emerald-400 focus-visible:ring-emerald-400",
      },
      {
        color: "emerald",
        variant: "secondary",
        className: "bg-emerald-50 text-emerald-900 hover:bg-emerald-100 dark:bg-emerald-950/40 dark:text-emerald-200 dark:hover:bg-emerald-950/60 focus-visible:ring-emerald-400",
      },
      {
        color: "emerald",
        variant: "outline",
        className: "border-emerald-200 text-emerald-600 hover:bg-emerald-50/50 dark:border-emerald-900/60 dark:text-emerald-400 dark:hover:bg-emerald-950/20 focus-visible:ring-emerald-400",
      },
      {
        color: "emerald",
        variant: "ghost",
        className: "text-emerald-600 hover:bg-emerald-50 dark:text-emerald-400 dark:hover:bg-emerald-950/30 focus-visible:ring-emerald-400",
      },
      {
        color: "emerald",
        variant: "link",
        className: "text-emerald-600 dark:text-emerald-400 focus-visible:ring-emerald-400",
      },

      // Violet
      {
        color: "violet",
        variant: "primary",
        className: "bg-violet-600 text-white hover:bg-violet-500 dark:bg-violet-500 dark:hover:bg-violet-400 focus-visible:ring-violet-400",
      },
      {
        color: "violet",
        variant: "secondary",
        className: "bg-violet-50 text-violet-900 hover:bg-violet-100 dark:bg-violet-950/40 dark:text-violet-200 dark:hover:bg-violet-950/60 focus-visible:ring-violet-400",
      },
      {
        color: "violet",
        variant: "outline",
        className: "border-violet-200 text-violet-600 hover:bg-violet-50/50 dark:border-violet-900/60 dark:text-violet-400 dark:hover:bg-violet-950/20 focus-visible:ring-violet-400",
      },
      {
        color: "violet",
        variant: "ghost",
        className: "text-violet-600 hover:bg-violet-50 dark:text-violet-400 dark:hover:bg-violet-950/30 focus-visible:ring-violet-400",
      },
      {
        color: "violet",
        variant: "link",
        className: "text-violet-600 dark:text-violet-400 focus-visible:ring-violet-400",
      },

      // Amber
      {
        color: "amber",
        variant: "primary",
        className: "bg-amber-600 text-white hover:bg-amber-500 dark:bg-amber-500 dark:text-zinc-950 dark:hover:bg-amber-400 focus-visible:ring-amber-400",
      },
      {
        color: "amber",
        variant: "secondary",
        className: "bg-amber-50 text-amber-900 hover:bg-amber-100 dark:bg-amber-950/40 dark:text-amber-200 dark:hover:bg-amber-950/60 focus-visible:ring-amber-400",
      },
      {
        color: "amber",
        variant: "outline",
        className: "border-amber-200 text-amber-600 hover:bg-amber-50/50 dark:border-amber-900/60 dark:text-amber-400 dark:hover:bg-amber-950/20 focus-visible:ring-amber-400",
      },
      {
        color: "amber",
        variant: "ghost",
        className: "text-amber-600 hover:bg-amber-50 dark:text-amber-400 dark:hover:bg-amber-950/30 focus-visible:ring-amber-400",
      },
      {
        color: "amber",
        variant: "link",
        className: "text-amber-600 dark:text-amber-400 focus-visible:ring-amber-400",
      },

      // Rose
      {
        color: "rose",
        variant: "primary",
        className: "bg-rose-600 text-white hover:bg-rose-500 dark:bg-rose-500 dark:hover:bg-rose-400 focus-visible:ring-rose-400",
      },
      {
        color: "rose",
        variant: "secondary",
        className: "bg-rose-50 text-rose-900 hover:bg-rose-100 dark:bg-rose-950/40 dark:text-rose-200 dark:hover:bg-rose-950/60 focus-visible:ring-rose-400",
      },
      {
        color: "rose",
        variant: "outline",
        className: "border-rose-200 text-rose-600 hover:bg-rose-50/50 dark:border-rose-900/60 dark:text-rose-400 dark:hover:bg-rose-950/20 focus-visible:ring-rose-400",
      },
      {
        color: "rose",
        variant: "ghost",
        className: "text-rose-600 hover:bg-rose-50 dark:text-rose-400 dark:hover:bg-rose-950/30 focus-visible:ring-rose-400",
      },
      {
        color: "rose",
        variant: "link",
        className: "text-rose-600 dark:text-rose-400 focus-visible:ring-rose-400",
      },
    ],
    defaultVariants: {
      variant: "primary",
      size: "default",
      color: "zinc",
    },
  }
)

interface ButtonProps
  extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "color">,
    VariantProps<typeof buttonVariants> {
  /** Inactive state rendering the button disabled */
  inactive?: boolean
}

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
  ({ className, variant, size, color, inactive, ...props }, ref) => {
    return (
      <button
        ref={ref}
        disabled={inactive}
        className={cn(buttonVariants({ variant, size, color, className }))}
        {...props}
      />
    )
  }
)

Button.displayName = "Button"

export { Button, buttonVariants }
export type { ButtonProps }

Props

PropTypeDefaultDescription
variant"primary" | "secondary" | "outline" | "ghost" | "link""primary"The visual style variant of the button.
color"zinc" | "blue" | "emerald" | "violet" | "amber" | "rose""zinc"The color theme of the button across its variants.
size"default" | "sm" | "lg" | "icon""default"The height and padding scale of the button.
inactivebooleanfalseWhen true, disables interactions and styles the button as inactive.
childrenrequiredReact.ReactNodeThe content (text, label, or icons) inside the button.
classNamestringAdditional CSS classes to apply custom overrides.