PasswordInput
Password field with a reveal eye, a strength tooltip and a generator. It is
InputBlock with the eye as its icon and a
Tooltip listing the rules the password has to meet.
Use this when / not when
- Use where a password is being set — signing up, resetting, changing — and the rules should be shown as they are met.
- Use
simpleViewwhere a password is only being entered, as at sign-in: it keeps the field and the eye and drops the checking entirely. - Not for any other secret. An API key or a token gets no value from the strength rules;
InputBlockwith an eye of your own is simpler. - Not to show the rules on their own. Every tooltip string is a prop, and an empty one is an empty line.
Import
import { PasswordInput } from "@onlyoffice/apps-ui-kit/components/password-input";
Also exported from the root barrel @onlyoffice/apps-ui-kit.
PasswordInputProps is not exported; PasswordInputHandle, the type of the ref, is.
Needs ThemeProvider from @onlyoffice/apps-ui-kit/providers/theme. Nothing here is
translated for you — every label in the tooltip is a prop.
Stories
Default
The field as a sign-up form uses it: type a character to open the rules tooltip and watch each rule turn green as the value meets it; change any other prop live in the Controls panel below.
Simple View
A sign-in form only needs the field and the eye button: the simple view drops the rules tooltip and skips rule checking, so the field accepts any value (simpleView).
States
Three fields a form may need side by side: Normal, ready for input; Disabled, greyed out with typing blocked and no tooltip (isDisabled); With error, drawn with a red border to flag a value the form rejected (hasError).
Custom Validation
A policy that asks for less: type into the field and the tooltip lists only a minimum length of 8, capital letters and digits, because special characters are switched off (passwordSettings).
Sizes
Pick the height that matches the other fields of the form: base, middle and large (size).

With Password Generator
Saves the user from inventing a password that meets every rule: type a character to open the tooltip, then click Generate password at its bottom; the field fills with a random password that passes all rules and shows its characters (generatePasswordTitle, symbols picked from generatorSpecial).
Right To Left
The field in a right-to-left layout: the hidden characters line up from the right edge and the eye button moves to the left end. The wrapper carries dir="rtl"; the direction also comes from the theme's interfaceDirection (the Direction toolbar).
Css Customization
The input variables set on one wrapper -- the variables are listed under CSS variables on this page. The example sets every variable but the tooltip width, which a wrapper cannot reach; hover and focus the field to see the border colors.
Minimal example
The field keeps the password itself; onChange's second argument is the value to store.
import { useState } from "react";
import { PasswordInput } from "@onlyoffice/apps-ui-kit/components/password-input";
export function NewPassword() {
const [password, setPassword] = useState("");
const [isStrong, setIsStrong] = useState(false);
return (
<PasswordInput
id="new-password"
inputValue={password}
isDisableTooltip
hasError={Boolean(password) && !isStrong}
onChange={(_event, value) => setPassword(value ?? "")}
onValidateInput={(passes) => setIsStrong(passes)}
/>
);
}
Props
Inherited from CommonProps
Declared by components/input-block and accepted here too.
Inherited from TextInputProps
Declared by components/text-input and accepted here too.
Plus 298 more props inherited from React.AriaAttributes, React.DOMAttributes, React.HTMLAttributes and React.InputHTMLAttributes, forwarded to the element.
Enums
Recipes
The rules tooltip, with a generator
Every string in the tooltip is a prop; generatePasswordTitle is what adds the generate link,
and without it there is no way to reach the generator except through the ref.
import { useState } from "react";
import { PasswordInput } from "@onlyoffice/apps-ui-kit/components/password-input";
const SETTINGS = {
minLength: 8,
upperCase: true,
digits: true,
specSymbols: true,
};
export function SignUpPassword() {
const [password, setPassword] = useState("");
const [isStrong, setIsStrong] = useState(false);
return (
<PasswordInput
id="sign-up-password"
inputValue={password}
passwordSettings={SETTINGS}
hasError={Boolean(password) && !isStrong}
tooltipPasswordTitle="Password must contain:"
tooltipPasswordLength="at least 8 characters"
tooltipPasswordDigits="a digit"
tooltipPasswordCapital="a capital letter"
tooltipPasswordSpecial="a symbol (!@#$%^&*)"
generatePasswordTitle="Generate password"
onChange={(_event, value) => setPassword(value ?? "")}
onValidateInput={(passes) => setIsStrong(passes)}
/>
);
}
Entering an existing password
simpleView is the sign-in shape: field, eye, nothing else. No tooltip, no generator, and
onValidateInput is never called.
import { useState } from "react";
import { PasswordInput } from "@onlyoffice/apps-ui-kit/components/password-input";
export function SignInPassword() {
const [password, setPassword] = useState("");
return (
<PasswordInput
id="sign-in-password"
simpleView
autoComplete="current-password"
inputValue={password}
placeholder="Password"
onChange={(_event, value) => setPassword(value ?? "")}
/>
);
}
Disabled / read-only
isDisabled greys the field, removes the eye — InputBlock drops
its icon when disabled — and forces the value back to hidden if it was revealed.
import { PasswordInput } from "@onlyoffice/apps-ui-kit/components/password-input";
export function LockedPassword({ password }: { password: string }) {
return (
<PasswordInput id="locked-password" inputValue={password} isDisabled />
);
}
Generating from outside
The ref gives you the generator and the current value, which is how a "generate" button
outside the field works.
import { useRef, useState } from "react";
import { Button, ButtonSize } from "@onlyoffice/apps-ui-kit/components/button";
import {
PasswordInput,
type PasswordInputHandle,
} from "@onlyoffice/apps-ui-kit/components/password-input";
export function PasswordWithButton() {
const handle = useRef<PasswordInputHandle | null>(null);
const [password, setPassword] = useState("");
return (
<div>
<PasswordInput
id="generated-password"
ref={handle}
inputValue={password}
isDisableTooltip
onChange={(_event, value) => setPassword(value ?? "")}
/>
<Button
size={ButtonSize.small}
label="Generate"
onClick={(event) => handle.current?.onGeneratePassword(event)}
/>
</div>
);
}
Behaviour the types don't state
inputValueis a seed, not a controlled value. The component holds the password in its own state; settinginputValueto something new is ignored, except when it becomes""— which does clear the field — or whenisSimulateTypeis on. Read the value back fromonChange's second argument or from theref.- The tooltip opens by itself, and needs
hasErrorto close. It opens whenever the value is shorter thanminLength, orhasErrororhasWarningis set; it closes only when the length is met andhasErroris defined and false. LeavehasErrorout altogether and the tooltip never closes on its own. - Two fields on one page need distinct
ids. The tooltip is anchored by a selector built fromidor, failing that,inputName— which defaults topasswordInputfor everyone. Two fields without ids share one anchor and the tooltip attaches to the wrong field. simpleViewdisables validation, not just the tooltip. The change handler stores the value and returns before checking, soonValidateInputnever fires and the strength state stays at its initial value.- The default rules check length only.
passwordSettingsdefaults tominLength: 8withupperCase,digitsandspecSymbolsallfalse, so a weak password passes unless you pass your own settings. isSimulateTyperenders a text input. The value shown issimulateSymbolrepeated, the real password lives in state, and the caret is restored by looking updocument.getElementById("conversion-password")— a literal id. Give the field exactly thatidor the caret jumps to the end on every keystroke.- Nothing in the tooltip is translated.
tooltipPasswordTitleand its siblings are printed as given; an omitted one renders an empty line, and the rules list still reserves its space. - The generate link appears only with
generatePasswordTitle. Without it the generator is reachable only through theref. - Generating reveals the password. The generated value is written into the field and the
type switches to
text, so the user sees what was made; the eye hides it again. isDisabledalso un-reveals: an effect forces the type back topassword, so a revealed field hides itself when it is disabled.scaledefaults totruehere, unlikeInputBlock, andautoCompleteto"new-password"; pass"current-password"at sign-in.sizefalls back toInputSize.middle, notbase.emailInputName,clipActionResourceandclipCopiedResourceare dead: they feed a copy button that is not rendered.- A click anywhere outside closes the tooltip, through a
mousedownlistener on the document.
CSS variables
The field's colours come from the shared input styles, so they follow
TextInput: set its --text-input-bg, --text-input-color,
--text-input-border-color, --text-input-border-hover, --text-input-border-focus and
--text-input-radius on any ancestor of the field. The tooltip follows
Tooltip. The rules in the tooltip are coloured green or red from the
kit's status colours, which are not overridable.
| Variable | Default | Effect |
|---|---|---|
--password-input-tooltip-width | 294px | Width of the rules tooltip on tablet and desktop |
The rules tooltip is rendered in a portal at the end of <body>, so a value set on a wrapper
around the field never reaches it: set --password-input-tooltip-width on :root or body. On
mobile the width is a fixed 320px and the variable is not read.
Accessibility
- The eye is
InputBlock's icon button, and it carries no label, so a screen reader announces an unnamed control that changes nothing it can perceive. - The strength tooltip is not tied to the field. It is opened imperatively and has no
aria-describedby, so the rules and whether they are met are invisible to assistive technology — and colour is the only signal that a rule now passes. - The field has no label of its own. Use
FieldContainerorLabelwithhtmlForpointing atid. - It is not in the tab order unless you pass
tabIndex. The prop goes straight toInputBlock, whose own default is-1. PasstabIndex={0}. isSimulateTypeputs the password into atype="text"field. Password managers, the browser's own reveal control and assistive technology all treat it as ordinary text; avoid it where a real password field will do.tabIndexcomes fromInputBlock, which defaults it to -1 — passtabIndex={0}or the field is not reachable by keyboard.
Test ids
| Element | data-testid |
|---|---|
| The wrapper | password-input, or testId |
| The tooltip anchor | tooltipContent |
| The eye | password_input_eye_icon, password_input_eye_off_icon |
| The generate link | generate_password_link |
Related
InputBlock— the field and icon underneath.TextInput— where most of the inherited props are documented.Tooltip— what the rules are shown in.