Built on Vercel’s UI SDK 0.1.0-beta.2. Its API may change.
Password input
A password field on Vercel's UI SDK with a show and hide toggle, a Caps Lock hint, a strength meter and the right autocomplete for password managers.
- Form components
- 6 parts
- 10 examples
@tabler/icons-react@ui-sdk/core@ui-sdk/react
pnpm dlx shadcn@latest add https://hextaui.com/r/ui-sdk-password-input.jsonAdds the component, the HextaUI theme tokens and any HextaUI components it depends on.
Add the theme tokens to your global CSS, if you haven’t yet.
Install the dependencies.
pnpm add @ui-sdk/react@0.1.0-beta.2 @ui-sdk/core@0.1.0-beta.2 @tabler/icons-react cnCopy and paste the following code into your project.
components/ui/ui-sdk-password-input.tsx Update the import paths to match your project setup.
UI SDK adds a little CSS of its own in a cascade layer named ui-sdk. Declare that layer at the top of your global stylesheet, above the Tailwind import, so your classes win over it.
The control stays a native password field, so password managers, autofill and form submission work as they do everywhere else. Put form options like name, required and autoComplete on PasswordInput, and input attributes like id and placeholder on PasswordInputControl.
autoComplete defaults to current-password for signing in. Use new-password to sign up or change a password, so the browser offers a strong one, and off for secrets that aren’t account passwords.
PasswordInputStrength scores the password from 0 to 4 as it’s typed. The checklist reads the same value with usePasswordInputValue(). The rules belong to the example, since the component sets no password policy.
Pair it with an email field set to autoComplete="username". Enter in the password submits the form, and submitting hides a shown password again so the browser offers to save it.
defaultVisible starts with the text showing, for a secret people need to read, like a Wi-Fi password.
A controller from createPasswordInputController() sets, shows, hides, clears and focuses the field from any button. Writes go through onValueChange like typing.
Pass visible and onVisibleChange. The reason tells a toggle press from a form submit, a reset or the page being hidden.
invalid marks the field and sets aria-invalid on the input. Point its aria-describedby at your message. A required field also turns red after someone leaves it empty.
A read-only field can be focused, shown and copied, but not changed, and still submits.
A disabled field and its toggle are skipped by Tab, and the value doesn’t submit.
The toggle sits on the left, and the strength meter fills from the right. Pass labels in your language.
| Key | Action |
|---|---|
| Tab | Moves from the field to the toggle. |
| SpaceEnter | Shows or hides the password from the toggle, and keeps focus on it. |
| Enter | Submits the form from the field. It never presses the toggle. |
The toggle is a toggle button with a fixed name, “Show password”, and aria-pressed tells screen readers whether the password is shown. Rename it for other secrets and languages. A pointer press on the toggle keeps the caret where it was in the field.
PasswordInputCapsLock opens below the field while Caps Lock is on and the field has focus, and says so through a status region. PasswordInputStrength is a meter whose value text is the strength label, read on demand rather than announced on every key. Shown passwords skip spellcheck, autocorrect and capitalization.
No part writes the password into a data-* attribute. The root and control only carry booleans like data-filled, and the meter carries the score. A controlled value does make React keep a value attribute in the DOM, so read the password with onValueChange or usePasswordInputValue() instead.
Each part wraps the UI SDK part of the same name and accepts all of its props, including render and a className that can be a function of the part’s state.
| Prop | Type | Default |
|---|---|---|
value | string | – |
defaultValue | string | – |
onValueChange | (value: string, details) => void | – |
visible | boolean | – |
defaultVisible | boolean | false |
onVisibleChangedetails.reason is toggle-press, form-submit, reset, page-hide or imperative. | (visible: boolean, details) => void | – |
autoComplete | "current-password" | "new-password" | "off" | string | "current-password" |
invalid | boolean | false |
disabled | boolean | false |
readOnly | boolean | false |
required | boolean | false |
name | string | – |
form | string | – |
controllerFrom createPasswordInputController(). | PasswordInputController | – |
| Attribute | Description |
|---|---|
data-slot="password-input" | Target the password input in CSS. |
data-visible | Present while the password is shown. |
data-capslock | Present while Caps Lock is on and the field has focus. |
data-filled | Present while the field holds any text. |
data-invalid | Present when invalid. |
data-disabled | Present when disabled. |
data-readonly | Present when read-only. |
data-required | Present when a password is required. |
The box around the field and the toggle. It draws the focus ring when the field has focus.
| Prop | Type | Default |
|---|---|---|
id | string | – |
placeholder | string | – |
render | ReactElement | (props, state) => ReactElement | – |
| Attribute | Description |
|---|---|
data-slot="password-input-control" | Target the native input in CSS. |
data-visible | Present while it’s a text field. |
| Prop | Type | Default |
|---|---|---|
aria-label | string | "Show password" |
childrenDefaults to an eye that crossfades to a closed eye. | ReactNode | (state) => ReactNode | – |
render | ReactElement | (props, state) => ReactElement | – |
| Attribute | Description |
|---|---|
data-slot="password-input-toggle" | Target the toggle in CSS. |
aria-pressed | true while the password is shown. |
| Prop | Type | Default |
|---|---|---|
children | ReactNode | "Caps Lock is on" |
| Attribute | Description |
|---|---|
data-slot="password-input-capslock" | Target the hint in CSS. |
data-active | Present while Caps Lock is on. |
| Prop | Type | Default |
|---|---|---|
getStrengthScores the password. The default weighs length, character variety, repeats and common passwords. Use a stronger estimator like zxcvbn for real policies. | (password: string) => 0 | 1 | 2 | 3 | 4 | scorePassword |
labels | [string, string, string, string, string] | ["", "Weak", "Fair", "Good", "Strong"] |
label | string | "Password strength" |
| Attribute | Description |
|---|---|
data-slot="password-input-strength" | Target the meter in CSS. |
data-score | The score, from 0 for empty to 4. |
- CalendarA date grid for single, range and multiple selection, with sliding months, range previews and touch-sized days.
- CheckboxA checkbox whose check draws in, with indeterminate parents, groups and labels that share its hover.
- ComboboxA filterable select with chips, groups and async results, in a popup that resizes as you type.
- Date pickerA button that opens a calendar in a popover, or a bottom sheet on phones, for single dates and ranges.
- FieldLabels, descriptions and errors wired to their control, with validation states and layouts for forms.
- InputA text input with three sizes, invalid and read-only states, native validation styling and a 16px touch font so phones never zoom in.