Button
Interactive elements that trigger actions or events when clicked
Buttons are interactive elements that trigger actions or events when clicked or interacted with. Our enhanced button component provides advanced features like motion effects, haptic feedback, loading states, and comprehensive accessibility support.
Preview
Installation
pnpm dlx shadcn@latest add @upkit/button
npx shadcn@latest add @upkit/button
bunx shadcn@latest add @upkit/button
yarn dlx shadcn@latest add @upkit/button
Usage
import { Button } from "@/ui/button"
export default function Example() {
return <Button>Click me</Button>
}
Variants
Choose button variants based on visual hierarchy and importance. Primary actions should stand out, while secondary and tertiary actions progressively recede. This creates clear action paths and reduces cognitive load for users. Learn more about button variations.
<div className="flex flex-wrap gap-2"> <Button variant="solid" type="button">Solid</Button> <Button variant="outline" type="button">Outline</Button> <Button variant="soft" type="button">Soft</Button> <Button variant="ghost" type="button">Ghost</Button> <Button variant="link" type="button">Link</Button> <Button variant="danger" type="button">Danger</Button> <Button variant="success" type="button">Success</Button> <Button variant="warning" type="button">Warning</Button></div>
Solid (Default)
The primary button style for main actions.
Danger
Use for destructive actions like deleting data.
Outline
A button with a border and transparent background.
Soft
For less prominent secondary actions.
Ghost
Minimal styling for tertiary actions.
Link
Styled to look like a link but with button behavior.
Success, Warning, Gradient & Glass
Additional variants for special use cases:
Sizes
Button size affects touch targets and visual weight. Larger buttons are easier to click but take more space. Follow minimum touch target guidelines (44x44px on mobile) while balancing information density with usability. See mobile considerations.
<div className="flex flex-wrap items-center gap-2"> <Button size="xs" type="button">Extra Small</Button> <Button size="sm" type="button">Small</Button> <Button size="md" type="button">Medium</Button> <Button size="lg" type="button">Large</Button></div>
Motion Effects
Subtle animations provide feedback and polish. Click effects confirm activation while hover effects preview interactivity. Use sparingly - motion should enhance clarity, not distract from the task. Read about state variations.
<div className="flex flex-col gap-4"> {/* Click Effects */} <div> <h3 className="text-sm font-medium mb-2">Click Effects</h3> <div className="flex flex-wrap gap-2"> <Button clickEffect="none" type="button">No Effect</Button> <Button clickEffect="scale" type="button">Scale</Button> <Button clickEffect="ripple" type="button">Ripple</Button> <Button clickEffect="pulse" type="button">Pulse</Button> <Button clickEffect="spring" type="button">Spring</Button> </div> </div> {/* Hover Effects */} <div> <h3 className="text-sm font-medium mb-2">Hover Effects</h3> <div className="flex flex-wrap gap-2"> <Button hoverEffect="none" type="button">No Effect</Button> <Button hoverEffect="glow" type="button">Glow</Button> <Button hoverEffect="lift" type="button">Lift</Button> </div> </div></div>
Motion Preference: All motion effects automatically respect prefers-reduced-motion
settings. Users who prefer reduced motion will get instant feedback without animations.
States
Clear state indicators prevent user confusion and repeated clicks. Loading states show progress, success confirms completion, and disabled states explain unavailability. Never leave users wondering if their action was registered. Learn about state variations.
<div className="space-y-4"> <div className="flex flex-wrap gap-2"> <Button state="idle" type="button">Idle State</Button> <Button state="loading" type="button">Loading State</Button> <Button state="success" type="button">Success State</Button> <Button state="error" type="button">Error State</Button> <Button state="disabled" type="button">Disabled State</Button> </div> <div> <Button type="button" state={state} onClick={handleClick} loadingText="Processing..." successText="Complete!" errorText="Try Again" > Click to Test States </Button></div></div>
Loading States
Multiple loading indicators for different contexts:
/** * @registry * @name button-loading-states * @title Loading States Button * @type registry:block * @description Button with various loading states and animations * @categories ["buttons", "loading", "states"] * @tags ["loading", "animation", "states", "interactive", "feedback"] * @dependencies ["react"] * @registryDependencies ["button"] */"use client";import { useEffect, useRef, useState } from "react";import { Button } from "@/ui/button";export default function ButtonLoadingStates() { const [isLoading, setIsLoading] = useState(false); const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null); const handleClick = () => { // Guard on timeoutRef to prevent re-entry within the same tick if (timeoutRef.current !== null) return; // Set timeoutRef immediately when accepting the click timeoutRef.current = setTimeout(() => { setIsLoading(false); timeoutRef.current = null; }, 2000); setIsLoading(true); }; useEffect(() => { return () => { if (timeoutRef.current) clearTimeout(timeoutRef.current); }; }, []); return ( <div className="space-y-4"> <div className="flex flex-wrap items-center gap-2"> <Button type="button" state={isLoading ? "loading" : "idle"} onClick={handleClick} loadingType="spinner" > Save Changes </Button> <Button state="loading" loadingType="spinner" type="button"> Loading Spinner </Button> <Button state="loading" loadingType="dots" type="button"> Loading Dots </Button> </div> <div className="flex flex-wrap items-center gap-2"> <Button state="loading" loadingText="Processing..." type="button"> Custom Loading Text </Button> <Button state="success" successText="Saved!" type="button"> Success State </Button> <Button state="error" errorText="Failed" type="button"> Error State </Button> </div> </div> );}
Disabled States
By default, the disabled
prop uses aria-disabled
for better accessibility (keeps button in tab order). Use forceNativeDisabled
to apply the native HTML disabled attribute when needed:
<div className="flex flex-wrap gap-2"> <Button disabled type="button">Default (ARIA Disabled)</Button> <Button disabled forceNativeDisabled type="button"> Force Native Disabled </Button> <Button state="disabled" type="button">State Disabled</Button> <Button variant="outline" disabled type="button"> Disabled Outline </Button></div>
Performance Note: When using loading states, always provide feedback within 100ms to prevent users from thinking the button is broken. For actions taking longer than 3 seconds, consider showing progress indicators.
Interactive Features
Multi-sensory feedback creates more engaging and accessible interactions. Haptics, sounds, and long-press gestures add depth to the user experience while maintaining accessibility for all users. Explore accessibility guidelines.
Haptic Feedback
Add tactile feedback on mobile devices:
<div className="flex flex-wrap gap-2"> <Button haptics="light" type="button">Light Haptic</Button> <Button haptics="medium" type="button">Medium Haptic</Button> <Button haptics="heavy" type="button">Heavy Haptic</Button> <Button haptics="off" type="button">No Haptic</Button></div>
Sound Effects
Provide audio feedback for interactions:
<div className="flex flex-wrap gap-2"> <Button sound="subtle" type="button"> Subtle Sound </Button> <Button sound="click" type="button"> Click Sound </Button> <Button sound="off" type="button"> No Sound </Button></div>
Long Press
Support long press interactions:
<div className="flex flex-wrap gap-2"> <Button type="button" longPress={{ duration: 500, onLongPress: () => alert("Long pressed for 500ms!"), }} > Hold 0.5s</Button><Buttontype="button"longPress={{duration: 1000,onLongPress: () => alert("Long pressed for 1 second!"),}}>Hold 1s</Button><Buttontype="button"longPress={{duration: 2000,onLongPress: () => alert("Long pressed for 2 seconds!"),}}>Hold 2s</Button></div>
Pro Tip: Our enhanced button component includes advanced features like haptic feedback, sound effects, and motion animations that work seamlessly across all platforms. These features are opt-in and don't affect the core button functionality.
With Icons
Icons improve scannability and reinforce meaning, making interfaces faster to parse. Always pair icons with text for clarity - icon-only buttons should be reserved for universally recognized actions and include proper labels for accessibility. See content composition.
Icon Guidelines: Ensure icons are from the same family (e.g., all Lucide icons) for visual consistency. Mix-and-match icon styles create visual discord.
Icon on the Left
<div className="flex flex-wrap gap-2"> <Button type="button"> <Mail className="h-4 w-4" /> Send Email </Button> <Button variant="outline" type="button"> <Save className="h-4 w-4" /> Save Document </Button> <Button variant="soft" type="button"> <Upload className="h-4 w-4" /> Upload File </Button></div>
Icon on the Right
<div className="flex flex-wrap gap-2"> <Button type="button"> Continue <ChevronRight className="h-4 w-4" /> </Button> <Button variant="outline" type="button"> Next Step <ArrowRight className="h-4 w-4" /> </Button> <Button variant="link" type="button"> Learn More <ExternalLink className="h-4 w-4" /> </Button></div>
Icon Only
<div className="flex flex-wrap gap-2"> <Button aria-label="Save" type="button"> <Save className="h-4 w-4" /> </Button> <Button aria-label="Delete" type="button"> <Trash2 className="h-4 w-4" /> </Button> <Button aria-label="Edit" type="button"> <Edit className="h-4 w-4" /> </Button> <Button aria-label="Settings" variant="outline" type="button"> <Settings className="h-4 w-4" /> </Button> <Button aria-label="Share" variant="ghost" type="button"> <Share2 className="h-4 w-4" /> </Button> <Button aria-label="Favorite" variant="soft" type="button"> <Heart className="h-4 w-4" /> </Button></div>
Double Icons
<div className="flex flex-wrap gap-2"> <Button> <Mail aria-hidden="true" className="h-4 w-4" /> Send Email <ArrowRight aria-hidden="true" className="h-4 w-4" /> </Button> <Button variant="outline"> <Download aria-hidden="true" className="h-4 w-4" /> Export PDF <ExternalLink aria-hidden="true" className="h-4 w-4" /> </Button> <Button variant="soft"> <Lock aria-hidden="true" className="h-4 w-4" /> View Details <ChevronRight aria-hidden="true" className="h-4 w-4" /> </Button></div>
With Icons (All Variations)
<div className="space-y-6"> <div className="space-y-2"> <h4 className="text-sm font-medium">Icon on the Left</h4> <div className="flex flex-wrap gap-2"> <Button type="button"> <Plus className="h-4 w-4" /> Add Item </Button> <Button variant="outline" type="button"> <Heart className="h-4 w-4" /> Like </Button> </div> </div> <div className="space-y-2"> <h4 className="text-sm font-medium">Icon on the Right</h4> <div className="flex flex-wrap gap-2"> <Button type="button"> Continue <ChevronRight className="h-4 w-4" /> </Button> <Button variant="outline" type="button"> Download <Download className="h-4 w-4" /> </Button> </div> </div> <div className="space-y-2"> <h4 className="text-sm font-medium">Icon Only</h4> <div className="flex flex-wrap gap-2"> <Button aria-label="Edit" type="button"> <Edit className="h-4 w-4" /> </Button> <Button variant="outline" aria-label="Delete" type="button"> <Trash className="h-4 w-4" /> </Button> <Button variant="ghost" aria-label="Share" type="button"> <Share2 className="h-4 w-4" /> </Button> </div> </div></div>
Layout Options
Button layout affects visual flow and interaction patterns. Full-width buttons work well in forms and modals, while button groups organize related actions. Consider thumb reach on mobile when positioning primary actions. Read about layout & positioning.
Full Width
<div className="w-full max-w-md space-y-4"> <Button wide type="button">Full Width with Wide Prop</Button> <Button wide variant="outline" type="button"> Full Width Outline </Button> <Button wide size="lg" type="button"> Full Width Large </Button> <div className="space-y-2"> <Button wide type="button">Primary Action</Button> <Button wide variant="ghost" type="button"> Secondary Action </Button> </div></div>
Button Groups
Group related actions together:
<div className="space-y-6"> <div className="space-y-2"> <h4 className="text-sm font-medium">Horizontal Group</h4> <div className="flex"> <Button className="rounded-r-none border-r-0" type="button">Left</Button> <Button variant="outline" className="rounded-none border-r-0" type="button"> Center </Button> <Button variant="outline" className="rounded-l-none" type="button"> Right </Button> </div> </div> <div className="space-y-2"> <h4 className="text-sm font-medium">Attached Group</h4> <div className="inline-flex rounded-md shadow-sm" role="group"> <Button variant="outline" className="rounded-r-none border-r-0" type="button"> Years </Button> <Button variant="outline" className="rounded-none border-r-0" type="button"> Months </Button> <Button variant="outline" className="rounded-l-none" type="button"> Days </Button> </div> </div> <div className="space-y-2"> <h4 className="text-sm font-medium">Icon Button Group</h4> <div className="inline-flex rounded-md shadow-sm" role="group"> <Button variant="outline" aria-label="Edit" className="rounded-r-none border-r-0" type="button" > <Edit className="h-4 w-4" /> </Button> <Button variant="outline" aria-label="Delete" className="rounded-none border-r-0" type="button" > <Trash2 className="h-4 w-4" /> </Button> <Button variant="outline" aria-label="Share" className="rounded-l-none" type="button" > <Share2 className="h-4 w-4" /></Button></div></div></div>
Design Tip: Group related actions but limit to 3-4 buttons maximum. For more options, consider a dropdown menu to reduce cognitive load.
Advanced Examples
Real-world buttons combine multiple patterns for specific use cases. These examples demonstrate practical implementations like social logins, payment flows, and confirmation actions that balance functionality with user experience.
As Child
Use button styling with other components like links:
<div className="flex flex-wrap gap-2"> <Button asChild> <a href="#pricing" className="no-underline"> View Pricing </a> </Button> <Button variant="outline" asChild> {/* Example with Next.js Link (uncomment and add the import above) */} {/* <Link href="/docs" className="no-underline"> */} <a href="#docs" className="no-underline"> Documentation </a> {/* </Link> */} </Button> <Button variant="ghost" asChild> <a href="#about">About Us</a> </Button> </div>
With Badges & Notifications
Badges communicate status and urgency without cluttering the interface. Use sparingly to maintain impact - when everything is urgent, nothing is. Ensure proper contrast and accessibility for color-blind users.
<div className="flex flex-col gap-4"> {/* Basic badges */} <div className="flex flex-wrap gap-2"> <Button aria-label="Messages, 12 new" type="button"> Messages <span className="ml-2 inline-flex h-5 select-none items-center justify-center rounded-full bg-primary-foreground/20 px-2 py-0.5 text-xs font-medium text-primary-foreground" aria-hidden="true" > 12 </span> </Button> <Button variant="outline" type="button"> Notifications <span className="sr-only">, 3 unread</span> <span className="ml-2 inline-flex h-5 select-none items-center justify-center rounded-full bg-amber-500/20 px-2 py-0.5 text-xs font-medium text-amber-600 dark:text-amber-400" aria-hidden="true" > 3 </span></Button><Button variant="soft" aria-describedby={updatesNewId} type="button"> Updates <span id={updatesNewId} className="ml-2 inline-flex h-5 select-none items-center justify-center rounded-full bg-green-500/20 px-2 py-0.5 text-xs font-medium text-green-600 dark:text-green-400" > New</span></Button></div>{/* Notification badges */}<div className="flex flex-wrap gap-2"> {/* Icon with badge */} <Button type="button" variant="outline" size="sm" aria-label={`Notifications${notifications > 0 ? ` (${notifications})` : ""}`} onClick={() => setNotifications(0
With Counters
Social proof and engagement metrics build trust and encourage interaction. Keep counts readable with abbreviations (1.2k vs 1,234) and ensure real-time updates don't distract from the primary action.
<div className="flex flex-col gap-4"> {/* Basic counters */} <div className="flex flex-wrap gap-2"> <Button type="button" variant="outline" className="tabular-nums" aria-pressed={starred} aria-label={`${starred ? "Unstar" : "Star"} this repository, ${starCount.toLocaleString()} stars`} onClick={() => { setStarred((prev) => { const next = !prev; setStarCount((c) => Math.max(0, c + (next ? 1 : -1))
With Avatar
Avatar buttons personalize the interface and provide quick access to account actions. The dropdown indicator clarifies that more options are available, preventing confusion about the button's purpose.
<div className="flex flex-wrap gap-2"> <Button variant="ghost"> <img loading="lazy" decoding="async" width={20} height={20} src="https://kit.uxpatterns.dev/avatar.jpg" alt="User avatar" className="h-5 w-5 rounded-full" /> @thedaviddias </Button> <Button variant="outline"> <img loading="lazy" decoding="async" width={20} height={20} src="https://github.com/vercel.png" alt="Team avatar" className="h-5 w-5 rounded-full" /> Vercel Team </Button> <Button variant="soft"> <span className="flex h-5 w-5 items-center justify-center rounded-full bg-gradient-to-br from-blue-500 to-purple-600 text-xs font-bold text-white"> JD </span> John Doe </Button> {/* Account menu button - common in headers */} <Button variant="ghost" size="sm" aria-label="Account menu" className="gap-1" > <img loading="lazy" decoding="async" width={24} height={24} src="https://kit.uxpatterns.dev/avatar.jpg" alt="User avatar" className="h-6 w-6 rounded-full" /> <ChevronDown className="h-4 w-4" /></Button></div>
With Keyboard Shortcut
Displaying keyboard shortcuts educates power users and improves efficiency. Show shortcuts subtly to avoid visual clutter while helping users transition from clicking to keyboard navigation.
<Button type="button"> <span>Save</span> <kbd className="pointer-events-none inline-flex h-5 select-none items-center rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground"> ⌘S </kbd></Button>
Confirmation Actions
Destructive actions need safeguards to prevent accidents. Inline confirmations work for low-risk actions, while modal dialogs better suit irreversible operations. Long-press alternatives reduce friction while maintaining safety.
<div className="flex flex-col gap-4"> {/* Delete with confirmation */} <div className="flex items-center gap-2" aria-live="polite"> {deleteState === "idle" ? ( <Button type="button" variant="danger" onClick={() => setDeleteState("confirming"
Component Composition: For modal confirmations, combine with the Dialog component. The inline confirmation pattern shown here is suitable for less critical actions.
UX Best Practice: Reserve confirmation patterns for destructive actions only. Overusing confirmations creates "confirmation fatigue" where users click through without reading.
Social Buttons
Social login reduces friction and password fatigue. Display recognizable brand colors and icons to build trust, but offer traditional signup as an alternative for privacy-conscious users.
<div className="flex flex-col gap-4"> {/* Primary social buttons */} <div className="flex flex-wrap gap-2"> <Button type="button" variant="solid" hoverEffect="lift" className="bg-gray-900 hover:bg-black text-white transition-all hover:shadow-lg hover:shadow-black/20" > <Github className="h-4 w-4" /> Sign in with GitHub </Button> <Button type="button" variant="solid" hoverEffect="lift" className="bg-black hover:bg-gray-900 text-white transition-all hover:shadow-lg hover:shadow-black/20" > <svg className="h-4 w-4" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" > <path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" /></svg>Sign in with X</Button><Buttontype="button"variant="solid"hoverEffect="lift"className="bg-[#4267B2] hover:bg-[#365899] text-white transition-all hover:shadow-lg hover:shadow-[#4267B2]/25"><Facebook className="h-4 w-4" />Sign in with Facebook</Button></div>{/* Outline social buttons */}<div className="flex flex-wrap gap-2"> <Button type="button" variant="outline" hoverEffect="lift" className="border-[#0077B5] text-[#0077B5] hover:bg-[#0077B5] hover:text-white hover:border-[#0077B5] transition-all hover:shadow-lg hover:shadow-[#0077B5]/20" > <Linkedin className="h-4 w-4" /> Connect LinkedIn</Button><Buttontype="button"variant="outline"hoverEffect="lift"className="border-[#E4405F] text-[#E4405F] hover:bg-[#E4405F] hover:text-white hover:border-[#E4405F] transition-all hover:shadow-lg hover:shadow-[#E4405F]/20"><Instagram className="h-4 w-4" />Follow on Instagram</Button><Buttontype="button"variant="outline"hoverEffect="lift"className="border-[#FF0000] text-[#FF0000] hover:bg-[#FF0000] hover:text-white hover:border-[#FF0000] transition-all hover:shadow-lg hover:shadow-[#FF0000]/20"><Youtube className="h-4 w-4" />Subscribe on YouTube</Button></div>{/* Icon-only social buttons */}<div className="flex flex-wrap gap-2"> <Button type="button" variant="solid" size="sm" hoverEffect="lift" className="bg-gray-900 hover:bg-black text-white transition-all hover:shadow-lg hover:shadow-black/20" aria-label="GitHub" > <Github className="h-4 w-4" /></Button><Buttontype="button"variant="solid"size="sm"hoverEffect="lift"className="bg-black hover:bg-gray-900 text-white transition-all hover:shadow-lg hover:shadow-black/20"aria-label="X"><svgclassName="h-4 w-4"viewBox="0 0 24 24"fill="currentColor"aria-hidden="true"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" /></svg></Button><Buttontype="button"variant="solid"size="sm"hoverEffect="lift"className="bg-[#4267B2] hover:bg-[#365899] text-white transition-all hover:shadow-lg hover:shadow-[#4267B2]/25"aria-label="Facebook"><Facebook className="h-4 w-4" /></Button><Buttontype="button"variant="solid"size="sm"hoverEffect="lift"className="bg-[#0077B5] hover:bg-[#006097] text-white transition-all hover:shadow-lg hover:shadow-[#0077B5]/25"aria-label="LinkedIn"><Linkedin className="h-4 w-4" /></Button><Buttontype="button"variant="solid"size="sm"hoverEffect="lift"className="bg-gradient-to-br from-[#833AB4] via-[#E4405F] to-[#FCAF45] hover:opacity-90 text-white transition-all hover:shadow-lg hover:shadow-[#E4405F]/25"aria-label="Instagram"><Instagram className="h-4 w-4" /></Button><Buttontype="button"variant="solid"size="sm"hoverEffect="lift"className="bg-[#FF0000] hover:bg-[#e60000] text-white transition-all hover:shadow-lg hover:shadow-[#FF0000]/25"aria-label="YouTube"><Youtube className="h-4 w-4" /></Button></div></div>
Payment Buttons
Payment buttons must inspire confidence through familiar branding and clear security indicators. Express checkout options reduce cart abandonment while maintaining trust through recognized payment providers.
<div className="flex flex-col gap-4"> {/* Primary payment methods */} <div className="flex flex-wrap gap-2"> <Button type="button" variant="solid" size="md" hoverEffect="lift" className="bg-[#5469d4] hover:bg-[#4456c7] text-white dark:bg-[#5469d4] dark:hover:bg-[#4456c7] transition-all hover:shadow-lg hover:shadow-[#5469d4]/20" > <CreditCard className="h-5 w-5" /> Pay with Card </Button> <Button type="button" variant="solid" size="md" hoverEffect="lift" className="bg-[#FFC439] hover:bg-[#f7b500] text-black dark:bg-[#FFC439] dark:hover:bg-[#f7b500] dark:text-black transition-all hover:shadow-lg hover:shadow-[#FFC439]/20" > <svg className="w-4 h-4" aria-hidden="true" focusable="false" data-prefix="fab" data-icon="paypal" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512" > <path fill="currentColor" d="M111.4 295.9c-3.5 19.2-17.4 108.7-21.5 134-.3 1.8-1 2.5-3 2.5H12.3c-7.6 0-13.1-6.6-12.1-13.9L58.8 46.6c1.5-9.6 10.1-16.9 20-16.9 152.3 0 165.1-3.7 204 11.4 60.1 23.3 65.6 79.5 44 140.3-21.5 62.6-72.5 89.5-140.1 90.3-43.4 .7-69.5-7-75.3 24.2zM357.1 152c-1.8-1.3-2.5-1.8-3 1.3-2 11.4-5.1 22.5-8.8 33.6-39.9 113.8-150.5 103.9-204.5 103.9-6.1 0-10.1 3.3-10.9 9.4-22.6 140.4-27.1 169.7-27.1 169.7-1 7.1 3.5 12.9 10.6 12.9h63.5c8.6 0 15.7-6.3 17.4-14.9 .7-5.4-1.1 6.1 14.4-91.3 4.6-22 14.3-19.7 29.3-19.7 71 0 126.4-28.8 142.9-112.3 6.5-34.8 4.6-71.4-23.8-92.6z" ></path></svg>PayPal</Button><Buttontype="button"variant="solid"size="md"hoverEffect="lift"className="bg-gray-900 hover:bg-black text-white dark:bg-gray-100 dark:hover:bg-white dark:text-black transition-all hover:shadow-lg hover:shadow-black/20 dark:hover:shadow-white/20"><svgclassName="w-5 h-5"aria-hidden="true"focusable="false"data-prefix="fab"data-icon="apple"role="img"xmlns="http://www.w3.org/2000/svg"viewBox="0 0 384 512"><pathfill="currentColor"d="M318.7 268.7c-.2-36.7 16.4-64.4 50-84.8-18.8-26.9-47.2-41.7-84.7-44.6-35.5-2.8-74.3 20.7-88.5 20.7-15 0-49.4-19.7-76.4-19.7C63.3 141.2 4 184.8 4 273.5q0 39.3 14.4 81.2c12.8 36.7 59 126.7 107.2 125.2 25.2-.6 43-17.9 75.8-17.9 31.8 0 48.3 17.9 76.4 17.9 48.6-.7 90.4-82.5 102.6-119.3-65.2-30.7-61.7-90-61.7-91.9zm-56.6-164.2c27.3-32.4 24.8-61.9 24-72.5-24.1 1.4-52 16.4-67.9 34.9-17.5 19.8-27.8 44.3-25.6 71.9 26.1 2 49.9-11.4 69.5-34.3z"></path></svg>Apple Pay</Button></div>{/* Checkout button */}<div className="flex flex-wrap gap-2"> <Button type="button" variant="success" size="md" wide hoverEffect="lift" className="font-semibold transition-all hover:shadow-lg hover:shadow-emerald-500/20" > <ShoppingCart className="h-5 w-5" /> Complete Purchase - $99.00</Button></div>{/* Modern alternative */}<div className="flex flex-wrap gap-2"> <Button type="button" variant="outline" size="md" wide hoverEffect="lift" className="border-orange-500 text-orange-600 hover:bg-orange-500 hover:text-white font-semibold transition-all hover:shadow-lg hover:shadow-orange-500/20" > <Clock className="h-5 w-5" /> Buy Now, Pay Later</Button></div></div>
Accessibility
Our button component includes comprehensive accessibility features by default:
<div className="space-y-4"> <div className="flex flex-wrap gap-2"> <Button aria-label="Save document" type="button"> <Save className="h-4 w-4" /> </Button> <Button aria-label="Delete item" type="button"> <Trash2 className="h-4 w-4" /> </Button> <Button aria-label="Edit content" type="button"> <Edit className="h-4 w-4" /> </Button> <Button aria-label="Share post" type="button"> <Share2 className="h-4 w-4" /> </Button> </div> <div className="flex flex-wrap gap-2"> <Button aria-disabled={true} type="button"> ARIA Disabled </Button> <Button announceChanges state="loading" type="button"> With Screen Reader Announcements </Button> <Button aria-busy={true} type="button"> ARIA Busy State </Button> </div> <div className="flex flex-wrap gap-2"> <Button type="button" aria-describedby={helpTextId} tooltipWhenDisabled="Feature coming soon" > With Description </Button> <span id={helpTextId} className="sr-only"> This button saves your current progress </span></div></div>
Accessibility First: Our button component prioritizes accessibility with comprehensive ARIA support, keyboard navigation, and screen reader compatibility. Learn more in the Button Pattern accessibility guide.
API Reference
Button Props
Prop | Type | Default |
---|---|---|
ref? | Ref<HTMLButtonElement> | - |
key? | Key | null | - |
disabled? | boolean | - |
form? | string | - |
formAction? | string | ((formData: FormData) => void | Promise<void>) | - |
formEncType? | string | - |
formMethod? | string | - |
formNoValidate? | boolean | - |
formTarget? | string | - |
name? | string | - |
type? | "button" | "submit" | "reset" | - |
value? | string | number | readonly string[] | - |
defaultChecked? | boolean | - |
defaultValue? | string | number | readonly string[] | - |
suppressContentEditableWarning? | boolean | - |
suppressHydrationWarning? | boolean | - |
accessKey? | string | - |
autoCapitalize? | "none" | "off" | "on" | "sentences" | "words" | "characters" | (string & {}) | - |
autoFocus? | boolean | - |
className? | string | - |
contentEditable? | "inherit" | Booleanish | "plaintext-only" | - |
contextMenu? | string | - |
dir? | string | - |
draggable? | Booleanish | - |
enterKeyHint? | "enter" | "done" | "go" | "next" | "previous" | "search" | "send" | - |
hidden? | boolean | - |
id? | string | - |
lang? | string | - |
nonce? | string | - |
slot? | string | - |
spellCheck? | Booleanish | - |
tabIndex? | number | - |
title? | string | - |
translate? | "yes" | "no" | - |
radioGroup? | string | - |
role? | AriaRole | - |
about? | string | - |
content? | string | - |
datatype? | string | - |
inlist? | any | - |
prefix? | string | - |
property? | string | - |
rel? | string | - |
resource? | string | - |
rev? | string | - |
typeof? | string | - |
vocab? | string | - |
autoCorrect? | string | - |
autoSave? | string | - |
color? | string | - |
itemProp? | string | - |
itemScope? | boolean | - |
itemType? | string | - |
itemID? | string | - |
itemRef? | string | - |
results? | number | - |
security? | string | - |
unselectable? | "off" | "on" | - |
popover? | "" | "auto" | "manual" | - |
popoverTargetAction? | "toggle" | "show" | "hide" | - |
popoverTarget? | string | - |
inert? | boolean | - |
inputMode? | "none" | "search" | "text" | "tel" | "url" | "email" | "numeric" | "decimal" | - |
is? | string | - |
exportparts? | string | - |
part? | string | - |
aria-activedescendant? | string | - |
aria-atomic? | Booleanish | - |
aria-autocomplete? | "none" | "list" | "inline" | "both" | - |
aria-braillelabel? | string | - |
aria-brailleroledescription? | string | - |
aria-busy? | Booleanish | - |
aria-checked? | boolean | "true" | "false" | "mixed" | - |
aria-colcount? | number | - |
aria-colindex? | number | - |
aria-colindextext? | string | - |
aria-colspan? | number | - |
aria-controls? | string | - |
aria-current? | boolean | "true" | "false" | "page" | "step" | "location" | "date" | "time" | - |
aria-describedby? | string | - |
aria-description? | string | - |
aria-details? | string | - |
aria-disabled? | Booleanish | - |
aria-dropeffect? | "link" | "none" | "copy" | "execute" | "move" | "popup" | - |
aria-errormessage? | string | - |
aria-expanded? | Booleanish | - |
aria-flowto? | string | - |
aria-grabbed? | Booleanish | - |
aria-haspopup? | boolean | "true" | "false" | "dialog" | "grid" | "listbox" | "menu" | "tree" | - |
aria-hidden? | Booleanish | - |
aria-invalid? | boolean | "true" | "false" | "grammar" | "spelling" | - |
aria-keyshortcuts? | string | - |
aria-label? | string | - |
aria-labelledby? | string | - |
aria-level? | number | - |
aria-live? | "off" | "assertive" | "polite" | - |
aria-modal? | Booleanish | - |
aria-multiline? | Booleanish | - |
aria-multiselectable? | Booleanish | - |
aria-orientation? | "horizontal" | "vertical" | - |
aria-owns? | string | - |
aria-placeholder? | string | - |
aria-posinset? | number | - |
aria-pressed? | boolean | "true" | "false" | "mixed" | - |
aria-readonly? | Booleanish | - |
aria-relevant? | "text" | "additions" | "additions removals" | "additions text" | "all" | "removals" | "removals additions" | "removals text" | "text additions" | "text removals" | - |
aria-required? | Booleanish | - |
aria-roledescription? | string | - |
aria-rowcount? | number | - |
aria-rowindex? | number | - |
aria-rowindextext? | string | - |
aria-rowspan? | number | - |
aria-selected? | Booleanish | - |
aria-setsize? | number | - |
aria-sort? | "none" | "ascending" | "descending" | "other" | - |
aria-valuemax? | number | - |
aria-valuemin? | number | - |
aria-valuenow? | number | - |
aria-valuetext? | string | - |
dangerouslySetInnerHTML? | { __html: string | TrustedHTML; } | - |
onCopy? | ClipboardEventHandler<HTMLButtonElement> | - |
onCopyCapture? | ClipboardEventHandler<HTMLButtonElement> | - |
onCut? | ClipboardEventHandler<HTMLButtonElement> | - |
onCutCapture? | ClipboardEventHandler<HTMLButtonElement> | - |
onPaste? | ClipboardEventHandler<HTMLButtonElement> | - |
onPasteCapture? | ClipboardEventHandler<HTMLButtonElement> | - |
onCompositionEnd? | CompositionEventHandler<HTMLButtonElement> | - |
onCompositionEndCapture? | CompositionEventHandler<HTMLButtonElement> | - |
onCompositionStart? | CompositionEventHandler<HTMLButtonElement> | - |
onCompositionStartCapture? | CompositionEventHandler<HTMLButtonElement> | - |
onCompositionUpdate? | CompositionEventHandler<HTMLButtonElement> | - |
onCompositionUpdateCapture? | CompositionEventHandler<HTMLButtonElement> | - |
onFocus? | FocusEventHandler<HTMLButtonElement> | - |
onFocusCapture? | FocusEventHandler<HTMLButtonElement> | - |
onBlur? | FocusEventHandler<HTMLButtonElement> | - |
onBlurCapture? | FocusEventHandler<HTMLButtonElement> | - |
onChange? | FormEventHandler<HTMLButtonElement> | - |
onChangeCapture? | FormEventHandler<HTMLButtonElement> | - |
onBeforeInput? | InputEventHandler<HTMLButtonElement> | - |
onBeforeInputCapture? | FormEventHandler<HTMLButtonElement> | - |
onInput? | FormEventHandler<HTMLButtonElement> | - |
onInputCapture? | FormEventHandler<HTMLButtonElement> | - |
onReset? | FormEventHandler<HTMLButtonElement> | - |
onResetCapture? | FormEventHandler<HTMLButtonElement> | - |
onSubmit? | FormEventHandler<HTMLButtonElement> | - |
onSubmitCapture? | FormEventHandler<HTMLButtonElement> | - |
onInvalid? | FormEventHandler<HTMLButtonElement> | - |
onInvalidCapture? | FormEventHandler<HTMLButtonElement> | - |
onLoad? | ReactEventHandler<HTMLButtonElement> | - |
onLoadCapture? | ReactEventHandler<HTMLButtonElement> | - |
onError? | ReactEventHandler<HTMLButtonElement> | - |
onErrorCapture? | ReactEventHandler<HTMLButtonElement> | - |
onKeyDown? | KeyboardEventHandler<HTMLButtonElement> | - |
onKeyDownCapture? | KeyboardEventHandler<HTMLButtonElement> | - |
onKeyPress? | KeyboardEventHandler<HTMLButtonElement> | - |
onKeyPressCapture? | KeyboardEventHandler<HTMLButtonElement> | - |
onKeyUp? | KeyboardEventHandler<HTMLButtonElement> | - |
onKeyUpCapture? | KeyboardEventHandler<HTMLButtonElement> | - |
onAbort? | ReactEventHandler<HTMLButtonElement> | - |
onAbortCapture? | ReactEventHandler<HTMLButtonElement> | - |
onCanPlay? | ReactEventHandler<HTMLButtonElement> | - |
onCanPlayCapture? | ReactEventHandler<HTMLButtonElement> | - |
onCanPlayThrough? | ReactEventHandler<HTMLButtonElement> | - |
onCanPlayThroughCapture? | ReactEventHandler<HTMLButtonElement> | - |
onDurationChange? | ReactEventHandler<HTMLButtonElement> | - |
onDurationChangeCapture? | ReactEventHandler<HTMLButtonElement> | - |
onEmptied? | ReactEventHandler<HTMLButtonElement> | - |
onEmptiedCapture? | ReactEventHandler<HTMLButtonElement> | - |
onEncrypted? | ReactEventHandler<HTMLButtonElement> | - |
onEncryptedCapture? | ReactEventHandler<HTMLButtonElement> | - |
onEnded? | ReactEventHandler<HTMLButtonElement> | - |
onEndedCapture? | ReactEventHandler<HTMLButtonElement> | - |
onLoadedData? | ReactEventHandler<HTMLButtonElement> | - |
onLoadedDataCapture? | ReactEventHandler<HTMLButtonElement> | - |
onLoadedMetadata? | ReactEventHandler<HTMLButtonElement> | - |
onLoadedMetadataCapture? | ReactEventHandler<HTMLButtonElement> | - |
onLoadStart? | ReactEventHandler<HTMLButtonElement> | - |
onLoadStartCapture? | ReactEventHandler<HTMLButtonElement> | - |
onPause? | ReactEventHandler<HTMLButtonElement> | - |
onPauseCapture? | ReactEventHandler<HTMLButtonElement> | - |
onPlay? | ReactEventHandler<HTMLButtonElement> | - |
onPlayCapture? | ReactEventHandler<HTMLButtonElement> | - |
onPlaying? | ReactEventHandler<HTMLButtonElement> | - |
onPlayingCapture? | ReactEventHandler<HTMLButtonElement> | - |
onProgress? | ReactEventHandler<HTMLButtonElement> | - |
onProgressCapture? | ReactEventHandler<HTMLButtonElement> | - |
onRateChange? | ReactEventHandler<HTMLButtonElement> | - |
onRateChangeCapture? | ReactEventHandler<HTMLButtonElement> | - |
onSeeked? | ReactEventHandler<HTMLButtonElement> | - |
onSeekedCapture? | ReactEventHandler<HTMLButtonElement> | - |
onSeeking? | ReactEventHandler<HTMLButtonElement> | - |
onSeekingCapture? | ReactEventHandler<HTMLButtonElement> | - |
onStalled? | ReactEventHandler<HTMLButtonElement> | - |
onStalledCapture? | ReactEventHandler<HTMLButtonElement> | - |
onSuspend? | ReactEventHandler<HTMLButtonElement> | - |
onSuspendCapture? | ReactEventHandler<HTMLButtonElement> | - |
onTimeUpdate? | ReactEventHandler<HTMLButtonElement> | - |
onTimeUpdateCapture? | ReactEventHandler<HTMLButtonElement> | - |
onVolumeChange? | ReactEventHandler<HTMLButtonElement> | - |
onVolumeChangeCapture? | ReactEventHandler<HTMLButtonElement> | - |
onWaiting? | ReactEventHandler<HTMLButtonElement> | - |
onWaitingCapture? | ReactEventHandler<HTMLButtonElement> | - |
onAuxClick? | MouseEventHandler<HTMLButtonElement> | - |
onAuxClickCapture? | MouseEventHandler<HTMLButtonElement> | - |
onClick? | MouseEventHandler<HTMLButtonElement> | - |
onClickCapture? | MouseEventHandler<HTMLButtonElement> | - |
onContextMenu? | MouseEventHandler<HTMLButtonElement> | - |
onContextMenuCapture? | MouseEventHandler<HTMLButtonElement> | - |
onDoubleClick? | MouseEventHandler<HTMLButtonElement> | - |
onDoubleClickCapture? | MouseEventHandler<HTMLButtonElement> | - |
onDragCapture? | DragEventHandler<HTMLButtonElement> | - |
onDragEndCapture? | DragEventHandler<HTMLButtonElement> | - |
onDragEnter? | DragEventHandler<HTMLButtonElement> | - |
onDragEnterCapture? | DragEventHandler<HTMLButtonElement> | - |
onDragExit? | DragEventHandler<HTMLButtonElement> | - |
onDragExitCapture? | DragEventHandler<HTMLButtonElement> | - |
onDragLeave? | DragEventHandler<HTMLButtonElement> | - |
onDragLeaveCapture? | DragEventHandler<HTMLButtonElement> | - |
onDragOver? | DragEventHandler<HTMLButtonElement> | - |
onDragOverCapture? | DragEventHandler<HTMLButtonElement> | - |
onDragStartCapture? | DragEventHandler<HTMLButtonElement> | - |
onDrop? | DragEventHandler<HTMLButtonElement> | - |
onDropCapture? | DragEventHandler<HTMLButtonElement> | - |
onMouseDown? | MouseEventHandler<HTMLButtonElement> | - |
onMouseDownCapture? | MouseEventHandler<HTMLButtonElement> | - |
onMouseEnter? | MouseEventHandler<HTMLButtonElement> | - |
onMouseLeave? | MouseEventHandler<HTMLButtonElement> | - |
onMouseMove? | MouseEventHandler<HTMLButtonElement> | - |
onMouseMoveCapture? | MouseEventHandler<HTMLButtonElement> | - |
onMouseOut? | MouseEventHandler<HTMLButtonElement> | - |
onMouseOutCapture? | MouseEventHandler<HTMLButtonElement> | - |
onMouseOver? | MouseEventHandler<HTMLButtonElement> | - |
onMouseOverCapture? | MouseEventHandler<HTMLButtonElement> | - |
onMouseUp? | MouseEventHandler<HTMLButtonElement> | - |
onMouseUpCapture? | MouseEventHandler<HTMLButtonElement> | - |
onSelect? | ReactEventHandler<HTMLButtonElement> | - |
onSelectCapture? | ReactEventHandler<HTMLButtonElement> | - |
onTouchCancel? | TouchEventHandler<HTMLButtonElement> | - |
onTouchCancelCapture? | TouchEventHandler<HTMLButtonElement> | - |
onTouchEnd? | TouchEventHandler<HTMLButtonElement> | - |
onTouchEndCapture? | TouchEventHandler<HTMLButtonElement> | - |
onTouchMove? | TouchEventHandler<HTMLButtonElement> | - |
onTouchMoveCapture? | TouchEventHandler<HTMLButtonElement> | - |
onTouchStart? | TouchEventHandler<HTMLButtonElement> | - |
onTouchStartCapture? | TouchEventHandler<HTMLButtonElement> | - |
onPointerDown? | PointerEventHandler<HTMLButtonElement> | - |
onPointerDownCapture? | PointerEventHandler<HTMLButtonElement> | - |
onPointerMove? | PointerEventHandler<HTMLButtonElement> | - |
onPointerMoveCapture? | PointerEventHandler<HTMLButtonElement> | - |
onPointerUp? | PointerEventHandler<HTMLButtonElement> | - |
onPointerUpCapture? | PointerEventHandler<HTMLButtonElement> | - |
onPointerCancel? | PointerEventHandler<HTMLButtonElement> | - |
onPointerCancelCapture? | PointerEventHandler<HTMLButtonElement> | - |
onPointerEnter? | PointerEventHandler<HTMLButtonElement> | - |
onPointerLeave? | PointerEventHandler<HTMLButtonElement> | - |
onPointerOver? | PointerEventHandler<HTMLButtonElement> | - |
onPointerOverCapture? | PointerEventHandler<HTMLButtonElement> | - |
onPointerOut? | PointerEventHandler<HTMLButtonElement> | - |
onPointerOutCapture? | PointerEventHandler<HTMLButtonElement> | - |
onGotPointerCapture? | PointerEventHandler<HTMLButtonElement> | - |
onGotPointerCaptureCapture? | PointerEventHandler<HTMLButtonElement> | - |
onLostPointerCapture? | PointerEventHandler<HTMLButtonElement> | - |
onLostPointerCaptureCapture? | PointerEventHandler<HTMLButtonElement> | - |
onScroll? | UIEventHandler<HTMLButtonElement> | - |
onScrollCapture? | UIEventHandler<HTMLButtonElement> | - |
onScrollEnd? | UIEventHandler<HTMLButtonElement> | - |
onScrollEndCapture? | UIEventHandler<HTMLButtonElement> | - |
onWheel? | WheelEventHandler<HTMLButtonElement> | - |
onWheelCapture? | WheelEventHandler<HTMLButtonElement> | - |
onAnimationStartCapture? | AnimationEventHandler<HTMLButtonElement> | - |
onAnimationEnd? | AnimationEventHandler<HTMLButtonElement> | - |
onAnimationEndCapture? | AnimationEventHandler<HTMLButtonElement> | - |
onAnimationIteration? | AnimationEventHandler<HTMLButtonElement> | - |
onAnimationIterationCapture? | AnimationEventHandler<HTMLButtonElement> | - |
onToggle? | ToggleEventHandler<HTMLButtonElement> | - |
onBeforeToggle? | ToggleEventHandler<HTMLButtonElement> | - |
onTransitionCancel? | TransitionEventHandler<HTMLButtonElement> | - |
onTransitionCancelCapture? | TransitionEventHandler<HTMLButtonElement> | - |
onTransitionEnd? | TransitionEventHandler<HTMLButtonElement> | - |
onTransitionEndCapture? | TransitionEventHandler<HTMLButtonElement> | - |
onTransitionRun? | TransitionEventHandler<HTMLButtonElement> | - |
onTransitionRunCapture? | TransitionEventHandler<HTMLButtonElement> | - |
onTransitionStart? | TransitionEventHandler<HTMLButtonElement> | - |
onTransitionStartCapture? | TransitionEventHandler<HTMLButtonElement> | - |
style? | MotionStyle | - |
children? | ReactNode | MotionValueNumber | MotionValueString | - |
initial? | boolean | TargetAndTransition | VariantLabels | - |
animate? | boolean | TargetAndTransition | VariantLabels | LegacyAnimationControls | - |
exit? | TargetAndTransition | VariantLabels | - |
variants? | Variants | - |
transition? | Transition<any> | - |
onUpdate? | ((latest: ResolvedValues) => void) | - |
onAnimationStart? | ((definition: AnimationDefinition) => void) | - |
onAnimationComplete? | ((definition: AnimationDefinition) => void) | - |
onBeforeLayoutMeasure? | ((box: Box) => void) | - |
onLayoutMeasure? | ((box: Box, prevBox: Box) => void) | - |
onLayoutAnimationStart? | (() => void) | - |
onLayoutAnimationComplete? | (() => void) | - |
onPan? | ((event: PointerEvent, info: PanInfo) => void) | - |
onPanStart? | ((event: PointerEvent, info: PanInfo) => void) | - |
onPanSessionStart? | ((event: PointerEvent, info: EventInfo) => void) | - |
onPanEnd? | ((event: PointerEvent, info: PanInfo) => void) | - |
onTap? | ((event: PointerEvent | MouseEvent | TouchEvent, info: TapInfo) => void) | - |
onTapStart? | ((event: PointerEvent | MouseEvent | TouchEvent, info: TapInfo) => void) | - |
onTapCancel? | ((event: PointerEvent | MouseEvent | TouchEvent, info: TapInfo) => void) | - |
whileTap? | TargetAndTransition | VariantLabels | - |
globalTapTarget? | boolean | - |
whileHover? | TargetAndTransition | VariantLabels | - |
onHoverStart? | ((event: MouseEvent, info: EventInfo) => void) | - |
onHoverEnd? | ((event: MouseEvent, info: EventInfo) => void) | - |
whileFocus? | TargetAndTransition | VariantLabels | - |
whileInView? | TargetAndTransition | VariantLabels | - |
onViewportEnter? | ViewportEventHandler | - |
onViewportLeave? | ViewportEventHandler | - |
viewport? | ViewportOptions | - |
onDragStart? | ((event: PointerEvent | MouseEvent | TouchEvent, info: PanInfo) => void) | - |
onDragEnd? | ((event: PointerEvent | MouseEvent | TouchEvent, info: PanInfo) => void) | - |
onDrag? | ((event: PointerEvent | MouseEvent | TouchEvent, info: PanInfo) => void) | - |
onDirectionLock? | ((axis: "x" | "y") => void) | - |
onDragTransitionEnd? | (() => void) | - |
drag? | boolean | "x" | "y" | - |
whileDrag? | TargetAndTransition | VariantLabels | - |
dragDirectionLock? | boolean | - |
dragPropagation? | boolean | - |
dragConstraints? | false | Partial<BoundingBox> | { current: Element | null; } | - |
dragElastic? | DragElastic | - |
dragMomentum? | boolean | - |
dragTransition? | InertiaOptions | - |
dragControls? | any | - |
dragSnapToOrigin? | boolean | - |
dragListener? | boolean | - |
onMeasureDragConstraints? | ((constraints: BoundingBox) => void | BoundingBox) | - |
_dragX? | MotionValue<number> | - |
_dragY? | MotionValue<number> | - |
layout? | boolean | "size" | "position" | "preserve-aspect" | - |
layoutId? | string | - |
layoutDependency? | any | - |
layoutScroll? | boolean | - |
layoutRoot? | boolean | - |
data-framer-portal-id? | string | - |
layoutCrossfade? | boolean | - |
custom? | any | - |
inherit? | boolean | - |
ignoreStrict? | boolean | - |
values? | { [key: string]: MotionValue<number> | MotionValue<string>; } | - |
transformTemplate? | TransformTemplate | - |
data-framer-appear-id? | string | - |
variant? | "solid" | "outline" | "ghost" | "link" | "soft" | "danger" | "success" | "warning" | null | - |
size? | "xs" | "sm" | "md" | "lg" | null | - |
clickEffect? | "none" | "scale" | "ripple" | "pulse" | "spring" | null | - |
hoverEffect? | "none" | "glow" | "lift" | null | - |
wide? | boolean | null | - |
rounded? | "default" | "pill" | null | - |
shadow? | "sm" | "md" | "lg" | "none" | "colored" | null | - |
asChild? | boolean | - |
state? | ButtonState | - |
loadingType? | LoadingType | - |
loadingText? | string | - |
successText? | string | - |
errorText? | string | - |
preventDoubleClick? | boolean | - |
longPress? | { duration?: number | undefined; onLongPress?: (() => void) | undefined; } | - |
tooltipWhenDisabled? | string | - |
preserveWidth? | boolean | - |
haptics? | "off" | "light" | "medium" | "heavy" | - |
sound? | "off" | "subtle" | "click" | - |
announceChanges? | boolean | - |
analytics? | { event: string; payload?: Record<string, unknown> | undefined; } | - |
onAction? | (() => void | Promise<void>) | - |
debug? | boolean | - |
forceNativeDisabled? | boolean | - |