PasswordInput

Capture password data from user

Import

Usage

PasswordInput component supports Input and Input.Wrapper components features and all input element props. PasswordInput documentation does not include all features supported by the component – see Input documentation to learn about all available features.

Input description

Variant
Size
Radius
import { PasswordInput } from '@mantine/core';

function Demo() {
  return (
    <PasswordInput
      label="Input label"
      description="Input description"
      placeholder="Input placeholder"
    />
  );
}

Controlled

import { useState } from 'react';
import { PasswordInput } from '@mantine/core';

function Demo() {
  const [value, setValue] = useState('');
  return <PasswordInput value={value} onChange={(event) => setValue(event.currentTarget.value)} />;
}

Controlled visibility toggle

Control visibility state with visible and onVisibilityChange props, for example, the props can be used to sync visibility state between two inputs:

import { useDisclosure } from '@mantine/hooks';
import { PasswordInput, Stack } from '@mantine/core';

function Demo() {
  const [visible, { toggle }] = useDisclosure(false);
  return (
    <Stack>
      <PasswordInput
        label="Password"
        defaultValue="secret"
        visible={visible}
        onVisibilityChange={toggle}
      />
      <PasswordInput
        label="Confirm password"
        defaultValue="secret"
        visible={visible}
        onVisibilityChange={toggle}
      />
    </Stack>
  );
}

Change visibility toggle icon

To change visibility toggle icon, pass a React component that accepts reveal prop to visibilityToggleIcon:

import { PasswordInput } from '@mantine/core';
import { IconEyeCheck, IconEyeOff } from '@tabler/icons-react';

function Demo() {
  return (
    <PasswordInput
      label="Change visibility toggle icon"
      placeholder="Change visibility toggle icon"
      defaultValue="secret"
      visibilityToggleIcon={({ reveal }) =>
        reveal ? (
          <IconEyeOff style={{ width: 'var(--psi-icon-size)', height: 'var(--psi-icon-size)' }} />
        ) : (
          <IconEyeCheck style={{ width: 'var(--psi-icon-size)', height: 'var(--psi-icon-size)' }} />
        )
      }
    />
  );
}

Strength meter example

Password strength meter example with Progress and Popover components:

import { useState } from 'react';
import { IconX, IconCheck } from '@tabler/icons-react';
import { PasswordInput, Progress, Text, Popover, Box, rem } from '@mantine/core';

function PasswordRequirement({ meets, label }: { meets: boolean; label: string }) {
  return (
    <Text
      c={meets ? 'teal' : 'red'}
      style={{ display: 'flex', alignItems: 'center' }}
      mt={7}
      size="sm"
    >
      {meets ? (
        <IconCheck style={{ width: rem(14), height: rem(14) }} />
      ) : (
        <IconX style={{ width: rem(14), height: rem(14) }} />
      )}{' '}
      <Box ml={10}>{label}</Box>
    </Text>
  );
}

const requirements = [
  { re: /[0-9]/, label: 'Includes number' },
  { re: /[a-z]/, label: 'Includes lowercase letter' },
  { re: /[A-Z]/, label: 'Includes uppercase letter' },
  { re: /[$&+,:;=?@#|'<>.^*()%!-]/, label: 'Includes special symbol' },
];

function getStrength(password: string) {
  let multiplier = password.length > 5 ? 0 : 1;

  requirements.forEach((requirement) => {
    if (!requirement.re.test(password)) {
      multiplier += 1;
    }
  });

  return Math.max(100 - (100 / (requirements.length + 1)) * multiplier, 10);
}

function Demo() {
  const [popoverOpened, setPopoverOpened] = useState(false);
  const [value, setValue] = useState('');
  const checks = requirements.map((requirement, index) => (
    <PasswordRequirement key={index} label={requirement.label} meets={requirement.re.test(value)} />
  ));

  const strength = getStrength(value);
  const color = strength === 100 ? 'teal' : strength > 50 ? 'yellow' : 'red';

  return (
    <Popover opened={popoverOpened} position="bottom" width="target" transitionProps={{ transition: 'pop' }}>
      <Popover.Target>
        <div
          onFocusCapture={() => setPopoverOpened(true)}
          onBlurCapture={() => setPopoverOpened(false)}
        >
          <PasswordInput
            withAsterisk
            label="Your password"
            placeholder="Your password"
            value={value}
            onChange={(event) => setValue(event.currentTarget.value)}
          />
        </div>
      </Popover.Target>
      <Popover.Dropdown>
        <Progress color={color} value={strength} size={5} mb="xs" />
        <PasswordRequirement label="Includes at least 6 characters" meets={value.length > 5} />
        {checks}
      </Popover.Dropdown>
    </Popover>
  );
}

Error state

Invalid name

import { PasswordInput } from '@mantine/core';

function Demo() {
  return (
    <>
      <PasswordInput label="Boolean error" placeholder="Boolean error" error />
      <PasswordInput
        mt="md"
        label="With error message"
        placeholder="With error message"
        error="Invalid name"
      />
    </>
  );
}

Styles API

PasswordInput supports Styles API, you can add styles to any inner element of the component withclassNames prop. Follow Styles API documentation to learn more.

Description

Error

Component Styles API

Hover over selectors to highlight corresponding elements

/*
 * Hover over selectors to apply outline styles
 *
 */

Get element ref

import { useRef } from 'react';
import { PasswordInput } from '@mantine/core';

function Demo() {
  const ref = useRef<HTMLInputElement>(null);
  return <PasswordInput ref={ref} />;
}

Accessibility

If PasswordInput is used without label prop, it will not be announced properly by screen reader:

import { PasswordInput } from '@mantine/core';

// Inaccessible input – screen reader will not announce it properly
function Demo() {
  return <PasswordInput />;
}

Set aria-label to make the input accessible. In this case label will not be visible, but screen reader will announce it:

import { PasswordInput } from '@mantine/core';

// Accessible input – it has aria-label
function Demo() {
  return <PasswordInput aria-label="My input" />;
}

If label prop is set, input will be accessible it is not required to set aria-label:

import { PasswordInput } from '@mantine/core';

// Accessible input – it has associated label element
function Demo() {
  return <PasswordInput label="My input" />;
}

To set aria-label on the visibility toggle button, use visibilityToggleButtonProps prop:

import { PasswordInput } from '@mantine/core';

function Demo() {
  return (
    <PasswordInput
      label="Password"
      visibilityToggleProps={{ 'aria-label': 'Toggle password visibility' }}
    />
  );
}