import type { ButtonHTMLAttributes, ReactNode } from "react"; import "@shared/components/Button.css"; export type ButtonVariant = "gradient" | "outline" | "ghost"; export type ButtonSize = "sm" | "md"; export type ButtonAccent = "blue" | "purple" | "green" | "amber" | "red"; export interface ButtonProps extends ButtonHTMLAttributes { /** Visual variant. `gradient` is the primary CTA; `outline` is secondary; `ghost` is tertiary/text. */ variant?: ButtonVariant; /** Optional accent colour. Currently affects `gradient` and `outline` variants. */ accent?: ButtonAccent; size?: ButtonSize; /** Icon node rendered before the label. */ leadingIcon?: ReactNode; /** Icon node rendered after the label (arrow → for "next" CTAs). */ trailingIcon?: ReactNode; /** Show a spinner and disable interactivity. */ loading?: boolean; /** Stretches to fill its parent container. */ fullWidth?: boolean; children?: ReactNode; } /** * Stirling's two-button system: a gradient primary CTA and an outlined * secondary action. Ghost is reserved for tertiary links inside a row. * * Buttons compose with the existing CSS variables — they re-skin cleanly in * dark mode without per-variant overrides. */ export function Button({ variant = "gradient", accent = "blue", size = "md", leadingIcon, trailingIcon, loading = false, fullWidth = false, disabled, className, children, ...rest }: ButtonProps) { const classes = [ "sui-btn", `sui-btn--${variant}`, `sui-btn--${accent}`, `sui-btn--${size}`, fullWidth ? "sui-btn--full" : "", loading ? "sui-btn--loading" : "", className ?? "", ] .filter(Boolean) .join(" "); return ( ); }