HextaUI

Field

Des libellés, descriptions et erreurs reliés à leur contrôle, avec états de validation et mises en page pour les formulaires.

Shown on your profile.

"use client"

import { Form } from "@base-ui/react/form"
import { IconAt } from "@tabler/icons-react"

import { Button } from "@/components/ui/button"
import {
  Field,
  FieldCounter,
  FieldDescription,
  FieldError,
  FieldGroup,
  FieldLabel,
  FieldStatus,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"
import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput,
  InputGroupTextarea,
} from "@/components/ui/input-group"

export function FieldDemo() {
  return (
    <Form
      className="w-full max-w-sm"
      onSubmit={(event) => event.preventDefault()}
    >
      <FieldGroup indicator="optional">
        <Field validationMode="onBlur">
          <FieldLabel>Display name</FieldLabel>
          <Input name="name" autoComplete="name" required />
          <FieldError match="valueMissing">
            Add the name people will see.
          </FieldError>
        </Field>
        <Field validationMode="onChange">
          <FieldLabel>Handle</FieldLabel>
          <InputGroup>
            <InputGroupInput
              name="handle"
              autoComplete="username"
              pattern="[a-z0-9_]{3,15}"
              maxLength={15}
              required
            />
            <InputGroupAddon>
              <IconAt />
            </InputGroupAddon>
            <InputGroupAddon align="inline-end">
              <FieldStatus />
            </InputGroupAddon>
          </InputGroup>
          <FieldError match="valueMissing">Pick a handle.</FieldError>
          <FieldError match="patternMismatch">
            Use 3–15 lowercase letters, numbers or underscores.
          </FieldError>
        </Field>
        <Field>
          <FieldLabel>Bio</FieldLabel>
          <InputGroup>
            <InputGroupTextarea name="bio" maxLength={160} />
          </InputGroup>
          <div className="flex items-baseline justify-between gap-3">
            <FieldDescription>Shown on your profile.</FieldDescription>
            <FieldCounter />
          </div>
        </Field>
        <Button type="submit">Save profile</Button>
      </FieldGroup>
    </Form>
  )
}
pnpm dlx shadcn@latest add https://hextaui.com/r/field.json

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

import {
  Field,
  FieldDescription,
  FieldError,
  FieldGroup,
  FieldLabel,
} from "@/components/ui/field"
<FieldGroup indicator="optional">
  <Field>
    <FieldLabel>Email</FieldLabel>
    <Input type="email" required />
    <FieldDescription>We’ll never share it.</FieldDescription>
    <FieldError />
  </Field>
</FieldGroup>

Placez n’importe quel contrôle HextaUI dans un <Field /> et il est automatiquement étiqueté, décrit et validé. Inutile de câbler id, htmlFor ou aria-describedby à la main.

Un contrôle avec son libellé, son texte d’aide et sa validation.

Field
├── FieldLabel
├── Input / Textarea / Select / …
├── FieldDescription
├── FieldError
├── FieldCounter
└── FieldStatus

Un interrupteur ou une case à cocher avec son texte à côté.

Field
├── Switch / Checkbox
└── FieldContent
    ├── FieldLabel
    └── FieldDescription

Un libellé qui enveloppe tout un champ, pour que la carte soit la cible du clic.

FieldLabel
└── Field
    ├── Checkbox / RadioGroupItem
    └── FieldContent
        ├── FieldTitle
        └── FieldDescription

Champs liés, espacés uniformément.

FieldGroup
├── Field
├── FieldSeparator
└── Field

Un groupe de champs avec titre, ou un groupe radio ou de cases à cocher avec un élément par option.

FieldSet
├── FieldLegend
├── FieldDescription
└── FieldGroup
    └── Field

FieldSet
├── FieldLegend
└── FieldItem
    ├── RadioGroupItem / Checkbox
    └── FieldLabel

Input

