npm install @thrivecart/uiyarn add @thrivecart/uipnpm add @thrivecart/uibun add @thrivecart/uiImport the Button component from the package. For examples with icons, you'll also need to import from react-icons/md:
import { Button } from '@thrivecart/ui';
import { MdAdd, MdSave, MdEdit, MdArrowForward, MdDownload, MdOpenInNew, MdDelete } from 'react-icons/md';The simplest form of a button
<Button>Click me</Button>Buttons come in different visual styles to indicate their importance and purpose.
Different visual styles for different use cases
<div className="flex flex-wrap gap-2">
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="destructive">Destructive</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="ghost-body">Ghost Body</Button>
<Button variant="ghost-destructive">Ghost Destructive</Button>
<Button variant="link">Link</Button>
</div>Buttons are available in four sizes to fit different contexts and density needs.
Four size options from extra small to large
<div className="flex items-center gap-2">
<Button size="xs">Extra Small</Button>
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>
</div>Size recommendations:
Buttons support icons on both the left and right sides, or as standalone icon-only buttons.
Using leftIcon and rightIcon props:
Use the leftIcon prop for icons before text
<div className="flex flex-wrap gap-2">
<Button variant="primary" leftIcon={<MdAdd />}>
Add Item
</Button>
<Button leftIcon={<MdSave />}>
Save Changes
</Button>
<Button variant="secondary" leftIcon={<MdEdit />}>
Edit
</Button>
</div>Right side icons:
Use the rightIcon prop for icons after text
<div className="flex flex-wrap gap-2">
<Button variant="primary" rightIcon={<MdArrowForward />}>
Continue
</Button>
<Button rightIcon={<MdDownload />}>
Download
</Button>
<Button variant="link" rightIcon={<MdOpenInNew />}>
Open Link
</Button>
</div>Buttons can display a loading state to provide feedback during async operations.
Show loading state during async operations
<div className="flex flex-wrap gap-2">
<Button variant="primary" loading disabled>
Processing...
</Button>
<Button variant="primary" loading loadingText="Saving..." disabled>
Save Changes
</Button>
<Button variant="secondary" loading disabled>
Loading
</Button>
<Button variant="destructive" loading loadingText="Deleting..." disabled>
Delete
</Button>
</div>Loading state behavior:
loadingTextButtons that are temporarily unavailable
<div className="flex flex-wrap gap-2">
<Button variant="primary" disabled>Primary Disabled</Button>
<Button variant="secondary" disabled>Secondary Disabled</Button>
<Button variant="destructive" disabled>Destructive Disabled</Button>
<Button variant="ghost" disabled>Ghost Disabled</Button>
</div>Use the destructive variant for actions that have permanent consequences like deleting data or canceling subscriptions.
Highlight permanent and dangerous actions
<div className="flex flex-wrap gap-2">
<Button variant="destructive">Delete Account</Button>
<Button variant="destructive" leftIcon={<MdDelete />}>
Remove Item
</Button>
<Button variant="primary">Save Changes</Button>
</div>You can render a button as a link element using the asChild prop, which is useful for semantic HTML.
Render button styles on a link element
<div className="flex flex-wrap gap-2">
<Button variant="primary" asChild>
<a href="/dashboard">Go to Dashboard</a>
</Button>
<Button variant="link" asChild>
<a href="/documentation">Read Docs</a>
</Button>
</div>Semantic HTML
When using asChild, the button style is applied to the child element. This is useful when you need proper <a> tags for SEO or when integrating with Next.js Link components.
Button text should clearly describe the action that will occur. Use verbs: "Save changes", "Delete account", "Add to cart", "Submit form".
Always show loading state during async operations to prevent users from clicking multiple times and to provide clear feedback.
Match button size to importance and density: xs/sm for tables and toolbars, md for forms, lg for prominent CTAs.
Use primary for main actions, secondary/destructive for important but not primary actions, ghost/link for subtle actions, and destructive for dangerous operations.
Don't use generic text like "Click here", "OK", "Submit". Be specific about what will happen.
Only one primary action per interface. Multiple primary buttons create confusion about hierarchy and importance.
Use <Link> or the asChild prop when navigating between pages. Save buttons for actions that change state.
Disable buttons when actions aren't available. Provide clear feedback about why an action is disabled.
Keyboard Navigation
Buttons can be activated using the Space or Enter key when focused. Use Tab to navigate between buttons.
Button vs Link
Use a button for actions that affect the current page. Use a link for navigation to different pages or sections.