Skip to content

BatchForm's per-recipient address/amount Inputs have no label or aria-label — the only financial form in the app with this gap #54

Description

@abayomicornelius

Problem

BatchForm's per-recipient address and amount fields are the only Input usages in the app's financial forms with no label prop and no aria-label fallback, unlike every other form in the app.

// src/components/BatchSend/BatchForm.tsx:89-105
<div className="flex-1 space-y-2">
  <Input
    placeholder="G... recipient address"
    fullWidth
    error={errors.recipients?.[index]?.destinationAddress?.message}
    {...register(`recipients.${index}.destinationAddress` as const)}
  />
  <Input
    placeholder="Amount"
    type="number"
    min="0"
    step="0.0000001"
    fullWidth
    error={errors.recipients?.[index]?.amount?.message}
    {...register(`recipients.${index}.amount` as const)}
  />
</div>

Neither Input receives a label. Input's own implementation only renders a <label> element — and only generates an id/htmlFor pairing at all — when label is provided:

// src/components/ui/Input.tsx:13-29
export const Input = forwardRef<HTMLInputElement, InputProps>(
  ({ label, error, hint, leftIcon, rightElement, fullWidth = false, className, id, ...props }, ref) => {
    const inputId = id || label?.toLowerCase().replace(/\s+/g, '-')
    return (
      <div ...>
        {label && (
          <label htmlFor={inputId} ...>{label}</label>
        )}
        <div ...>
          ...
          <input ref={ref} id={inputId} ... {...props} />

With no label and no id passed explicitly, inputId is undefined, no <label> renders, and the <input> gets no id either — so these two fields have no accessible name at all: no associated <label>, no aria-label, no aria-labelledby. A placeholder is not an accessible name (it disappears once text is entered, and most screen readers don't reliably announce it as a label in the first place).

Why it matters

This is the same defect category as the already-filed "Form inputs in AddContact and RecipientStep lack associated label elements" issue in this repo (#10), but in a file that issue doesn't mention: BatchForm.tsx is the only other place in the entire app's financial forms (SendForm, EscrowForm, SubscriptionForm, CreateRequestForm all correctly pass label="..." to every Input/Select) that has this specific gap, and arguably a higher-stakes one — it's per-recipient address and amount entry for a batch of up to 100 payments (MAX_BATCH_RECIPIENTS), sent as a single atomic transaction the user cannot partially undo. A screen-reader user filling out this form hears "edit text" (or similar generic control name) for every recipient row's address and amount fields, with no way to distinguish "recipient 3's address" from "recipient 3's amount" from "recipient 4's address" by name alone — they'd have to rely entirely on DOM/reading order and memory to keep track of which field is which while filling in multiple recipients.

Reproduction

  • Open the Batch Send form with a screen reader (or inspect the rendered DOM) and add a second recipient row. Neither the address nor amount <input> for any row has an id, and no <label> element referencing it exists anywhere in the row — confirmed by Input.tsx's own conditional rendering, since label is never passed at either call site.

Suggested fix

  • Pass a (visually hidden, if the current compact layout is intentional) label to both Inputs, e.g. label={Recipient ${index + 1} address} / label={Recipient ${index + 1} amount} using the app's existing VisuallyHidden component (src/components/common/VisuallyHidden.tsx, itself currently unused anywhere — see its own definition file) if a visible label would break the current row layout, or at minimum add explicit aria-label props with the same per-row-indexed text.

Additional Notes

  • src/components/BatchSend/BatchForm.tsx:89-105, src/components/ui/Input.tsx:13-29 (the conditional-label mechanism that silently produces no accessible name when label is omitted).
  • Related to, but a distinct file from, the already-filed issue Form inputs in AddContact and RecipientStep lack associated label elements #10 (AddContact/RecipientStep) — same underlying defect shape, different, previously-uncovered form.
  • Testing strategy: extend BatchForm.test.tsx (which currently only asserts on validation/submission behavior) with an assertion that every rendered recipient row's address and amount inputs have an accessible name (e.g. via Testing Library's getByRole('textbox', { name: /recipient 1 address/i })), which would fail against the current markup.

Metadata

Metadata

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial Campaign | FWC26Campaign: Official Campaign | FWC26Third CampaignCampaign: Third CampaignaccessibilityAccessibility (a11y)very hardVery difficult / senior-level bounty issue

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions