HextaUI

Button: Controlled loading

Set loading yourself when the work is tracked elsewhere. The button stays focusable and announces that it is busy.

"use client"

import * as React from "react"
import { IconSend } from "@tabler/icons-react"

import { Button } from "@/components/ui/button"

export function ButtonControlledLoading() {
  const [loading, setLoading] = React.useState(false)

  return (
    <div className="flex flex-wrap items-center justify-center gap-2">
      <Button loading={loading} onClick={() => setLoading(true)}>
        <IconSend data-icon="inline-start" />
        Send invite
      </Button>
      <Button variant="ghost" onClick={() => setLoading(false)}>
        Stop loading
      </Button>
    </div>
  )
}

This adds the example as components/examples/button/controlled-loading.tsx, together with the Button component and the HextaUI theme tokens it needs.

pnpm dlx shadcn@latest add https://hextaui.com/r/button-controlled-loading.json

To add only the component, follow the Button installation.

Props in this example

The Button props this example sets, from the API reference.

PropTypeDefault
variant
"default" | "outline" | "secondary" | "ghost" | "ghost-destructive" | "destructive" | "link""default"
onClickReturn a promise to drive feedback.
(event) => unknown–
loadingControlled loading state.
boolean–

Every prop is in the Button API reference.

See them all, with keyboard support and accessibility notes, on the Button page.