Un libellé, un contrôle et une description. Cliquer sur le libellé donne le focus au champ, et les lecteurs d’écran lisent la description après le libellé.

import { Field, FieldDescription, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"

export function FieldInput() {
  return (
    <Field className="max-w-sm">
      <FieldLabel>Username</FieldLabel>
      <Input placeholder="ada" autoComplete="username" />
      <FieldDescription>
        Shown on your profile. You can change it once a month.
      </FieldDescription>
    </Field>
  )
}

Validation

Les contraintes natives comme required et minLength sont vérifiées au blur. Donnez à chaque <FieldError /> un match pour formuler le message selon le problème. Un champ requis vide n’est signalé qu’après avoir été modifié : le franchir par tabulation ne déclenche donc pas d’alerte.

import {
  Field,
  FieldDescription,
  FieldError,
  FieldLabel,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"

export function FieldValidation() {
  return (
    <Field validationMode="onBlur" className="max-w-sm">
      <FieldLabel>Password</FieldLabel>
      <Input
        type="password"
        autoComplete="new-password"
        required
        minLength={8}
      />
      <FieldDescription>At least 8 characters.</FieldDescription>
      <FieldError match="valueMissing">Choose a password.</FieldError>
      <FieldError match="tooShort">
        That’s too short. Use 8 or more characters.
      </FieldError>
    </Field>
  )
}

Validation personnalisée

Passez validate pour vérifier n’importe quoi, y compris des recherches asynchrones. Retournez un message pour échouer ou rien pour réussir. Avec validationMode="onChange" et validationDebounceTime, elle s’exécute pendant la saisie sans se déclencher à chaque touche. Essayez « ada ».

"use client"

import {
  Field,
  FieldDescription,
  FieldError,
  FieldLabel,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"

const taken = ["admin", "ada", "hexta"]

async function checkUsername(value: unknown) {
  const name = String(value ?? "")
    .trim()
    .toLowerCase()
  if (name.length === 0) {
    return null
  }
  if (!/^[a-z0-9_]+$/.test(name)) {
    return "Use letters, numbers and underscores only."
  }
  await new Promise((resolve) => setTimeout(resolve, 400))
  return taken.includes(name) ? `“${name}” is taken.` : null
}

export function FieldCustomValidation() {
  return (
    <Field
      validationMode="onChange"
      validationDebounceTime={300}
      validate={checkUsername}
      className="max-w-sm"
    >
      <FieldLabel>Username</FieldLabel>
      <Input placeholder="Try “ada”" autoComplete="off" />
      <FieldDescription>Checked as you type.</FieldDescription>
      <FieldError />
    </Field>
  )
}

Requis et facultatif

Définissez indicator sur un FieldGroup, FieldSet ou Field et chaque libellé à l’intérieur se marque d’après l’attribut required de son contrôle. "optional" signale les champs que l’on peut ignorer, ce qui paraît plus calme quand la plupart des champs sont requis. "required" ajoute un astérisque. La marque est masquée aux lecteurs d’écran, car le contrôle l’annonce déjà.

import {
  Field,
  FieldGroup,
  FieldLabel,
  FieldSeparator,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"

export function FieldIndicatorDemo() {
  return (
    <div className="flex w-full max-w-sm flex-col gap-8">
      <FieldGroup indicator="optional">
        <Field>
          <FieldLabel>Email</FieldLabel>
          <Input type="email" autoComplete="email" required />
        </Field>
        <Field>
          <FieldLabel>Company</FieldLabel>
          <Input autoComplete="organization" />
        </Field>
      </FieldGroup>
      <FieldSeparator />
      <FieldGroup indicator="required">
        <Field>
          <FieldLabel>Card number</FieldLabel>
          <Input inputMode="numeric" autoComplete="cc-number" required />
        </Field>
        <Field>
          <FieldLabel>Billing note</FieldLabel>
          <Input />
        </Field>
      </FieldGroup>
    </div>
  )
}

Statut

<FieldStatus /> dessine une coche lorsqu’un champ modifié passe la validation, et affiche une icône d’alerte tant qu’elle échoue. Il suit le validationMode du champ et ne juge donc jamais un champ avant l’exécution de la validation.

import {
  Field,
  FieldDescription,
  FieldError,
  FieldLabel,
  FieldStatus,
} from "@/components/ui/field"
import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput,
} from "@/components/ui/input-group"

export function FieldStatusDemo() {
  return (
    <Field validationMode="onChange" className="max-w-sm">
      <FieldLabel>Invite code</FieldLabel>
      <InputGroup>
        <InputGroupInput
          name="code"
          pattern="HX-[0-9]{4}"
          placeholder="HX-0000"
          autoComplete="off"
        />
        <InputGroupAddon align="inline-end">
          <FieldStatus />
        </InputGroupAddon>
      </InputGroup>
      <FieldDescription>Try HX-2026.</FieldDescription>
      <FieldError match="patternMismatch">
        Codes look like HX- followed by four digits.
      </FieldError>
    </Field>
  )
}

Compteur de caractères

<FieldCounter /> trouve le contrôle de texte de son champ et compte par rapport à son maxLength. Il ne fait qu’écouter : la saisie n’est jamais ralentie ni modifiée.

import {
  Field,
  FieldCounter,
  FieldDescription,
  FieldLabel,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"

export function FieldCounterDemo() {
  return (
    <Field className="max-w-sm">
      <FieldLabel>Status</FieldLabel>
      <Input defaultValue="Shipping the field rework" maxLength={40} />
      <div className="flex items-baseline justify-between gap-3">
        <FieldDescription>Clears after 24 hours.</FieldDescription>
        <FieldCounter />
      </div>
    </Field>
  )
}

Erreurs d’une bibliothèque de formulaires ou du serveur

Passez invalid au champ et un tableau errors à <FieldError />. Il accepte la forme { message } que renvoient React Hook Form et la plupart des bibliothèques de schémas. Les doublons sont supprimés, et plusieurs messages deviennent une liste. Lorsque les messages changent, les nouveaux apparaissent en fondu et la hauteur s’adapte en douceur : rien en dessous ne saute. Soumettez à vide, puis corrigez une règle à la fois.

"use client"

import * as React from "react"

import { Button } from "@/components/ui/button"
import {
  Field,
  FieldError,
  FieldGroup,
  FieldLabel,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"

type Errors = {
  email?: { message: string }[]
  password?: { message: string }[]
}

export function FieldErrors() {
  const [errors, setErrors] = React.useState<Errors>({})

  return (
    <form
      className="w-full max-w-sm"
      onSubmit={(event) => {
        event.preventDefault()
        const data = new FormData(event.currentTarget)
        const password = String(data.get("password") ?? "")
        const next: Errors = {}
        if (!String(data.get("email") ?? "").includes("@")) {
          next.email = [{ message: "Enter a valid email." }]
        }
        const problems = []
        if (password.length < 8) {
          problems.push({ message: "Use at least 8 characters." })
        }
        if (!/\d/.test(password)) {
          problems.push({ message: "Include a number." })
        }
        if (problems.length > 0) {
          next.password = problems
        }
        setErrors(next)
      }}
    >
      <FieldGroup>
        <Field invalid={Boolean(errors.email)}>
          <FieldLabel>Email</FieldLabel>
          <Input name="email" autoComplete="email" />
          <FieldError errors={errors.email ?? []} />
        </Field>
        <Field invalid={Boolean(errors.password)}>
          <FieldLabel>Password</FieldLabel>
          <Input name="password" type="password" autoComplete="new-password" />
          <FieldError errors={errors.password ?? []} />
        </Field>
        <Button type="submit">Sign up</Button>
      </FieldGroup>
    </form>
  )
}

Cases à cocher

Utilisez orientation="horizontal" pour placer la case à cocher à côté de son libellé. Dans un <FieldSet />, la légende nomme tout le groupe.

import { Checkbox, CheckboxGroup } from "@/components/ui/checkbox"
import {
  Field,
  FieldDescription,
  FieldLabel,
  FieldLegend,
  FieldSet,
} from "@/components/ui/field"

const options = [
  { value: "mentions", label: "Mentions" },
  { value: "replies", label: "Replies to my comments" },
  { value: "digest", label: "Weekly digest" },
]

export function FieldCheckbox() {
  return (
    <FieldSet className="w-full max-w-sm">
      <FieldLegend variant="label">Email me about</FieldLegend>
      <FieldDescription>Security alerts are always on.</FieldDescription>
      <CheckboxGroup defaultValue={["mentions", "replies"]}>
        {options.map((option) => (
          <Field key={option.value} orientation="horizontal">
            <Checkbox name="notifications" value={option.value} />
            <FieldLabel>{option.label}</FieldLabel>
          </Field>
        ))}
      </CheckboxGroup>
    </FieldSet>
  )
}

Cartes de choix

Enveloppez tout un champ dans <FieldLabel /> pour que la carte soit la cible du clic. Utilisez <FieldTitle /> à l’intérieur, car les labels ne peuvent pas s’imbriquer. La carte se teinte lorsqu’elle est cochée et affiche l’anneau de focus lorsque sa case à cocher a le focus.

import { Checkbox } from "@/components/ui/checkbox"
import {
  Field,
  FieldContent,
  FieldDescription,
  FieldLabel,
  FieldLegend,
  FieldSet,
  FieldTitle,
} from "@/components/ui/field"

export function FieldChoiceCard() {
  return (
    <FieldSet className="w-full max-w-sm">
      <FieldLegend variant="label">Add-ons</FieldLegend>
      <div className="flex flex-col gap-3">
        <FieldLabel>
          <Field orientation="horizontal">
            <Checkbox name="backups" defaultChecked />
            <FieldContent>
              <FieldTitle>Daily backups</FieldTitle>
              <FieldDescription>
                Restore any day from the last 30.
              </FieldDescription>
            </FieldContent>
          </Field>
        </FieldLabel>
        <FieldLabel>
          <Field orientation="horizontal">
            <Checkbox name="support" />
            <FieldContent>
              <FieldTitle>Priority support</FieldTitle>
              <FieldDescription>Replies within four hours.</FieldDescription>
            </FieldContent>
          </Field>
        </FieldLabel>
        <FieldLabel>
          <Field orientation="horizontal" disabled>
            <Checkbox name="sso" />
            <FieldContent>
              <FieldTitle>Single sign-on</FieldTitle>
              <FieldDescription>
                Available on the Business plan.
              </FieldDescription>
            </FieldContent>
          </Field>
        </FieldLabel>
      </div>
    </FieldSet>
  )
}

Fieldset

<FieldSet /> regroupe des champs liés sous un <FieldLegend />, qui devient le nom accessible du groupe. Disposez les champs côte à côte avec une simple grille.

import {
  Field,
  FieldDescription,
  FieldGroup,
  FieldLabel,
  FieldLegend,
  FieldSet,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"

export function FieldFieldset() {
  return (
    <FieldSet className="w-full max-w-md">
      <FieldLegend>Shipping address</FieldLegend>
      <FieldDescription>Where should we send your order?</FieldDescription>
      <FieldGroup>
        <Field>
          <FieldLabel>Street address</FieldLabel>
          <Input autoComplete="street-address" />
        </Field>
        <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
          <Field>
            <FieldLabel>City</FieldLabel>
            <Input autoComplete="address-level2" />
          </Field>
          <Field>
            <FieldLabel>Postal code</FieldLabel>
            <Input autoComplete="postal-code" />
          </Field>
        </div>
      </FieldGroup>
    </FieldSet>
  )
}

Responsive

orientation="responsive" empile le libellé et le contrôle dans les espaces étroits et les place côte à côte dès que le <FieldGroup /> environnant est assez large. Il réagit à la largeur du groupe, pas à celle de la fenêtre.

import {
  Field,
  FieldContent,
  FieldDescription,
  FieldGroup,
  FieldLabel,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"

export function FieldResponsive() {
  return (
    <FieldGroup className="w-full max-w-xl">
      <Field orientation="responsive">
        <FieldContent>
          <FieldLabel>Display name</FieldLabel>
          <FieldDescription>Shown next to your messages.</FieldDescription>
        </FieldContent>
        <Input placeholder="Ada" className="sm:max-w-56" />
      </Field>
      <Field orientation="responsive">
        <FieldContent>
          <FieldLabel>Website</FieldLabel>
          <FieldDescription>Linked from your profile.</FieldDescription>
        </FieldContent>
        <Input placeholder="example.com" className="sm:max-w-56" />
      </Field>
    </FieldGroup>
  )
}

Désactivé

Désactiver un <FieldSet /> désactive chaque champ et contrôle à l’intérieur. Passez disabled à un seul <Field /> pour ne désactiver que celui-là.

import { Checkbox } from "@/components/ui/checkbox"
import {
  Field,
  FieldDescription,
  FieldGroup,
  FieldLabel,
  FieldLegend,
  FieldSet,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"

export function FieldDisabled() {
  return (
    <FieldSet disabled className="w-full max-w-sm">
      <FieldLegend>Billing details</FieldLegend>
      <FieldDescription>Managed by your organization’s admin.</FieldDescription>
      <FieldGroup>
        <Field>
          <FieldLabel>Company</FieldLabel>
          <Input defaultValue="Acme Inc." />
        </Field>
        <Field orientation="horizontal">
          <Checkbox defaultChecked />
          <FieldLabel>Send invoices by email</FieldLabel>
        </Field>
      </FieldGroup>
    </FieldSet>
  )
}

Contenu long

Les libellés, descriptions et erreurs passent à la ligne dans les formulaires étroits, y compris les chaînes sans coupure, et n’élargissent jamais la mise en page.

import {
  Field,
  FieldDescription,
  FieldError,
  FieldLabel,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"

export function FieldLongContent() {
  return (
    <Field invalid className="w-72">
      <FieldLabel>
        A label long enough to wrap onto a second line in a narrow form
      </FieldLabel>
      <Input defaultValue="averyveryverylongunbrokenvaluethatkeepsgoing" />
      <FieldDescription>
        averyveryverylongunbrokendescriptionthatmustwrapinsteadofoverflowing
      </FieldDescription>
      <FieldError
        errors={[
          {
            message:
              "This message is long on purpose and wraps onto several lines without pushing anything wider.",
          },
        ]}
      />
    </Field>
  )
}

De droite à gauche

Le texte, la position des cases à cocher et les listes d’erreurs suivent le sens de lecture.

import { Checkbox } from "@/components/ui/checkbox"
import {
  Field,
  FieldDescription,
  FieldError,
  FieldGroup,
  FieldLabel,
} from "@/components/ui/field"
import { Input } from "@/components/ui/input"

export function FieldRtl() {
  return (
    <div dir="rtl" className="w-full max-w-sm">
      <FieldGroup>
        <Field invalid>
          <FieldLabel>البريد الإلكتروني</FieldLabel>
          <Input type="email" defaultValue="ada@" />
          <FieldDescription>
            سنرسل رابط التأكيد إلى هذا العنوان.
          </FieldDescription>
          <FieldError errors={[{ message: "أدخل عنوان بريد صالحًا." }]} />
        </Field>
        <Field orientation="horizontal">
          <Checkbox defaultChecked />
          <FieldLabel>تذكرني</FieldLabel>
        </Field>
      </FieldGroup>
    </div>
  )
}
  • Le libellé, la description et les erreurs visibles sont reliés au contrôle pour vous : les lecteurs d’écran annoncent donc les trois lorsqu’il reçoit le focus.
  • Les contrôles invalides reçoivent aria-invalid, qui dessine aussi leur anneau d’erreur.
  • Les erreurs ne sont pas des régions live. Elles sont lues lorsque le contrôle reçoit le focus : valider à chaque changement n’interrompt donc pas la saisie. À la soumission, déplacez le focus vers le premier champ invalide.
  • Les erreurs grandissent et apparaissent en fondu sur place au lieu de repousser le contenu. Avec la réduction des animations, elles apparaissent sans animation.

Construit sur le field et le fieldset de Base UI. Chaque partie accepte les props de l’élément ou de la primitive qu’elle rend.

PropTypePar défaut
orientation
"vertical" | "horizontal" | "responsive""vertical"
indicatorMarque le libellé d’après l’attribut required du contrôle. Hérité de FieldGroup ou FieldSet.
"required" | "optional" | null–
nameIdentifie le champ lors de la soumission du formulaire.
string–
validateRetournez un ou plusieurs messages pour échouer, ou rien pour réussir. L’asynchrone est pris en charge.
(value, formValues) => string | string[] | null | Promise<…>–
validationMode
"onSubmit" | "onBlur" | "onChange""onSubmit"
validationDebounceTimeMillisecondes d’attente entre les validations onChange.
number0
invalidÀ définir depuis une bibliothèque de formulaires ou une réponse du serveur.
boolean–
disabled
booleanfalse
dirty
boolean–
touched
boolean–
actionsRefValide le champ de façon impérative.
RefObject<{ validate: () => void }>–
render
ReactElement | (props, state) => ReactElement<div>
AttributDescription
data-slot="field"Ciblez les champs en CSS.
data-orientationL’orientation actuelle.
data-disabledPrésent lorsque le champ est désactivé.
data-validPrésent lorsque le champ est valide.
data-invalidPrésent lorsque le champ est invalide.
data-dirtyPrésent une fois que la valeur a changé par rapport à sa valeur initiale.
data-touchedPrésent une fois que le contrôle a reçu puis perdu le focus.
data-filledPrésent lorsque le contrôle a une valeur.
data-focusedPrésent tant que le contrôle a le focus.
PropTypePar défaut
nativeLabelÀ définir sur false lorsque render remplace le libellé par un élément qui n’est pas un label.
booleantrue
optionalTextTexte affiché avec indicator="optional".
ReactNode"Optional"
render
ReactElement | (props, state) => ReactElement<label>
AttributDescription
data-slot="field-label"Ciblez les libellés en CSS. En dehors d’un champ, il rend un label simple, ce qui fait fonctionner les cartes de choix.
data-disabledPrésent lorsque le champ est désactivé.
data-validPrésent lorsque le champ est valide.
data-invalidPrésent lorsque le champ est invalide.
data-dirtyPrésent une fois que la valeur a changé par rapport à sa valeur initiale.
data-touchedPrésent une fois que le contrôle a reçu puis perdu le focus.
data-filledPrésent lorsque le contrôle a une valeur.
data-focusedPrésent tant que le contrôle a le focus.

Une icône qui reflète la validité du champ. Elle est décorative, car le message d’erreur porte le sens.

AttributDescription
data-slot="field-status"Ciblez l’icône de statut en CSS.
PropTypePar défaut
threshold
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="field-counter"Ciblez le compteur en CSS.
data-state="near" | "limit"Présent dans le seuil, et à la limite.
PropTypePar défaut
render
ReactElement | (props, state) => ReactElement<p>
AttributDescription
data-slot="field-description"Ciblez les descriptions en CSS.
data-disabledPrésent lorsque le champ est désactivé.
data-validPrésent lorsque le champ est valide.
data-invalidPrésent lorsque le champ est invalide.
data-dirtyPrésent une fois que la valeur a changé par rapport à sa valeur initiale.
data-touchedPrésent une fois que le contrôle a reçu puis perdu le focus.
data-filledPrésent lorsque le contrôle a une valeur.
data-focusedPrésent tant que le contrôle a le focus.
PropTypePar défaut
matchN’affiche que pour ce problème de validité. true l’affiche toujours.
boolean | "valueMissing" | "typeMismatch" | "tooShort" | "tooLong" | "patternMismatch" | "rangeOverflow" | "rangeUnderflow" | "stepMismatch" | "badInput" | "customError" | "valid"–
errorsErreurs d’une bibliothèque de formulaires ou du serveur. Affichées lorsque la liste contient un message.
Array<{ message?: string } | undefined>–
childrenPar défaut, le message de validation.
ReactNode–
render
ReactElement | (props, state) => ReactElement<div>
AttributDescription
data-slot="field-error"Ciblez les erreurs en CSS.
data-starting-stylePrésent pendant que l’erreur apparaît.
data-ending-stylePrésent pendant que l’erreur se replie.
data-disabledPrésent lorsque le champ est désactivé.
data-validPrésent lorsque le champ est valide.
data-invalidPrésent lorsque le champ est invalide.
data-dirtyPrésent une fois que la valeur a changé par rapport à sa valeur initiale.
data-touchedPrésent une fois que le contrôle a reçu puis perdu le focus.
data-filledPrésent lorsque le contrôle a une valeur.
data-focusedPrésent tant que le contrôle a le focus.

Empile un libellé, une description et une erreur à côté d’un contrôle dans un champ horizontal.

PropTypePar défaut
render
ReactElement | (props, state) => ReactElement<div>

Un titre au style de libellé pour le contenu d’un <FieldLabel />, comme des cartes de choix.

PropTypePar défaut
render
ReactElement | (props, state) => ReactElement<div>

Espace les champs et constitue le conteneur que mesurent les champs responsives.

PropTypePar défaut
indicatorS’applique à chaque champ à l’intérieur.
"required" | "optional" | null–
render
ReactElement | (props, state) => ReactElement<div>
PropTypePar défaut
indicatorS’applique à chaque champ à l’intérieur.
"required" | "optional" | null–
disabledDésactive chaque champ à l’intérieur.
booleanfalse
render
ReactElement | (props, state) => ReactElement<fieldset>
AttributDescription
data-slot="field-set"Ciblez les fieldsets en CSS.
data-disabledPrésent lorsque le fieldset est désactivé.
PropTypePar défaut
variantlabel correspond à la taille d’un libellé de champ.
"legend" | "label""legend"
render
ReactElement | (props, state) => ReactElement<div>
AttributDescription
data-slot="field-legend"Ciblez les légendes en CSS.
data-variantLa variante actuelle.

Un <Separator /> espacé pour les formulaires, qui accepte toutes ses props.

PropTypePar défaut
childrenTexte facultatif affiché au milieu de la ligne.
ReactNode–
alignOù le texte se place le long de la ligne.
"start" | "center" | "end""center"
decorativeMasque une ligne simple aux lecteurs d’écran lorsqu’elle est purement visuelle.
booleanfalse
render
ReactElement | (props, state) => ReactElement<div>
AttributDescription
data-slot="field-separator"Ciblez les séparateurs de champs en CSS.
data-contentPrésent lorsque le séparateur contient du texte.
data-slot="separator-label"L’élément qui enveloppe le texte.

Enveloppe une case à cocher ou un radio et son libellé dans un groupe, pour que chaque élément puisse être désactivé séparément.

PropTypePar défaut
disabled
booleanfalse
render
ReactElement | (props, state) => ReactElement<div>

Rend n’importe quoi à partir de l’état de validité du champ, par exemple un indicateur de robustesse ou un compteur de caractères.

PropTypePar défaut
children
(state: { validity, errors, error, value }) => ReactNode–

Utilisé dans les blocks

Des blocks qui s’appuient sur Field.