From 10981c589c6fd8cf8b11f564c0498e2d87b4f1a6 Mon Sep 17 00:00:00 2001 From: Veerle van Leemput Date: Wed, 4 Nov 2026 09:17:26 +0100 Subject: [PATCH 1/4] Release flow: main only, tagged releases, pkgdown deployment Same change as rivm-syso/ROvis.utils#18: release.yaml, pkgdown job re-enabled, pkgdown development mode, URL/BugReports, usethis NEWS heading, install instructions and a Releases section in CONTRIBUTING.md. Remotes entries point at the latest release (@*release). Co-Authored-By: Claude Opus 5.5 --- .github/CONTRIBUTING.md | 20 ++++++ .github/workflows/ci.yaml | 92 ++++++++++++------------ .github/workflows/release.yaml | 124 +++++++++++++++++++++++++++++++++ DESCRIPTION | 6 +- NEWS.md | 2 +- README.md | 13 +++- _pkgdown.yml | 6 +- 7 files changed, 211 insertions(+), 52 deletions(-) create mode 100644 .github/workflows/release.yaml diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index b8531b0..77b4bae 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -108,6 +108,26 @@ When coding: - As an author: respond to every comment, and only resolve a thread once it's addressed. - The author merges the pull request after approval, unless agreed otherwise. +## Releases + +`main` is the only long-lived branch. Between releases it has a development version ending in `.9000`. A release is a tag `vX.Y.Z` on `main` with a GitHub release. [R-universe](https://rivm-syso.r-universe.dev) builds the latest release. + +### In every pull request + +- Add a bullet to `NEWS.md` under the `(development version)` heading for every user-facing change. These bullets become the release notes. +- Don't change `Version` in `DESCRIPTION`. It only changes in a release pull request. +- Every `Remotes:` entry for an ROvis package ends in `@*release`, for example `rivm-syso/ROvis.utils@*release`. If you need an unreleased change from another ROvis package, remove `@*release` from that entry and raise the minimum version in `Imports:` to its development version. That package is then released first. + +### Making a release (maintainers) + +1. Open a release pull request. Run `usethis::use_version()` with `"patch"` (bug fixes only), `"minor"` (new features) or `"major"` (breaking changes). It sets `Version` and renames the `(development version)` heading in `NEWS.md`. Check that every `Remotes:` entry ends in `@*release`. +2. Merge it after review. `release.yaml` creates the tag and the GitHub release, with the `NEWS.md` section as release notes, and opens a pull request that sets the next development version. +3. Merge that pull request. + +R-universe builds the release within about an hour. If `release.yaml` fails, run `usethis::use_github_release()` on `main` and `usethis::use_dev_version()` in a new pull request. + +When several ROvis packages are released together, release them in dependency order: `ROvis.utils`, then `ROvis.table`, `ROvis.ggplot2`, `ROvis.plotly` and `ROvis.echarts`, then `ROvis.shiny`, then `ROvis`. + ## Code standards - **Single source of truth**: all color definitions live in `color()`. Build on existing functions rather than duplicating logic. diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2a52386..21ebebb 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -267,49 +267,49 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.AT_ROvis || secrets.GITHUB_TOKEN }} - # pkgdown: - # needs: test-coverage - # # test-coverage only runs on push/pull_request (see its `if:`), so on a - # # release/workflow_dispatch trigger it's skipped rather than successful - - # # explicitly allow that here, otherwise the default needs-gating would - # # skip this job too. - # if: | - # github.event_name != 'pull_request' && - # !cancelled() && - # (needs.test-coverage.result == 'success' || needs.test-coverage.result == 'skipped') - # runs-on: ubuntu-latest - # container: - # image: daratools/robase:latest - # permissions: - # contents: write - # pages: write - # env: - # GITHUB_PAT: ${{ secrets.AT_ROvis || secrets.GITHUB_TOKEN }} - # steps: - # - name: Checkout repository - # uses: actions/checkout@v5 - - # # rocker-based images run as root; mark the workspace as safe for git - # - name: Fix git safe directory - # run: git config --global --add safe.directory "$GITHUB_WORKSPACE" - - # # No setup-r step needed — R is already installed in your Docker image - # - name: Setup pandoc - # uses: r-lib/actions/setup-pandoc@v2 - - # - name: Setup R dependencies - # uses: r-lib/actions/setup-r-dependencies@v2 - # with: - # extra-packages: any::pkgdown, local::. - # needs: website - - # - name: Build pkgdown site - # run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) - # shell: Rscript {0} - - # - name: Deploy to GitHub Pages - # uses: JamesIves/github-pages-deploy-action@v4 - # with: - # clean: false # keeps the badges/ folder written by the coverage job - # branch: gh-pages - # folder: docs + pkgdown: + needs: test-coverage + # test-coverage only runs on push/pull_request (see its `if:`), so on a + # release/workflow_dispatch trigger it's skipped rather than successful - + # explicitly allow that here, otherwise the default needs-gating would + # skip this job too. + if: | + github.event_name != 'pull_request' && + !cancelled() && + (needs.test-coverage.result == 'success' || needs.test-coverage.result == 'skipped') + runs-on: ubuntu-latest + container: + image: daratools/robase:latest + permissions: + contents: write + pages: write + env: + GITHUB_PAT: ${{ secrets.AT_ROvis || secrets.GITHUB_TOKEN }} + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + # rocker-based images run as root; mark the workspace as safe for git + - name: Fix git safe directory + run: git config --global --add safe.directory "$GITHUB_WORKSPACE" + + # No setup-r step needed — R is already installed in your Docker image + - name: Setup pandoc + uses: r-lib/actions/setup-pandoc@v2 + + - name: Setup R dependencies + uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::pkgdown, local::. + needs: website + + - name: Build pkgdown site + run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) + shell: Rscript {0} + + - name: Deploy to GitHub Pages + uses: JamesIves/github-pages-deploy-action@v4 + with: + clean: false # keeps the badges/ folder written by the coverage job + branch: gh-pages + folder: docs diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..c9f498b --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,124 @@ +# Publishes a release when main has a release version (no .9000) that has no tag yet: +# creates the tag and GitHub release, then opens the dev version PR. +# See "Releases" in .github/CONTRIBUTING.md. +on: + push: + branches: [main] + workflow_dispatch: + +name: Release + +permissions: read-all + +jobs: + release: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + env: + # A release or PR created with the default GITHUB_TOKEN does not trigger other + # workflows, so ci.yaml would not deploy pkgdown on the release and would not run + # on the dev version PR. AT_ROvis does trigger them. + GH_TOKEN: ${{ secrets.AT_ROvis || secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v5 + with: + token: ${{ secrets.AT_ROvis || secrets.GITHUB_TOKEN }} + + # Decides whether this push is a release. The result is passed to the next steps + # as steps.version.outputs.release ("true" or "false"); they only run on "true". + - name: Check version + id: version + run: | + # Read the "Package:" and "Version:" fields from DESCRIPTION, + # e.g. PKG=ROvis.utils and VERSION=0.2.0 + PKG=$(grep '^Package:' DESCRIPTION | cut -d ' ' -f 2) + VERSION=$(grep '^Version:' DESCRIPTION | cut -d ' ' -f 2) + + # Make both values available to the next steps + echo "package=$PKG" >> "$GITHUB_OUTPUT" + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + + # A release version has exactly three numbers (0.2.0). + # A development version has four (0.2.0.9000): no release. + if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Version $VERSION is a development version, nothing to release." + echo "release=false" >> "$GITHUB_OUTPUT" + + # Already released: the tag v0.2.0 exists on GitHub. This happens on every + # push between merging the release PR and merging the dev version PR. + elif git ls-remote --exit-code --tags origin "refs/tags/v$VERSION" > /dev/null; then + echo "Tag v$VERSION already exists, nothing to release." + echo "release=false" >> "$GITHUB_OUTPUT" + + # Release version without a tag: the release PR was just merged + else + echo "Version $VERSION has no tag yet, releasing." + echo "release=true" >> "$GITHUB_OUTPUT" + fi + + - name: Create tag and GitHub release + if: steps.version.outputs.release == 'true' + env: + PKG: ${{ steps.version.outputs.package }} + VERSION: ${{ steps.version.outputs.version }} + run: | + # Copy the release notes from NEWS.md: every line below the heading + # "# ROvis.utils 0.2.0", up to the next "# " heading (the previous release). + # awk reads NEWS.md line by line: + # - strip trailing spaces, so "# ROvis.utils 0.2.0 " still matches + # - at the heading: start copying, skip the heading itself + # - at the next "# " heading while copying: stop + # - while copying: print the line + awk -v heading="# $PKG $VERSION" ' + { sub(/[[:space:]]+$/, "") } + $0 == heading { copying = 1; next } + copying && /^# / { exit } + copying { print } + ' NEWS.md > "$RUNNER_TEMP/release-notes.md" + + # Stop if nothing was copied: the heading is missing or misspelled + if [ ! -s "$RUNNER_TEMP/release-notes.md" ]; then + echo "::error::NEWS.md has no '# $PKG $VERSION' section. Run usethis::use_version() in the release PR." + exit 1 + fi + + # Create tag v0.2.0 on the merged commit and a GitHub release with those notes + gh release create "v$VERSION" \ + --target "$GITHUB_SHA" \ + --title "$PKG $VERSION" \ + --notes-file "$RUNNER_TEMP/release-notes.md" + + - name: Open dev version PR + if: steps.version.outputs.release == 'true' + env: + PKG: ${{ steps.version.outputs.package }} + VERSION: ${{ steps.version.outputs.version }} + run: | + # Same result as usethis::use_dev_version(): 0.2.0 becomes 0.2.0.9000 + DEV_VERSION="$VERSION.9000" + BRANCH="dev-version-$DEV_VERSION" + + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git switch -c "$BRANCH" + + # Replace the "Version:" line in DESCRIPTION + sed -i "s/^Version: .*/Version: $DEV_VERSION/" DESCRIPTION + + # Add "# ROvis.utils (development version)" at the top of NEWS.md, + # where the bullets for the next release go + { printf '# %s (development version)\n\n' "$PKG"; cat NEWS.md; } > "$RUNNER_TEMP/NEWS.md" + mv "$RUNNER_TEMP/NEWS.md" NEWS.md + + # Commit on the new branch, push it and open the PR into main + git add DESCRIPTION NEWS.md + git commit -m "Increment version number to $DEV_VERSION" + git push origin "$BRANCH" + + gh pr create \ + --base main \ + --head "$BRANCH" \ + --title "Increment version number to $DEV_VERSION" \ + --body "Opened by \`release.yaml\` after the v$VERSION release. Sets the development version and adds a new \`NEWS.md\` heading. Merge this PR to continue development." diff --git a/DESCRIPTION b/DESCRIPTION index ce24dca..8b2ba19 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -4,6 +4,8 @@ Version: 0.1.0 Authors@R: person("ROvis team", email = "spin@rivm.nl", role = c("cre", "aut")) Description: Provides accessible, keyboard-navigable 'plotly' visualisations in Rijksoverheid style. License: EUPL (>= 1.2) +URL: https://rivm-syso.github.io/ROvis.plotly/, https://github.com/rivm-syso/ROvis.plotly +BugReports: https://github.com/rivm-syso/ROvis.plotly/issues Depends: R (>= 4.5.0) Imports: @@ -27,8 +29,8 @@ Suggests: tibble (>= 3.3.0), tidyr (>= 1.3.1), zoo (>= 1.8-14) -Remotes: - rivm-syso/ROvis.utils +Remotes: + rivm-syso/ROvis.utils@*release VignetteBuilder: quarto Config/roxygen2/version: 8.1.0 Config/testthat/edition: 3 diff --git a/NEWS.md b/NEWS.md index 5ef1e8a..5637148 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,4 @@ -# ROvis.plotly v0.1.0 +# ROvis.plotly 0.1.0 First release since `ROvis.plotly` was split out of the `ROvis` monolith into its own package, and the repository moved from GitLab to GitHub. diff --git a/README.md b/README.md index daa13c3..2c5ee46 100644 --- a/README.md +++ b/README.md @@ -14,12 +14,23 @@ A tool to uniformly visualise interactive graphs in 'plotly' using standardized ## Installation +Install the latest release from [R-universe](https://rivm-syso.r-universe.dev): + +```r +install.packages( + "ROvis.plotly", + repos = c("https://rivm-syso.r-universe.dev", "https://cloud.r-project.org") +) +``` + +Install the development version from GitHub: + ```r -# Install from GitHub # install.packages("pak") pak::pak("rivm-syso/ROvis.plotly") ``` +A version number ending in `.9000` is a development version. ## Usage diff --git a/_pkgdown.yml b/_pkgdown.yml index d71acfb..24ae835 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -1,4 +1,6 @@ -url: ~ +url: https://rivm-syso.github.io/ROvis.plotly/ template: bootstrap: 5 - +# Released versions build the site root, development versions (.9000) build /dev/ +development: + mode: auto From a63cbd079382becf305619b9265f88004b248966 Mon Sep 17 00:00:00 2001 From: Veerle van Leemput Date: Wed, 4 Nov 2026 09:30:04 +0100 Subject: [PATCH 2/4] Pin third-party GitHub Actions to commit SHAs, add Dependabot Pins the third-party actions in ci.yaml to the commits their current tags point to (CodeQL actions/unpinned-tag). Dependabot keeps them up to date with one grouped PR per month. Co-Authored-By: Claude Opus 5.5 --- .github/dependabot.yml | 12 ++++++++++++ .github/workflows/ci.yaml | 16 ++++++++-------- 2 files changed, 20 insertions(+), 8 deletions(-) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..0164ff4 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +# Keeps the GitHub Actions in .github/workflows up to date, including the commit SHA +# pins in ci.yaml. One grouped PR per month at most. +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: monthly + groups: + github-actions: + patterns: + - "*" diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 21ebebb..430c3a3 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -20,7 +20,7 @@ jobs: steps: - uses: actions/checkout@v5 - - uses: posit-dev/setup-air@v1 + - uses: posit-dev/setup-air@fd20dd239848b9d807848a7ab92265cf197de694 # v1.0.2 - name: Check formatting run: | @@ -47,7 +47,7 @@ jobs: run: git config --global --add safe.directory "$GITHUB_WORKSPACE" # R is already baked into daratools/robase - no setup-r needed. - - uses: r-lib/actions/setup-r-dependencies@v2 + - uses: r-lib/actions/setup-r-dependencies@f9a764fea8d5c63df6ef9a5c7795bf7deb5d7e05 # v2.14.0 with: extra-packages: any::lintr needs: lint @@ -127,12 +127,12 @@ jobs: run: git config --global --add safe.directory "$GITHUB_WORKSPACE" # R and pandoc are already baked into daratools/robase - no setup-r/setup-pandoc needed. - - uses: r-lib/actions/setup-r-dependencies@v2 + - uses: r-lib/actions/setup-r-dependencies@f9a764fea8d5c63df6ef9a5c7795bf7deb5d7e05 # v2.14.0 with: extra-packages: any::rcmdcheck needs: check - - uses: r-lib/actions/check-r-package@v2 + - uses: r-lib/actions/check-r-package@f9a764fea8d5c63df6ef9a5c7795bf7deb5d7e05 # v2.14.0 with: upload-snapshots: true build_args: 'c("--no-manual", "--compact-vignettes=gs+qpdf")' @@ -201,7 +201,7 @@ jobs: # R is already baked into daratools/robase - no setup-r step needed. - name: Setup R dependencies - uses: r-lib/actions/setup-r-dependencies@v2 + uses: r-lib/actions/setup-r-dependencies@f9a764fea8d5c63df6ef9a5c7795bf7deb5d7e05 # v2.14.0 with: extra-packages: any::covr, any::jsonlite, any::dplyr needs: coverage @@ -295,10 +295,10 @@ jobs: # No setup-r step needed — R is already installed in your Docker image - name: Setup pandoc - uses: r-lib/actions/setup-pandoc@v2 + uses: r-lib/actions/setup-pandoc@f9a764fea8d5c63df6ef9a5c7795bf7deb5d7e05 # v2.14.0 - name: Setup R dependencies - uses: r-lib/actions/setup-r-dependencies@v2 + uses: r-lib/actions/setup-r-dependencies@f9a764fea8d5c63df6ef9a5c7795bf7deb5d7e05 # v2.14.0 with: extra-packages: any::pkgdown, local::. needs: website @@ -308,7 +308,7 @@ jobs: shell: Rscript {0} - name: Deploy to GitHub Pages - uses: JamesIves/github-pages-deploy-action@v4 + uses: JamesIves/github-pages-deploy-action@fa24774553152dd7873cd16ebd8d959b010c5445 # v4.9.0 with: clean: false # keeps the badges/ folder written by the coverage job branch: gh-pages From c9fbd062727ef486e0b33fd4c406ca14acbd1fd0 Mon Sep 17 00:00:00 2001 From: Veerle van Leemput Date: Mon, 9 Nov 2026 14:06:00 +0100 Subject: [PATCH 3/4] Format with air Four files were not formatted, so the air-format CI job failed. Whitespace and line breaks only. Co-Authored-By: Claude Opus 5.5 --- R/ro_ply_disable_toolbar.R | 1 - R/ro_ply_keyboard_accessibility.R | 20 +-- R/ro_ply_keyboard_nav_legend.R | 1 - R/ro_ply_standard.R | 210 ++++++++++++++++++------------ 4 files changed, 137 insertions(+), 95 deletions(-) diff --git a/R/ro_ply_disable_toolbar.R b/R/ro_ply_disable_toolbar.R index bfc8af4..6eaf93d 100644 --- a/R/ro_ply_disable_toolbar.R +++ b/R/ro_ply_disable_toolbar.R @@ -1,4 +1,3 @@ - #' Disable the plotly modebar (toolbar) and legend pop-up #' #' `r ROvis.utils::ro_group_badge('toegankelijkheid')` diff --git a/R/ro_ply_keyboard_accessibility.R b/R/ro_ply_keyboard_accessibility.R index 91bb756..ef33aa4 100644 --- a/R/ro_ply_keyboard_accessibility.R +++ b/R/ro_ply_keyboard_accessibility.R @@ -83,7 +83,9 @@ #' } ro_ply_keyboard_nav_barchart <- function(fig) { # Add a java-script so that the tooltip is accessible with the keyboard - fig2 <- onRender(fig, " + fig2 <- onRender( + fig, + " function(el, x) { // Helper to hide Plotly hover label function hidePlotlyHoverlabel() { @@ -559,10 +561,10 @@ ro_ply_keyboard_nav_barchart <- function(fig) { scrollParent = scrollParent.parentElement; } } - ") + " + ) return(fig2) - } @@ -624,7 +626,9 @@ ro_ply_keyboard_nav_barchart <- function(fig) { ro_ply_keyboard_nav_bargraph <- function(fig) { # Add a java-script so that the tooltip is accessible with the keyboard - fig2 <- onRender(fig, " + fig2 <- onRender( + fig, + " function(el, x) { // Helper to hide Plotly hover label function hidePlotlyHoverlabel() { @@ -1073,8 +1077,8 @@ ro_ply_keyboard_nav_bargraph <- function(fig) { } }); } - ") - + " + ) return(fig2) } @@ -1135,7 +1139,7 @@ ro_ply_keyboard_nav_bargraph <- function(fig) { ro_ply_keyboard_nav_trendline <- function(fig) { # Add custom Javascript to make the points and lines accessible with the keyboard - fig2 <- + fig2 <- onRender( fig, " @@ -1904,5 +1908,3 @@ var trace = traceObj.trace; return(fig2) } - - diff --git a/R/ro_ply_keyboard_nav_legend.R b/R/ro_ply_keyboard_nav_legend.R index e5668e4..f5ff470 100644 --- a/R/ro_ply_keyboard_nav_legend.R +++ b/R/ro_ply_keyboard_nav_legend.R @@ -1,4 +1,3 @@ - #' Improve keyboard accessibility for plotly legends #' #' `r ROvis.utils::ro_group_badge('toegankelijkheid')` diff --git a/R/ro_ply_standard.R b/R/ro_ply_standard.R index d037b89..a03b7df 100644 --- a/R/ro_ply_standard.R +++ b/R/ro_ply_standard.R @@ -1,4 +1,3 @@ - #' Apply styling and accesibility features to plotly figures #' #' This function applies a standardized RIVM theme and accessibility features to a given plotly figure object. @@ -108,98 +107,141 @@ #' #' fig #' } -ro_ply_standard <- function(fig, type = c("none", "barchart", "bargraph", "linechart", "trendline"), - - # parameters for ro_ply_theme - barmode = "vgroup", - #Font - base_family = "RijksoverheidSansWebText", - # Titles - title_color = ro_color(color_name = "lintblauw"), # "#154273" - title_size = 17, - y_axis_title_size = 13, - x_axis_title_size = 13, - # Ticks and grids - axis_tick_size = 12, - axis_title_color = ro_color(color_name = "lintblauw"), # "#154273" - axis_tick_color = ro_color(color_name = "grijs_7"), # "#535353" - grid_color = ro_color(color_name = "grijs_3"), # "#cccccc" - grid_width = 0.25, - y_axis_showgrid = TRUE, - x_axis_showgrid = FALSE, - x_axis_tick_format = NULL, # For most barplots etc. no ticks - y_axis_tick_format = ",.0f", #for thousand seperator as , - # Axis lines - y_axis_showline = FALSE, - x_axis_showline = TRUE, - x_line_color = ro_color(color_name = "grijs_7"), # "#535353" - y_line_color = ro_color(color_name = "lintblauw"), # "#154273" - x_line_width = 1.5, - y_line_width = 0, - # Crosshair / Spikes - y_axis_spike = FALSE, - x_axis_spike = TRUE, - cross_hair_color = "#535353", - cross_hair_style = "dash", - cross_hair_width = 1, - # General color theming - colorway = c( - ro_color(color_name = "hemelblauw"), - ro_color(color_name = "donkergeel"), - ro_color(color_name = "robijnrood"), - ro_color(color_name = "paars_tint90"), - ro_color(color_name = "mintgroen_tint110"), - ro_color(color_name = "oranje"), - ro_color(color_name = "groen"), - ro_color(color_name = "donkerbruin") - ), #c("#007bc7", "#ffb612", "#ca005d", "#552c6f", "#6abda4", "#e17000", "#39870c", "#673327") - # Legend - legend_font_size = 13, - legend_color = ro_color(color_name = "grijs_7"), # "#535353" - # General theming - plot_bgcolor = "#ffffff", #"#ffffff" - paper_bgcolor = "#ffffff", #"#ffffff" - # Tooltip - tooltip_color = "#000000", - tooltip_border_color = "#000000", - tooltip_background_color = "#ffffff", - tooltip_font_size = 13, +ro_ply_standard <- function( + fig, + type = c("none", "barchart", "bargraph", "linechart", "trendline"), + # parameters for ro_ply_theme + barmode = "vgroup", + #Font + base_family = "RijksoverheidSansWebText", + # Titles + title_color = ro_color(color_name = "lintblauw"), # "#154273" + title_size = 17, + y_axis_title_size = 13, + x_axis_title_size = 13, + # Ticks and grids + axis_tick_size = 12, + axis_title_color = ro_color(color_name = "lintblauw"), # "#154273" + axis_tick_color = ro_color(color_name = "grijs_7"), # "#535353" + grid_color = ro_color(color_name = "grijs_3"), # "#cccccc" + grid_width = 0.25, + y_axis_showgrid = TRUE, + x_axis_showgrid = FALSE, + x_axis_tick_format = NULL, # For most barplots etc. no ticks + y_axis_tick_format = ",.0f", #for thousand seperator as , + # Axis lines + y_axis_showline = FALSE, + x_axis_showline = TRUE, + x_line_color = ro_color(color_name = "grijs_7"), # "#535353" + y_line_color = ro_color(color_name = "lintblauw"), # "#154273" + x_line_width = 1.5, + y_line_width = 0, + # Crosshair / Spikes + y_axis_spike = FALSE, + x_axis_spike = TRUE, + cross_hair_color = "#535353", + cross_hair_style = "dash", + cross_hair_width = 1, + # General color theming + colorway = c( + ro_color(color_name = "hemelblauw"), + ro_color(color_name = "donkergeel"), + ro_color(color_name = "robijnrood"), + ro_color(color_name = "paars_tint90"), + ro_color(color_name = "mintgroen_tint110"), + ro_color(color_name = "oranje"), + ro_color(color_name = "groen"), + ro_color(color_name = "donkerbruin") + ), #c("#007bc7", "#ffb612", "#ca005d", "#552c6f", "#6abda4", "#e17000", "#39870c", "#673327") + # Legend + legend_font_size = 13, + legend_color = ro_color(color_name = "grijs_7"), # "#535353" + # General theming + plot_bgcolor = "#ffffff", #"#ffffff" + paper_bgcolor = "#ffffff", #"#ffffff" + # Tooltip + tooltip_color = "#000000", + tooltip_border_color = "#000000", + tooltip_background_color = "#ffffff", + tooltip_font_size = 13, - # parameters for ro_ply_title - y_data = NULL, y_label = NULL, x_label = NULL, title = NULL, - canvas_width = 776, - left_margin_base = 10, char_width = 7, # Average size of characters for Ariasl - #title_size = 17, # RIVM theming - axis_title_size = 13, # RIVM theming - #title_color = ro_color(color_name = "lintblauw"), # "#154273" = RIVM theming - thousand_seperator = ".", # Dutch way of seperators - decimal_seperator = ",", # Dutch way of seperators - - # parameters for ro_ply_dim - width = 776, height = 400 - ){ + # parameters for ro_ply_title + y_data = NULL, + y_label = NULL, + x_label = NULL, + title = NULL, + canvas_width = 776, + left_margin_base = 10, + char_width = 7, # Average size of characters for Ariasl + #title_size = 17, # RIVM theming + axis_title_size = 13, # RIVM theming + #title_color = ro_color(color_name = "lintblauw"), # "#154273" = RIVM theming + thousand_seperator = ".", # Dutch way of seperators + decimal_seperator = ",", # Dutch way of seperators + # parameters for ro_ply_dim + width = 776, + height = 400 +) { # Theming functions - theme <- ro_ply_theme(barmode, base_family, title_color, title_size, y_axis_title_size, x_axis_title_size, - axis_tick_size, axis_title_color, axis_tick_color, grid_color, grid_width, - y_axis_showgrid, x_axis_showgrid, x_axis_tick_format, y_axis_tick_format, - y_axis_showline, x_axis_showline, x_line_color, y_line_color, x_line_width, - y_line_width, y_axis_spike, x_axis_spike, cross_hair_color, cross_hair_style, - cross_hair_width, colorway, legend_font_size, legend_color, - plot_bgcolor, paper_bgcolor, - tooltip_color, tooltip_border_color, tooltip_background_color, - tooltip_font_size) + theme <- ro_ply_theme( + barmode, + base_family, + title_color, + title_size, + y_axis_title_size, + x_axis_title_size, + axis_tick_size, + axis_title_color, + axis_tick_color, + grid_color, + grid_width, + y_axis_showgrid, + x_axis_showgrid, + x_axis_tick_format, + y_axis_tick_format, + y_axis_showline, + x_axis_showline, + x_line_color, + y_line_color, + x_line_width, + y_line_width, + y_axis_spike, + x_axis_spike, + cross_hair_color, + cross_hair_style, + cross_hair_width, + colorway, + legend_font_size, + legend_color, + plot_bgcolor, + paper_bgcolor, + tooltip_color, + tooltip_border_color, + tooltip_background_color, + tooltip_font_size + ) fig <- ro_ply_add_theme(fig = fig, theme = theme) - fig <- ro_ply_title(fig, y_data = y_data, y_label = y_label, x_label = x_label, title = title, - canvas_width = canvas_width, left_margin_base = left_margin_base, char_width = char_width, - title_size = title_size, axis_title_size = axis_title_size, title_color = title_color, - thousand_seperator = thousand_seperator, decimal_seperator = decimal_seperator) + fig <- ro_ply_title( + fig, + y_data = y_data, + y_label = y_label, + x_label = x_label, + title = title, + canvas_width = canvas_width, + left_margin_base = left_margin_base, + char_width = char_width, + title_size = title_size, + axis_title_size = axis_title_size, + title_color = title_color, + thousand_seperator = thousand_seperator, + decimal_seperator = decimal_seperator + ) fig <- ro_ply_cursor(fig) fig <- ro_ply_legend_theme(fig) fig <- ro_ply_dim(fig, width = width, height = height) - # Accessibility functions if (type == "barchart") { fig <- ro_ply_keyboard_nav_barchart(fig) From f6c255d53d287db7020f742fa378caf9ec3b35f3 Mon Sep 17 00:00:00 2001 From: Veerle van Leemput Date: Mon, 9 Nov 2026 14:24:10 +0100 Subject: [PATCH 4/4] Fix lintr issues CI now runs on PRs into main and lintr flagged these: - vignette: indentation of ro_ply_standard() calls, trailing comma - long @param lines and a long JS selector line (> 120 characters) - htmlwidgets::onRender() while onRender is already imported Layout only, no behaviour changes. Co-Authored-By: Claude Opus 5.5 --- R/ro_ply_cursor.R | 5 +- R/ro_ply_keyboard_accessibility.R | 2 +- R/ro_ply_standard.R | 6 +- man/ro_ply_standard.Rd | 6 +- vignettes/plotly-figures-standard.qmd | 144 ++++++++++++++------------ 5 files changed, 90 insertions(+), 73 deletions(-) diff --git a/R/ro_ply_cursor.R b/R/ro_ply_cursor.R index c73f023..f351325 100644 --- a/R/ro_ply_cursor.R +++ b/R/ro_ply_cursor.R @@ -21,7 +21,10 @@ ro_ply_cursor <- function(fig) { ' function(el, x) { el.style.cursor = "default"; - var layers = el.querySelectorAll(".plotly .cursor-crosshair, .plotly .scatterlayer, .plotly .cartesianlayer, .plotly .hoverlayer"); + var layers = el.querySelectorAll( + ".plotly .cursor-crosshair, .plotly .scatterlayer, " + + ".plotly .cartesianlayer, .plotly .hoverlayer" + ); layers.forEach(function(layer) { layer.style.cursor = "default"; }); diff --git a/R/ro_ply_keyboard_accessibility.R b/R/ro_ply_keyboard_accessibility.R index ef33aa4..60d13de 100644 --- a/R/ro_ply_keyboard_accessibility.R +++ b/R/ro_ply_keyboard_accessibility.R @@ -1538,7 +1538,7 @@ ro_ply_keyboard_nav_trendline <- function(fig) { #' fig #' } ro_ply_keyboard_nav_linechart <- function(fig) { - fig2 <- htmlwidgets::onRender( + fig2 <- onRender( fig, " function(el, x) { diff --git a/R/ro_ply_standard.R b/R/ro_ply_standard.R index a03b7df..bb07672 100644 --- a/R/ro_ply_standard.R +++ b/R/ro_ply_standard.R @@ -3,8 +3,10 @@ #' This function applies a standardized RIVM theme and accessibility features to a given plotly figure object. #' It wraps several (internal) ROvis functions. #' -#' @param fig A plotly figure object created by \code{plotly::plot_ly()} to which the styling and accesibility features will be added. -#' @param type Type of chart for which to apply keyboard navigation. Options are "none", "barchart", "bargraph", "linechart", or "trendline". Default is "none". +#' @param fig A plotly figure object created by \code{plotly::plot_ly()} to which the styling and +#' accesibility features will be added. +#' @param type Type of chart for which to apply keyboard navigation. Options are "none", "barchart", +#' "bargraph", "linechart", or "trendline". Default is "none". #' @param barmode Bar mode for bar charts/graphs. Options are "vgroup" (default), "stack", or "overlay". #' @param base_family Font family for all text (default = "RijksoverheidSansWebText"). #' @param title_color Color for the main title text. diff --git a/man/ro_ply_standard.Rd b/man/ro_ply_standard.Rd index 7b1ad14..ed63767 100644 --- a/man/ro_ply_standard.Rd +++ b/man/ro_ply_standard.Rd @@ -60,9 +60,11 @@ ro_ply_standard( ) } \arguments{ -\item{fig}{A plotly figure object created by \code{plotly::plot_ly()} to which the styling and accesibility features will be added.} +\item{fig}{A plotly figure object created by \code{plotly::plot_ly()} to which the styling and +accesibility features will be added.} -\item{type}{Type of chart for which to apply keyboard navigation. Options are "none", "barchart", "bargraph", "linechart", or "trendline". Default is "none".} +\item{type}{Type of chart for which to apply keyboard navigation. Options are "none", "barchart", +"bargraph", "linechart", or "trendline". Default is "none".} \item{barmode}{Bar mode for bar charts. "vgroup" by default.} diff --git a/vignettes/plotly-figures-standard.qmd b/vignettes/plotly-figures-standard.qmd index 51b1e51..f7fab02 100644 --- a/vignettes/plotly-figures-standard.qmd +++ b/vignettes/plotly-figures-standard.qmd @@ -87,13 +87,15 @@ fig <- plot_ly( ) # And apply the Rijksoverheid / RIVM theme, and accesibility features -fig <- ro_ply_standard(fig, - type = "bargraph", - barmode = "group", - y_data = data$"Age group", - y_label = "Aantal cases", - title = "COVID-19 cases per leeftijdsgroep en geslacht", - x_label = "Leeftijdsgroepen") +fig <- ro_ply_standard( + fig, + type = "bargraph", + barmode = "group", + y_data = data$"Age group", + y_label = "Aantal cases", + title = "COVID-19 cases per leeftijdsgroep en geslacht", + x_label = "Leeftijdsgroepen" +) fig ``` @@ -131,12 +133,14 @@ fig <- plot_ly( ) # And apply the Rijksoverheid / RIVM theme, and accesibility features -fig <- ro_ply_standard(fig, - type = "bargraph", - y_data = bar_data$n, - y_label = "Aantal cases", - title = "COVID-19 cases per geslacht", - x_label = "Geslacht") +fig <- ro_ply_standard( + fig, + type = "bargraph", + y_data = bar_data$n, + y_label = "Aantal cases", + title = "COVID-19 cases per geslacht", + x_label = "Geslacht" +) fig ``` @@ -180,19 +184,20 @@ fig <- plot_ly() |> ) # And apply the Rijksoverheid / RIVM theme, and accesibility features -fig <- ro_ply_standard(fig, - type = "barchart", - y_data = data$"Age group", - y_label = "Groep", - title = "COVID-19 cases per geslacht en groep", - x_label = "Aantal cases", - y_axis_spike = TRUE, - x_axis_spike = FALSE, - y_axis_showline = TRUE, - x_axis_showline = FALSE, - y_axis_showgrid = FALSE, - x_axis_showgrid = TRUE - ) +fig <- ro_ply_standard( + fig, + type = "barchart", + y_data = data$"Age group", + y_label = "Groep", + title = "COVID-19 cases per geslacht en groep", + x_label = "Aantal cases", + y_axis_spike = TRUE, + x_axis_spike = FALSE, + y_axis_showline = TRUE, + x_axis_showline = FALSE, + y_axis_showgrid = FALSE, + x_axis_showgrid = TRUE +) fig ``` @@ -210,7 +215,7 @@ library(dplyr) # We first make some random data stacked_data <- tibble::tibble( Agegroup = rep(c("0-9", "10-19", "20-29", "30-39"), each = 3), - Sex = factor(rep(c("Man", "Vrouw", "Onbekend"), times = 4), + Sex = factor(rep(c("Man", "Vrouw", "Onbekend"), times = 4), levels = c("Man", "Vrouw", "Onbekend")), n = c(10, 14, 2, 15, 17, 1, 23, 18, 0, 9, 11, 3) ) @@ -246,14 +251,15 @@ fig <- plot_ly( ) # And apply the Rijksoverheid / RIVM theme, and accesibility features -fig <- ro_ply_standard(fig, - type = "bargraph", - barmode = "stack", - y_data = stacked_data |> group_by(Agegroup) |> summarise(n_total = sum(n)) |> pull(n_total), - title = "COVID-19 cases per leeftijdsgroep en geslacht", - x_label = "Leeftijdsgroep", - y_label = "Aantal cases" - ) +fig <- ro_ply_standard( + fig, + type = "bargraph", + barmode = "stack", + y_data = stacked_data |> group_by(Agegroup) |> summarise(n_total = sum(n)) |> pull(n_total), + title = "COVID-19 cases per leeftijdsgroep en geslacht", + x_label = "Leeftijdsgroep", + y_label = "Aantal cases" +) fig ``` ## Proportional Stacked Bar Graph @@ -312,15 +318,16 @@ fig <- plot_ly( ) # And apply the Rijksoverheid / RIVM theme, and accesibility features -fig <- ro_ply_standard(fig, - type = "bargraph", - barmode = "stack", - y_data = prop_data$bar_label, - y_label = "Leeftijdsgroep", - title = "Percentage COVID-19 cases per leeftijdsgroep en geslacht", - x_label = "Percentage", - x_axis_tick_format = ".0%", - ) +fig <- ro_ply_standard( + fig, + type = "bargraph", + barmode = "stack", + y_data = prop_data$bar_label, + y_label = "Leeftijdsgroep", + title = "Percentage COVID-19 cases per leeftijdsgroep en geslacht", + x_label = "Percentage", + x_axis_tick_format = ".0%" +) fig ``` @@ -370,14 +377,15 @@ fig <- plot_ly( ) # And apply the Rijksoverheid / RIVM theme, and accesibility features -fig <- ro_ply_standard(fig, - type = "trendline", - y_data = tab_cases_rolling_average$n, - y_label = "Aantal gevallen", - title = "COVID-19 gevallen per dag en 7-daags gemiddelde", - x_label = "Datum", - x_axis_tick_format = "%d %b" - ) +fig <- ro_ply_standard( + fig, + type = "trendline", + y_data = tab_cases_rolling_average$n, + y_label = "Aantal gevallen", + title = "COVID-19 gevallen per dag en 7-daags gemiddelde", + x_label = "Datum", + x_axis_tick_format = "%d %b" +) fig ``` @@ -426,14 +434,15 @@ for (prov in prov_names) { # And apply the Rijksoverheid / RIVM theme, and accesibility features -fig <- ro_ply_standard(fig, - type = "trendline", - y_data = tab_cases_week_by_prov$n, - y_label = "Aantal gevallen", - title = "COVID-19 gevallen per week voor twee provincies", - x_label = "Week", - x_axis_tick_format = "%d %b" - ) +fig <- ro_ply_standard( + fig, + type = "trendline", + y_data = tab_cases_week_by_prov$n, + y_label = "Aantal gevallen", + title = "COVID-19 gevallen per week voor twee provincies", + x_label = "Week", + x_axis_tick_format = "%d %b" +) fig ``` @@ -486,13 +495,14 @@ for (geslacht in levels(data_all$Geslacht)) { } # And apply the Rijksoverheid / RIVM theme, and accesibility features -fig <- ro_ply_standard(fig, - type = "linechart", - y_data = data_all$value, - y_label = "Aantal cases", - title = "COVID-19 cases per geslacht", - x_label = "" #For the year, no x-axis title is needed - ) +fig <- ro_ply_standard( + fig, + type = "linechart", + y_data = data_all$value, + y_label = "Aantal cases", + title = "COVID-19 cases per geslacht", + x_label = "" #For the year, no x-axis title is needed +) fig ```