如何修改Shiny应用中不同对象之间的Tab键焦点跳转顺序
我需要调整Shiny应用中按下Tab键在各组件间移动焦点的顺序。当前Tab键会从Name输入框直接跳转到Next按钮,原因是二者处于同一列。我期望按下Tab键时的焦点顺序为:Name输入框、Prediction 1输入框、Prediction 2输入框、Next按钮。
其中Name输入框和Next按钮位于同一个fluidRow的列中,两个预测输入框分别处于fluidRow的独立列内。
我了解到可通过tabindex = "##"标签修改索引顺序(##为目标顺序编号),参考Stack Overflow的相关回答后,我认为需要修改.shiny-input-container:not(.shiny-input-container-inline)对应的CSS样式,但不清楚具体实现方法,尝试了多种组合均未成功,下方示例代码的注释行中记录了部分尝试内容,示例中我使用tabindex = "-1"将输入设为模态,以此验证修改是否生效。
编辑补充
发布问题后我得知,出于无障碍访问的要求,不建议按照我提问的方式使用tabindex,可参考WebAIM和MDN的相关说明。虽然@ismirsehregal提供的解决方案效果很好,我仍想了解其他实现思路,不过我推测其他方案也可能存在无障碍访问相关的问题。
最小可复现示例(MWE)
library(shiny) ui <- fluidPage( fluidRow( column( 3, textInput(inputId = "name", label = "Name"), actionButton(inputId = "next", label = "Next") ), column( 3, #tags$style(HTML(`tabindex` = "-1")) #tags$style(HTML(.shiny-input-container:not(.shiny-input-container-inline) {`tabindex` = "-1"})) # 我也尝试过使用tags$div和tags$input但均未成功 textAreaInput(# 我也曾尝试在此处添加修改代码 inputId = "pred1", label = "Prediction 1") ), column(3, textAreaInput(inputId = "pred2", label = "Prediction 2")) ) ) server <- function(input, output) { } shinyApp(ui = ui, server = server)
2021-10-05由reprex包(v2.0.1)创建
方案1:直接指定tabindex属性(快速实现)
不需要修改全局CSS,直接通过Shiny的tagAppendAttributes()函数为每个交互组件指定对应顺序的tabindex值即可:
library(shiny) ui <- fluidPage( fluidRow( column( 3, textInput(inputId = "name", label = "Name") |> tagAppendAttributes(tabindex = 1), actionButton(inputId = "next", label = "Next") |> tagAppendAttributes(tabindex = 4) ), column( 3, textAreaInput(inputId = "pred1", label = "Prediction 1") |> tagAppendAttributes(tabindex = 2) ), column( 3, textAreaInput(inputId = "pred2", label = "Prediction 2") |> tagAppendAttributes(tabindex = 3) ) ) ) server <- function(input, output) { } shinyApp(ui = ui, server = server)
若使用的R版本不支持|>管道符,替换为嵌套写法即可:
tagAppendAttributes(textInput(inputId = "name", label = "Name"), tabindex = 1)
注:该方案使用了正数值的tabindex,确实会绕过页面默认的焦点导航逻辑,不符合无障碍访问规范,仅适合内部工具等无无障碍要求的场景使用。
方案2:适配无障碍规范的实现思路
如果需要满足无障碍访问要求,不要使用正的tabindex值,可调整DOM结构和CSS布局实现:
- 先按照期望的Tab顺序排列所有组件:Name输入框→Pred1输入框→Pred2输入框→Next按钮
- 通过CSS Grid或者浮动布局,将Next按钮视觉上固定到第一列Name输入框的下方
这样默认的Tab导航顺序和视觉顺序完全一致,不需要手动修改tabindex,也符合无障碍访问标准。
内容的提问来源于stack exchange,提问作者Michael S Taylor

