Interface: Forms
Rule
Input Types
- MUSTCorrect
typefor keyboard/validation:email,tel,url,number,search,password
Input Attributes
- MUST
autocomplete+ meaningfulnamefor login/address forms - SHOULD
spellcheck="false"for emails, codes, usernames - SHOULD
data-1p-ignoreto suppress password manager icons where unwanted
<input type="text" spellcheck="false" autocomplete="off" data-1p-ignore />
Input Decorations
- SHOULDPosition icons absolutely inside input with padding offset
- MUSTClickable icons trigger input focus
<div className="relative">
<SearchIcon className="absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none text-gray-400" />
<input className="pl-10 ..." />
</div>
iOS
- MUST
text-baseminimum on mobile inputs (16px prevents zoom on focus)
Autofocus
- SHOULDAutofocus primary input on desktop
- NEVERAutofocus on touch devices (opens keyboard unexpectedly)
<input autoFocus={!('ontouchstart' in window)} />
Form Behavior
- MUSTWrap inputs in
<form>for Enter submission - MUST⌘/Ctrl+Enter submits
<textarea>; Enter adds newline - MUSTKeep submit enabled until request starts, then disable + show spinner + keep original label
- MUSTUse idempotency keys on submit to prevent duplicate requests
- MUSTAccept free text input; validate after, don't block typing
- MUSTAllow submitting incomplete forms to surface validation errors
- MUSTWarn on unsaved changes before navigation
- MUSTAllow pasting (never block paste)
- MUSTTrim whitespace from values
- MUSTHydration-safe inputs — no lost focus or value after hydration
- MUSTCompatible with password managers and 2FA; allow pasting one-time codes
- SHOULDPrefill with user data when available
- SHOULDPlaceholder ends with ellipsis:
Search…,sk-012345…
Buttons
- MUSTDisable after submission to prevent duplicates
- SHOULDShow keyboard shortcut in tooltip:
Save (⌘S) - SHOULD
active:scale-[0.97]for press feedback
<button className="active:scale-[0.97] transition-transform">Submit</button>
Checkboxes/Radios
- MUSTNo dead zones — entire row clickable
<label className="flex items-center gap-2 cursor-pointer">
<input type="checkbox" />
<span>Remember me</span>
</label>
Validation
- MUSTUse
aria-invalidon invalid inputs
<input aria-invalid={!!error} className={error ? "border-red-500" : ""} />
{error && <span className="text-sm text-red-500">{error}</span>}
Destructive Actions
- MUSTRequire confirmation (use
AlertDialog, notconfirm())