HextaUI

Input group

Un champ de saisie avec icônes, texte, boutons ou indice clavier attachés, partageant une même bordure et un même anneau de focus.

"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

Ajoute le composant, les tokens de thème HextaUI et les composants HextaUI dont il dépend.

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>

Placez <InputGroupInput /> ou <InputGroupTextarea /> en premier et les addons après. Les addons se placent eux-mêmes avec align, si bien que le champ vient en premier dans l’ordre de tabulation et pour les lecteurs d’écran.

Le groupe suit son champ : les parties intelligentes n’ont donc besoin d’aucun câblage. <InputGroupClear />, <InputGroupPasswordToggle /> et <InputGroupCount /> lisent la valeur, type et maxLength du champ, qu’il soit contrôlé ou non.

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

Icône

Les icônes se placent à l’intérieur de la bordure de chaque côté. Cliquer sur une icône donne le focus au champ : tout le groupe se comporte donc comme un seul champ.

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

Effacer

<InputGroupClear /> apparaît en fondu dès qu’il y a une valeur. Il efface via l’historique d’édition du navigateur, si bien que Cmd+Z ramène le texte, et il déclenche votre onChange. Escape efface aussi. Un second Escape est laissé à la boîte de dialogue ou au popover autour.

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

Compteur de caractères

<InputGroupCount /> compte par rapport au maxLength du champ. Seuls les chiffres qui changent défilent. Le compteur fonce près de la limite et devient rouge lorsqu’elle est atteinte, et une touche tapée au-delà le fait légèrement vibrer. Les lecteurs d’écran entendent un message lorsque le champ approche de la limite et lorsqu’il l’atteint, jamais à chaque touche.

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

Texte

Utilisez <InputGroupText /> pour les unités, les devises et les parties d’URL. Le remplissage du champ diminue à côté d’un addon pour que le texte se lise comme une seule valeur.

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 /> est un bouton ghost dimensionné pour tenir dans le champ. Ses coins sont concentriques à ceux du groupe, et il a son propre anneau de focus.

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

Indication clavier

Un <kbd> simple dans un addon est stylisé comme une touche de clavier. C’est uniquement un repère visuel : associez le raccourci vous-même.

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 /> grandit avec son contenu jusqu’à 16 rem, puis défile. La hauteur s’adapte en douceur d’une ligne à l’autre au lieu de sauter. Un addon block-end devient une barre d’outils en dessous, et les boutons sur ses bords reçoivent le même retrait que le coin où ils se trouvent.

"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 place au-dessus du champ. Ajoutez separator pour tracer un filet fin entre les deux.

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

Mot de passe

<InputGroupPasswordToggle /> fait passer un champ type="password" en texte et inversement. Le curseur et la sélection restent où ils étaient, un clic de souris garde le focus dans le champ, et le mot de passe est de nouveau masqué à la soumission du formulaire. Contrôlez-le avec 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>
  )
}

Tailles

size sur le groupe définit la hauteur et la transmet au champ, en cohérence avec les tailles de <Input />. Les boutons gardent des coins concentriques à toutes les tailles.

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

Invalide

Définissez aria-invalid sur le champ et tout le groupe devient rouge, y compris son anneau de focus. Reliez le message avec 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>
  )
}

Désactivé

Un champ désactivé atténue tout le groupe et affiche un curseur d’interdiction dessus. Désactivez aussi les boutons des addons, car ils restent sinon utilisables.

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

Chargement

Les addons en ligne s’adaptent en douceur à leur nouvelle largeur lorsque leur contenu change : le champ ne saute donc jamais quand un spinner devient un nombre de résultats. Le spinner ne tourne que si l’animation est autorisée, et role="status" annonce le texte.

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

Rendez un <InputGroupButton /> comme déclencheur de menu déroulant pour restreindre la portée de la saisie.

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

Contenu long

Les valeurs longues défilent dans le champ au lieu d’étirer le groupe. Enveloppez un long texte d’addon dans un span tronquant avec une largeur maximale.

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 droite à gauche

Les addons, le remplissage et les rayons de coin utilisent des côtés logiques : inline-start se place donc à droite.

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>
  )
}
ToucheAction
TabPasse du champ à chaque bouton d’addon, dans l’ordre du source.
ShiftTabRevient en arrière parmi les boutons et le champ.
EscapeAvec un InputGroupClear, efface le champ. S’il est déjà vide, Escape passe au travers.
  • Chaque champ a besoin d’un nom. Utilisez un libellé visible, un Field ou aria-label. Les icônes et le texte des addons ne font pas partie du nom du champ.
  • Donnez un aria-label aux boutons réduits à une icône.
  • Lorsque le texte d’un addon porte du sens, comme une devise ou un domaine, ajoutez-le au libellé ou référencez-le avec aria-describedby.
  • <InputGroupClear /> est ignoré dans l’ordre de tabulation, car Escape fait la même chose. Le bouton d’affichage du mot de passe reste atteignable par tabulation et garde le même nom, avec aria-pressed pour indiquer son état.
  • Lorsqu’une soumission trouve le champ invalide, le groupe vibre une fois. Avec la réduction des animations, la bordure rouge est le seul indice.
  • Sur écran tactile, le texte du champ fait au moins 16 px pour que les téléphones ne zooment pas lorsqu’il reçoit le focus.

