macbetter

Text and fields

Secure Field

Enter a password, and show it when you need to read it.

Use at least 8 characters.
import { Field, FieldDescription, FieldLabel } from "macbetter/field"
import { SecureField } from "macbetter/secure-field"

export default function Example() {
  return (
    <div style={{ width: "100%", maxWidth: 300 }}>
      <Field name="password">
        <FieldLabel>Password</FieldLabel>
        <SecureField defaultValue="correct-horse" autoComplete="current-password" />
        <FieldDescription>Use at least 8 characters.</FieldDescription>
      </Field>
    </div>
  )
}

When to use it

Use a secure field for passwords, PINs and recovery keys. It looks like a Text Field but shows dots, offers the right password to password managers and hides the text again when its form submits.

Set autoComplete="current-password" when signing in and "new-password" when creating or changing one. Keep the show button unless the value is a PIN typed on a shared screen.

Usage

import { SecureField, SecureFieldInput, SecureFieldToggle } from "macbetter/secure-field"

Form options (name, required, disabled, readOnly, autoComplete, value) go on SecureField. placeholder, id, autoFocus and ARIA names go to the input. Pass children to lay out SecureFieldInput and SecureFieldToggle yourself.

Shown at first and no toggle

defaultVisible starts with the text shown, for something people read aloud or copy, like a Wi-Fi password. toggle={false} leaves the eye button out.

import { Field, FieldLabel } from "macbetter/field"
import { SecureField } from "macbetter/secure-field"

export default function Example() {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 16, width: "100%", maxWidth: 300 }}>
      <Field name="wifi-password">
        <FieldLabel>Wi-Fi password</FieldLabel>
        <SecureField defaultVisible defaultValue="maple-orbit-42" autoComplete="new-password" />
      </Field>
      <Field name="pin">
        <FieldLabel>Device PIN</FieldLabel>
        <SecureField toggle={false} inputMode="numeric" placeholder="Required" autoComplete="off" />
      </Field>
    </div>
  )
}

Platform behavior

  • macOS. The bordered text field. The eye sits at the trailing edge in secondary gray and turns accent while the password shows. While Caps Lock is on and the field is focused, a ⇪ appears beside it, as in the macOS login window.
  • iPadOS and iOS. The filled gray field at 44 points, with a 17-point eye that keeps a 44-point touch target.
  • Every platform. Dots are spaced slightly wider than letters, and the caret stays where it was when the password is shown or hidden.

Accessibility

  • The toggle is a real button with aria-pressed, named "Show password". Rename it with toggleLabel, like "Show recovery key".
  • The toggle is type="button", so Return in the field still submits the form.
  • The text is hidden again when the form submits or the page is hidden, so it isn't left on screen.

API

SecureField

PropTypeDefaultDescription
size"sm" | "md" | "lg""md"Height, padding and type size.
variant"auto" | "bordered" | "filled" | "plain""auto"Bordered on macOS and filled on touch, or a fixed look.
placeholderstring—Passed to the input.
togglebooleantrueShows the eye button.
toggleLabelstring"Show password"The eye button's name.
autoComplete"current-password" | "new-password" | "off""current-password"What password managers offer.
defaultVisiblebooleanfalseStarts with the text shown.
visibleboolean—Whether the text shows, for a controlled field.
onVisibleChange(visible, details) => void—Runs when the text is shown or hidden.

SecureFieldInput takes the props of an input; SecureFieldToggle the props of a button, and draws eye or eye.slash unless it has children.

Data attributes

AttributeOnValues
data-size, data-variantSecureFieldAs on Text Field
data-visibleEvery partPresent while the text shows
data-capslockEvery partPresent while Caps Lock is on and the field is focused
data-filled, data-disabled, data-readonlyEvery partField state

CSS variables

It reads the Text Field's variables: --mb-text-field-radius, --mb-text-field-padding, --mb-text-field-font and --mb-text-field-icon.