react ~3 KB 0 deps v0.3.0 β†— GitHub β†—

@mshafiqyajid/react-button

Headless button hook + styled component. Variants (solid/outline/ghost/link), tones (neutral/primary/success/danger), three sizes, async loading state (Promise-driven), icon slots, full-width block mode, fully accessible.

Playground #

clicked: 0
Props
TSX
import { ButtonStyled } from "@mshafiqyajid/react-button/styled";
import "@mshafiqyajid/react-button/styles.css";

<ButtonStyled
  onClick={() => setCount(c => c + 1)}
  children="Click me"
/>

Install #

npm install @mshafiqyajid/react-button

Quick start #

import { ButtonStyled } from "@mshafiqyajid/react-button/styled";
import "@mshafiqyajid/react-button/styles.css";

<ButtonStyled tone="primary" size="md" onClick={() => alert("hi")}>
  Click me
</ButtonStyled>

Async clicks #

Return a Promise from onClick and the button shows a spinner, blocks further clicks, and clears automatically when the promise resolves or rejects.

<ButtonStyled
  tone="primary"
  onClick={async () => {
    await fetch("/api/checkout", { method: "POST" });
  }}
>
  Checkout
</ButtonStyled>

Headless #

import { useButton } from "@mshafiqyajid/react-button";

const { buttonProps, isPending } = useButton({
  onClick: async () => {
    await fetch("/api/save", { method: "POST" });
  },
});

return <button {...buttonProps}>{isPending ? "Saving…" : "Save"}</button>;

API #

PropTypeDefaultDescription
onClick(e) => void | Promise<void>β€”Click handler. Promise drives the spinner.
variant"solid" | "outline" | "ghost" | "link""solid"Visual style
tone"neutral" | "primary" | "success" | "danger""primary"Color
size"sm" | "md" | "lg""md"Size
radius"default" | "pill" | "sharp""default"Border radius shape
blockbooleanfalseFull-width
loadingbooleanfalseForce spinner
loadingTextReactNodeβ€”Replaces children while loading (no layout shift)
pulsebooleanfalseSoft pulsing ring β€” use for primary CTAs
ripplebooleantrueMaterial-style click ripple
disabledbooleanfalseDisable
iconLeftReactNodeβ€”Icon before label
iconRightReactNodeβ€”Icon after label
Edit this page on GitHub