<InputGroupInput /> et <InputGroupTextarea /> acceptent les props des éléments qu’ils rendent. Les autres parties acceptent les attributs de leur élément.

PropTypePar défaut
sizeHauteur du groupe, transmise au champ.
"sm" | "default" | "lg""default"
AttributDescription
data-slot="input-group"Ciblez le groupe en CSS. Rend role="group".
data-sizeLa taille actuelle.
data-filledPrésent tant que le champ a une valeur.
data-shakePrésent pendant que le groupe vibre après une soumission échouée.
data-disabledDéfinissez-le vous-même pour atténuer le groupe lorsque seuls les addons sont désactivés.
--input-group-radiusRayon des coins du groupe. Les boutons et les touches en déduisent leur rayon.
--input-group-heightHauteur du groupe pour la taille actuelle.
PropTypePar défaut
sizeHérité du groupe.
"sm" | "default" | "lg"–
aria-invalid
boolean–
disabled
booleanfalse
readOnly
booleanfalse
AttributDescription
data-slot="input-group-control"Marque le champ. Le groupe en lit les états de focus, d’invalidité, de désactivation et de lecture seule.
data-invalidPrésent lorsqu’un Field englobant marque la valeur comme invalide.
data-disabledPrésent lorsque le champ est désactivé.
data-focusedPrésent tant que le champ a le focus.
data-filledPrésent lorsque le champ a une valeur.
data-dirtyPrésent une fois que la valeur diffère de la valeur initiale.
data-touchedPrésent une fois que le champ a reçu puis perdu le focus.
PropTypePar défaut
autoResizeGrandit avec le contenu jusqu’à 16 rem, avec une transition douce entre les hauteurs.
booleantrue
shakeFait vibrer le groupe lorsqu’une soumission le trouve invalide.
booleantrue
rows
number–
aria-invalid
boolean–
disabled
booleanfalse
AttributDescription
data-slot="input-group-control"Marque le champ. Le groupe en lit les états de focus, d’invalidité, de désactivation et de lecture seule.
data-invalidPrésent lorsqu’un Field englobant marque la valeur comme invalide.
data-disabledPrésent lorsque le champ est désactivé.
data-focusedPrésent tant que le champ a le focus.
data-filledPrésent lorsque le champ a une valeur.
data-dirtyPrésent une fois que la valeur diffère de la valeur initiale.
data-touchedPrésent une fois que le champ a reçu puis perdu le focus.
PropTypePar défaut
align
"inline-start" | "inline-end" | "block-start" | "block-end""inline-start"
separatorTrace un filet fin entre un addon de bloc et le champ.
booleanfalse
AttributDescription
data-slot="input-group-addon"Ciblez les addons en CSS.
data-alignL’alignement actuel.
data-separatorPrésent lorsque separator est défini.
--input-group-addon-insetEspace entre le bord du groupe et un bouton ou une touche à l’intérieur.
PropTypePar défaut
variant
"default" | "outline" | "secondary" | "ghost" | "destructive" | "link""ghost"
size
"xs" | "sm" | "icon-xs" | "icon-sm""xs"
type
string"button"
feedbackToutes les props de Button fonctionnent, y compris le flux de chargement et de succès.
booleanfalse
AttributDescription
data-slot="input-group-button"Ciblez les boutons d’addon en CSS.
data-sizeLa taille actuelle.
PropTypePar défaut
onClearAppelé après l’effacement du champ.
() => void–
aria-label
string"Clear"
children
ReactNode<IconX />
AttributDescription
data-slot="input-group-clear"Ciblez le bouton d’effacement en CSS.
data-visiblePrésent tant que le champ a une valeur et est modifiable.
PropTypePar défaut
revealedÉtat contrôlé. Laissez non défini pour qu’il se gère lui-même.
boolean–
onRevealedChange
(revealed: boolean) => void–
aria-label
string"Show password"
AttributDescription
data-slot="input-group-password-toggle"Ciblez le bouton d’affichage en CSS.
data-revealedPrésent tant que le mot de passe est affiché.
PropTypePar défaut
thresholdCaractères restants à partir desquels le compteur se démarque.
number10% of maxLength, at most 20
announcementMessage pour les lecteurs d’écran lorsque le compteur franchit le seuil ou atteint la limite.
(remaining: number) => string–
AttributDescription
data-slot="input-group-count"Ciblez le compteur en CSS.
data-state="near" | "limit"Présent dans le seuil, et lorsqu’il ne reste plus de caractères.
data-bumpPrésent brièvement lorsqu’une touche est pressée à la limite.
AttributDescription
data-slot="input-group-text"Ciblez le texte d’addon en CSS.

Utilisé dans les blocks

Des blocks qui s’appuient sur Input group.