@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 #
| Prop | Type | Default | Description |
|---|---|---|---|
| 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 |
| block | boolean | false | Full-width |
| loading | boolean | false | Force spinner |
| loadingText | ReactNode | β | Replaces children while loading (no layout shift) |
| pulse | boolean | false | Soft pulsing ring β use for primary CTAs |
| ripple | boolean | true | Material-style click ripple |
| disabled | boolean | false | Disable |
| iconLeft | ReactNode | β | Icon before label |
| iconRight | ReactNode | β | Icon after label |