Changelog
Source:NEWS.md
hdatools 0.6.0
PHA rebrand
PHA issued new brand guidelines in 2026. This release rebuilds .brands$pha around them: palette, continuous ramps, and fonts all change. Charts built with any *_pha() function will render in different colors and a different typeface after upgrading.
New PHA palette (breaking).
pha_colorsis now Orange#f78f49, Teal#42a18d, Blue#3990b1, Navy#0b242e, Orange Deep#a4560c, and Teal Light#a0d0c3. The first four are PHA’s own guide colors, so a chart with four or fewer categories uses only sanctioned brand colors; Orange Deep and Teal Light are tints derived from Orange and Teal, and appear only at five and six categories. The old Green, Light Blue, Red, Purple, and Dark Blue names are gone — the guide dropped those hue families outright, andpha_color("Green")now errors. Only"Orange"carries over by name, and its hex changed from#f39152to#f78f49.gradientisNULLfor PHA. The field has had no reader since thescale_*_gradient_pha()functions were removed in 0.5.0, so it is no longer populated, matchinghfvandvha.na_coloris unchanged at#e2e4e3.PHA’s continuous ramps are re-anchored. Both old anchors read their hue off colors the new guide dropped. The sequential ramp now anchors on Orange and the diverging ramp pairs Blue/Navy against Orange, re-tuned and CVD-checked in the Ramp Lab (
plans/ramp-lab/REVIEW.md, 2026-08-24). Everyscale_*_pha_c()andscale_*_pha_b()output changes. Both tuned ramps beat the retired ones on every CVD separation floor, except the protanopia inner-pair merge on the diverging ramp, which is unchanged and already documented.theme_pha()uses Raleway and Mulish. PHA’s guidelines specify Raleway for headings and Mulish for body text, replacing Noto Sans. Both are bundled ininst/fonts/and registered byregister_hda_fonts().theme_pha()’sbase_familydefault changes from"Noto Sans"to"Mulish"— the body font, matching howtheme_hda()defaults to Lato rather than Roboto Slab. Titles and subtitles take Raleway; captions and strip labels take Mulish. Noto Sans stays bundled and registered, but no brand references it now.Documented CVD limitation: PHA Teal vs Blue. These two guide colors collapse to delta-E 6.6 under simulated tritanopia. The guide’s two cool hues sit at HCL 168.6 and 227.1, which a tritan simulation maps close together, so no fix exists that does not invent an unsanctioned hue. Documented in
vignette("cvd-audit")rather than worked around, following the same posture as the HDA Green/Sea Green pair. Protanopia and deuteranopia are unaffected.
hdatools 0.5.0
Fixed an unwanted stroke outline on
geom_col()/geom_bar()bars: brand themes (theme_hda(),theme_hfv(),theme_pha(),theme_vha()) now setcolour = NAin theirggplot2::element_geom()default instead of the fill color, so column/bar charts no longer render a visible border (closes #21).get_output_format()now distinguishes"typst"and"docx"output from"pdf"instead of folding all three into"pdf".The “Using branded themes in hdatools” article no longer requires a Census API key or network access to build — it now uses a small bundled data table instead of a live
tidycensus::get_acs()call.Replaced the
showtext/sysfontsfont stack withsystemfonts(raggmoved to Suggests, as a recommended rendering device — hdatools itself never calls it).register_hda_fonts()now registers the bundled Lato, Roboto Slab, Open Sans, Poppins, Noto Sans, and Montserrat faces viasystemfonts::register_font(); thehdatools.fontsopt-out still works the same way. Consumers rendering with knitr/Quarto must adddev: "ragg_png"underknitr: opts_chunk:in_quarto.yml(seeREADME.md) — the default Cairo device does not consult the systemfonts registry, so without it the bundled fonts won’t appear in rendered output. hdatools no longer setsknitr::opts_chunk$set(fig.showtext = TRUE)as a load-time global side effect.Removed
hda_pal_discrete(),hfv_pal_discrete(),pha_pal_discrete(),scale_color_gradient_hda(),scale_colour_gradient_hda(),scale_color_gradient_pha(),scale_colour_gradient_pha(), andscale_fill_gradient_pha()— all soft-deprecated in 0.3.0. Use the discrete scales (scale_color_hda()/scale_fill_hda()etc.) and continuous ramp scales (scale_color_hda_c()/scale_fill_hda_c()etc.) introduced in 0.3.0 and 0.4.0 respectively.
hdatools 0.4.0
New
hda_focus_pal()/hfv_focus_pal()/pha_focus_pal()/vha_focus_pal()return a focus/emphasis palette for “highlight one series, mute the rest” charts: element 1 is the named brand color hex, elements 2–nare the brand’s neutral gray. Pass directly toscale_fill_manual(values = …)orscale_colour_manual(values = …).New
hda_span()/hfv_span()/pha_span()/vha_span()wrap a text string in<span style='color:#…'>…</span>using a named brand color, for use withggtext::element_markdown()andggtext::element_textbox(). Color is resolved through the per-brand.*_color()accessor, so invalid names error with the valid list.New pkgdown article “CVD accessibility audit” (
vignettes/articles/cvd-audit.Rmd) documents pairwise perceptual-distance (delta-E, CIE76) results for all four brand palettes under full-severity protanopia, deuteranopia, and tritanopia. Key findings: HDA Green vs Sea Green collapses to delta-E ≈ 6 under tritanopia (positions 2 and 6; use a secondary encoding if both must appear in a tritanopia-sensitive chart); HFV Sky vs Grass is borderline (~12 delta-E) under all CVD types; PHA Orange vs Red — flagged during design review — passes all CVD types (≥ 22). No palette order was changed (Q7,plans/DECISIONS.md, 2026-07-18). Newtests/testthat/test-cvd.Raddscolorspace::simulate_cvd()-based regression assertions that guard minimum pairwise delta-E for the first four slots of each brand palette.Added VHA as a fourth first-class brand:
theme_vha(),scale_color_vha()/scale_fill_vha()(+scale_colour_vha()alias), the fullscale_*_vha_c()/scale_*_vha_b()continuous/binned matrix, andvha_colors/vha_color()— all generated from a single.brands$vharegistry entry (R/brands.R), with no VHA-specific code inR/scales.R/R/themes.R. Montserrat (OFL) is bundled alongside the existing fonts. See the new pkgdown article “Adding a new client brand to hdatools” (vignettes/articles/adding-a-brand.Rmd) for the general pattern this proves out. VHA’s diverging ramp is provisional — it pairs Dark Turq against Yellow, the palette’s only warm hue, but Yellow’s natural HCL lightness is too high to survive as a dark, saturated anchor, so that arm renders golden/olive rather than bright yellow (an sRGB gamut limit, not a tuning slip); candidate for a follow-up Ramp Lab pass, same as HDA’s diverging ramp.theme_hda()/theme_hfv()/theme_pha()alone now brand a plot with noscale_*()call required, via ggplot2 4.0’s theme-carried palettes: each theme setspalette.colour.discrete/palette.fill.discreteto the brand’s full discrete palette andpalette.colour.continuous/palette.fill.continuousto the brand’s sequential ramp (the same ramps behindscale_color_hda_c()and friends). An explicitscale_*()call (or a manualaes()value) always overrides these theme-carried defaults, so every existing plot that already sets its own scale is unaffected.The same three themes now set a default
geomfill/colour (viaggplot2::element_geom()), so a baregeom_bar()/geom_col()/geom_point()/geom_line()with nofill/colourmapping at all renders in the brand’s first palette color instead of ggplot2’s stock grey/black.Raised the
ggplot2dependency floor to>= 4.0.0(from>= 3.5.0), the version required for the theme-carried palette/element_geom()features above.New
scale_color_hda_c()/scale_colour_hda_c()/scale_fill_hda_c()(and the matchinghfv/phaversions) — a full continuous color/fill scale matrix (9 exports) built from sixcolorspaceHCL sequential/diverging ramps tuned and CVD-checked (protanopia/deuteranopia/tritanopia) in the Ramp Lab review (plans/ramp-lab/REVIEW.md). Each takespalette = c("sequential", "diverging")to choose the ramp, plusdirection,na.value, andguide. Sequential ramps default to higher value = darker color; diverging ramps default to the ramp’s own low-to-high arm order as reviewed. HDA’s diverging ramp (Blue vs Coral) is provisional — it’s a near-twin of PHA’s and is pending a follow-up Ramp Lab pass to differentiate it before final adoption (plans/DECISIONS.md, 2026-07-18).New
scale_color_hda_b()/scale_colour_hda_b()/scale_fill_hda_b()(and the matchinghfv/phaversions) — the binned counterpart of the above (9 exports), defaulting ton.breaks = 7, the class count every ramp was tuned and CVD-checked against.7-class diverging maps built from any of the six ramps lose sign distinction in their innermost class pair under protanopia (structural to the shared cream center) — always pair a
palette = "diverging"map with a legend or direct labels (documented on every new scale’s help page).scale_color_gradient_hda(),scale_color_gradient_pha(), andscale_fill_gradient_pha()’s existing soft-deprecation notices now name their replacement (e.g.scale_color_hda_c()) vialifecycle’suse_instead, now that one exists."Leaf"(#6fb547) and"Cerulean"(#7fc7e0) joinhfv_colorsand.brands$hfv$paletteas official HFV secondary colors — both HFV ramps are built on Leaf, and Cerulean was approved alongside it at Ramp Lab sign-off.HFV gets its first
na.valuedefault (#d6dadd), needed now that it has continuous scales for the first time; HDA/PHA already had their own (#cfcfd0/#e2e4e3).colorspacejoins Imports (used only internally by the new ramp scales).New
hda_colors,hfv_colors,pha_colors— exported named character vectors of each brand’s palette hex values, sourced directly from the internal.brandsregistry. Downstream consumers can now reference brand hexes by name (e.g.hda_colors["Blue"]) or pass the full vector toscale_fill_manual(values = hda_colors)without hardcoding hex strings.New
hda_color(),hfv_color(),pha_color()— per-brand accessors that return the hex for a named color and error with the list of valid names on an unknown input.
hdatools 0.3.0
New
scale_colour_hda(),scale_colour_hfv(),scale_colour_pha(),scale_colour_gradient_hda(), andscale_colour_gradient_pha()— British- spelling aliases of the existingscale_color_*()exports, for parity with ggplot2’s owncolour/coloraliasing. No change to any existing export.hda_pal_discrete(),hfv_pal_discrete(),pha_pal_discrete(),scale_color_gradient_hda(),scale_color_gradient_pha(), andscale_fill_gradient_pha()are now soft-deprecated (lifecycle:: deprecate_soft()); they keep working exactly as before, but calling them directly will surface a one-time deprecation notice.lifecyclemoves to Imports.Internal-only: the three brands’ discrete palettes, gradient stops, NA colours, and select theme parameters (
base_size,html_adjust,pdf_adjust,lineheight) now live in one internal registry (R/brands.R), and the 9 exported discrete/gradient scales are now thin wrappers over two shared internal constructors. No behavior change; every pre-refactor identity test asserting exact hex/parameter values passes unmodified.Internal-only:
theme_hda(),theme_hfv(), andtheme_pha()are now thin wrappers over one shared internal builder (.brand_theme()inR/themes.R), reading the font/margin/size parameters that differ per brand from theR/brands.Rregistry. No behavior change; signatures and...passthrough are unchanged, and every pre-refactor theme-identity test passes unmodified.pkgdown site rebuilt on Bootstrap 5 (
template: bootstrap: 5); reference index now groups exports into Themes, Palettes & scales, Helpers, and Analysis utils. Fixed “depreciated” → “deprecated” wording in thespaceparameter docs forscale_color_gradient_hda(),scale_color_gradient_pha(), andscale_fill_gradient_pha(). No behavior change.Internal cleanup only, no behavior changes: enabled Roxygen markdown so help pages and the pkgdown site render
code/bold correctly, corrected theget_logo()@returndescription, dropped unused namespace imports, addedflip_gridlines()/get_logo()/get_output_format()/adjust_base_size()to the README, removed the dead internaladd_google_fonts()alias, and made the package startup message fire only when font registration actually succeeds.
hdatools 0.2.0
Breaking changes
-
add_reliability()gains acv_colargument. Supplying it switches to a new classification path: tidy-eval column selection, ascaleargument ("percent", the default, or"proportion"), and<=boundaries (a CV of exactly 15 percent is now “High”). Omittingcv_colkeeps the original behavior byte-for-byte: auto-detect a single column ending in_cv, treat it as a 0-1 proportion, and use strict<boundaries. -
flip_gridlines()’ssizeargument is deprecated in favor oflinewidth, matching ggplot2’s ownsize→linewidthrename. -
ggiraphmoves from Imports to Suggests.publish_plot()now errors with an install hint if ggiraph isn’t installed, instead of failing to load the package at all.
New features
- Fonts are bundled and registered offline.
inst/fonts/ships the exact static TTF facestheme_hda(),theme_hfv(), andtheme_pha()use (Lato, Roboto Slab, Open Sans, Poppins, Noto Sans), registered by the new exportedregister_hda_fonts()— no more per-session network download from Google Fonts, and no more silent failure when a render happens offline. Opt out withoptions(hdatools.fonts = FALSE)or theHDATOOLS_NO_FONTSenvironment variable. Seeinst/fonts/LICENSES.mdfor the OFL and Apache 2.0 texts covering each face. -
theme_pha()reaches parity withtheme_hda()/theme_hfv(): newoutput_format,html_adjust/pdf_adjust, and...passthrough arguments, and astrip.textelement somarkdown_wrap_gen()facet labels render correctly.html_adjust/pdf_adjustdefault to 0/0, so existingtheme_pha()output is unchanged.theme_hda()/theme_hfv()also gain explicithtml_adjust/pdf_adjustparameters (defaults match prior hardcoded behavior). -
get_logo()now resolves its image path from the installed package (system.file()) instead of a hardcoded relative path, so it works correctly once the package is installed rather than only from source.
Modernization for ggplot2 4.0
- Dropped the deprecated positional
scale_nameargument from all discrete and gradient scales. - Renamed every deprecated
size=tolinewidth=in the themes and inadd_zero_line(). - Raised the
ggplot2floor to >= 3.5.0 (required for thescale_namedeprecation shape) and added floors to all other Imports, chosen below every known consumer’s lockfile.
Documentation & housekeeping
- Fixed a broken
add_reliability()README example (it passed 10 values into an 8-row data frame and relied on_cvauto-detection against a column literally namedcv). - Documented that
strip.textoverrides on any theme must useggtext::element_markdown(), not a rawggplot2::element_text()— ggplot2 4.0 only merges theme elements of the same class. - Slimmed the namespace: replaced blanket
@importpackage imports with qualifiedpkg::calls throughout, keeping only%+replace%and rlang’s tidy-eval helpers as bare imports. - Fixed the
Authors@Rgiven/family name order for all three authors. Jonathan Knopf is now the maintainer; Kyle Walker moves toaut. - Added
URL/BugReports, droppedDate/LazyData, and removed the legacyAuthor:field. - Removed the dead
data-raw/DATASET.Rstub and movedvignettes/branded-themes.Rmdtovignettes/articles/(pkgdown builds it as a long-form article; it was never wired up as a real package vignette).
hdatools 0.1.0
- Merges updates in
jtkbranch to original build-out inmain. - Adds new color scale functions, including
scale_color_gradient_*. - Adds new color palette (
pha_pal_discrete()) for the Partnership for Housing Affordability (PHA). - Theme helper functions now load more Google Font options and include
flip_gridlines()shortcut. -
hda_pal_discrete()now includesrepeat_paloption to loop colors for data with more than six variables.