Skip to content

DropdownSelect / DropdownCascader overwrite the caller's aria-label with "Select" #96

Description

@kemuru

Version: 3.9.0 (also 3.8.0)

Both components spread the incoming props onto react-aria's Select and then set
aria-label={label ?? "Select"} after the spread:

  • src/lib/dropdown/select/index.tsx (lines 48-53)
  • src/lib/dropdown/cascader/index.tsx (lines 37-42)

So a consumer-supplied aria-label is always replaced by the literal "Select". Only
aria-labelledby survives, because it is forwarded by the spread.

Impact

Every dropdown rendered without a visible label is announced to screen readers as "Select",
regardless of what the app passes. Consumers end up writing wrappers to work around it, e.g.
web/src/components/LabeledDropdown.tsx in kleros/kleros-v2#2281, which renders a
visually-hidden span and points aria-labelledby at it.

Proposed fix

Only fall back to "Select" when nothing else labels the field, and let the spread win:

<AriaSelect
  className={cn("flex flex-col gap-1", className)}
  aria-label={label || props["aria-label"] || props["aria-labelledby"] ? undefined : "Select"}
  {...props}
  onSelectionChange={handleSelection}
>

Same change in the cascader. Alternatively, simply move the aria-label line above the
{...props} spread so consumer props take precedence.

Once released, the kleros-v2 wrapper can be deleted and callers pass aria-label directly.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions