一键导入
form-error-ux
Show inline validation errors with aria-invalid + aria-describedby. Focus first invalid field on submit. Use Kobalte Form.Field for a11y wiring.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Show inline validation errors with aria-invalid + aria-describedby. Focus first invalid field on submit. Use Kobalte Form.Field for a11y wiring.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Bump the patch version in server/Cargo.toml or website/package.json after completing a major change. Use when the user asks to bump/release a version, or when CLAUDE.md's rule about version bumps after major changes applies.
Before a non-trivial change, list affected systems — DB schema, API contract, Telegram handlers, jobs, TS types, docs. Catch ripple effects upfront, not after CI fails. Use when planning a feature, migration, refactor, or any cross-module touch.
Self-review before push — read the diff as a reader, scan for vixen footguns (token leaks, PII, idempotency, captcha asset overwrites), run validation pipeline, no surprise files. Use before "git push", before opening a PR, or when the user says "ready to commit".
Write a git commit message for vixen-rs following the project's Conventional Commits convention. Use when the user asks to commit, create a commit, or write a commit message.
Reproduce → bisect → root cause → fix → verify. Don't speculate, don't "add more error handling" as a guess. Use when something is broken, when a test fails intermittently, when the user says "this isn't working" or "investigate why".
Write small, fast, reproducible Dockerfiles for the vixen-rs server (Rust) and website (bun) using multi-stage builds, cache mounts, distroless/alpine runtime images, and non-root users. Use when editing server/Dockerfile, website/Dockerfile, docker-compose.yml, or when the user asks to shrink an image or speed up a Docker build.
| name | form-error-ux |
| description | Show inline validation errors with aria-invalid + aria-describedby. Focus first invalid field on submit. Use Kobalte Form.Field for a11y wiring. |
Source: Smashing Magazine — accessible form validation, WebAIM form validation.
Read first:
<Form.Field name="threshold" validationState={isValid() ? "valid" : "invalid"}>
<Form.Label>{t("settings.spam-threshold")}</Form.Label>
<Form.Input type="number" min={0} max={100} value={threshold()} onInput={onInput} />
<Form.Description>{t("settings.threshold-hint")}</Form.Description>
<Form.ErrorMessage>{errorMsg()}</Form.ErrorMessage>
</Form.Field>
Kobalte wires aria-invalid="true" on the input and links the error via aria-describedby automatically when validationState="invalid".
blur — first validation. Don't fire mid-typing; users hate it.async function onSubmit(e: SubmitEvent) {
e.preventDefault();
const errors = validateAll(form);
if (errors.length > 0) {
setErrorCount(errors.length); // for aria-live
requestAnimationFrame(() => errors[0].field.focus());
return;
}
await save();
}
<div aria-live="polite" class="sr-only">
<Show when={errorCount() > 0}>{t("forms.errors-count", { count: errorCount() })}</Show>
</div>
Disabled submit hides errors from SR users and is confusing. Let users submit; surface errors inline and at the form level.
Map ApiError.code to a specific field when possible; fall back to a form-level <Alert>:
catch (e) {
if (e instanceof ApiError && e.code === "THRESHOLD_OUT_OF_RANGE")
setFieldError("threshold", t("errors.threshold-range"));
else
setFormError(t("errors.generic"));
}
Error messages explain what + how to fix.
Invalid input.Threshold must be between 0 and 100. Try 50.Required.Reason is required to log this ban.Ban @user? This action is logged.Saved · 2s ago). No separate Save button when changes are non-destructive.Incorrect — new image generated and refetch.aria-describedby pointing at a non-existent id → SR reads nothing or stale text. Always render the error element (use hidden attr if no error) so the id is stable.placeholder → vanishes on type, fails a11y. Always use a separate element." bob " was accepted; show normalized value.ui-accessibility — focus-visible, aria patterns.interaction-states-kobalte — data-[invalid] styling.loading-empty-error-states — the wider error UX system.