Skip to content
WingoUI
ComponentsTemplatesDocsPricingAI agentsBlogChangelogContact
Components
Buttons & Actions
ButtonButton GroupCopy ButtonDelete ButtonTheme ToggleToggleToggle Group
Inputs
Avatar UploadCalendarCheckboxColor PickerComboboxCountry SelectCron PickerCurrency InputDate PickerDate Range PickerDate Time PickerDuration PickerEmail InputEmoji PickerFile UploadFilter BuilderInputInput GroupListboxMasked InputMention InputMonth PickerMulti SelectNumber InputOTP InputPassword InputPhone InputRadio GroupRatingSearch InputSegmented ControlSelectSignature PadSliderSwitchTag InputTextareaTime PickerTimezone SelectTree Select
Forms
Address InputBooking WidgetCSV ImportFieldForm WizardInline EditInvoice line itemsRich Text EditorSchema Builder
Navigation
Back To TopBounce SidebarBreadcrumbCommand MenuGlobal SearchGooey NavHook SidebarNav MenuNav TabsPaginationProximity SidebarScroll ProgressSidebarStepsTable Of ContentsTabsTopbarUser MenuWorkspace Switcher
Overlays
Alert DialogContext MenuDialogDrawerDropdown MenuFamily DrawerHover CardPopoverShare DialogSheetShortcuts DialogTooltipTour
Feedback
AlertBannerCookie ConsentEmoji ReactionEmpty StateNotification BellNotification CenterProgressRoute ProgressSetup ChecklistSkeletonSpinnerToast
Data Display
Approval FlowAvatarBadgeCalendar ViewCode BlockComment ThreadContact cardCountdownDescription ListDiff ViewerFile ListFile managerFolderGanttJSON ViewerKbdLog ViewerMarkdownPresenceSchedulerTagTimelineTree View
Tables & Lists
Audit LogData TableDeal PipelineEditable GridKanbanListMembers tablePermissions MatrixTableTask ListVirtual List
Charts & Stats
Animated CounterArea chartBar chartDonut chartFunnel chartGaugeGitHub ActivityHeatmap calendarLeaderboardLine chartRadar chartRadial barSparklineStat CardTrackerTrend badge
Layout
AccordionApp ShellCardCollapsibleDetail LayoutEntity HeaderPage HeaderScroll AreaSeparatorSettings LayoutSplit ViewToolbar
Media
Audio PlayerCarouselCSV ViewerDOCX EditorDOCX ViewerExcel ViewerFile SystemImage compareImage CropperImage GalleryImage LightboxLocation MapPDF ViewerPowerPoint ViewerQR CodeStep PlayerVideo Player
AI Kit
Agent Status CardChat MessageChat ThreadChat WidgetConversation ListFluid OrbGrid RevealMatrix OrbModel PickerPrompt InputReasoning IndicatorRule BuilderSuggestion ChipsTool Call TimelineUsage MeterVoice InputWorkflow Canvas
Text & Effects
Background PatternGravity LettersMarqueeTerminalText AnimateText Rotate
Mobile
Action SheetBottom Tab BarFABHaptic ButtonHero HeaderInstall PromptLarge Title HeaderNotification BannerOnboarding CarouselPicker WheelPull To RefreshSlide To ConfirmSticky CTA BarSwipe DeckSwipeable Tabs
Commerce
Cart drawerCategory pickerCheckout stepsCoupon inputFavorite buttonFilter panelListing cardListing gridOrder trackerPricePrice rangePricing tableProduct galleryQuantity stepperReviewsSeller card
Marketing Sections
App Download SectionBlog Cards SectionCTA SectionFAQ SectionFeature GridFeature ShowcaseHero SectionIntegrations SectionLogo CloudMarketing FooterMarketing HeaderMarketing SectionNewsletter SectionPricing SectionStats SectionSteps SectionTeam SectionTestimonials SectionTimeline SectionVideo Section
Blocks
Admin Dashboard PageAdmin ShellAI Chat PageAPI Keys PageAutomation Builder PageCheckout PageCRM Contact PageCRM Pipeline PageError PagesInbox PageInvoice PageKPI DashboardListing Detail PageLogin PageMarketplace Home PageMarketplace Search PageMarketplace ShellMobile App HomeOnboarding FlowOrder History PagePost Listing WizardPricing PageProfile PageRegister PageSettings PageUsers Admin Page
Templates
About PageAcademy PageAccessibility PageAffiliate PageAgency PageAI Product PageAppointment Booking PageBlog PageBlog Post PageBug Bounty PageCareers PageChangelog PageCommunity PageCompare PageContact PageCustomer Story PageCustomers PageDemo Booking PageDevelopers PageDocs Home PageDownload PageEnterprise PageEvents PageExperts PageFAQ PageFeature PageGlossary PageHelp Article PageHelp Center PageHome Services PageImpact PageIntegration Detail PageIntegrations PageJob Detail PageLanding PageLaunch PageLegal PageManifesto PagePortfolio PagePress PageProduct Tour PagePromo PageReal Estate PageReferral PageResearch Report PageRestaurant PageRoadmap PageROI Calculator PageSecurity PageSolutions PageStartups PageStatus PageStorefront PageSwitch PageTemplate Gallery PageTravel PageWaitlist PageYear in Review Page
Hooks & Utilities
AI ChatChart kitCommerceDate utilsFile exportFile typesFiltersForm validationHapticsInvoicingMotion presetsNavigationNumber formatRelative timeRomanian locationsSpreadsheetText matchTonesUIProvideruseClipboarduseConsentuseControllableStateuseCooldownuseDebounceuseKeyboardInsetuseLocaleuseLongPressuseMediaControlsuseMediaQueryuseOverflowItemsusePersistedStateuseScrollEdgesuseScrollStateuseSelectionuseShortcutuseStickToBottom
GalleryTheme

Buttons & Actions

Button

Buttons & Actions

Button React component for Tailwind CSS v4

useStickToBottomButton Group
Live props
Content
children
Appearance
variant
tone
size
radius
color
State
loading
loadingText
disabled
Layout
fullWidth
Behavior
asChild
type
Code
import { Button } from "@/components/ui/button"

<Button>Continue</Button>
  1. Home
  2. Components
  3. Buttons & Actions
  4. Button
Free

Button React component for Tailwind CSS v4

v1.0.0·Added in 1.0.0

The React button component every screen starts with: five variants, six tones, all sizes, and a loading state that never jumps.

Press it and it dips on a quick spring, then settles back; with a mouse the surface tints on hover. Tab to it for a focus ring that never touches the edge. Tap the playground button to see it load: the spinner takes the label's place and the width holds still. On a phone the medium size grows to 44px so it is easy to hit.

Button is a free React component in the React button components category, written in TypeScript for React 19 and Tailwind CSS v4. It installs as source with npx wingo-ui@latest add button, together with Motion presets, Tones and UIProvider and the npm packages @radix-ui/react-slot and motion.

Add to a project

Requirements: React 19 and Tailwind CSS v4, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup

npx wingo-ui@latest add button

Usage

Import Button from @/components/ui/button.

import { ArrowRight } from "lucide-react"
import { Button } from "@/components/ui/button"

export function CheckoutActions({ paying, onPay }: { paying: boolean; onPay: () => void }) {
  return (
    <div className="flex gap-2">
      <Button variant="ghost">Cancel</Button>
      <Button tone="brand" loading={paying} loadingText="Paying" rightIcon={<ArrowRight />} onClick={onPay}>
        Pay now
      </Button>
    </div>
  )
}

Props

  • childrendefault "Continue"
    ReactNode

    The label. For icon sizes pass the icon itself and an aria-label.

  • variantdefault "solid"
    "solid" | "soft" | "outline" | "ghost" | "link"

    solid for the one main action on a screen, soft or outline for secondary actions, ghost for toolbars and dense rows, link for actions inside text (always underlined, so it reads as a link without color or hover).

  • tonedefault "neutral"
    "neutral" | "brand" | "success" | "warning" | "danger" | "info"

    Semantic color from the design tokens. neutral is black in light mode and white in dark mode; danger is for destructive actions.

  • sizedefault "md"
    "sm" | "md" | "lg" | "icon-sm" | "icon" | "icon-lg"

    Height 32 / 40 / 48px with matching padding, type and icon size. The icon sizes are square. On touch screens md grows to 44px and sm keeps its look with a 44px hit area.

  • radiusdefault "md"
    "none" | "sm" | "md" | "lg" | "full"

    Corner shape. Scales with the size (md is 8 / 10 / 12px) so every size reads as the same shape; full makes a pill.

  • colordefault ""
    string

    Any CSS color. Replaces the tone in every variant; text on a solid fill turns black or white by lightness. Leave empty to use the tone.

  • loadingdefault false
    boolean

    Shows a spinner in place of the label, keeps the width, sets aria-busy and ignores clicks. The button stays focusable, so keyboard focus is not lost.

  • loadingTextdefault ""
    ReactNode

    Text next to the spinner while loading, like "Saving". The button reserves room for it, so it never changes width.

  • disableddefault false
    boolean

    Dims the button and blocks it. With asChild the link gets aria-disabled and leaves the tab order.

  • fullWidthdefault false
    boolean

    Stretches to the container width. The usual choice for the main action at the bottom of a phone screen.

  • asChilddefault false
    boolean

    Renders your single child (an <a>, a router Link) with the button's look, press and icons, instead of a <button>. The demo swaps in a link.

  • leftIcon
    ReactNode

    An icon before the label. Unsized svgs follow the button size (14 / 16 / 18px).

  • rightIcon
    ReactNode

    An icon after the label, like an arrow or a chevron.

  • spinner
    ReactNode

    Replaces the default spinner.

  • typedefault "button"
    "button" | "submit" | "reset"

    Defaults to "button" so a button inside a form never submits by accident. Set "submit" for the form's main action.

  • onClick
    (event: MouseEvent<HTMLButtonElement>) => void

    Not called while loading or disabled.

  • classNames
    Partial<Record<"content" | "icon" | "spinner", string>>

    Extra classes for the inner parts: the label wrapper, each icon wrapper, the spinner.

  • className
    string

    Extra classes for the button itself, merged last. Override the tone vars here, e.g. [--tone-foreground:white].

Examples

Variants and tones

Five variants across the six tones, all driven by the design tokens.

Sizes

32, 40 and 48px, plus square icon sizes. Unsized icons follow along.

Loading

The spinner takes the label's place and the width holds. loadingText gets room reserved up front.

Icon buttons

Always with an aria-label. aria-pressed turns one into a toggle.

As a link

asChild renders your <a> or router Link with the button's look and press.

Custom color

Any CSS color. Text on the fill turns black or white on its own; soft and outline mix it for contrast.

Radius

none to full; each step scales with the size.

Checkout on a phone

fullWidth, lg, and a price formatted in dollars.

Dependencies

@radix-ui/react-slotmotionmotiontonesui-config

Files

  • components/ui/button.tsx

FAQ

Is the React Button component free?

Yes. The source is free and needs no account: copy it from the Code tab or install it with the CLI.

How do I install Button?

Run npx wingo-ui@latest add button. It also adds the Wingo UI items it builds on (Motion presets, Tones and UIProvider) and the npm packages @radix-ui/react-slot and motion. With shadcn, run npx shadcn@latest add https://wingo-ui.com/r/button.json.

How does Button behave on phones?

On a phone the medium size grows to 44px so it is easy to hit.

See also

Button GroupCopy ButtonDelete ButtonHaptic ButtonToneslibMotion presetslib

Used in

QR CodeCarouselAvatar UploadPowerPoint ViewerHero HeaderColor PickerOnboarding FlowProduct galleryCalendarImage LightboxVideo PlayerLogin Page

and 212 more.

More React button components

Theme ToggleToggle GroupToggle
All 7 React button components

Articles using this component

  • Antigravity MCP Setup: The Right Config Path and Prompts

    Building UI with AI agents · Nov 6, 2026 · 10 min read

  • Codex Frontend Design Skill: Pair It With Real Components

    Building UI with AI agents · Nov 6, 2026 · 10 min read

  • Is shadcn Free for Commercial Use? MIT vs Paid Kits

    Comparisons and alternatives · Nov 6, 2026 · 10 min read

  • OpenCode MCP Setup: opencode.json for v1 and v2

    Building UI with AI agents · Nov 6, 2026 · 11 min read

PrevioususeStickToBottomNext Button Group

Click it to watch the loading state keep its width