Creating a colour palette package

This vignette shows you how to create a colour palette package with palettes.

Set up advice

This vignette assumes that you are already familiar with R package development and have setup your system for creating R packages. If this is your first time creating an R package, the book R Packages by Hadley Wickham and Jenny Bryan gives you all the tools you need to start, and I highly recommend using it as a supplement to this vignette.

A good way to check that you are ready to create a colour palette package is to run devtools::dev_sitrep(), which prints info about your development setup. If this reveals that certain tools or packages are missing or out-of-date, you are encouraged to update them.

Attach devtools

All the code below assumes you’ve attached devtools in your R session:

library(devtools)

You can initiate your new package from any active R session. You don’t need to worry about whether you’re in an existing or new project or not. The functions we use take care of this.

Example package: sunsets

We will use various functions from devtools and palettes to build a small example package from scratch. We call the package sunsets and you can take a peek at the finished product we are working towards by visiting sunsets on GitHub: https://github.com/mccarthy-m-g/sunsets.

Creating the package

The first step is to create your R package and set up its basic structure. There are many ways to accomplish this, but here we demonstrate usethis::create_package():

create_package("~/path/to/sunsets")

If create_package() package drops you into a fresh R session in your new package, you probably need to call library(devtools) again. You can also set the open argument to FALSE in create_package() if you are using it in the same session your R package will be created in.

Adding package metadata

At this point we can add important metadata about what our package does in DESCRIPTION with usethis::use_package():

use_description(
  fields = list(
    Title = "Sunset Colour Palettes",
    `Authors@R` = 
      'person("First", "Last", , "[email protected]", c("aut", "cre"))',
    Description = paste0(
      "Colour palettes inspired by sunsets in the Canadian Prairies. ",
      "Built using the 'palettes' package, which provides methods for ",
      "printing, formatting, casting and coercion, extraction and updating ",
      "of components, plotting, colour mixing arithmetic, and colour ",
      "interpolation."
    ),
    URL = "https://github.com/user/repo",
    BugReports = "https://github.com/user/repo/issues"
  )
)

Choosing a license

Because our package will primarily contain colour palette data, not code, we recommend choosing a Creative Commons license:

  • For minimal restrictions choose the CC0 license with usethis::use_cc0_license()
  • To require attribution when your colour palettes are used, choose the CC BY license with usethis::use_ccby_license()

For sunsets we choose the CC0 license with usethis::use_cc0_license():

use_cc0_license()

Creating colour palettes

Colour palette packages made with palettes are examples of so-called “data packages”—they exist solely for the purpose of distributing colour palettes created with pal_palette(), along with their documentation.

To make it easy to update or reproduce our colour palettes, we first set up a data-creating script that includes the code used to create them with usethis::use_data_raw():

use_data_raw(name = "sunset_palettes")

For the sunsets package our final script for creating colour palettes looks like this:

library(palettes)

# Discrete palettes -----------------------------------------------------------
sunset_palettes_discrete <- pal_palette(
  light = c("#dc8951", "#4E8AC9", "#F5D06D", "#69ca97", "#c978b5"),
  dark = c("#EE6720", "#0792C9", "#E4B854", "#24B079", "#9A4F80")
)

plot(sunset_palettes_discrete)

usethis::use_data(sunset_palettes_discrete, overwrite = TRUE)

# Sequential palettes ---------------------------------------------------------
sunset_palettes_sequential <- pal_palette(
  orange = pal_ramp(pal_colour(c("#EE6720", "#FBE0D1")), n = 7),
  blue   = pal_ramp(pal_colour(c("#0792C9", "#C1D1EB")), n = 7),
  yellow = pal_ramp(pal_colour(c("#E4B854", "#FFECC8")), n = 7),
  green  = pal_ramp(pal_colour(c("#24B079", "#C9EBD7")), n = 7),
  purple = pal_ramp(pal_colour(c("#9A4F80", "#ECCCE2")), n = 7)
)

plot(sunset_palettes_sequential)

usethis::use_data(sunset_palettes_sequential, overwrite = TRUE)

# All palettes ----------------------------------------------------------------
sunset_palettes <- c(
  sunset_palettes_sequential,
  sunset_palettes_discrete
)

plot(sunset_palettes)

usethis::use_data(sunset_palettes, overwrite = TRUE)

