Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make sliderInput() accessible for keyboard and screen readers #3011

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

cpsievert
Copy link
Collaborator

@cpsievert cpsievert commented Aug 20, 2020

Supercedes #3003

Testing notes

Ensure the following example is fully accessible (i.e., screen reader makes announcements of min/max/values and values can be changes without a mouse by tabbing)

library(shiny)
ui <- fluidPage(
  numericInput("min", "Set the minimum", value = 0),
  numericInput("value", "Set the value", value = 40),
  numericInput("max", "Set the maximum", value = 100),
  sliderInput("slider", "Here's a slider", value = 40, min = 0, max = 100)
)
server <- function(input, output, session) {
  observe({
    updateSliderInput(
      session, "slider", min = input$min, value = input$value, max = input$max
    )
  })
}
shinyApp(ui, server)

@cpsievert cpsievert force-pushed the carson/feature/accessible-slider branch from d9982a4 to 2691bcd Compare August 20, 2020 20:55
@cpsievert cpsievert changed the title Add ARIA labels for sliderInput() Make sliderInput() accessible for keyboard and screen readers Aug 20, 2020
@jooyoungseo
Copy link

jooyoungseo commented Aug 21, 2020

There's one extra stop before the slider widget when tabbing through because span element also has tabindex="0".

As a minimal example, I've run the following:

library(shiny)
example(sliderInput)

You'd find the following <span> has a tabindex:

  • Selector: body > div > div.form-group.shiny-input-container > span > span.irs > span.irs-line

@jooyoungseo
Copy link

jooyoungseo commented Aug 21, 2020

Current issue I've noticed is as follows:

  • One sliderInput widget produces two tabbable focus.
  • The first tab-focus has no label (silent for screen readers), but this is where you would press left/right arrows to change values (no feedback is heard, either).
  • The second tab-focus has all the labels for screen readers, but this is just the output area that you can check the result that you changed through the previous (silent) tab-focus.

@jooyoungseo
Copy link

Ideally, we would like to integrate the two tabbable focus into one tab-focus area where we can adjust values and check the results at the same time via assistive technologies.

Copy link

@jooyoungseo jooyoungseo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect! Now it is very accessible to screen readers! Thanks a lot!

@jooyoungseo jooyoungseo added this to the 1.5.1 milestone Aug 21, 2020
@cpsievert
Copy link
Collaborator Author

Unfortunately ion.RangeSlider doesn't seem to support keyboard control of both slider handles (just the from handle) IonDen/ion.rangeSlider#548

That restriction is likely going to prevent us from being able to have a fully accessible slider when value is of length 2 without a significant patch to ion.RangeSlider

Copy link

@jooyoungseo jooyoungseo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately ion.RangeSlider doesn't seem to support keyboard control of both slider handles (just the from handle) IonDen/ion.rangeSlider#548

That restriction is likely going to prevent us from being able to have a fully accessible slider when value is of length 2 without a significant patch to ion.RangeSlider

This is odd. At least, there should then be a way for us to bind aria markups to the from value of a double-handle slider.

I tested with the following classes by assigning all the necessary aria labels; unfortunately, none of them worked. We may want to find a way for keyboard users to control lower value of a double-handle sliderbar at least.

  • .irs-line (you know, this is the right place for a single-handle slider, but it does NOT work for the double-handle one)
  • .irs-from (this is what you've assigned, and this does not work, either.)
  • .irs-line-left (I gave it a try, but it did not work)

}
line.attr("tabindex", "-1");
var from = data.slider.find(".irs-from");
setAriaLabels(from, label "-lower", data.from, data.min, data.max);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

el.id "-label" is tied to ./R/input-utils.R#L7, and is calling a label string defined within shinyInputLabel().

This is not a right way to concatenate label string. Please take a look at this document.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could make an invisible <span id = "lower"> with the inner text as "lower", and then pass this span id to the aria-labelledby right after the original label id using a whitespace separator to concatenate. I know, it is sort of tricky... I'm sorry.

}
line.attr("tabindex", "-1");
var from = data.slider.find(".irs-from");
setAriaLabels(from, label "-lower", data.from, data.min, data.max);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

el.id "-label" is tied to ./R/input-utils.R#L7, and is calling a label string defined within shinyInputLabel().

This is not a right way to concatenate label string. Please take a look at this document.

var from = data.slider.find(".irs-from");
setAriaLabels(from, label "-lower", data.from, data.min, data.max);
var to = data.slider.find(".irs-to");
setAriaLabels(to, label "-upper", data.to, data.min, data.max);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same issue as the above.

@cpsievert cpsievert modified the milestones: 1.5.1, 1.6 Oct 30, 2020
@wch wch modified the milestones: 1.6, 1.7 Dec 4, 2020
@cpsievert cpsievert removed this from the 1.7 milestone Jun 29, 2021
@mciethan
Copy link

Any updates on this? I have an app with a slider for which it'd be nice to have screen reader navigability.

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

Successfully merging this pull request may close these issues.

sliderInput control inaccessible for keyboard or screen reader users
4 participants