HextaUI

Input group

Un input con iconos, texto, botones o una pista de teclado acoplados, que comparten un solo borde y anillo de foco.

"use client"

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

import {
  InputGroup,
  InputGroupAddon,
  InputGroupButton,
  InputGroupClear,
  InputGroupCount,
  InputGroupInput,
  InputGroupPasswordToggle,
  InputGroupTextarea,
} from "@/components/ui/input-group"

export function InputGroupDemo() {
  const [message, setMessage] = React.useState("")

  return (
    <div className="flex w-full max-w-sm flex-col gap-4">
      <InputGroup>
        <InputGroupInput
          type="search"
          defaultValue="Accordion"
          placeholder="Search components"
          aria-label="Search components"
        />
        <InputGroupAddon>
          <IconSearch />
        </InputGroupAddon>
        <InputGroupAddon align="inline-end">
          <InputGroupClear />
        </InputGroupAddon>
      </InputGroup>
      <InputGroup>
        <InputGroupInput
          type="password"
          defaultValue="hunter2-but-longer"
          autoComplete="current-password"
          aria-label="Password"
        />
        <InputGroupAddon>
          <IconLock />
        </InputGroupAddon>
        <InputGroupAddon align="inline-end">
          <InputGroupPasswordToggle />
        </InputGroupAddon>
      </InputGroup>
      <InputGroup>
        <InputGroupTextarea
          value={message}
          onChange={(event) => setMessage(event.target.value)}
          maxLength={140}
          placeholder="Leave a note for the team"
          aria-label="Note"
        />
        <InputGroupAddon align="block-end">
          <InputGroupCount />
          <InputGroupButton
            variant="default"
            size="icon-xs"
            aria-label="Post note"
            disabled={!message.trim()}
            className="ms-auto"
          >
            <IconArrowUp />
          </InputGroupButton>
        </InputGroupAddon>
      </InputGroup>
    </div>
  )
}
pnpm dlx shadcn@latest add https://hextaui.com/r/input-group.json

Añade el componente, los tokens del tema de HextaUI y los componentes de HextaUI de los que depende.

import {
  InputGroup,
  InputGroupAddon,
  InputGroupButton,
  InputGroupClear,
  InputGroupCount,
  InputGroupInput,
  InputGroupPasswordToggle,
  InputGroupText,
  InputGroupTextarea,
} from "@/components/ui/input-group"
<InputGroup>
  <InputGroupInput placeholder="Search…" aria-label="Search" />
  <InputGroupAddon>
    <IconSearch />
  </InputGroupAddon>
  <InputGroupAddon align="inline-end">
    <InputGroupClear />
  </InputGroupAddon>
</InputGroup>

Pon <InputGroupInput /> o <InputGroupTextarea /> primero y los addons después. Los addons se colocan solos con align, así que el campo va primero en el orden de tabulación y para los lectores de pantalla.

El grupo sigue a su campo, así que las partes inteligentes no necesitan conexión. <InputGroupClear />, <InputGroupPasswordToggle /> y <InputGroupCount /> leen el valor, type y maxLength del campo, sea controlado o no.

InputGroup
├── InputGroupAddon
│   ├── InputGroupText
│   ├── InputGroupButton
│   ├── InputGroupClear
│   ├── InputGroupCount
│   └── InputGroupPasswordToggle
└── InputGroupInput / InputGroupTextarea

Icono

Los iconos van dentro del borde a ambos lados. Hacer clic en un icono da foco al input, así que todo el grupo se siente como un solo campo.

import { IconCheck, IconMail, IconSearch } from "@tabler/icons-react"

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

export function InputGroupIcon() {
  return (
    <div className="flex w-full max-w-sm flex-col gap-4">
      <InputGroup>
        <InputGroupInput placeholder="Search…" aria-label="Search" />
        <InputGroupAddon>
          <IconSearch />
        </InputGroupAddon>
      </InputGroup>
      <InputGroup>
        <InputGroupInput
          type="email"
          defaultValue="[email protected]"
          aria-label="Email"
        />
        <InputGroupAddon>
          <IconMail />
        </InputGroupAddon>
        <InputGroupAddon align="inline-end">
          <IconCheck className="text-success" aria-label="Verified" />
        </InputGroupAddon>
      </InputGroup>
    </div>
  )
}

Borrar

<InputGroupClear /> aparece con un fundido cuando hay un valor. Borra a través del historial de edición del navegador, así que Cmd+Z devuelve el texto, y dispara tu onChange. Escape también borra. Un segundo Escape se deja para el diálogo o popover que lo rodea.

"use client"

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

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

const fruits = ["Apple", "Apricot", "Banana", "Blackberry", "Cherry", "Fig"]

export function InputGroupClearDemo() {
  const [query, setQuery] = React.useState("ap")
  const matches = fruits.filter((fruit) =>
    fruit.toLowerCase().includes(query.trim().toLowerCase())
  )

  return (
    <div className="flex w-full max-w-sm flex-col gap-3">
      <InputGroup>
        <InputGroupInput
          type="search"
          value={query}
          onChange={(event) => setQuery(event.target.value)}
          placeholder="Filter fruit"
          aria-label="Filter fruit"
        />
        <InputGroupAddon>
          <IconSearch />
        </InputGroupAddon>
        <InputGroupAddon align="inline-end">
          <InputGroupClear />
        </InputGroupAddon>
      </InputGroup>
      <p className="text-sm text-muted-foreground">
        {matches.length > 0 ? matches.join(", ") : "No fruit matches."}
      </p>
    </div>
  )
}

Contador de caracteres

<InputGroupCount /> cuenta respecto al maxLength del campo. Solo ruedan los dígitos que cambian. El recuento se oscurece cerca del límite y se vuelve rojo al alcanzarlo, y una tecla pulsada más allá del límite lo sacude ligeramente. Los lectores de pantalla oyen un mensaje cuando el campo se acerca al límite y cuando lo alcanza, nunca en cada tecla.

import { IconAt } from "@tabler/icons-react"

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

export function InputGroupCountDemo() {
  return (
    <InputGroup className="max-w-sm">
      <InputGroupInput
        defaultValue="hextaui"
        maxLength={15}
        autoComplete="username"
        aria-label="Username"
      />
      <InputGroupAddon>
        <IconAt />
      </InputGroupAddon>
      <InputGroupAddon align="inline-end">
        <InputGroupCount />
      </InputGroupAddon>
    </InputGroup>
  )
}

Texto

Usa <InputGroupText /> para unidades, monedas y partes de URL. El relleno del input se reduce junto a un addon para que el texto se lea como un solo valor.

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

export function InputGroupTextDemo() {
  return (
    <div className="flex w-full max-w-sm flex-col gap-4">
      <InputGroup>
        <InputGroupInput
          placeholder="0.00"
          inputMode="decimal"
          aria-label="Price"
        />
        <InputGroupAddon>
          <InputGroupText>$</InputGroupText>
        </InputGroupAddon>
        <InputGroupAddon align="inline-end">
          <InputGroupText>USD</InputGroupText>
        </InputGroupAddon>
      </InputGroup>
      <InputGroup>
        <InputGroupInput placeholder="hextaui" aria-label="Domain" />
        <InputGroupAddon>
          <InputGroupText>https://</InputGroupText>
        </InputGroupAddon>
        <InputGroupAddon align="inline-end">
          <InputGroupText>.com</InputGroupText>
        </InputGroupAddon>
      </InputGroup>
    </div>
  )
}

Button

<InputGroupButton /> es un botón ghost dimensionado para caber dentro del campo. Sus esquinas son concéntricas con las del grupo y tiene su propio anillo de foco.

"use client"

import * as React from "react"
import { IconCheck, IconCopy, IconX } from "@tabler/icons-react"

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

