axokit-react
v0.0.7
Published
Headless async button and hook for React
Maintainers
Readme
AxoKit React — AsyncButton & useAsyncAction
Production-ready async interaction primitives for React & Next.js.
Package name: axokit-react (install with npm install axokit-react).
Features
- Automatic loading / success / error states
- Hook (
useAsyncAction) and headless component - TypeScript support
- Minimal styles; load your own CSS or Tailwind classes
- Works with React 18+
Why AxoKit?
- Production‑ready async state management with minimal boilerplate.
- Works with both component and hook patterns.
- Tiny footprint and zero runtime dependencies.
- Fully typed for TypeScript and compatible with React 18+.
- Accessible ARIA attributes and easy styling with Tailwind or CSS.
Installation
npm install axokit-react
# also install peer dependencies
Requires `react` and `react-dom` 18+ as peer dependencies.Usage (component)
import { AsyncButton } from 'axokit-react';
function SaveButton() {
const save = () => fetch('/api/save', { method: 'POST' });
return (
<AsyncButton
onAction={save}
loadingText="Saving..."
successText="Saved ✓"
errorText="Try again"
showSpinner // built‑in loader
disableOnSuccess={false} // optional
className="px-4 py-2 rounded bg-blue-600 text-white"
>
Save
</AsyncButton>
);
}Next.js (App Router)
If you're using the App Router, add 'use client' at the top of your component file:
'use client';
import { AsyncButton } from 'axokit-react';Usage (hook)
import { useAsyncAction } from 'axokit-react';
function HookExample() {
const save = () => fetch('/api/save', { method: 'POST' });
const { state, trigger, reset } = useAsyncAction(save);
return (
<div>
<button onClick={trigger} disabled={state === 'loading'}>
{state === 'loading' ? 'Saving…' : state === 'success' ? 'Saved' : 'Save'}
</button>
<button onClick={reset}>Reset</button>
</div>
);
}Example
import { AsyncButton } from 'axokit-react';
function Demo() {
const doWork = () => fetch('/api/work');
return (
<AsyncButton
onAction={doWork}
loadingText="Working…"
successText="Done!"
errorText="Failed"
showSpinner
className="btn"
>
Click me
</AsyncButton>
);
}API
AsyncButton(props)
onAction: () => Promise<unknown>— required.loadingText?: string— default:"Loading...".successText?: string— default:"Done!".errorText?: string— default:"Try again".successDuration?: number— default:1200ms.errorDuration?: number— default:3000ms.disableOnSuccess?: boolean— default:true.showSpinner?: boolean— default:false. Whentrue, a tiny built‑in SVG spinner appears to the left of the label during loading.onSuccess?: () => void.onActionError?: (error: Error) => void.- All other native
buttonprops are forwarded.
useAsyncAction(action, options?)
Returns { state, error, trigger, reset } with state 'idle'|'loading'|'success'|'error'.
Accessibility
- Button sets
aria-busywhile loading. - Exposes
data-stateattribute for styling. - The hook returns state for building your own live regions.
Styling
Use data-state to adjust styles via CSS/Tailwind.
.btn { @apply px-4 py-2 rounded; }
.btn[data-state="loading"] { opacity: 0.7; }
.btn[data-state="success"] { background-color: theme(colors.green.600); }
.btn[data-state="error"] { background-color: theme(colors.red.600); }License
MIT
Keywords
async, react, async-button, useAsyncAction, hook, component, loading, success, error, state, nextjs, tailwind, aria, accessible, typescript
