I am trying to fix some accessibility issues on one of my Shiny apps. The problem is that Shiny's tabPanel
default behavior is that once a tab has been visited its tabindex
becomes -1, making it inaccessible for users accessing through keyboard navigation (before being clicked a tab would be tabindex = 0).
The example below shows how keyboard navigation doesn't work for the tabs. I am using Shiny 1.7.2 and R 4.0.3.
I have tried using the library bslib
and its page_navbar
/nav_panel
functions but no luck. I also tried to add HTML
to the tabPanel
calls and explore if I could do anything through CSS
but had no luck. I have investigated the code of these functions to see if I could modify them, but I am not sure how. Maybe it can be done with JS
, but I know only the very basics of it. I also tried using htmltools::tagAppendatrribute
as suggested in this response, but it doesn't modify the behavior after clicking.
Any pointers or solutions would be great.
library(shiny)
# Define UI
ui <- navbarPage(
title = "Test accessibility issue",
tabPanel(title = "Home", icon = icon("house"), value = "home",
p("Test")),
tabPanel(title = "Trends", icon = icon("list-ul"), value = "trends",
p("Test")),
tabPanel(title = "Geography", icon = icon("globe"), value = "geo",
p("Test"))
)
# Define server logic
server <- function(input, output) {
}
# Run the application
shinyApp(ui = ui, server = server)
What you can do is to use a MutationObserver
and listen to changes of the attribute tabindex
. If the attribute is set to "-1", you can edit it to e.g. "0". In the following example this is applied to all elements, but you can of course change this.
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
var attributeValue = $(mutation.target).prop(mutation.attributeName);
if (mutation.attributeName === "tabindex" && attributeValue == "-1") {
$(mutation.target).prop(mutation.attributeName, "0");
}
});
});
$("*").each(function() {
observer.observe(this, {
attributes: true
});
});
library(shiny)
js <- "
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
var attributeValue = $(mutation.target).prop(mutation.attributeName);
if (mutation.attributeName === 'tabindex' && attributeValue == '-1') {
$(mutation.target).prop(mutation.attributeName, '0');
}
});
});
$('*').each(function() {
observer.observe(this, {
attributes: true
});
});
"
# Define UI
ui <- shinyUI(
navbarPage(
header = tags$script(HTML(js)),
title = "Test accessibility issue",
tabPanel(
title = "Home",
icon = icon("house"),
value = "home",
p("Test")
),
tabPanel(
title = "Trends",
icon = icon("list-ul"),
value = "trends",
p("Test")
),
tabPanel(
title = "Geography",
icon = icon("globe"),
value = "geo",
p("Test")
)
)
)
# Define server logic
server <- function(input, output) {
}
# Run the application
shinyApp(ui = ui, server = server)