Button
A versatile button component with multiple variants, states, and sizes
Button
A versatile button component that supports various styles, states, and interactive features. Button is built with accessibility in mind and provides consistent interaction patterns across all variants.
Each button can be customized with different variants, colors, and sizes, making it adaptable to any UI context. All buttons include proper focus states, loading indicators, and keyboard interactions.
Basic Variants
Button comes in three basic variants that serve different UI purposes:
Primary
The default button style with a solid background. Use for primary actions and main call-to-actions.
Light
Dark
Outline
Button with transparent background and visible border. Ideal for secondary actions that don't require as much visual emphasis.
Light
Dark
Ghost
Button with no background or border until interacted with. Perfect for tertiary actions or when space is limited.
Light
Dark
Color Variants
Each button variant can be combined with different color schemes to convey the nature of the action:
Danger - Primary
Solid background danger variant for destructive actions that should be clearly highlighted.
Light
Dark
Danger - Outline
Danger variant with outline style. Use for destructive actions that require less visual prominence.
Light
Dark
Danger - Ghost
Minimal danger variant. Suitable for destructive actions in tight UI spaces or alongside other content.
Light
Dark
Warning - Primary
Warning variant with solid background for actions that require caution but aren't destructive.
Light
Dark
Warning - Outline
Warning variant with outline style for secondary cautionary actions.
Light
Dark
Warning - Ghost
Warning variant with ghost style for tertiary cautionary actions.
Light
Dark
Success - Primary
Success variant with solid background for positive or confirming actions.
Light
Dark
Success - Outline
Success variant with outline style for secondary positive actions.
Light
Dark
Success - Ghost
Success variant with ghost style for subtle positive actions.
Light
Dark
Size Variants
All button variants and color schemes can be combined with different sizes to fit various UI contexts.
Light
Dark
Special Features
Button includes additional features that enhance usability and interaction:
With Icons
Buttons can include icons from the Lucide library for enhanced visual meaning. Icons can be placed before or after text.
Light
Dark
With Keyboard Shortcuts
Buttons can display and respond to keyboard shortcuts for improved accessibility and power-user workflows.
Press ⌘B to increment the counter
Additional Features
The Button component includes some additional features not shown in the examples above:
Legacy Variant Support
For backward compatibility, the component supports legacy variants:
default
will be mapped toprimary
variantdestructive
will be mapped toprimary
variant withdanger
color
Shape Variants
For special layouts, buttons can use the shape
prop:
Light
Dark
Props
The Button component accepts all standard HTML button attributes plus the following:
Prop | Type | Default |
---|---|---|
variant | "default" | "destructive" | "primary" | "outline" | "ghost" | - |
shape | "square" | - |
color | "default" | "success" | "warning" | "danger" | - |
size | "icon" | "sm" | "md" | "lg" | "xlg" | "2xlg" | - |
disabled | boolean | - |
form | string | - |
formAction | string | - |
formEncType | string | - |
formMethod | string | - |
formNoValidate | boolean | - |
formTarget | string | - |
name | string | - |
type | "submit" | "reset" | "button" | - |
value | string | number | readonly string[] | - |
defaultChecked | boolean | - |
defaultValue | string | number | readonly string[] | - |
suppressContentEditableWarning | boolean | - |
suppressHydrationWarning | boolean | - |
accessKey | string | - |
autoCapitalize | "off" | "none" | "on" | "sentences" | "words" | "characters" | (string & {}) | - |
autoFocus | boolean | - |
className | string | - |
contentEditable | Booleanish | "inherit" | "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 | - |
style | CSSProperties | - |
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 | - |
itemProp | string | - |
itemScope | boolean | - |
itemType | string | - |
itemID | string | - |
itemRef | string | - |
results | number | - |
security | string | - |
unselectable | "off" | "on" | - |
inputMode | "none" | "search" | "text" | "tel" | "url" | "email" | "numeric" | "decimal" | - |
is | 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 | "none" | "link" | "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 | - |
children | ReactNode | - |
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 | FormEventHandler<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> | - |
onResize | ReactEventHandler<HTMLButtonElement> | - |
onResizeCapture | 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> | - |
onDrag | DragEventHandler<HTMLButtonElement> | - |
onDragCapture | DragEventHandler<HTMLButtonElement> | - |
onDragEnd | 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> | - |
onDragStart | 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> | - |
onWheel | WheelEventHandler<HTMLButtonElement> | - |
onWheelCapture | WheelEventHandler<HTMLButtonElement> | - |
onAnimationStart | AnimationEventHandler<HTMLButtonElement> | - |
onAnimationStartCapture | AnimationEventHandler<HTMLButtonElement> | - |
onAnimationEnd | AnimationEventHandler<HTMLButtonElement> | - |
onAnimationEndCapture | AnimationEventHandler<HTMLButtonElement> | - |
onAnimationIteration | AnimationEventHandler<HTMLButtonElement> | - |
onAnimationIterationCapture | AnimationEventHandler<HTMLButtonElement> | - |
onTransitionEnd | TransitionEventHandler<HTMLButtonElement> | - |
onTransitionEndCapture | TransitionEventHandler<HTMLButtonElement> | - |
loading | boolean | - |
keyboard | { display: string; trigger: (e: KeyboardEvent) => boolean; callback: (e: KeyboardEvent) => void | Promise<void>; } | - |
asChild | boolean | - |
loadingLabel | string | - |
Usage Guidelines
When using the Button component:
- Hierarchy: Maintain a clear visual hierarchy with your button choices
- Use primary buttons for main actions and primary call-to-actions
- Use outline buttons for secondary actions
- Use ghost buttons for tertiary actions or in dense UIs
- Color semantics: Apply color variants based on the action's impact:
- Default for neutral or standard actions
- Success for positive, confirming, or creative actions
- Warning for cautionary actions that require attention
- Danger for destructive or irreversible actions
- Interaction states:
- Ensure loading state is shown during asynchronous operations to prevent multiple submissions
- Use disabled state appropriately for actions that are currently unavailable
- Test that focus states are clearly visible for keyboard navigation
- Sizing and spacing:
- Use appropriate size based on the button's importance and the available space
- Maintain consistent spacing between buttons in a group (recommend 16px/1rem)
- For button groups, maintain consistent sizing within the group
- Content guidelines:
- Use concise, action-oriented text (e.g., "Save changes" instead of "Submit")
- Add icons to enhance meaning, but avoid overloading buttons with too many elements
- For destructive actions, consider using explicit verbs ("Delete" instead of "Remove")
- Accessibility:
- Consider adding keyboard shortcuts for frequently used actions
- Ensure sufficient color contrast between text and background (WCAG AA minimum)
- Add appropriate aria attributes for complex button behaviors
- Responsive behavior:
- On mobile, ensure buttons are at least 44×44px (touch target size)
- Consider stacking buttons vertically on very small screens