Przejdź do głównej zawartości

Input, Label i Field

Techniczny: DraftAkceptacja: Draft

Materiał odziedziczony z PoC. Działający przykład pokazuje stan kodu, nie zatwierdzenie nowej identyfikacji. Rozstrzygnięcia warsztatów mają pierwszeństwo.

Otwórz w nowej karcie ↗

Użyjemy go tylko do wysyłki polisy.

Domyślny
import { Field, Input } from "@polisoteka/design-ui"

export function InputBasic() {
  return (
    <Field label="Adres e-mail" hint="Użyjemy go tylko do wysyłki polisy.">
      <Input type="email" placeholder="jan.kowalski@przyklad.pl" />
    </Field>
  )
}

export default InputBasic

Wprowadź poprawny 10-cyfrowy NIP.

Z błędem
import { Field, Input } from "@polisoteka/design-ui"

export function InputInvalid() {
  return (
    <Field label="NIP" error="Wprowadź poprawny 10-cyfrowy NIP.">
      <Input required defaultValue="123-456" />
    </Field>
  )
}

export default InputInvalid

Używaj Input przez Field, nie samodzielnie — Field dostarcza etykietę i powiązania a11y: etykietę z kontrolką (aria-labelledby) i aria-invalid wiąże kontekst Base UI, a aria-describedby składa sam Field z identyfikatorów podpowiedzi i błędu. id, name i natywne required ustawiaj na Input, nie na Field. Użycie samego Input bez Field/Label ma sens tylko w kontekstach bez formularza (np. pole wyszukiwarki z widoczną ikoną zamiast etykiety — wtedy aria-label musisz dodać ręcznie).

Nie pokazuj błędu walidacji, zanim użytkownik nie skończył interakcji z polem (nie waliduj on-keystroke od pierwszego znaku) — to reguła UX, nie własność komponentu; Field tylko renderuje błąd, który mu przekażesz.

Base UI jest zależnością wewnętrzną. Aplikacja używa wyłącznie komponentów DS. Input.onValueChange(value, eventDetails) służy wartości kontrolowanej razem z value. Field.error przyjmuje wynik walidacji aplikacji/API — reguły domenowe nie są częścią komponentu. Jedna kontrolka DS na Field. Samodzielny Label pozostaje natywną etykietą.

NazwaTypWymaganyDomyślnieOpis
onValueChangeBaseInput.Props['onValueChange']nieundefinedCallback (value, eventDetails) przy zmianie wartości; do pola kontrolowanego używaj razem z value.
NazwaTypWymaganyDomyślnieOpis
labelstringtak—Treść etykiety powiązanej z kontrolką.
childrenReact.ReactNodetak—Jedna kontrolka DS (np. Input); może być wewnątrz kontenera. Kontekst Base UI dostarcza powiązania dostępności.
errorstringnieundefinedBłąd z walidacji aplikacji/API — ustawia invalid i opisuje kontrolkę. Nie dodaje role='alert'.
hintstringnieundefinedPodpowiedź pod polem. Pokazywana ZAWSZE, niezależnie od error — gdy oba są podane, oba renderują się jednocześnie i oba trafiają do aria-describedby.
classNamestringnieundefinedKlasy na kontenerze pola (div).
NazwaTypWymaganyDomyślnieOpis
Brak propsów ponad natywne atrybuty elementu — patrz opis komponentu wyżej.

Zapewnione przez Field:

  • Base UI nadaje identyfikator kontrolce i wiąże z nią etykietę przez kontekst, także gdy Input jest zagnieżdżony w kontenerze.
  • Identyfikatory podpowiedzi i błędu nadaje Field (React.useId()), żeby powiązanie aria-describedby istniało już w HTML serwera — Base UI rejestruje własne dopiero po hydratacji. Input scala je z własnym aria-describedby.
  • error → aria-invalid + aria-describedby; bez dodatkowego role="alert".
  • hint renderuje się ZAWSZE, niezależnie od error — gdy oba są podane, aria-describedby wskazuje na OBA (id połączone spacją), a id/ aria-describedby już obecne na przekazanej kontrolce są respektowane, nie nadpisywane.
  • Natywne required na Input niesie wymagalność. CSS :has(:required) pokazuje dekoracyjny * przy etykiecie (ukryty dla czytnika). Wymagalność ma jedno źródło.

Sprawdź przy użyciu:

  • Sam Input bez Field NIE ma żadnego z powyższych — dodaj je ręcznie albo użyj Field.
  • Stan błędu sygnalizowany tylko aria-invalid + kolorem obramowania — jeśli Twój formularz pokazuje błędy zbiorczo na górze strony, upewnij się, że tekst błędu przy polu i tekst w podsumowaniu są identyczne (nie tylko kolor prowadzi do pola).

@todo(input): wykonać poniższy brief, przedstawić rezultat i dowody odbioru. Usunięcie znacznika nie jest wykonaniem zadania.

  • Zakres: Zachowaj działające demo; sprawdź błędy, pomoc, wymagalność, autofill, powiązania ARIA i brak utraty danych.
  • Konwencja: najpierw reguła lub gotowe zastosowanie, potem przykład i kontrprzykład, następnie granice oraz sposób sprawdzenia. Nie zastępuj materiału opisem planu jego przygotowania.
  • Źródła: platforma marki; zaakceptowane decyzje warsztatów. Zastane demo lub deklaracja PoC nie zatwierdzają nowej reguły.
  • Powiązania: Tokeny i zależności, Mikrocopy i komunikaty operacyjne.
  • Granica swobody: możesz redagować i pokazywać istniejące ustalenia. Nową obietnicę, wybór wizualny, dane firmy i twierdzenie produktowe przedstaw do decyzji; nie uzupełniaj z pamięci.

Sprawdź rzeczywisty render i użycie wspólnego kodu, desktop/mobile, jasny/ciemny tryb oraz właściwe konteksty portali. Bramka techniczna: pnpm design:check; przed wydaniem także pnpm design:audit. Sam opis ani zielony test innego demo nie jest dowodem odbioru tego elementu.