export function InputGroupButtonDemo() {
  const [copied, setCopied] = React.useState(false)
  const [query, setQuery] = React.useState("button group")

  return (
    <div className="flex w-full max-w-sm flex-col gap-4">
      <InputGroup>
        <InputGroupInput
          readOnly
          defaultValue="https://hextaui.com/docs/input-group"
          aria-label="Share link"
        />
        <InputGroupAddon align="inline-end">
          <InputGroupButton
            size="icon-xs"
            aria-label={copied ? "Copied" : "Copy link"}
            onClick={async () => {
              await navigator.clipboard
                ?.writeText("https://hextaui.com/docs/input-group")
                .catch(() => {})
              setCopied(true)
              setTimeout(() => setCopied(false), 1500)
            }}
          >
            {copied ? <IconCheck /> : <IconCopy />}
          </InputGroupButton>
        </InputGroupAddon>
      </InputGroup>
      <InputGroup>
        <InputGroupInput
          value={query}
          onChange={(event) => setQuery(event.target.value)}
          placeholder="Search components…"
          aria-label="Search components"
        />
        <InputGroupAddon align="inline-end">
          {query ? (
            <InputGroupButton
              size="icon-xs"
              aria-label="Clear search"
              onClick={() => setQuery("")}
            >
              <IconX />
            </InputGroupButton>
          ) : null}
          <InputGroupButton variant="secondary">Search</InputGroupButton>
        </InputGroupAddon>
      </InputGroup>
    </div>
  )
}

Pista de teclado

Un <kbd> simple dentro de un addon recibe estilo de tecla. Es solo una pista visual, así que enlaza el atajo tú mismo.

import { IconSearch } from "@tabler/icons-react"

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

export function InputGroupKbd() {
  return (
    <div className="flex w-full max-w-sm flex-col gap-4">
      <InputGroup>
        <InputGroupInput placeholder="Search docs…" aria-label="Search docs" />
        <InputGroupAddon>
          <IconSearch />
        </InputGroupAddon>
        <InputGroupAddon align="inline-end">
          <kbd>⌘</kbd>
          <kbd>K</kbd>
        </InputGroupAddon>
      </InputGroup>
      <InputGroup>
        <InputGroupInput
          placeholder="Jump to file…"
          aria-label="Jump to file"
        />
        <InputGroupAddon align="inline-end">
          <kbd>/</kbd>
        </InputGroupAddon>
      </InputGroup>
    </div>
  )
}

Textarea

<InputGroupTextarea /> crece con su contenido hasta 16rem y luego se desplaza. La altura se ajusta suavemente entre líneas en lugar de saltar. Un addon block-end se convierte en una barra de herramientas debajo, y los botones en sus bordes reciben el mismo margen interior que la esquina en que se sitúan.

"use client"

import * as React from "react"
import { IconArrowUp, IconPaperclip } from "@tabler/icons-react"

import {
  InputGroup,
  InputGroupAddon,
  InputGroupButton,
  InputGroupCount,
  InputGroupTextarea,
} from "@/components/ui/input-group"

export function InputGroupTextareaDemo() {
  const [value, setValue] = React.useState("")

  return (
    <InputGroup className="max-w-sm">
      <InputGroupTextarea
        value={value}
        onChange={(event) => setValue(event.target.value)}
        maxLength={280}
        placeholder="Write a reply…"
        aria-label="Reply"
      />
      <InputGroupAddon align="block-end">
        <InputGroupButton size="icon-xs" aria-label="Attach a file">
          <IconPaperclip />
        </InputGroupButton>
        <InputGroupCount className="ms-auto" />
        <InputGroupButton
          variant="default"
          size="icon-xs"
          aria-label="Send"
          disabled={!value.trim()}
        >
          <IconArrowUp />
        </InputGroupButton>
      </InputGroupAddon>
    </InputGroup>
  )
}

Un addon block-start se sitúa sobre el campo. Añade separator para dibujar una línea fina entre ambos.

import { IconCopy, IconFileCode } from "@tabler/icons-react"

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

export function InputGroupBlockStart() {
  return (
    <InputGroup className="max-w-sm">
      <InputGroupTextarea
        defaultValue={'console.log("Hello from HextaUI")'}
        aria-label="script.js"
      />
      <InputGroupAddon align="block-start" separator>
        <InputGroupText>
          <IconFileCode />
          script.js
        </InputGroupText>
        <InputGroupButton size="icon-xs" aria-label="Copy" className="ms-auto">
          <IconCopy />
        </InputGroupButton>
      </InputGroupAddon>
    </InputGroup>
  )
}

Contraseña

