MyNixOS website logo
Description

Accessibility Enhancements to Popular R Shiny Functions.

Accessible wrappers for popular 'shiny' UI components, enforcing ARIA attributes and structural requirements in line with BITV 2.0 (Barrierefreie-Informationstechnik-Verordnung) and WCAG 2.1 AA. Covers action buttons, text and select inputs, fluid page layouts with HTML landmarks and skip links, 'DT' data tables, and bar and line graphs from 'ggplot2'. Components validate label presence, expose keyboard-accessible ARIA states, and provide a high-contrast toggle. This package was developed by d-fine GmbH on behalf of the German Federal Ministry of Research, Technology and Space (BMFTR).

a11yShiny

EUPL-1.2 R version

Accessible wrappers for popular R Shiny UI components, enforcing ARIA attributes and structural requirements in line with BITV 2.0 and WCAG 2.1 AA.

Installation

Install the package directly from GitLab:

install.packages("devtools")
devtools::install_git("https://gitlab.opencode.de/bmbf/datenlabor/barrierefrei-r.git")

Alternatively, clone the repository and use renv for reproducible dependency management:

# Set your working directory to the package root
setwd("path/to/barrierefrei-r")

renv::init()
renv::install(".")
renv::snapshot()

Getting Started

Load the package and replace standard Shiny UI functions with their accessible counterparts:

library(a11yShiny)

ui <- a11y_fluidPage(
  lang = "de",
  title = "Accessible Demo",
  a11y_fluidRow(
    a11y_column(6, a11y_actionButton("go", label = "Go!")),
    a11y_column(6, a11y_selectInput("sel", label = "Choose", choices = 1:3))
  )
)

For accessible DataTables and basic line/bar charts:

output$tbl <- a11y_renderDataTable({ head(iris, 10) }, lang = "de")

output$plt <- renderPlotly({
  p <- a11y_ggplot2_line(data = iris, x = ~Species, y = ~Sepal.Length)
  plotly::ggplotly(p)
})

A full demo app is included in the package:

shiny::runApp(system.file("examples", "demo", "app.R", package = "a11yShiny"))

For detailed documentation on each function, see the package reference (?a11y_fluidPage, ?a11y_actionButton, etc.) and the examples in inst/examples/.

Core Functions & Accessibility Features

Layout & Structure

a11y_fluidPage, a11y_fluidRow, a11y_column:

Wrappers for fluidPage(), fluidRow() and column().

  • Sets and validates <title> title, <lang> language, and unique <main> landmark.
  • Ensures flexible layout with classes .a11y-flow, .a11y-row, .a11y-col and optional header/nav/footer.
  • Ensures that only a11y_columns are used within a11y_fluidRow() (not the standard shiny column() function).
  • Validates sum of column widths and offset (12) and single column width and offset (1–12) within a11y_fluidRow() (only for direct children columns).
  • Warnings if nested fluidRows are detected because it can potentially create problems for keyboard users.
  • Optional aria-labels can be added.
  • BITV 2.0 Criteria:9.2.4.2, 9.3.1.1, 9.2.4.1, 9.1.4.10, 9.1.3.4, 9.1.4.4
  • Limitations: Heading levels/order (<h1>, <h2>, ...) is not enforced. No validation of meanigful (ARIA) text label (9.2.4.6). If nested fluidRows are used seamless keyboard navigation is not guaranteed (9.2.1.1)

Inputs

a11y_actionButton

Wrapper for actionButton().

  • Sets and validates visible label or non-visible aria-label.
  • Sets and validates aria-label for icon-only buttons for screenreader users.
  • Ensures clear contrast and focus styling with class .a11y-btn.
  • BITV 2.0 Criteria:9.1.1.1a, 9.1.4.1, 9.1.4.11, 9.1.4.3, 9.2.1.1, 9.2.4.7, 9.2.5.3, 9.4.1.2
  • Limitations: No validation of meanigful text label (9.2.4.6).

a11y_selectInput(), a11y_numericInput(), a11y_textInput, a11y_dateInput, a11y_radioButtons

Wrapper for selectInput(), numericInput(), textInput(), dateInput() and radioButtons().

  • Sets and validates visible label.
  • Optional headline marking (aria-level) can be added (1-6 for <h1>-<h6>).
  • Optional helping description (aria-describedby) can be added - either reference an existing text (via ID) or add a non-visible text which only Screenreaders can read (via class .a11y-sr-only).
  • Ensures clear contrast and focus styling with classes .a11y-select, .a11y-numeric, .a11y-text, .a11y-date and .a11y-radio.
  • BITV 2.0 Criteria:9.3.3.2, 9.1.3.1a, 9.1.3.1h, 9.1.4.1, 9.1.3.2, 9.1.4.3, 9.1.4.11, 9.1.4.13, 9.2.1.1, 9.2.4.7, 9.2.5.3, 9.4.1.2
  • Limitations: No validation of correct headline order (9.1.3.1a), meanigful text label (9.2.4.6). Semantic groupings of combined input elements is not covered.

a11y_textButtonGroup()

Composite wrapper combining a labeled text input and an action button (e. g. for a search bar with button).

  • Internally uses a11y_textInput() and a11y_actionButton() with their validations and CSS focus styling.
  • Adds aria-controls to the button, by default pointing to the text input ID (configurable), so assistive technologies understand which control is affected by the button.
  • Optional helping description (aria-describedby) can be added - either reference an existing text (via ID) or add a non-visible text which only Screenreaders can read (via class .a11y-sr-only).
  • Supports different layout modes (e.g. inline vs. stacked) via .a11y-text-action-group and modifier classes.
  • Each inner element has its own ID and can be addressed separately in server logic and UI.
  • BITV 2.0 Criteria:9.1.1.1a, 9.1.3.1a, 9.1.3.1h, 9.1.3.2, 9.1.4.1, 9.1.4.3, 9.1.4.11, 9.2.1.1, 9.2.4.7, 9.2.5.3, 9.3.3.2, 9.4.1.2
  • Limitations: No automatic validation of semantic button text or the precise semantics of aria-controls (9.2.4.6). Correct wiring between button and controlled element remains responsibility of the user.

a11y_textInputsGroup()

Wrapper for a group of related textInput elements inside a <fieldset> with <legend> (e.g. address fields, date components, grouped inputs).

  • Renders a <fieldset> with a visible <legend> as group label and marks it with role="group" and aria-labelledby to the legend.
  • Each inner text input:
    • Sets and validates visible label.
    • Optional headline marking (aria-level) can be added (1-6 for <h1>-<h6>).
    • Optional helping description (aria-describedby) can be added - either reference an existing text (via ID) or add a non-visible text which only Screenreaders can read (via class .a11y-sr-only).
    • Ensures clear contrast and focus styling with class .a11y-text.
  • BITV 2.0 Criteria:9.1.3.1a, 9.1.3.1h, 9.1.3.2, 9.1.4.1, 9.1.4.3, 9.2.1.1, 9.2.4.7, 9.2.5.3, 9.3.3.2, 9.4.1.2
  • Limitations: No validation of the semantic correctness of group labels or titles; it only enforces that an accessible name is present. Logical grouping and content semantics must be chosen by the user.

Tables

a11y_renderDataTable()

Wrapper for renderDataTable().

  • Sets and validates language (supports German and English by default).
  • Optional language can be set (other than de/en) via dt_language file internationalization.
  • Warnings if non-accessible "Copy", "Pdf" and "Print" export functions are used.
  • Warnings if non-accessible dataTable filter in numeric columns are used.
  • Sets KeyTab keyboard navigation as default.
  • Optional clear contrast and focus styling with the class .a11y-dt: To enable CSS style, wrap dataTableOutput() in a div with a custom class, e.g.:
div(class = "a11y-dt", DT::dataTableOutput("mytable"))
  • BITV 2.0 Criteria:9.3.1.2, 9.1.3.1e, 9.2.4.7, 9.1.4.3, 9.1.3.4, 9.1.4.4
  • Limitations: DataTable can adapt to different screen sizes (smaller displays, mobile) only via horizontal scrolling (9.1.4.10). Setting a language attribute (lang) or other ARIA attributes around the DataTable is not reliably possible using a wrapper because after rendering the JavaScript/widget binding replaces or overwrites some attributes and may reset or remove classes/IDs/ARIA attributes - it must be set individually by the user if it differs from the language in the body (9.3.1.2).

Charts

A generic wrapper for ggplot2/ggplotly charts is not recommended due to low flexibility and high risk of errors. Several approaches for accessible diagram wrappers were evaluated, but due to limitations, only the first option was implemented in this package as a minimal example:

  1. Minimal ggplot2 Wrapper per Chart Type which can be manipulated afterwards (see a11y_ggplot2_bar/line). Limitation: Must be created for every chart type; user modifications after the wrapper can impair accessibility.
  2. Full Chart Wrapper with Internal ggplotly Conversion which create a complete interactive chart. Limitation: Most accessible, but least flexible -- only practical for fixed chart formats.
  3. Generic ggplotly Wrapper which patches accessibility features into a ggplot2 object after creation. Limitation: Messy and error-prone; post-hoc changes often fail as ggplotly may not reliably map all properties.
  4. A wrapper for plotlyOutput which adds landmarks and ARIA attributes (aria-describedby). Limitation: plotlyOutput first renders a simple DIV placeholder in the UI, but after rendering the JavaScript/widget binding replaces or overwrites some attributes and may reset or remove classes/IDs/ARIA attributes; the attribute is not always guaranteed to be visible in the finished DOM tree. It must be set individually by the user.

Support for pattern fills, certain ARIA attributes, or colorblind-friendly mapping is always limited by ggplot2/plotly's underlying capabilities and design. Instead users should follow accessibility guidelines for charts. Best practice: Users should

  • use high-contrast palettes, distinct markers for different groups/lines, outlines for bars, clear labeling,
  • add additional labels, descriptions, and helper texts accessible for keyboards and screenreaders.

