Password
Masked entry with a reveal toggle, and a requirements block that reports which rules a password meets as it is typed.
Must contain at least;
- At least 1 symbol, not met
- At least 1 uppercase, not met
- At least 1 number, not met
- At least 8 characters, not met
<PasswordInput
size="md"
label="Password"
info="Use something you have not used elsewhere."
forgotHref="/reset"
/>Requirements
This is the part worth reading. Yöte does not decide what a good password is. The rules are yours, passed in as { label, test } pairs. The component runs each test against the current value, renders whether it passes, and counts how many do. That is the same line the rest of the library holds: validation state comes in as a prop, and this is the prop.
import { PasswordInput } from 'yote-ui'
<PasswordInput
label="Password"
requirements={[
{ label: 'At least 12 characters', test: (v) => v.length >= 12 },
{ label: 'Not your email', test: (v) => !v.includes(email) },
]}
/>Leave requirements unset and it uses the four below, so the field is useful with nothing configured. They are exported, so you can spread, filter or extend them rather than retyping.
import { DEFAULT_PASSWORD_REQUIREMENTS } from 'yote-ui'
// At least 1 symbol /[^\w\s]/
// At least 1 uppercase /[A-Z]/
// At least 1 number /\d/
// At least 8 characters v.length >= 8
<PasswordInput
requirements={[
...DEFAULT_PASSWORD_REQUIREMENTS,
{ label: 'Not a common password', test: (v) => !COMMON.has(v) },
]}
/>Pass requirements={[]}, or showRequirements={false}, and the whole block disappears. A sign-in field wants the input and nothing else.
Strength
The bar has one segment per rule, so it keeps working whether you pass three or six. The ramp is named rather than counted, and reads off data-strength on the requirements block.
| data-strength | Colour | When |
|---|---|---|
none | Grey | Nothing typed yet. |
partial | Amber | One rule up to all but one. Only the met segments fill. |
strong | Green | Every rule passes. |
invalid | Red | The consumer says the entry is wrong. Colours the whole bar. |
Two orderings are deliberate. invalid beats the count, because a green bar inside a red field claims the entry is fine and wrong at once. And disabled beats everything: a disabled field shows neutral marks, not greyed ticks, since a tick on a field nobody can type into reports an achievement that was never earned.
Props
| Prop | Type | Default | Notes |
|---|---|---|---|
requirements | PasswordRequirement[] | the four below | Rules to report on. Pass [] to hide the block. |
requirementsTitle | ReactNode | "Must contain at least;" | Heading above the list. |
showRequirements | boolean | true | Show the strength bar and list. |
revealable | boolean | true | Show the reveal toggle. |
forgotHref | string | — | Renders the forgot link under the field. |
forgotLabel | ReactNode | "Forgot password" | Text for that link. |
info | string | — | Info marker beside the label, with this as its tooltip. |
Shared
| Prop | Type | Default | Notes |
|---|---|---|---|
value | string | — | Controlled value. |
defaultValue | string | — | Initial value when uncontrolled. |
onChange | (value: string) => void | — | Receives the value, never the event. |
label | ReactNode | — | Rendered as a real <label> wired by htmlFor. |
hint | ReactNode | — | Helper text under the field. |
error | ReactNode | — | Error text. Implies invalid unless invalid says otherwise. |
invalid | boolean | — | Forces the error styling on or off. |
errorKey | string | number | — | Change it to replay the error animation. |
disabled | boolean | false | Greys the field out. |
readOnly | boolean | false | Reads as filled, stays focusable. |
size | 'sm' | 'md' | 'lg' | 'md' | Size scale, where the component defines one. |
classNames | Record<Part, string> | — | Per-part class names. |
Accessibility
The rule list is the accessible source of truth: each item announces its label and whether it is met, and the bar above it is hidden from assistive tech because it says the same thing in colour. The reveal control is a real toggle with aria-pressed, and the input keeps autocomplete="current-password" so managers still work.