Skip to content

[Bug]: Unified search results nest a link inside role="option" (axe nested-interactive) #65305

Description

@Dennis-Otto

⚠️ This issue respects the following points: ⚠️

  • This is not a troubleshooting question, general support matter, or webserver/proxy problem, but likely a bug.
  • This issue is not already reported on Github OR solved at the Community Help Forum (I've searched!).
  • I'm using a maintained major version of Nextcloud Server and tested against the latest patch level.
  • I agree to follow Nextcloud's Code of Conduct.
  • I've tried my best to provide clear reproduction steps that someone unfamiliar with this bug could use to reproduce it.

Bug description

On desktop widths, the unified search modal renders the results of each provider as a listbox whose rows are options, and every option contains a link to the result:

  • UnifiedSearchModal.vue: <ul role="listbox"> with <SearchResult role="option"> for each result.
  • SearchResult.vue: NcListItem with :href="resourceUrl", which renders an <a> inside the <li role="option">.

axe-core 4.13 reports this as a serious violation of the rule nested-interactive (WCAG 2.1 SC 4.1.2 Name, Role, Value) for every result row, whatever app provides it. The children of an option are presentational, so assistive technology may not expose the focusable link inside it, and keyboard users can reach a control that a screen reader doesn't announce as such.

On small mobile widths the roles are dropped (isSmallMobile ? undefined : 'listbox'), so the plain list of links there passes.

Steps to reproduce

  1. Start the official Docker image, e.g. nextcloud:35.0.1-apache, with any user and a file that a search finds.
  2. Open the unified search from the magnifier in the header on a desktop-sized window and search for that file, so that at least one result row shows.
  3. Run axe-core on the open modal, for example in the browser console with axe-core loaded: await axe.run(document.querySelector('.unified-search-modal'), { runOnly: ['wcag2a', 'wcag2aa'] }).
  4. axe reports nested-interactive (impact serious) on each li.result-item[role="option"].

Expected behavior

No nested interactive control inside an option. Two ways that would fit the current code:

  • Keep the combobox/listbox pattern that the modal already uses (aria-activedescendant on the input) and let the option itself open the result on Enter or click, without a focusable link inside it (for example, tabindex="-1" on the inner link or rendering it as non-interactive content); or
  • drop the listbox/option roles on desktop as well, as on small mobile, and keep the plain list of links.

Nextcloud Server version

35

Operating system

Other

PHP engine version

Other

Web server

Apache (supported)

Database engine version

SQLite

Is this bug present after an update or on a fresh install?

Fresh Nextcloud Server install

Are you using the Nextcloud Server Encryption module?

Encryption is Disabled

What user-backends are you using?

  • Default user-backend (database)

Configuration report

Official Docker image, default configuration; installed with occ maintenance:install --database=sqlite.

List of activated Apps

Default apps of the image.

Nextcloud Signing status

No errors have been found.

Nextcloud Logs

Not applicable: a front-end accessibility issue without server errors.

Additional info

Found while adding axe-core checks to the end-to-end tests of a third-party search provider (paperless_unified_search). The violation appears with every provider, Files included, and is the same on Nextcloud 33.0.9, 35.0.1 and the master build of 2026-09-30. The PHP version is the one of the official image.

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions