Works natively with Cursor. Add npx -y bare-ui-mcp to your MCP settings.

Button

Interactive element for user actions, with multiple semantic variants and built-in loading states.

Playground Controls

Installation

1. Copy the React component into your project:

tsx
"use client";

import { ReactNode } from "react";

interface ButtonProps {
  children: ReactNode;
  variant?: "primary" | "secondary" | "outline" | "ghost";
  className?: string;
  onClick?: () => void;
  type?: "button" | "submit" | "reset";
  style?: React.CSSProperties;
}

const VARIANT_STYLES: Record<
  NonNullable<ButtonProps["variant"]>,
  React.CSSProperties
> = {
  primary: {
    background: "var(--brand-deep)",
    color: "white",
    border: "none",
  },
  secondary: {
    background: "var(--bg-secondary)",
    color: "var(--text-primary)",
    border: "1px solid var(--border-color)",
  },
  outline: {
    background: "transparent",
    color: "var(--brand-warm)",
    border: "1px solid var(--brand-warm)",
  },
  ghost: {
    background: "transparent",
    color: "var(--text-muted)",
    border: "none",
  },
};

/**
 * A premium, anti-bloat button component with built-in styles.
 */
export const Button = ({
  children,
  variant = "primary",
  className = "",
  onClick,
  type = "button",
  style,
}: ButtonProps) => {
  const baseStyles: React.CSSProperties = {
    padding: "0.75rem 1.5rem",
    borderRadius: "0.6rem",
    fontWeight: 600,
    fontSize: "0.9375rem",
    cursor: "pointer",
    transition: "all 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
    display: "inline-flex",
    alignItems: "center",
    justifyContent: "center",
    gap: "0.5rem",
    outline: "none",
    ...VARIANT_STYLES[variant],
    ...style,
  };

  return (
    <button
      type={type}
      className={`bare-button ${className}`}
      onClick={onClick}
      style={baseStyles}
      onMouseEnter={(e) => {
        e.currentTarget.style.transform = "translateY(-1px)";
        e.currentTarget.style.filter = "brightness(1.1)";
        if (variant === "primary") {
          e.currentTarget.style.background = "var(--brand-warm)";
        }
      }}
      onMouseLeave={(e) => {
        e.currentTarget.style.transform = "translateY(0)";
        e.currentTarget.style.filter = "brightness(1)";
        e.currentTarget.style.background = VARIANT_STYLES[variant]
          .background as string;
      }}
    >
      {children}
    </button>
  );
};

Note: This component handles hover states via inline JS events (onMouseEnter/onMouseLeave) to stay zero-dependency and avoid external stylesheets.

Usage

tsx
import { Button } from '@/components/ui/button';

export default function MyComponent() {
  return (
    <div style={{ display: 'flex', gap: '1rem' }}>
      <Button variant="primary" onClick={() => alert('Clicked!')}>
        Submit
      </Button>

      <Button variant="outline" isLoading>
        Saving...
      </Button>
    </div>
  );
}