Button
Actions with explicit loading and completion feedback.
Usage
import { Button } from '@commenda/pathfinder/button';
<Button
variant="primary"
loadingConfig={{ isLoading: isSaving, label: 'Saving changes' }}
completionConfig={{ isComplete: isSaved, label: 'Changes saved' }}
disabled={!canSave}
disabledReason="Administrator access required"
onClick={onSave}
>
Save changes
</Button>;Installation
pnpm --filter your-app add "@commenda/pathfinder@workspace:*"The package currently lives in the Commenda workspace. External installation requires a published version or packed tarball. Import the precompiled stylesheet once; no application Tailwind setup is required.
Examples
Variants
Sizes and icons
Loading and completion
Disabled reason
API reference
| Prop | Type | Behavior |
|---|---|---|
variantConditional | "primary"|"secondary"|"tertiary"|"link"|"link-subtle" | primary |
size | "sm"|"md"|"lg" | md; 28/32/36px minimum height |
destructiveConditional | boolean | false; only primary/secondary/tertiary |
loadingConfig | LoadingConfigView fields | Spinner with optional replacement label |
completionConfig | CompletionConfigView fields | Explicit success, default check; only non-destructive primary/secondary/tertiary |
leadingIcon | ReactNode | Decorative icon slots, 16px at sm/md and 20px at lg |
trailingIcon | ReactNode | Decorative icon slots, 16px at sm/md and 20px at lg |
disabledReason | string | Prevent activation; explain unavailable actions |
className | string | Additional classes for the component root. |
ButtonProps, ButtonBaseProps, LoadingConfig and CompletionConfig are exported from root and /button.
Feedback rules
CONTROL-STATE-01: Loading ending does not mean success. Set isComplete only after application success. Loading wins if both flags are true. Disabled always blocks activation. Loading blocks repeat activation while retaining keyboard focus; the label and busy state remain accessible. Feedback replaces the normal leading icon; the trailing icon remains.
The application owns completion timing. Figma's recipe resets after 1.5 seconds; clear your timer on unmount and reset success before the next request. Errors belong in application feedback. No status or onActionComplete configuration prop exists.
Keyboard and labels
Tab focuses the control; Enter/Space activates it. Disabled controls normally leave tab order. A disabled control with a reason remains focusable with aria-disabled, an accessible description and a tooltip; activation is blocked. Loading controls remain focusable. Preserve this behavior when composing custom elements.
BUTTON-COPY-01: Name the action and object in sentence case: “Export entities”, “Delete version”. Avoid “Submit” and “OK”. Icon-only actions use IconButton. Labels wrap at narrow widths and enlarged text sizes; minimum heights can grow to keep content readable. Unnamed/whitespace-only labels are invalid.
Import @commenda/pathfinder/styles.css once at the app root. Event handlers require a client component in Next.js App Router.
For navigation, use a real anchor or Next Link. Base UI Button composition can assign button semantics to an anchor; changing the rendered tag alone does not guarantee link semantics.
Design rules
Figma guidance and reviewed implementation decisions for this component. Rule IDs remain stable for source comments and AI references.
Action rules
-
BUTTON-COPY-01— Figma: labels name the action and object in sentence case. Use one primary main action; secondary alongside it; tertiary for quiet repeated actions. Add icons only when they add meaning. Navigation uses a real link. -
CONTROL-STATE-01— Pathfinder: loadingConfig and completionConfig are explicit application signals. Loading wins over completion; disabled blocks activation. Ending loading never implies success. Applications own the 1.5-second completion reset recipe from Figma. -
CONTROL-SIZE-01— Figma: Button and SplitButton sm/md/lg have 28/32/36px visual heights; md default. IconButton adds xs 24. Button icons are 16 through md and 20 at lg; pass size to generated icons to select optical artwork. Link styles have text-sized geometry. Long content can increase minimum height for accessibility. -
CONTROL-FOCUS-01— Figma: show focus from keyboard, not pointer click. Button family uses a blue ring separated by a white gap. Open triggers retain hover styling. Disabled reason is a Pathfinder extension: retain action name, expose description, and allow focus without activation where the native wrapper supports it.