<InputGroupPasswordToggle /> cambia un campo type="password" a texto y viceversa. El cursor y la selección se quedan donde estaban, un clic del ratón mantiene el foco en el campo, y la contraseña vuelve a ocultarse al enviar el formulario. Contrólalo con revealed.

import { IconLock } from "@tabler/icons-react"

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

export function InputGroupPassword() {
  return (
    <InputGroup className="max-w-sm">
      <InputGroupInput
        type="password"
        defaultValue="correct horse battery staple"
        autoComplete="current-password"
        aria-label="Password"
      />
      <InputGroupAddon>
        <IconLock />
      </InputGroupAddon>
      <InputGroupAddon align="inline-end">
        <InputGroupPasswordToggle />
      </InputGroupAddon>
    </InputGroup>
  )
}

Tamaños

size en el grupo define la altura y se pasa al input, coincidiendo con los tamaños de <Input />. Los botones conservan esquinas concéntricas en todos los tamaños.

import { IconSearch } from "@tabler/icons-react"

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

export function InputGroupSizes() {
  return (
    <div className="flex w-full max-w-sm flex-col gap-4">
      {(["sm", "default", "lg"] as const).map((size) => (
        <InputGroup key={size} size={size}>
          <InputGroupInput
            placeholder={`Size ${size}`}
            aria-label={`Size ${size}`}
          />
          <InputGroupAddon>
            <IconSearch />
          </InputGroupAddon>
          <InputGroupAddon align="inline-end">
            <InputGroupButton>Go</InputGroupButton>
          </InputGroupAddon>
        </InputGroup>
      ))}
    </div>
  )
}

Inválido

Define aria-invalid en el input y todo el grupo se vuelve rojo, incluido su anillo de foco. Vincula el mensaje con aria-describedby.

import { IconAt, IconAlertCircle } from "@tabler/icons-react"

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

export function InputGroupInvalid() {
  return (
    <div className="flex w-full max-w-sm flex-col gap-2">
      <InputGroup>
        <InputGroupInput
          defaultValue="preet@"
          aria-label="Email"
          aria-invalid
          aria-describedby="email-error"
        />
        <InputGroupAddon>
          <IconAt />
        </InputGroupAddon>
        <InputGroupAddon align="inline-end">
          <IconAlertCircle className="text-destructive" aria-hidden />
        </InputGroupAddon>
      </InputGroup>
      <p id="email-error" className="text-sm text-destructive">
        Enter a complete email address.
      </p>
    </div>
  )
}

Deshabilitado

Un input deshabilitado atenúa todo el grupo y muestra un cursor de no permitido sobre él. Deshabilita también los botones de los addons, ya que de otro modo siguen siendo utilizables.

import { IconLink } from "@tabler/icons-react"

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

export function InputGroupDisabled() {
  return (
    <InputGroup className="max-w-sm">
      <InputGroupInput
        disabled
        defaultValue="https://hextaui.com"
        aria-label="Link"
      />
      <InputGroupAddon>
        <IconLink />
      </InputGroupAddon>
      <InputGroupAddon align="inline-end">
        <InputGroupButton disabled>Copy</InputGroupButton>
      </InputGroupAddon>
    </InputGroup>
  )
}

Cargando

Los addons en línea se ajustan suavemente a su nuevo ancho cuando cambia su contenido, así que el campo nunca salta cuando un spinner se convierte en un recuento de resultados. El spinner solo gira cuando se permite el movimiento, y role="status" anuncia el texto.

"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>
  )
}

Renderiza un <InputGroupButton /> como trigger de un dropdown para acotar el input.

import { IconChevronDown } from "@tabler/icons-react"

import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import {
  InputGroup,
  InputGroupAddon,
  InputGroupButton,
  InputGroupInput,
} from "@/components/ui/input-group"

export function InputGroupDropdown() {
  return (
    <InputGroup className="max-w-sm">
      <InputGroupInput placeholder="Enter a search term" aria-label="Search" />
      <InputGroupAddon align="inline-end">
        <DropdownMenu>
          <DropdownMenuTrigger render={<InputGroupButton />}>
            Everywhere
            <IconChevronDown data-icon="inline-end" />
          </DropdownMenuTrigger>
          <DropdownMenuContent align="end">
            <DropdownMenuGroup>
              <DropdownMenuItem>Everywhere</DropdownMenuItem>
              <DropdownMenuItem>This project</DropdownMenuItem>
              <DropdownMenuItem>Documentation</DropdownMenuItem>
            </DropdownMenuGroup>
          </DropdownMenuContent>
        </DropdownMenu>
      </InputGroupAddon>
    </InputGroup>
  )
}

