Toolbox

Password Manager Ignore

See on GitHub

Data attributes to prevent password managers from hijacking your inputs.

'use client'

import { useState } from 'react'
import { cn } from '@/lib/utils'
import { ShieldOff, ShieldCheck, Mail, Lock } from 'lucide-react'

const pwIgnoreProps = {
  'data-1p-ignore': true,
  'data-lpignore': 'true',
  'data-bwignore': true,
  'data-form-type': 'other',
} as const

const inputClassName =
  'border-border bg-background text-foreground placeholder:text-muted-foreground focus:border-foreground focus:ring-foreground/10 w-full rounded-lg border px-3 py-2.5 text-sm outline-none transition-all duration-200 focus:ring-2'

function PwManagerIgnoreDemo() {
  const [withAttrs, setWithAttrs] = useState(true)

  // Key changes on toggle so inputs get re-created and pw managers
  // re-evaluate their targeting criteria on the fresh DOM elements.
  const inputKey = withAttrs ? 'ignored' : 'active'

  return (
    <div className="bg-muted/50 flex min-h-[500px] w-full items-center justify-center p-4 sm:p-8">
      <div className="w-full max-w-md space-y-6">
        <label className="flex cursor-pointer items-center justify-between">
          <div className="flex items-center gap-2">
            {withAttrs ? (
              <ShieldOff className="text-muted-foreground size-5" />
            ) : (
              <ShieldCheck className="size-5 text-amber-500" />
            )}
            <span className="text-foreground text-sm font-semibold">
              {withAttrs
                ? 'Password managers ignored'
                : 'Password managers active'}
            </span>
          </div>
          <button
            type="button"
            role="switch"
            aria-checked={withAttrs}
            onClick={() => setWithAttrs((v) => !v)}
            className={cn(
              'relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200',
              withAttrs ? 'bg-foreground' : 'bg-muted-foreground/30'
            )}
          >
            <span
              className={cn(
                'bg-background pointer-events-none inline-block size-5 rounded-full shadow-lg ring-0 transition-transform duration-200',
                withAttrs ? 'translate-x-5' : 'translate-x-0'
              )}
            />
          </button>
        </label>

        <form
          className="bg-card border-border space-y-4 rounded-xl border p-5 shadow-lg"
          onSubmit={(e) => e.preventDefault()}
          autoComplete="off"
        >
          <div className="space-y-1.5">
            <label className="text-foreground flex items-center gap-2 text-sm font-medium">
              <Mail className="size-4" />
              Email
            </label>
            <input
              key={`email-${inputKey}`}
              type="email"
              placeholder="you@example.com"
              autoComplete="off"
              className={inputClassName}
              {...(withAttrs && pwIgnoreProps)}
            />
          </div>

          <div className="space-y-1.5">
            <label className="text-foreground flex items-center gap-2 text-sm font-medium">
              <Lock className="size-4" />
              Password
            </label>
            <input
              key={`password-${inputKey}`}
              type="password"
              placeholder="********"
              autoComplete="off"
              className={inputClassName}
              {...(withAttrs && pwIgnoreProps)}
            />
          </div>

          <div className="space-y-1.5">
            <label className="text-foreground flex items-center gap-2 text-sm font-medium">
              OTP
            </label>
            <input
              key={`otp-${inputKey}`}
              type="text"
              placeholder="000000"
              inputMode="numeric"
              maxLength={6}
              autoComplete="one-time-code"
              className={inputClassName}
              {...(withAttrs && pwIgnoreProps)}
            />
          </div>

        </form>
      </div>
    </div>
  )
}

export default PwManagerIgnoreDemo

The problem

Password managers like 1Password, LastPass, and Bitwarden will try to autofill any input that looks like a username, email, or password field. This is annoying for inputs that aren't credentials — invite codes, OTPs, search bars, etc.

The fix

Add these data attributes to your inputs:

<input
  data-1p-ignore
  data-lpignore="true"
  data-bwignore
  data-form-type="other"
/>
AttributePassword Manager
data-1p-ignore1Password
data-lpignore="true"LastPass
data-bwignoreBitwarden
data-form-type="other"Dashlane

As a reusable helper

If you're doing this often, extract the attributes:

lib/pw-ignore.ts
export const pwIgnoreProps = {
  'data-1p-ignore': true,
  'data-lpignore': 'true',
  'data-bwignore': true,
  'data-form-type': 'other',
} as const
import { pwIgnoreProps } from '@/lib/pw-ignore'
 
<input type="text" placeholder="Invite code" {...pwIgnoreProps} />

Related Toolboxs