Form field
wu-field stacks a label, a control and its messages. The required marker and the error message follow the control’s own state, with no script.
| Class, attribute or variable | Effect |
|---|---|
wu-field |
Root. Column of label, control and messages |
wu-field-label |
Part, on <label>. Medium weight label |
required or aria-required="true" on the control |
Adds a * after the label, kept out of the label’s accessible name |
wu-field-message error inside the field |
Hidden until the control has aria-invalid="true" or matches :user-invalid. Reference its id from aria-describedby only while it shows |
horizontal |
Label beside the control from sm up |
floating |
Label inside the input, moved up on focus or once filled |
animated |
The floating label slides, opt-in |
--wu-field--LabelWidth |
Label column width in horizontal |
Default
Section titled “Default”<div class="wu-field"> <label class="wu-field-label" for="field-name">Full name</label> <input class="wu-input" id="field-name" type="text" aria-describedby="field-name-hint"> <p class="wu-field-message" id="field-name-hint">As it appears on your ID.</p></div>Required and invalid
Section titled “Required and invalid”The error message shows once the control is invalid: after the user has interacted (:user-invalid), or right away with aria-invalid="true".
A screen reader reads everything aria-describedby points to, hidden or not. So the error’s id joins aria-describedby only while the error shows:
- Invalid when the page is rendered (server validation): set
aria-invalid="true"and add the error id toaria-describedby, as in the invite code field. - Invalid after the user acts (
:user-invalid): leave the error id out, as in the email field. The error shows for sighted users and the browser announces its own validation message on submit. To announce your own text instead, have your script setaria-invalid="true"and add the id when the field turns invalid.
<div class="flex col gap-4"> <div class="wu-field"> <label class="wu-field-label" for="field-email">Email</label> <input class="wu-input" id="field-email" type="email" required> <p class="wu-field-message error" id="field-email-error">Error: enter an email address.</p> </div> <div class="wu-field"> <label class="wu-field-label" for="field-code">Invite code</label> <input class="wu-input" id="field-code" type="text" value="ABC" aria-invalid="true" aria-describedby="field-code-error"> <p class="wu-field-message error" id="field-code-error">Error: the code has 8 characters.</p> </div></div>Horizontal
Section titled “Horizontal”Set --wu-field--LabelWidth on a shared parent, so the controls of every field line up in one column.
<div class="flex col gap-4" style="--wu-field--LabelWidth: 6rem"> <div class="wu-field horizontal"> <label class="wu-field-label" for="field-company">Company</label> <input class="wu-input" id="field-company" type="text"> </div> <div class="wu-field horizontal"> <label class="wu-field-label" for="field-city">City</label> <input class="wu-input" id="field-city" type="text" aria-describedby="field-city-hint"> <p class="wu-field-message" id="field-city-hint">Used for tax.</p> </div></div>Floating label
Section titled “Floating label”Needs placeholder=" " on the input, so the label knows when it is filled. Not combined with horizontal.
<div class="wu-field floating animated"> <label class="wu-field-label" for="field-search">Search projects</label> <input class="wu-input" id="field-search" type="search" placeholder=" "></div>Right to left
Section titled “Right to left”The label, the required marker and the horizontal layout follow the inline direction.
<div class="wu-field horizontal"> <label class="wu-field-label" for="field-rtl">البريد الإلكتروني</label> <input class="wu-input" id="field-rtl" type="email" required> <p class="wu-field-message">تلميح: لا نشاركه أبدًا.</p></div>Load only the field
Section titled “Load only the field”@use "@wovenui/components/field";The field needs no other component. The examples above also use the input and the field message.