edbnedbn/ui
Get Started
WelcomeChangelogLicenseOverview
Components
Button
Alert DialogPopoverDropdown Menu
Motion
Motion ProviderSpring PresetsHooks
Components
Blocks
HomeDocsComponentsButtons

On this page

Button

A unified button component with motion animations, loading states, and icon support. Built on Radix UI Slot with Premium spring physics.

Source Code

Copy the component source code into your project. Place this file at components/ui/button.tsx.

Installation

This will also install: motion-provider, icons

Terminal
npx shadcn@latest add https://ui.edbn.me/r/button.json

Variants

Six visual styles to match different contexts and actions.

Sizes

Multiple size options for different contexts and layouts.

With Icons

Add icons at the start or end of the button with smooth enter/exit animations.

Loading State

Built-in loading spinner with automatic button disabling.

Success State

Show a success checkmark with animation after completing an action.

Ripple Effect

Material Design-inspired ripple effect on click for enhanced visual feedback. Automatically enabled on all variants except ghost and link.

The ripple effect uses currentColor, so it automatically adapts to your button's text color. It fades smoothly during loading and success state transitions.

Icon Button

Square buttons for icon-only actions with required accessible labels.

Animation Control

Disable animations per-component or respect system reduced-motion preferences.

As Child (Composition)

Merge button styles with any child element using Radix Slot.

TypeScript
import Link from "next/link"

{/* Render as a link with button styles */}
<Button asChild>
  <Link href="/dashboard">Go to Dashboard</Link>
</Button>

{/* Use with any component */}
<Button asChild variant="ghost">
  <a href="https://github.com" target="_blank">
    View on GitHub
  </a>
</Button>

API Reference

Button Props

PropTypeDefaultDescription
variant"default" | "destructive" | "outline" | "secondary" | "ghost" | "link""default"Visual style of the button
size"sm" | "default" | "lg" | "xl" | "icon" | "icon-sm" | "icon-lg""default"Size of the button
loadingbooleanfalseShow loading spinner and disable button
successbooleanfalseShow success checkmark with animation
iconStartLucideIcon—Icon displayed at the start (left)
iconEndLucideIcon—Icon displayed at the end (right)
disableAnimationbooleanfalseDisable motion animations
asChildbooleanfalseMerge props with child element

IconButton Props

PropTypeDefaultDescription
iconLucideIconRequiredThe icon to display
aria-labelstringRequiredAccessible label for screen readers

Accessibility

Built with WCAG 2.1 guidelines. Keyboard and screen reader support included.

Keyboard

TabMove focus to button
Enter/Space
Activate button

Screen Readers

• Icon buttons require aria-label

• Loading states use aria-busy

• Spinners are aria-hidden

Best Practices

Stable dimensions
Keep button width constant across loading and success states.
Announce changes
Use a toast or live region to inform users of async results.
Restore focus
After async actions complete, return focus to the triggering element.

Motion Preferences

Respects prefers-reduced-motion. Override with disableAnimation prop or MotionProvider.