Contenido largo

Los valores largos se desplazan dentro del input en lugar de estirar el grupo. Envuelve el texto largo de un addon en un span que se trunque con un ancho máximo.

import { IconWorld } from "@tabler/icons-react"

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

export function InputGroupLongContent() {
  return (
    <div className="flex w-72 flex-col gap-4">
      <InputGroup>
        <InputGroupInput
          defaultValue="averyveryverylongunbrokenvaluethatkeepsgoingandgoing"
          aria-label="Value"
        />
        <InputGroupAddon>
          <IconWorld />
        </InputGroupAddon>
        <InputGroupAddon align="inline-end">
          <InputGroupText>.example.com</InputGroupText>
        </InputGroupAddon>
      </InputGroup>
      <InputGroup>
        <InputGroupInput placeholder="name" aria-label="Subdomain" />
        <InputGroupAddon>
          <InputGroupText className="max-w-28">
            <span className="truncate">
              https://workspace-with-a-long-name.
            </span>
          </InputGroupText>
        </InputGroupAddon>
      </InputGroup>
    </div>
  )
}

De derecha a izquierda

Los addons, el relleno y los radios de las esquinas usan lados lógicos, así que inline-start queda a la derecha.

import { IconArrowUp, IconSearch } from "@tabler/icons-react"

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

export function InputGroupRtl() {
  return (
    <div dir="rtl" className="flex w-full max-w-sm flex-col gap-4">
      <InputGroup>
        <InputGroupInput placeholder="ابحث…" aria-label="بحث" />
        <InputGroupAddon>
          <IconSearch />
        </InputGroupAddon>
        <InputGroupAddon align="inline-end">
          <kbd>⌘K</kbd>
        </InputGroupAddon>
      </InputGroup>
      <InputGroup>
        <InputGroupInput placeholder="0.00" aria-label="السعر" />
        <InputGroupAddon>
          <InputGroupText>ر.س</InputGroupText>
        </InputGroupAddon>
        <InputGroupAddon align="inline-end">
          <InputGroupButton variant="default" size="icon-xs" aria-label="إرسال">
            <IconArrowUp />
          </InputGroupButton>
        </InputGroupAddon>
      </InputGroup>
    </div>
  )
}
KeyAcción
TabPasa del campo a cada botón de los addons, en el orden del código fuente.
ShiftTabRetrocede por los botones y el campo.
EscapeCon un InputGroupClear, borra el campo. Si ya está vacío, Escape pasa de largo.
  • Cada campo necesita un nombre. Usa una etiqueta visible, un Field o aria-label. Los iconos y el texto de los addons no forman parte del nombre del campo.
  • Dale a los botones solo con icono un aria-label.
  • Cuando el texto de un addon tiene significado, como una moneda o un dominio, añádelo a la etiqueta o referénciaslo con aria-describedby.
  • <InputGroupClear /> se omite en el orden de tabulación porque Escape hace lo mismo. El interruptor de contraseña sigue siendo tabulable y conserva el mismo nombre, con aria-pressed informando de su estado.
  • Cuando un envío encuentra el campo no válido, el grupo se sacude una vez. Con movimiento reducido, el borde rojo es la única señal.
  • En pantallas táctiles el texto del campo es de al menos 16px para que los teléfonos no hagan zoom cuando recibe foco.

<InputGroupInput /> y <InputGroupTextarea /> aceptan las props de los elementos que renderizan. Las demás partes aceptan los atributos de su elemento.

