Two findings + a stale comment crossed the production build threshold
because the eslint-disable-next-line directives didn't actually cover
the line that triggered the rule.
- clients-by-country-widget.tsx: the disable on line 96 targeted the
JSX `href={` opener on line 97, but the `as any` cast lived on
line 98. Collapsed to one line so the directive applies to the
cast directly.
- use-form-scroll-to-error.ts: single disable above the type alias
targeted the type's name line, not the `any` typed params two lines
below. Moved per-param disables next to each `any`.
`pnpm lint`: 3 errors -> 0 errors (41 warnings unchanged).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two new building blocks for the platform-wide form-error UX rework.
Expense form adopts both as the validation that the pattern works
before the broader sweep across the ~29 useForm callers.
- `useFormScrollToError(handleSubmit, errors)` — wraps RHF's
handleSubmit. On validation failure it locates the first errored
field via `[name="..."]` (or id fallback), walks ancestors to find
the nearest scrolling container (key for forms inside Sheet /
Dialog bodies that own their own overflow-y), and
scrollTo({ behavior: 'smooth' }) + focus({ preventScroll }) on it.
Type-loose handleSubmit signature so 2-arg and 3-arg useForm()
callers (input vs transformed types) both work.
- `<FormErrorSummary errors={errors} labels={…}>` — top-of-form alert
banner listing each failed field as a clickable anchor. Renders
only when ≥2 errors (single-error case is handled by the hook
alone). role="alert" aria-live="polite" for SR users.
- expense-form-dialog adopts both: `onSubmitWithScroll(onSubmit)`
replaces the bare `handleSubmit(onSubmit)`, plus a labelled
`<FormErrorSummary>` at the top of the form. Closes the loop on
the silent-no-op zod-refine bug fixed in PR1 (the underlying
setValue() fix already routes errors through formState; this
surfaces them visibly).
tsc clean. 1419/1419 vitest pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>