Skip to content

a11y: Checkboxes not working correctly with keyboard #3350

Closed
nextcloud-libraries/nextcloud-vue
#8324

Description

@Chartman123

checkboxes: a bug on the Nextcloud side for checking a box, SPACE SELECTED the voice says it's checked, which isn't the case, a second press on space actually checks the box when the voice only says SPACE.

Activity

  1. added
    bugSomething isn't working
    javascriptJavascript related ticket
    upstreamBlocked or cause by an upstream issue
    on May 22, 2026
  2. added theissue type on May 22, 2026
  3. added this to the 5.3 milestone on May 22, 2026
  4. Chartman123 commented on Jun 2, 2026

    @Chartman123
    CollaboratorAuthor

    Copilot thinks that this comes from a problem in the nextcloud-vue lib:

    The component only attaches change (and click for button variants) via listeners on the inner . Keyboard Space toggles are handled by the browser and produce a change later, so the component relies on the change path and the parent update cycle to reflect the new checked state.

    That creates a timing/race: the native input.checked (and screen reader) change immediately on Space, but the component's isChecked (based on internalModelValue) only updates after the component emits update:modelValue and the parent re-renders. That can produce the symptom you saw (SR announces checked on first press, visible tick only after second press).
    Minimal, reliable fix

    Handle Space at the component level and invoke the same toggle logic synchronously, preventing the native toggle so the component is the single source of truth. Concretely, add a keydown handler on the internal input:
    In NcCheckboxRadioSwitch.vue, change the input element to include:

    @keydown.space.prevent="onToggle"
    Example (near the existing input):

    before:
    v-on="listeners"
    after:
    v-on="listeners" @keydown.space.prevent="onToggle"
    Why this fixes it

    Preventing the native Space toggle and calling the existing onToggle immediately means we update internalModelValue (via the setter) and emit update:modelValue before any native DOM change. The visual state is then controlled by Vue's reactivity consistently, avoiding the one-press-only mismatch between SR and rendered UI.

  5. Chartman123 commented on Jun 5, 2026

    @Chartman123
    CollaboratorAuthor

    Fixed upstream

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

    1. to developAccepted and waiting to be taken care ofa11yrelated to accessibilitybugSomething isn't workingjavascriptJavascript related ticketupstreamBlocked or cause by an upstream issue

    Type

    Projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions