HextaUI

Input group: Loading

Inline addons ease to their new width when their content changes, so the field never jumps as a spinner turns into a result count. The spinner only turns when motion is allowed, and role="status" announces the text.

5 packages
"use client"

import * as React from "react"
import { IconLoader2, IconSearch } from "@tabler/icons-react"

import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput,
  InputGroupText,
} from "@/components/ui/input-group"

const packages = ["react", "react-dom", "react-hook-form", "redux", "remix"]

export function InputGroupLoading() {
  const [query, setQuery] = React.useState("re")
  const [pending, setPending] = React.useState(false)
  const timer = React.useRef<ReturnType<typeof setTimeout>>(undefined)
  const results = packages.filter((name) => name.includes(query.trim()))

  React.useEffect(() => () => clearTimeout(timer.current), [])

  return (
    <InputGroup className="max-w-sm">
      <InputGroupInput
        value={query}
        onChange={(event) => {
          setQuery(event.target.value)
          setPending(true)
          clearTimeout(timer.current)
          timer.current = setTimeout(() => setPending(false), 600)
        }}
        aria-label="Search packages"
        aria-busy={pending}
      />
      <InputGroupAddon>
        <IconSearch />
      </InputGroupAddon>
      <InputGroupAddon align="inline-end">
        <InputGroupText role="status">
          {pending ? (
            <>
              <IconLoader2 className="motion-safe:animate-spin" aria-hidden />
              Searching
            </>
          ) : results.length === 1 ? (
            "1 package"
          ) : (
            `${results.length} packages`
          )}
        </InputGroupText>
      </InputGroupAddon>
    </InputGroup>
  )
}

This adds the example as components/examples/input-group/loading.tsx, together with the Input group component and the HextaUI theme tokens it needs.

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

To add only the component, follow the Input group installation.

Props in this example

The Input group props this example sets, from the API reference.

PropTypeDefault
align
"inline-start" | "inline-end" | "block-start" | "block-end""inline-start"

Every prop is in the Input group API reference.

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