This demonstrates three important points about making colour palettes:

  • Palettes can be created manually, as in the “discrete palettes” section
  • Palettes can be made programmatically, as in the “sequential palettes” section
  • Multiple palette objects can coerced together, as in the “all palettes” section

To store these colour palettes and make them available to users of our package, we save them as .rda files in the data/ directory with usethis::use_data().

Attaching the palettes package

Our colour palettes in data/ are always effectively exported, which can be seen by running devtools::load_all() then running sunset_palettes in the console. However, to make the functions from palettes available to users of sunsets, we need to add palettes as a dependency and attach it at runtime. We can add the necessary text to DESCRIPTION with usethis::use_package():

usethis::use_package("palettes", "Depends")

We use Depends instead of Imports because sunsets is designed to be used in conjunction with palettes and is not useful without it. This is a valid exception to the general advice to always use Imports.

We also need to import palettes in our package’s NAMESPACE for its methods to be available when sunsets is loaded but not attached (i.e., sunsets::my_fun()). To import palettes in our package’s NAMESPACE, we create a basic package-level documentation script in R/ where we will import palettes with usethis::use_package_doc():

use_package_doc()

Then in R/sunsets-package.R we write roxygen2 blocks to document our colour palettes, and run devtools::document() when we’re finished. For the sunsets package our documentation looks like this:

#' @keywords internal
"_PACKAGE"

#' Internal palettes methods
#'
#' @import palettes
#' @keywords internal
#' @name sunsets-palettes
NULL

Documenting colour palettes

Our colour palettes in data/ are always effectively exported, but we still need to document them. To document our colour palettes, we create a script in R/ where we will document the names of our colour palettes with usethis::use_r():

usethis::use_r("palettes")

You can name the script anything you like, but we suggest “palettes” if all your colour palette documentation will be in a single file.

Then in R/palettes.R we write roxygen2 blocks to document our colour palettes, and run devtools::document() when we’re finished. For the sunsets package our documentation looks like this:

#' Sunset palettes
#'
#' Palettes inspired by sunsets in the Canadian Prairies.
#'
#' @format ## `sunset_palettes`
#' An object of class `palettes_palette` with `r length(sunset_palettes)`
#' colour palettes. Use `names(sunset_palettes)` to return all palette names.
#' @source <https://github.com/mccarthy-m-g/sunsets>
#' @author [Michael McCarthy](https://github.com/mccarthy-m-g)
#' @seealso [pal_palette()], [pal_colour()]
#' @examples
#' # Get all palettes by name.
#' names(sunset_palettes)
#'
#' # Plot all palettes.
#' plot(sunset_palettes)
"sunset_palettes"

#' @rdname sunset_palettes
#' @format ## `sunset_palettes_discrete`
#' An object of class `palettes_palette` with
#' `r length(sunset_palettes_discrete)` discrete colour palettes.
#'  Use `names(sunset_palettes_discrete)` to return all palette names.
"sunset_palettes_discrete"

#' @rdname sunset_palettes
#' @format ## `sunset_palettes_sequential`
#' An object of class `palettes_palette` with
#' `r length(sunset_palettes_sequential)` sequential colour palettes.
#'  Use `names(sunset_palettes_sequential)` to return all palette names.
"sunset_palettes_sequential"

Adding README.md and NEWS.md

You now have a package that is ready to submit to CRAN. But before you do, you should update two important documentation files:

  • README.md, which describes what the package does
  • NEWS.md, which describes what’s changed since the previous version

See the Documentation chapter in R Packages by Hadley Wickham and Jenny Bryan for advice on writing these files.

If you want to include printed colour previews of your colour palettes in README.md like there are in palettes’ README.md, you will need to write a README.Rmd file that uses the asciicast knitr engine. For a working example, refer to the code in palettes’ README.Rmd file.

Optionally, you might also consider adding vignettes or a pkgdown website to your package.

Package maintenance

Because colour palette packages made with palettes are data packages, they are very low maintenance. You will typically only need to update them if you are changing or updating your colour palettes. Moreover, when new features are added to palettes, users of your package can gain access to them by installing the new update—you do not need to make any changes to your own package to make them available.

Distributing your package

See the Maintenance and distribution chapter in R Packages by Hadley Wickham and Jenny Bryan for advice on distributing your package.