R/plots.R

Defines functions a11y_ggplot2_bar a11y_ggplot2_line

Documented in a11y_ggplot2_bar a11y_ggplot2_line

#' Accessible line chart
#'
#' A minimal wrapper for a multi-line chart with accessibility features using
#' [ggplot2]. Provides a high-contrast color palette, distinct marker shapes,
#' and a minimal theme by default.
#'
#' @param data Data frame
#' @param x Column name for the x-axis (unquoted)
#' @param y Column name for the y-axis (unquoted)
#' @param group (optional) Column name for grouping lines (unquoted)
#' @param accessible_colors (optional) Character vector of colors for the
#'   palette
#' @param marker_shapes (optional) Numeric vector of point shapes, e.g.
#'   `c(16, 17, 15, 3, 7, 4, 10)`
#' @param marker_size (optional) Point size (default: `2`)
#' @param line_width (optional) Line width (default: `1`)
#' @param legend_title (optional) Title for the legend
#' @param ... Additional arguments passed to [ggplot2::labs()]
#' @return A [ggplot2::ggplot()] object
#'
#' @examples
#' # Simple line chart (no grouping)
#' df <- data.frame(year = 2020:2024, value = c(10, 14, 13, 17, 20))
#' a11y_ggplot2_line(
#'   data = df, x = year, y = value,
#'   title = "Trend"
#' )
#'
#' # Grouped line chart
#' df2 <- data.frame(
#'   year  = rep(2020:2024, 2),
#'   value = c(10, 14, 13, 17, 20, 8, 9, 11, 12, 15),
#'   grp   = rep(c("A", "B"), each = 5)
#' )
#' a11y_ggplot2_line(
#'   data = df2, x = year, y = value,
#'   group = grp, title = "Trend by Group"
#' )
#'
#' # With legend title and additional ggplot2 layers
#' p <- a11y_ggplot2_line(
#'   data = df2, x = year, y = value, group = grp,
#'   legend_title = "Group",
#'   title = "Trend by Group"
#' )
#' p + ggplot2::geom_hline(yintercept = 12, linetype = "dashed") +
#'   ggplot2::labs(
#'     x = "Year", y = "Value",
#'     subtitle = "With custom axis labels"
#'   )
#'
#' @importFrom rlang .data
#' @export
a11y_ggplot2_line <- function(
  data, x, y, group = NULL,
  accessible_colors = NULL,
  marker_shapes = NULL,
  line_width = 1,
  marker_size = 2,
  legend_title = NULL,
  ...
) {
  x_var <- deparse(substitute(x))
  y_var <- deparse(substitute(y))
  group_sub <- substitute(group)
  group_name <- if (!is.null(group_sub) && !identical(group_sub, NULL)) {
    deparse(group_sub)
  } else {
    NULL
  }

  # Set high-contrast color palette if not provided
  acc_color_palette <- c(
    "#032D51", "#B21B45", "#6E787F", "#559EA5",
    "#9B5372", "#548A70", "#C38700", "#9BAA50",
    "#D15805", "#7A99AC"
  )
  if (!is.null(accessible_colors)) {
    warning("a11y_ggplot2_line: You are overriding the accessible_colors palette; please ensure sufficient contrast (3:1 ratio to background)", call. = FALSE)
  } else {
    accessible_colors <- acc_color_palette
  }
  # Set marker shapes automatically if not set
  default_shapes <- c(16, 17, 15, 3, 7, 4, 10, 8, 9, 12)
  if (is.null(marker_shapes)) marker_shapes <- default_shapes

  if (!is.null(group_name)) {
    mapping <- ggplot2::aes(
      x = .data[[x_var]], y = .data[[y_var]],
      color = .data[[group_name]], shape = .data[[group_name]],
      group = .data[[group_name]]
    )
  } else {
    mapping <- ggplot2::aes(x = .data[[x_var]], y = .data[[y_var]])
  }
  p <- ggplot2::ggplot(data, mapping) +
    ggplot2::geom_line(linewidth = line_width) +
    ggplot2::geom_point(size = marker_size) +
    ggplot2::scale_color_manual(name = legend_title, values = accessible_colors) +
    ggplot2::scale_shape_manual(name = NULL, values = marker_shapes) +
    ggplot2::theme_minimal() +
    ggplot2::labs(...)

  p
}

#' Accessible bar chart
#'
#' A minimal wrapper for a simple bar chart with accessibility features using
#' [ggplot2]. Provides a high-contrast color palette, black bar outlines, and a
#' minimal theme by default.
#'
#' @param data Data frame
#' @param x Column name for categories (unquoted)
#' @param y Column name for bar heights (unquoted)
#' @param accessible_colors (optional) Character vector of colors for the
#'   palette
#' @param border_color (optional) Color for bar outlines (default: `"#000000"`)
#' @param bar_width (optional) Bar width (default: `0.9`)
#' @param legend_title (optional) Title for the legend (default: `NULL`)
#' @param ... Additional arguments passed to [ggplot2::labs()] (e.g. `title`,
#'   axis labels)
#' @return A [ggplot2::ggplot()] object
#'
#' @examples
#' df <- data.frame(
#'   category = c("Alpha", "Beta", "Gamma"),
#'   count    = c(23, 17, 31)
#' )
#' a11y_ggplot2_bar(
#'   data = df, x = category, y = count,
#'   title = "Counts by Category"
#' )
#'
#' @export
a11y_ggplot2_bar <- function(
  data, x, y,
  accessible_colors = NULL,
  border_color = "#000000",
  bar_width = 0.9,
  legend_title = NULL,
  ...
) {
  x_var <- deparse(substitute(x))
  y_var <- deparse(substitute(y))

  # Set a high-contrast color palette if not provided
  acc_color_palette <- c(
    "#032D51", "#B21B45", "#6E787F", "#559EA5",
    "#9B5372", "#548A70", "#C38700", "#9BAA50",
    "#D15805", "#7A99AC"
  )
  if (!is.null(accessible_colors)) {
    warning("a11y_ggplot2_bar: You are overriding the accessible_colors palette; please ensure sufficient contrast (3:1 ratio to background)", call. = FALSE)
  } else {
    accessible_colors <- acc_color_palette
  }

  # Construct basic mapping (bars colored by x variable)
  mapping <- ggplot2::aes(x = .data[[x_var]], y = .data[[y_var]], fill = .data[[x_var]])

  # Build the ggplot object: bar chart with chosen palette and border
  p <- ggplot2::ggplot(data, mapping) +
    ggplot2::geom_bar(
      stat = "identity",
      width = bar_width,
      color = border_color
    ) +
    ggplot2::scale_fill_manual(name = legend_title, values = accessible_colors) +
    ggplot2::theme_minimal() +
    ggplot2::labs(...)

  p
}

Try the a11yShiny package in your browser

Any scripts or data that you put into this service are public.

a11yShiny documentation built on April 1, 2026, 5:07 p.m.