form-patterns
Form design and validation patterns. UX, accessibility, React Hook Form, Zod, error handling.
소스 정보
- 저장소
- skeletorflet/opencode-kit
- 최근 소스 활동
- 2026년 4월 3일 15:32
- 감지된 SKILL.md 언어
- 영어
- 스타
- 10
- 포크
- 1
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
SKILL.md 표시 중
SKILL.md
소스 지침 · 읽기 전용 미리보기- name
- form-patterns
- description
- Form design and validation patterns. UX, accessibility, React Hook Form, Zod, error handling.
# Form Patterns
> Forms are where users do work. Remove every obstacle.
---
## 1. Form Anatomy
```
Label (above input, never placeholder-only)
Input / Select / Checkbox / Radio
Helper text (optional guidance below)
Error message (replaces helper text on error)
```
---
## 2. Input Types Reference
| Data | Input Type |
|------|-----------|
| Short text | `<input type="text">` |
| Email | `<input type="email">` |
| Password | `<input type="password">` + show toggle |
| Number | `<input type="number">` or text + mask |
| Long text | `<textarea>` |
| Date | Native `date` or custom picker |
| One of few options | Radio group (≤5) or Select (>5) |
| Many options | Multi-select or Combobox |
| Boolean | Checkbox or Toggle |
| File | `<input type="file">` with drag zone |
---
## 3. Validation Strategy
```
When to validate:
├── On blur (field loses focus) → best UX
├── On submit → acceptable
├── On change → only after first error shown (revalidate)
└── NEVER on keypress for first validation
Server-side:
├── Always re-validate server-side regardless of client
├── Return field-level errors { field: "email", message: "..." }
└── Show server errors inline next to fields
```
---
## 4. React Hook Form + Zod
```tsx
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
const schema = z.object({
email: z.string().email("Invalid email"),
password: z.string().min(8, "Min 8 characters"),
});
type FormData = z.infer<typeof schema>;
export function LoginForm() {
const { register, handleSubmit, formState: { errors, isSubmitting } } = useForm<FormData>({
resolver: zodResolver(schema),
});
const onSubmit = async (data: FormData) => {
await loginUser(data);
};
return (
<form onSubmit={handleSubmit(onSubmit)} noValidate>
<div>
<label htmlFor="email">Email</label>
<input id="email" type="email" {...register("email")}
aria-describedby={errors.email ? "email-error" : undefined}
aria-invalid={!!errors.email} />
{errors.email && (
<span id="email-error" role="alert">{errors.email.message}</span>
)}
</div>
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? "Logging in..." : "Log in"}
</button>
</form>
);
}
```
---
## 5. Error Message Guidelines
| ❌ Bad | ✅ Good |
|--------|---------|
| "Invalid input" | "Email must include @" |
| "Error 422" | "This email is already registered" |
| "Required" | "Please enter your name" |
| "Password wrong" | "Incorrect password. Forgot it?" |
**Rules:**
- Tell what\'s wrong AND how to fix it
- Place error directly under the field
- Use `role="alert"` for screen readers
- Red text with icon; never red alone (color blindness)
---
## 6. Multi-Step Forms
```
Progress indicator:
Step 1: Account Step 2: Profile Step 3: Review
Rules:
├── Show step X of Y
├── Allow back navigation without data loss
├── Persist state (localStorage / URL params)
├── Validate step before proceeding
└── Show summary on final step before submit
```
---
## 7. Accessibility Checklist
- [ ] Every input has associated `<label>` (not just placeholder)
- [ ] Error messages linked via `aria-describedby`
- [ ] Invalid fields have `aria-invalid="true"`
- [ ] Required fields marked with `required` attr + visual indicator
- [ ] Form submittable via keyboard (Enter)
- [ ] Focus moves to first error after failed submit
- [ ] Autocomplete attributes set (`autocomplete="email"` etc.)
---
## 8. UX Patterns
| Pattern | Description |
|---------|-------------|
| **Inline validation** | Validate on blur, not keypress |
| **Password strength** | Visual meter + requirements list |
| **Input masks** | Phone, credit card, date formatting |
| **Autofocus** | First field on page load (not modals unless modal-only) |
| **Smart defaults** | Pre-fill from account, geolocation |
| **Disable submit** | Only while submitting (not on invalid) |
| **Success feedback** | Clear confirmation, not just form reset |
---
## 9. Anti-Patterns
| ❌ Don\'t | ✅ Do |
|----------|-------|
| Placeholder as label | Visible label always |
| Validate on every keypress | Validate on blur |
| Generic "form error" at top only | Field-level inline errors |
| Password confirm field | Show/hide toggle instead |
| Disable browser autocomplete | Allow it |
| Asterisk without explanation | "(required)" in legend or label |
"""
GitHub에서 보기