a11y_ggplot2_line() / a11y_ggplot2_bar()

Minimal wrapper for ggplot2() for a multi-line and simple bar chart.

  • Pre-set accessible color palette (3:1 contrast to white) and warning if user overwrites color palette.
  • Pre-set markers (line) and black outline (bar).
  • Optional setting of legend title (which prevents legend title duplication due to marker and color legend).
  • Wrapper can be flexibly adjusted with ggplot2 (see example in inst/examples/demo/app.R).
  • BITV 2.0 Criteria:9.1.4.1, 9.1.4.11
  • Limitations:
    • ARIA/landmark features for charts must be set via JS or on container level.
    • Minimal wrapper for each chart type needed; modifying chart after wrapper may impair accessibility.
    • No wrapper can guarantee full accessibility once plots are heavily adapted post-hoc.

High-contrast mode

Wrapper for a global high-contrast mode toggle button.

  • Renders a clearly emphasized high-contrast button with its own strong contrast style, independent of whether high-contrast mode is active.
  • On click it toggles the high-contrast class on the <body> element: All standard Shiny buttons, form controls and dataTable controls switch to a high-contrast style (inverted colors, clear borders and focus outline)
  • Sets and updates aria-pressed="true"/"false" on the button so screen readers can understand the toggle state.
  • Internally uses a11y_actionButton() and inherits its validation.
  • Receives an additional class .a11y-high-contrast-toggle that the JS and CSS high-contrast styling are attached to.
  • BITV 2.0 Criteria:9.1.4.1, 9.1.4.3, 9.1.4.11, 9.2.4.7
  • Limitations: High-contrast mode is applied globally via a CSS class on <body>. Components with heavily customized styles may need additional adjustments to ensure sufficient contrast and visible focus states in high-contrast mode.

Utility Functions

  • add_aria, add_aria_inside, find_html_tags, find_direct_children_without_class, is_nonblank_string
    • Utility functions to add ARIA attributes and search tags for custom accessibility patterns.

Known Limitations

Limitations are mainly library-dependent. Some specific capabilities (modal copy dialogs, responsive DT layouts, numeric DT filters, chart tooltips) cannot yet be made fully accessible through wrappers alone. Always test your outputs with accessibility auditing tools (see below).

Getting Help

Contributing

Contributions to a11yShiny are welcome. Please open an issue or submit a merge request on the GitLab repository.

License

a11yShiny is licensed under the European Union Public Licence (EUPL) v1.2.

R Version Support

a11yShiny requires R >= 4.1.

Metadata

Version

0.1.4

License

Unknown

Platforms (79)

    Darwin
    FreeBSD
    Genode
    GHCJS
    Linux
    MMIXware
    NetBSD
    none
    OpenBSD
    Redox
    Solaris
    uefi
    wasip1
    Windows
Show all
  • aarch64-darwin
  • aarch64-freebsd
  • aarch64-genode
  • aarch64-linux
  • aarch64-netbsd
  • aarch64-none
  • aarch64-uefi
  • aarch64-windows
  • aarch64_be-none
  • arc-linux
  • arm-none
  • armv5tel-linux
  • armv6l-linux
  • armv6l-netbsd
  • armv6l-none
  • armv7a-linux
  • armv7a-netbsd
  • armv7l-linux
  • armv7l-netbsd
  • avr-none
  • i686-cygwin
  • i686-freebsd
  • i686-genode
  • i686-linux
  • i686-netbsd
  • i686-none
  • i686-openbsd
  • i686-windows
  • javascript-ghcjs
  • loongarch64-linux
  • m68k-linux
  • m68k-netbsd
  • m68k-none
  • microblaze-linux
  • microblaze-none
  • microblazeel-linux
  • microblazeel-none
  • mips-linux
  • mips-none
  • mips64-linux
  • mips64-none
  • mips64el-linux
  • mipsel-linux
  • mipsel-netbsd
  • mmix-mmixware
  • msp430-none
  • or1k-none
  • powerpc-linux
  • powerpc-netbsd
  • powerpc-none
  • powerpc64-linux
  • powerpc64le-linux
  • powerpcle-none
  • riscv32-linux
  • riscv32-netbsd
  • riscv32-none
  • riscv64-linux
  • riscv64-netbsd
  • riscv64-none
  • rx-none
  • s390-linux
  • s390-none
  • s390x-linux
  • s390x-none
  • sh4-linux
  • vc4-none
  • wasm32-wasip1
  • wasm64-wasip1
  • x86_64-cygwin
  • x86_64-freebsd
  • x86_64-genode
  • x86_64-linux
  • x86_64-netbsd
  • x86_64-none
  • x86_64-openbsd
  • x86_64-redox
  • x86_64-solaris
  • x86_64-uefi
  • x86_64-windows