PropTipoPredeterminado
sizeAltura del grupo, pasada al input.
"sm" | "default" | "lg""default"
AtributoDescripción
data-slot="input-group"Selecciona el grupo en CSS. Renderiza role="group".
data-sizeEl tamaño actual.
data-filledPresente mientras el campo tiene un valor.
data-shakePresente mientras el grupo se sacude tras un envío fallido.
data-disabledDefínelo tú mismo para atenuar el grupo cuando solo los addons están deshabilitados.
--input-group-radiusRadio de las esquinas del grupo. Los botones y las teclas derivan su radio de él.
--input-group-heightAltura del grupo para el tamaño actual.
PropTipoPredeterminado
sizeSe hereda del grupo.
"sm" | "default" | "lg"–
aria-invalid
boolean–
disabled
booleanfalse
readOnly
booleanfalse
AtributoDescripción
data-slot="input-group-control"Marca el campo. El grupo lee de él sus estados de foco, no válido, deshabilitado y solo lectura.
data-invalidPresente cuando un Field circundante marca el valor como no válido.
data-disabledPresente cuando el campo está deshabilitado.
data-focusedPresente mientras el campo tiene foco.
data-filledPresente cuando el campo tiene un valor.
data-dirtyPresente una vez que el valor difiere del inicial.
data-touchedPresente una vez que el campo ha recibido foco y lo ha perdido.
PropTipoPredeterminado
autoResizeCrece con el contenido hasta 16rem, ajustándose suavemente entre alturas.
booleantrue
shakeSacude el grupo cuando un envío lo encuentra no válido.
booleantrue
rows
number–
aria-invalid
boolean–
disabled
booleanfalse
AtributoDescripción
data-slot="input-group-control"Marca el campo. El grupo lee de él sus estados de foco, no válido, deshabilitado y solo lectura.
data-invalidPresente cuando un Field circundante marca el valor como no válido.
data-disabledPresente cuando el campo está deshabilitado.
data-focusedPresente mientras el campo tiene foco.
data-filledPresente cuando el campo tiene un valor.
data-dirtyPresente una vez que el valor difiere del inicial.
data-touchedPresente una vez que el campo ha recibido foco y lo ha perdido.
PropTipoPredeterminado
align
"inline-start" | "inline-end" | "block-start" | "block-end""inline-start"
separatorDibuja una línea fina entre un addon de bloque y el campo.
booleanfalse
AtributoDescripción
data-slot="input-group-addon"Selecciona los addons en CSS.
data-alignLa alineación actual.
data-separatorPresente cuando se define separator.
--input-group-addon-insetEspacio entre el borde del grupo y un botón o tecla de su interior.
PropTipoPredeterminado
variant
"default" | "outline" | "secondary" | "ghost" | "destructive" | "link""ghost"
size
"xs" | "sm" | "icon-xs" | "icon-sm""xs"
type
string"button"
feedbackTodas las props de Button funcionan, incluido el flujo de carga y éxito.
booleanfalse
AtributoDescripción
data-slot="input-group-button"Selecciona los botones de los addons en CSS.
data-sizeEl tamaño actual.
PropTipoPredeterminado
onClearSe llama después de borrar el campo.
() => void–
aria-label
string"Clear"
children
ReactNode<IconX />
AtributoDescripción
data-slot="input-group-clear"Selecciona el botón de borrar en CSS.
data-visiblePresente mientras el campo tiene un valor y es editable.
PropTipoPredeterminado
revealedEstado controlado. Déjalo sin definir para que se gestione solo.
boolean–
onRevealedChange
(revealed: boolean) => void–
aria-label
string"Show password"
AtributoDescripción
data-slot="input-group-password-toggle"Selecciona el interruptor en CSS.
data-revealedPresente mientras se muestra la contraseña.
PropTipoPredeterminado
thresholdCaracteres restantes a partir de los cuales el recuento empieza a destacar.
number10% of maxLength, at most 20
announcementMensaje para lectores de pantalla cuando el recuento cruza el umbral o llega al límite.
(remaining: number) => string–
AtributoDescripción
data-slot="input-group-count"Apunta al contador en CSS.
data-state="near" | "limit"Presente dentro del umbral y cuando no quedan caracteres.
data-bumpPresente brevemente cuando se pulsa una tecla en el límite.
AtributoDescripción
data-slot="input-group-text"Selecciona el texto de los addons en CSS.

Usado en bloques

Bloques que se construyen sobre Input group.