Skip to content

FormField has never rendered — delete it (FormError is live and must stay) #856

Description

@TortoiseWolfe

Corrected 2026-08-20. This issue as originally written was wrong twice, and acting on it as written would have broken production. Both corrections are folded into the body below rather than appended as comments.

  1. FormError is NOT dead — it is live. src/components/forms/ValidatedInput.tsx:6 imports it and renders it at :225. ValidatedInput is used by CaptainShipCrewWithNPC.tsx:606, which src/app/game/page.tsx mounts. Deleting FormError would break validation errors on /game. Only FormField is dead.
  2. There are no 5-file siblings to remove. src/components/forms/ contains only FormError.tsx, FormField.tsx, ValidatedInput.tsx and index.ts — all three are recorded as intentionally bare in scripts/audit-components.js:64-66 (KNOWN_BARE_COMPONENTS). Deletion is cheaper than claimed; adoption is more expensive, since it would mean creating five files that do not exist.

Also: the help-text gate is at FormField.tsx:84, not :82.

The finding

src/components/forms/FormField.tsx (140 lines) has been in the tree since the initial commit and is rendered nowhere. The only references outside the file itself are its own barrel re-export (src/components/forms/index.ts:10-11), two script comments, and two unrelated FormFieldConfig types. It has no .stories.tsx, so it never appears in Storybook either.

Every form in the product hand-rolls its own markup instead — ContactForm, SignInForm, SignUpForm.

Why it matters

It is not merely unused, it is misleading. It looks like the project's form-field abstraction, so the natural move when adding a field is to reach for it. Two things make that a trap:

  1. Its help text is gated {helpText && !error} (FormField.tsx:84) — the hint disappears the moment an error appears, removing the constraint exactly when the user needs it. That is the opposite of what Contact form constraints are invisible until submit fails — add help text to subject and message #855 asked for, and feat(#855): tell people the length limits before Send fails, not after #858 deliberately hand-rolled the hints in ContactForm rather than adopt this.
  2. It renders a label with htmlFor={name} but leaves the input entirely to the caller, so the ARIA wiring its own docstring advertises is not actually guaranteed by using it.

The decision

Delete FormField.tsx (leaving FormError and ValidatedInput alone), or adopt it across ContactForm / SignInForm / SignUpForm after first fixing the && !error gate and giving it the five-file structure it currently lacks.

The evidence now leans to delete: #858 has already shipped the help-text pattern by hand in ContactForm, so adopting would mean rewriting working, tested markup onto a component that has never rendered.

Blocks #857

Hand-rolling the ContactForm pattern into the auth forms for #857 effectively votes "delete" here. Either settle this first, or state the pre-commitment explicitly in #857's PR body. See also #547, of which this is a scoped subset.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions