From 9904efca6cc00b5a3889f9dd289843b6f07e6241 Mon Sep 17 00:00:00 2001 From: Carl Suster Date: Wed, 1 Apr 2026 11:47:02 +1100 Subject: [PATCH 1/8] Test for incomplete `theme()` docs --- tests/testthat/test-theme.R | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/testthat/test-theme.R b/tests/testthat/test-theme.R index 55f9b8d47d..f6d929704f 100644 --- a/tests/testthat/test-theme.R +++ b/tests/testthat/test-theme.R @@ -693,3 +693,14 @@ test_that("legends are placed correctly when using stretchy spacing", { p + theme(legend.position = "top", legend.spacing.x = unit(1, "null")) ) }) + +test_that("all theme elements are documented", { + all_elems <- names(.element_tree) + doc_fmls <- rlang::fn_fmls_names(theme) + missing_elems <- setdiff(all_elems, doc_fmls) + + expect(length(missing_elems) == 0, c( + "Expected all elements in `.element_tree` to have corresponding parameters in `theme()`.", + sprintf("Element is missing from theme(): %s", paste(missing_elems)) + )) +}) From d20c7e96b53868d94a3f39b373bd52b54b9d62e5 Mon Sep 17 00:00:00 2001 From: Carl Suster Date: Wed, 1 Apr 2026 11:47:13 +1100 Subject: [PATCH 2/8] Document strip.placement.* --- R/theme.R | 10 +++++++--- man/theme.Rd | 9 ++++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/R/theme.R b/R/theme.R index d263ff0fe6..5c602e0a6b 100644 --- a/R/theme.R +++ b/R/theme.R @@ -192,9 +192,11 @@ #' inherits from `rect`). Horizontal facet background (`strip.background.x`) #' & vertical facet background (`strip.background.y`) inherit from #' `strip.background` or can be specified separately -#' @param strip.placement placement of strip with respect to axes, -#' either "inside" or "outside". Only important when axes and strips are -#' on the same side of the plot. +#' @param strip.placement,strip.placement.x,strip.placement.y +#' placement of strip with respect to axes, either "inside" or "outside". +#' Only important when axes and strips are on the same side of the plot. +#' Horizontal (`strip.placement.x`) & vertical (`strip.placement.y`) placements +#' inherit from `strip.placement` or can be specified separately #' @param strip.clip should strip background edges and strip labels be clipped #' to the extend of the strip background? Options are `"on"` to clip, `"off"` #' to disable clipping or `"inherit"` (default) to take the clipping setting @@ -474,6 +476,8 @@ theme <- function(..., strip.background.y, strip.clip, strip.placement, + strip.placement.x, + strip.placement.y, strip.text, strip.text.x, strip.text.x.bottom, diff --git a/man/theme.Rd b/man/theme.Rd index 66a9be0d32..d3e1ee77e2 100644 --- a/man/theme.Rd +++ b/man/theme.Rd @@ -141,6 +141,8 @@ theme( strip.background.y, strip.clip, strip.placement, + strip.placement.x, + strip.placement.y, strip.text, strip.text.x, strip.text.x.bottom, @@ -378,9 +380,10 @@ to the extend of the strip background? Options are \code{"on"} to clip, \code{"o to disable clipping or \code{"inherit"} (default) to take the clipping setting from the parent viewport.} -\item{strip.placement}{placement of strip with respect to axes, -either "inside" or "outside". Only important when axes and strips are -on the same side of the plot.} +\item{strip.placement, strip.placement.x, strip.placement.y}{placement of strip with respect to axes, either "inside" or "outside". +Only important when axes and strips are on the same side of the plot. +Horizontal (\code{strip.placement.x}) & vertical (\code{strip.placement.y}) placements +inherit from \code{strip.placement} or can be specified separately} \item{strip.text, strip.text.x, strip.text.y, strip.text.x.top, strip.text.x.bottom, strip.text.y.left, strip.text.y.right}{facet labels (\code{\link[=element_text]{element_text()}}; inherits from \code{text}). Horizontal facet labels (\code{strip.text.x}) & vertical facet labels (\code{strip.text.y}) inherit from \code{strip.text} or can be specified From d190adfb086b61a3d052a866776bd0c2c044a737 Mon Sep 17 00:00:00 2001 From: Carl Suster Date: Wed, 1 Apr 2026 12:28:18 +1100 Subject: [PATCH 3/8] Document palette.* in theme --- R/theme.R | 29 +++++++++++++++++++++++++++++ man/theme.Rd | 27 +++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/R/theme.R b/R/theme.R index 5c602e0a6b..7496fa9c35 100644 --- a/R/theme.R +++ b/R/theme.R @@ -132,6 +132,21 @@ #' @param legend.box.spacing The spacing between the plotting area and the #' legend box (`unit`); inherits from `spacing`. #' +#' @param palette.colour.discrete,palette.colour.continuous,palette.fill.discrete,palette.fill.continuous +#' default palettes for the colour and fill aesthetics to use for discrete or +#' continuous data. Can be a character vector of colours or a palette function +#' such as [scales::pal_hue()]. `palette.fill.discrete` inherits from +#' palette.colour.discrete` and `palette.fill.continuous` inherits from +#' `palette.colour.continuous`. +#' @param palette.alpha.discrete,palette.linewidth.discrete,palette.size.discrete,palette.shape.discrete,palette.linetype.discrete +#' default palette to use for discrete scales for the corresponding aesthetic. +#' See the `palette` parameter of [discrete_scale()] and +#' `vignette("ggplot2-specs")` for allowed values. +#' @param palette.alpha.continuous,palette.linewidth.continuous,palette.size.continuous,palette.shape.continuous,palette.linetype.continuous +#' default palette to use for continuous scales for the corresponding aesthetic. +#' See the `palette` parameter of [continuous_scale()] and +#' `vignette("ggplot2-specs")` for allowed values. +#' #' @param panel.background background of plotting area, drawn underneath plot #' ([element_rect()]; inherits from `rect`) #' @param panel.border border around plotting area, drawn on top of plot so that @@ -446,6 +461,20 @@ theme <- function(..., legend.box.margin, legend.box.background, legend.box.spacing, + palette.colour.discrete, + palette.colour.continuous, + palette.fill.discrete, + palette.fill.continuous, + palette.alpha.discrete, + palette.alpha.continuous, + palette.linewidth.discrete, + palette.linewidth.continuous, + palette.size.discrete, + palette.size.continuous, + palette.shape.discrete, + palette.shape.continuous, + palette.linetype.discrete, + palette.linetype.continuous, panel.background, panel.border, panel.spacing, diff --git a/man/theme.Rd b/man/theme.Rd index d3e1ee77e2..4b7f3a4928 100644 --- a/man/theme.Rd +++ b/man/theme.Rd @@ -111,6 +111,20 @@ theme( legend.box.margin, legend.box.background, legend.box.spacing, + palette.colour.discrete, + palette.colour.continuous, + palette.fill.discrete, + palette.fill.continuous, + palette.alpha.discrete, + palette.alpha.continuous, + palette.linewidth.discrete, + palette.linewidth.continuous, + palette.size.discrete, + palette.size.continuous, + palette.shape.discrete, + palette.shape.continuous, + palette.linetype.discrete, + palette.linetype.continuous, panel.background, panel.border, panel.spacing, @@ -303,6 +317,19 @@ inherits from \code{rect})} \item{legend.box.spacing}{The spacing between the plotting area and the legend box (\code{unit}); inherits from \code{spacing}.} +\item{palette.colour.discrete, palette.colour.continuous, palette.fill.discrete, palette.fill.continuous}{default palettes for the colour and fill aesthetics to use for discrete or +continuous data. Can be a character vector of colours or a palette function +such as \code{\link[scales:pal_hue]{scales::pal_hue()}}. \code{palette.fill.discrete} inherits from +palette.colour.discrete\code{and}palette.fill.continuous\verb{inherits from}palette.colour.continuous`.} + +\item{palette.alpha.discrete, palette.linewidth.discrete, palette.size.discrete, palette.shape.discrete, palette.linetype.discrete}{default palette to use for discrete scales for the corresponding aesthetic. +See the \code{palette} parameter of \code{\link[=discrete_scale]{discrete_scale()}} and +\code{vignette("ggplot2-specs")} for allowed values.} + +\item{palette.alpha.continuous, palette.linewidth.continuous, palette.size.continuous, palette.shape.continuous, palette.linetype.continuous}{default palette to use for continuous scales for the corresponding aesthetic. +See the \code{palette} parameter of \code{\link[=continuous_scale]{continuous_scale()}} and +\code{vignette("ggplot2-specs")} for allowed values.} + \item{panel.background}{background of plotting area, drawn underneath plot (\code{\link[=element_rect]{element_rect()}}; inherits from \code{rect})} From 463caf609708853e64e1a04bb19d28810f5b33eb Mon Sep 17 00:00:00 2001 From: Carl Suster Date: Wed, 1 Apr 2026 13:52:53 +1100 Subject: [PATCH 4/8] Avoid unneeded ns in test --- tests/testthat/test-theme.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/test-theme.R b/tests/testthat/test-theme.R index f6d929704f..42c77b35f8 100644 --- a/tests/testthat/test-theme.R +++ b/tests/testthat/test-theme.R @@ -696,7 +696,7 @@ test_that("legends are placed correctly when using stretchy spacing", { test_that("all theme elements are documented", { all_elems <- names(.element_tree) - doc_fmls <- rlang::fn_fmls_names(theme) + doc_fmls <- fn_fmls_names(theme) missing_elems <- setdiff(all_elems, doc_fmls) expect(length(missing_elems) == 0, c( From 8f29761a322b1e19222c9666406885c937a83c3c Mon Sep 17 00:00:00 2001 From: Carl Suster Date: Wed, 1 Apr 2026 13:54:00 +1100 Subject: [PATCH 5/8] Add missing params to theme_sub_strip() --- R/theme-sub.R | 3 ++- man/subtheme.Rd | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/R/theme-sub.R b/R/theme-sub.R index f7644fc08d..65090e89aa 100644 --- a/R/theme-sub.R +++ b/R/theme-sub.R @@ -149,7 +149,8 @@ theme_sub_plot <- function(..., background, title, title.position, subtitle, cap #' @export #' @describeIn subtheme Theme specification for facet strips. theme_sub_strip <- function(..., background, background.x, background.y, clip, - placement, text, text.x, text.x.bottom, text.x.top, + placement, placement.x, placement.y, text, text.x, + text.x.bottom, text.x.top, text.y, text.y.left, text.y.right, switch.pad.grid, switch.pad.wrap) { warn_dots_empty() diff --git a/man/subtheme.Rd b/man/subtheme.Rd index 1200580280..0e24783b49 100644 --- a/man/subtheme.Rd +++ b/man/subtheme.Rd @@ -162,6 +162,8 @@ theme_sub_strip( background.y, clip, placement, + placement.x, + placement.y, text, text.x, text.x.bottom, @@ -176,7 +178,7 @@ theme_sub_strip( \arguments{ \item{...}{Not in use, expected to be empty.} -\item{axis.line, background, background.x, background.y, border, box, box.background, box.just, box.margin, box.spacing, byrow, caption, caption.position, clip, direction, frame, grid, grid.major, grid.major.x, grid.major.y, grid.minor, grid.minor.x, grid.minor.y, heights, justification, justification.bottom, justification.inside, justification.left, justification.right, justification.top, key, key.height, key.justification, key.size, key.spacing, key.spacing.x, key.spacing.y, key.width, line, location, margin, minor.ticks, minor.ticks.length, ontop, placement, position, position.inside, spacing, spacing.x, spacing.y, subtitle, switch.pad.grid, switch.pad.wrap, tag, tag.location, tag.position, text, text.position, text.x, text.x.bottom, text.x.top, text.y, text.y.left, text.y.right, ticks, ticks.length, title, title.position, widths}{Arguments that are renamed and passed on to \code{\link[=theme]{theme()}}.} +\item{axis.line, background, background.x, background.y, border, box, box.background, box.just, box.margin, box.spacing, byrow, caption, caption.position, clip, direction, frame, grid, grid.major, grid.major.x, grid.major.y, grid.minor, grid.minor.x, grid.minor.y, heights, justification, justification.bottom, justification.inside, justification.left, justification.right, justification.top, key, key.height, key.justification, key.size, key.spacing, key.spacing.x, key.spacing.y, key.width, line, location, margin, minor.ticks, minor.ticks.length, ontop, placement, placement.x, placement.y, position, position.inside, spacing, spacing.x, spacing.y, subtitle, switch.pad.grid, switch.pad.wrap, tag, tag.location, tag.position, text, text.position, text.x, text.x.bottom, text.x.top, text.y, text.y.left, text.y.right, ticks, ticks.length, title, title.position, widths}{Arguments that are renamed and passed on to \code{\link[=theme]{theme()}}.} } \value{ A \code{theme}-class object that can be added to a plot. From 2c0050acdb6132f579ea95c3f475847356a0e73c Mon Sep 17 00:00:00 2001 From: Carl Suster Date: Wed, 1 Apr 2026 13:59:57 +1100 Subject: [PATCH 6/8] Add `theme_sub_palette()` --- NAMESPACE | 1 + R/theme-sub.R | 12 ++++++++++++ man/subtheme.Rd | 21 +++++++++++++++++++++ tests/testthat/test-theme-sub.R | 3 +++ 4 files changed, 37 insertions(+) diff --git a/NAMESPACE b/NAMESPACE index d03570d983..5a3038454a 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -737,6 +737,7 @@ export(theme_sub_axis_top) export(theme_sub_axis_x) export(theme_sub_axis_y) export(theme_sub_legend) +export(theme_sub_palette) export(theme_sub_panel) export(theme_sub_plot) export(theme_sub_strip) diff --git a/R/theme-sub.R b/R/theme-sub.R index 65090e89aa..ce7522343b 100644 --- a/R/theme-sub.R +++ b/R/theme-sub.R @@ -127,6 +127,18 @@ theme_sub_legend <- function( subtheme(find_args(), "legend.") } +#' @export +#' @describeIn subtheme Theme specification for palettes. +theme_sub_palette <- function(..., colour.continuous, colour.discrete, + fill.continuous, fill.discrete, alpha.continuous, + alpha.discrete, linewidth.continuous, + linewidth.discrete, size.continuous, + size.discrete, shape.continuous, shape.discrete, + linetype.continuous, linetype.discrete) { + warn_dots_empty() + subtheme(find_args(), "palette.") +} + #' @export #' @describeIn subtheme Theme specification for the panels. theme_sub_panel <- function(..., background, border, diff --git a/man/subtheme.Rd b/man/subtheme.Rd index 0e24783b49..90f8d89383 100644 --- a/man/subtheme.Rd +++ b/man/subtheme.Rd @@ -10,6 +10,7 @@ \alias{theme_sub_axis_left} \alias{theme_sub_axis_right} \alias{theme_sub_legend} +\alias{theme_sub_palette} \alias{theme_sub_panel} \alias{theme_sub_plot} \alias{theme_sub_strip} @@ -122,6 +123,24 @@ theme_sub_legend( box.spacing ) +theme_sub_palette( + ..., + colour.continuous, + colour.discrete, + fill.continuous, + fill.discrete, + alpha.continuous, + alpha.discrete, + linewidth.continuous, + linewidth.discrete, + size.continuous, + size.discrete, + shape.continuous, + shape.discrete, + linetype.continuous, + linetype.discrete +) + theme_sub_panel( ..., background, @@ -206,6 +225,8 @@ keeping theme declarations more organised. \item \code{theme_sub_legend()}: Theme specification for the legend. +\item \code{theme_sub_palette()}: Theme specification for palettes. + \item \code{theme_sub_panel()}: Theme specification for the panels. \item \code{theme_sub_plot()}: Theme specification for the whole plot. diff --git a/tests/testthat/test-theme-sub.R b/tests/testthat/test-theme-sub.R index 32d4f98d92..7a1247e05c 100644 --- a/tests/testthat/test-theme-sub.R +++ b/tests/testthat/test-theme-sub.R @@ -13,6 +13,8 @@ test_that("subtheme functions rename arguments as intended", { expect_equal(theme_sub_axis_left(ticks = line), theme(axis.ticks.y.left = line)) expect_equal(theme_sub_axis_right(ticks = line), theme(axis.ticks.y.right = line)) expect_equal(theme_sub_legend(key = rect), theme(legend.key = rect)) + expect_equal(theme_sub_palette(fill.discrete = c()), + theme(palette.fill.discrete = c())) expect_equal(theme_sub_panel(border = rect), theme(panel.border = rect)) expect_equal(theme_sub_plot(background = rect), theme(plot.background = rect)) expect_equal(theme_sub_strip(background = rect), theme(strip.background = rect)) @@ -41,6 +43,7 @@ test_that("theme elements are covered in `theme_sub_*()` functions", { fmls <- c(fmls, paste0("axis.", fn_fmls_names(theme_sub_axis_right), ".y.right")) fmls <- c(fmls, paste0("legend.", fn_fmls_names(theme_sub_legend))) fmls <- c(fmls, paste0("plot.", fn_fmls_names(theme_sub_plot))) + fmls <- c(fmls, paste0("palette.",fn_fmls_names(theme_sub_palette))) fmls <- c(fmls, paste0("panel.", fn_fmls_names(theme_sub_panel))) fmls <- c(fmls, paste0("strip.", fn_fmls_names(theme_sub_strip))) From 187fae5777499414bc48b58ecbab1e3c4967a9e1 Mon Sep 17 00:00:00 2001 From: Carl Suster Date: Wed, 1 Apr 2026 14:02:55 +1100 Subject: [PATCH 7/8] Add news for theme doc changes --- NEWS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS.md b/NEWS.md index 6a9d993fe8..ff180b8f20 100644 --- a/NEWS.md +++ b/NEWS.md @@ -33,6 +33,10 @@ * New `position_dodge2(group.row)` argument that can be set to `"many"` to dodge groups with more than one row, such as in `geom_violin()` (@teunbrand, #6663) +* `palette.{aes}.discrete` and `palette.{aes}.continuous` are now documented + in `theme()` and have a new helper `theme_sub_palette()`. + `strip.position.x` and `strip.position.y` are also documented and work + with `theme_sub_strip()` (@arcresu, #6829). # ggplot2 4.0.2 From 51ba718ab376cd668a6d0ee5e41533fd26bb2cac Mon Sep 17 00:00:00 2001 From: Carl Suster Date: Wed, 1 Apr 2026 14:34:16 +1100 Subject: [PATCH 8/8] Document `theme_sub_palette()` properly --- R/theme-sub.R | 2 +- man/subtheme.Rd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/R/theme-sub.R b/R/theme-sub.R index ce7522343b..e3ee89ec1d 100644 --- a/R/theme-sub.R +++ b/R/theme-sub.R @@ -173,7 +173,7 @@ subtheme_param_doc <- function() { funs <- list( theme_sub_axis, theme_sub_axis_x, theme_sub_axis_y, theme_sub_axis_bottom, theme_sub_axis_top, theme_sub_axis_left, theme_sub_axis_right, theme_sub_legend, - theme_sub_panel, theme_sub_plot, theme_sub_strip + theme_sub_panel, theme_sub_plot, theme_sub_strip, theme_sub_palette ) args <- sort(unique(unlist(lapply(funs, fn_fmls_names), use.names = FALSE))) args <- setdiff(args, "...") diff --git a/man/subtheme.Rd b/man/subtheme.Rd index 90f8d89383..349316aeb2 100644 --- a/man/subtheme.Rd +++ b/man/subtheme.Rd @@ -197,7 +197,7 @@ theme_sub_strip( \arguments{ \item{...}{Not in use, expected to be empty.} -\item{axis.line, background, background.x, background.y, border, box, box.background, box.just, box.margin, box.spacing, byrow, caption, caption.position, clip, direction, frame, grid, grid.major, grid.major.x, grid.major.y, grid.minor, grid.minor.x, grid.minor.y, heights, justification, justification.bottom, justification.inside, justification.left, justification.right, justification.top, key, key.height, key.justification, key.size, key.spacing, key.spacing.x, key.spacing.y, key.width, line, location, margin, minor.ticks, minor.ticks.length, ontop, placement, placement.x, placement.y, position, position.inside, spacing, spacing.x, spacing.y, subtitle, switch.pad.grid, switch.pad.wrap, tag, tag.location, tag.position, text, text.position, text.x, text.x.bottom, text.x.top, text.y, text.y.left, text.y.right, ticks, ticks.length, title, title.position, widths}{Arguments that are renamed and passed on to \code{\link[=theme]{theme()}}.} +\item{alpha.continuous, alpha.discrete, axis.line, background, background.x, background.y, border, box, box.background, box.just, box.margin, box.spacing, byrow, caption, caption.position, clip, colour.continuous, colour.discrete, direction, fill.continuous, fill.discrete, frame, grid, grid.major, grid.major.x, grid.major.y, grid.minor, grid.minor.x, grid.minor.y, heights, justification, justification.bottom, justification.inside, justification.left, justification.right, justification.top, key, key.height, key.justification, key.size, key.spacing, key.spacing.x, key.spacing.y, key.width, line, linetype.continuous, linetype.discrete, linewidth.continuous, linewidth.discrete, location, margin, minor.ticks, minor.ticks.length, ontop, placement, placement.x, placement.y, position, position.inside, shape.continuous, shape.discrete, size.continuous, size.discrete, spacing, spacing.x, spacing.y, subtitle, switch.pad.grid, switch.pad.wrap, tag, tag.location, tag.position, text, text.position, text.x, text.x.bottom, text.x.top, text.y, text.y.left, text.y.right, ticks, ticks.length, title, title.position, widths}{Arguments that are renamed and passed on to \code{\link[=theme]{theme()}}.} } \value{ A \code{theme}-class object that can be added to a plot.