# Don't Block Typing

**MUST** · **ID:** `forms-dont-block-typing` · **Category:** forms
**Source:** [Vercel](https://github.com/vercel-labs/agent-skills/blob/main/skills/web-design-guidelines/SKILL.md)
**Interactive version:** https://ui-guides-agent-rules.netlify.app/principles/forms-dont-block-typing

> MUST: Don't block typing; accept free text and validate after

Allow all input and show validation feedback instead of blocking keystrokes

When you prevent users from typing certain characters, they don't understand why their keyboard isn't working. It's better to accept all input and provide clear validation messages that explain what format is expected.

## Bad — do not do this

`forms-dont-block-typing-bad`

```tsx
import { useState } from 'react';

export function DontBlockTypingBad() {
  const [phoneNumber, setPhoneNumber] = useState('');

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const value = e.target.value;
    if (/^\d*$/.test(value)) {
      setPhoneNumber(value);
    }
  };

  return (
    <div className="w-full max-w-sm">
      <div>
        <label htmlFor="bad-phone" className="block text-sm font-medium text-foreground mb-1">
          Phone Number (numbers only)
        </label>
        <input
          id="bad-phone"
          type="text"
          value={phoneNumber}
          onChange={handleChange}
          className="w-full px-3 py-2 border border-border rounded-lg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
          placeholder="5551234567"
        />
      </div>
      <p className="text-xs text-muted-foreground mt-4">
        Try typing letters - they're blocked with no explanation
      </p>
    </div>
  );
}
```

## Good — do this

`forms-dont-block-typing-good`

```tsx
import { useState } from 'react';

export function DontBlockTypingGood() {
  const [phoneNumber, setPhoneNumber] = useState('');
  const [error, setError] = useState('');

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const value = e.target.value;
    setPhoneNumber(value);

    if (value && !/^\d+$/.test(value)) {
      setError('Please enter numbers only');
    } else {
      setError('');
    }
  };

  return (
    <div className="w-full max-w-sm">
      <div>
        <label htmlFor="good-phone" className="block text-sm font-medium text-foreground mb-1">
          Phone Number
        </label>
        <input
          id="good-phone"
          type="text"
          value={phoneNumber}
          onChange={handleChange}
          className={`w-full px-3 py-2 border rounded-lg focus-visible:outline-hidden focus-visible:ring-2 ${
            error
              ? 'border-error/50 focus-visible:ring-error'
              : 'border-border focus-visible:ring-ring'
          }`}
          placeholder="5551234567"
        />
        {error && (
          <p className="text-xs text-error mt-1">{error}</p>
        )}
      </div>
      <p className="text-xs text-success mt-4">
        All input allowed - clear feedback about format
      </p>
    </div>
  );
}
```

## References

- [Form Validation UX](https://www.nngroup.com/articles/errors-forms-design-guidelines/)
