Fields
Password Field
A hidden-first password input with a built-in show and hide action.
When to use it: Use it for sign-in, account creation, and password changes where people may need to inspect what they entered.
Example
import { useState } from "react";
import {
Description,
FieldError,
Label,
PasswordField,
PasswordFieldInput,
PasswordFieldToggle,
} from "@comp0/react";
import { EyeIcon, EyeSlashIcon } from "@heroicons/react/16/solid";
export function Example() {
const [hasValidationError, setHasValidationError] = useState(false);
const [signedIn, setSignedIn] = useState(false);
return (
<form
className="flex max-w-sm flex-col gap-5 rounded-xl border border-zinc-950/10 bg-white p-5 shadow-sm dark:border-white/10 dark:bg-zinc-900"
onSubmit={(event) => {
event.preventDefault();
setSignedIn(true);
}}
>
<div>
<h2 className="text-lg font-semibold text-zinc-950 dark:text-zinc-50">Sign in</h2>
<p className="mt-1 text-base text-zinc-600 sm:text-sm dark:text-zinc-400">
Enter the password for ada@example.com.
</p>
</div>
<PasswordField
as="div"
className="flex flex-col gap-1.5"
invalid={hasValidationError}
onChange={() => setHasValidationError(false)}
required
>
<Label className="text-base font-medium text-zinc-900 sm:text-sm dark:text-zinc-100">
Password
</Label>
<div className="relative">
<PasswordFieldInput
autoComplete="current-password"
className="w-full rounded border border-zinc-950/10 bg-white px-3 py-2.5 pr-24 text-base text-zinc-950 outline-teal-600 focus-visible:outline-2 sm:py-2 sm:text-sm dark:border-white/10 dark:bg-zinc-950 dark:text-zinc-50 dark:outline-teal-400"
name="password"
onInvalid={() => setHasValidationError(true)}
/>
<PasswordFieldToggle className="absolute top-1/2 right-1 flex h-8 -translate-y-1/2 items-center justify-center gap-1.5 rounded px-2 text-sm font-medium text-zinc-500 outline-teal-600 hover:bg-zinc-100 hover:text-zinc-800 focus-visible:outline-2 dark:text-zinc-400 dark:outline-teal-400 dark:hover:bg-zinc-800 dark:hover:text-zinc-100">
{({ passwordVisible }) => {
if (passwordVisible) {
return (
<>
<EyeSlashIcon className="size-4" aria-hidden="true" />
Hide
</>
);
}
return (
<>
<EyeIcon className="size-4" aria-hidden="true" />
Show
</>
);
}}
</PasswordFieldToggle>
</div>
<Description className="text-base text-zinc-600 sm:text-sm dark:text-zinc-400">
You can paste a password or use your password manager.
</Description>
<FieldError className="text-base text-red-600 sm:text-sm dark:text-red-400">
Enter your password to sign in.
</FieldError>
</PasswordField>
<button
className="rounded bg-teal-600 px-3 py-2.5 text-base font-medium text-white outline-teal-600 hover:bg-teal-700 focus-visible:outline-2 focus-visible:outline-offset-2 sm:py-2 sm:text-sm dark:bg-teal-500 dark:hover:bg-teal-400"
type="submit"
>
Sign in
</button>
{signedIn && (
<p className="text-base text-emerald-700 sm:text-sm dark:text-emerald-400" role="status">
Signed in.
</p>
)}
</form>
);
}Anatomy
Dashed frames are invisible state providers; shaded shapes own real DOM. Numbered pins match the list below.
A wireframe sketch of the assembled component. Each numbered marker matches a part in the list that follows.
PasswordField
Field provider with an internal hidden-first reveal state; it owns no DOM unless as is supplied. Does not add a DOM element.
Label
Native label linked to the password input. Owns a DOM element.
PasswordFieldInput
Native password input that becomes text only while the field is revealed. Owns a DOM element.
PasswordFieldToggle
Client-only native button that reveals or re-hides the same input; its name changes between Show password and Hide password. Owns a DOM element.
Description / FieldErrorOptional
Linked help or error text. Owns a DOM element.
Step by step
- 1
Add the main part
Start PasswordField with a Label and PasswordFieldInput.
- 2
Add the supporting parts
Add PasswordFieldToggle plus Description and FieldError when people need help or validation feedback.
- 3
Make the behavior clear
Choose current-password for sign-in or new-password for a new credential; the field starts hidden and manages revealing itself.
Exampletsx <PasswordField required><Label>Password</Label><PasswordFieldInput name="password" autoComplete="current-password" /><PasswordFieldToggle /><Description>Use a password manager if you have one.</Description><FieldError>Enter your password.</FieldError></PasswordField>
Keyboard
- ⇥
- Moves from the password input to the reveal button.
- ↵Space
- Shows or hides the password from the reveal button.
- ↵
- Submits the surrounding form from the password input.
Forms and accessibility
PasswordFieldInput submits its native name and password value. It re-hides after the owning form submits and when a page is restored from the back-forward cache.
Accessibility checklist
- PasswordField is progressively enhanced: without JavaScript, the native password input still works; the reveal button appears only after hydration.
- Use autoComplete="current-password" for sign-in and autoComplete="new-password" for a new credential. Keep paste and password-manager filling available; PasswordFieldInput defaults to spellCheck={false} and autoCapitalize="none".
- The changing Show password and Hide password name describes the action, so the toggle does not use aria-pressed. Avoid confirm-password fields and maxLength: let people inspect or paste the credential, then show a clear validation error if needed.
API reference
import { Description, FieldError, Label, PasswordField, PasswordFieldInput, PasswordFieldToggle } from "@comp0/react";PasswordField
Context onlyField provider with an internal hidden-first reveal state; it owns no DOM unless as is supplied.
| Prop | Type | Description |
|---|---|---|
value | string | Controlled password value. |
defaultValue | string | Initial password value. |
onChange | (value: string) => void | Receives the next password value. |
disabled / invalid / required | boolean | Field-wide states shared with every part. |
visibleAnnouncement / hiddenAnnouncement | string | Localizes the polite status announced after the reveal state changes. |
Label
DOM elementNative label linked to the password input.
| Prop | Type | Description |
|---|---|---|
htmlFor | string | Auto-wired to the field control; set it only to override. |
PasswordFieldInput
DOM elementNative password input that becomes text only while the field is revealed.
| Prop | Type | Description |
|---|---|---|
name | string | Submission name for the password. |
autoComplete | "current-password" | "new-password" | Password-manager hint chosen for this form. |
spellCheck | boolean | Defaults to false to keep password text out of spell checking. |
autoCapitalize | string | Defaults to "none", including while the password is revealed as text. |
PasswordFieldToggle
DOM elementClient-only native button that reveals or re-hides the same input; its name changes between Show password and Hide password.
| Prop | Type | Description |
|---|---|---|
children | ({ passwordVisible }) => ReactNode | Optional visible content based on the current visibility; defaults to the current action label. |
showLabel / hideLabel | string | Localizes the changing accessible and default visible action labels. |
disabled | boolean | Overrides the field-wide disabled state for this button. |
Description / FieldError
OptionalDOM elementLinked help or error text.
| Prop | Type | Description |
|---|---|---|
forceMount | boolean | FieldError only: keep it rendered while the field is valid. |
Style hooks
Attributes that appear while a state is true. Target them with Tailwind data variants such as data-open:bg-zinc-100, or with any CSS selector.
[data-visible]on PasswordField wrapper, PasswordFieldInput, PasswordFieldToggle
- The password is revealed.
[data-invalid]on PasswordFieldInput
- The field is invalid.
[data-disabled]on PasswordFieldInput, PasswordFieldToggle
- The field is disabled.