Skip to content

Conversation

teunbrand
Copy link
Collaborator

@teunbrand teunbrand commented Dec 1, 2023

This PR aims to fix #5348 and also fixes #5539, fixes #5540 and fixes #5541 and implements #5473 (comment).

Briefly, it is quite a beefy PR that adds a theme argument to all guide_*() functions and adds guide style elements to theme().

Less briefly; I could not find a satisfactory way to simplify guide styling without breaking some backward compatibility. I attempted this in #5512, but that PR added as much complexity as it took away. The crux of the PR is this:

  • The theme() function has new arguments for styling guides, like legend.frame, legend.ticks etc.
  • guide_*() functions no longer have style arguments, like frame, ticks, etc.
  • To style individual guides, one can now use guide_*(theme = theme(...))

This allows one to change the look of an individual guide with, for example, a preset theme:

devtools::load_all("~/packages/ggplot2")
#> ℹ Loading ggplot2

p <- ggplot(mpg, aes(displ, hwy)) +
  geom_point(aes(fill = cyl, colour = cty), shape = 21)

p + guides(fill = guide_legend(theme = theme_dark()))

In addition, all guide style options are now settable from the plot's theme:

red_frame <- theme(legend.frame = element_rect(colour = "red"))

p + red_frame

While retaining flexibility in individual guides.

p + guides(colour = guide_colourbar(theme = red_frame))

The 'old' options still work, but are passed through the ... argument and are undocumented.

p + guides(colour = guide_colourbar(frame.colour = "red"))

Also, the 'old' options are soft-deprecated so developers will start seeing warnings about them:

withr::with_options(
  list(lifecycle_verbosity = "error"),
  guide_colourbar(frame.colour = "red")
)
#> Error:
#> ! The `frame.colour` argument of `guide_colourbar()` is deprecated as of
#>   ggplot2 3.5.0.
#> ℹ Please use the `theme` argument instead.

Created on 2023-12-01 with reprex v2.0.2

Some additional notes:

  • theme() is already widely used to style non-data elements of the plot, so the way to style guides should be familiar.
  • The PR greatly reduced argument clutter in guides.
  • There is now harmony in which style element can be set from the guide and which element from the theme.
  • The inheritance logic is now clear: it is (plot_theme %||% guide_defaults) + guide_theme (with %||% applied element-wise, and + meaning add_theme()). This should allow for easier maintenance of the guides, as well as make it easier to extend guides.
  • Some legend styling options don't have plot-level defaults as different guides had different defaults that I preserved. For example, guide_colourbar() has white ticks by default, guide_bins() has black ticks by default and guide_coloursteps has hidden ticks by default.
  • We lose the 'expressions are right-aligned by default' heuristic. This is only a 'con' if you rely on this behaviour, it is less of a con if you, like me and others (Legend mis-alignement for parsing greek letters using scale::parse_format #4814) are surprised by this behaviour. Removing this heuristic is a net positive I think, as it is now far more straightforward to derive the horizontal justification for legend labels.
  • The legend.key.spacing is now set to the half the theme's base_size, which already is the default in 99% of legends except in the 1% where the legend doesn't have a title. Previously, it was half the title size, and if that was missing half the label size and if that was missing 5.5 points. This resulted in 1 visual snapshot without a legend title changing slightly. The additional text margins introduced in Rework legend spacing #5456 also derive from this setting for symmetry reasons.
  • A downside is that it is somewhat more verbose to set guide-level themes, but I think it is worth it overall.
  • If we ever want to get rid of guide code gnarlyness, now is the time to do it.

# Converts the `elements` field to proper elements to be accepted by
# `element_grob()`. String-interpolates aesthetic/position dependent elements.
setup_elements = function(params, elements, theme) {
theme <- add_theme(theme, params$theme)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the crucial step.

@teunbrand teunbrand added this to the ggplot2 3.5.0 milestone Dec 1, 2023
@teunbrand teunbrand requested a review from thomasp85 December 1, 2023 14:42
Merge branch 'main' into guide_themes

# Conflicts:
#	R/guide-bins.R
#	R/guide-colorbar.R
#	R/guide-legend.R
#	R/theme-elements.R
#	R/theme.R
#	man/guide_bins.Rd
#	man/guide_coloursteps.Rd
#	man/guide_legend.Rd
#	man/theme.Rd
Merge branch 'main' into guide_themes

# Conflicts:
#	R/guide-colorbar.R
#	R/guide-legend.R
#	man/guide_bins.Rd
#	man/guide_colourbar.Rd
#	man/guide_coloursteps.Rd
#	man/guide_legend.Rd
@thomasp85
Copy link
Member

a14493b is about the guide stretching stuff, right?

@teunbrand
Copy link
Collaborator Author

And long title placement, yes

Copy link
Member

@thomasp85 thomasp85 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@teunbrand
Copy link
Collaborator Author

Thanks Thomas!

@teunbrand teunbrand merged commit 8e1c085 into tidyverse:main Dec 13, 2023
@teunbrand teunbrand deleted the guide_themes branch December 13, 2023 09:04
teunbrand added a commit to teunbrand/ggplot2 that referenced this pull request Dec 20, 2023
@teunbrand teunbrand mentioned this pull request Dec 20, 2023
teunbrand added a commit that referenced this pull request Dec 22, 2023
* Apply #5554 to `guide_custom()`

* build in early exit
thomasp85 pushed a commit that referenced this pull request Feb 23, 2024
* Apply #5554 to `guide_custom()`

* build in early exit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants