From 9730e264267f00b0e22f4d7c183164f737e25ccb Mon Sep 17 00:00:00 2001 From: Emil Hvitfeldt Date: Wed, 15 Apr 2026 08:03:53 -0700 Subject: [PATCH 1/4] add skill to find and improve alt text for pkgdown documentation --- .claude-plugin/marketplace.json | 3 +- README.md | 1 + r-lib/README.md | 10 +- r-lib/pkgdown-alt-text/SKILL.md | 207 ++++++++++++++++++++++++++++++++ 4 files changed, 219 insertions(+), 2 deletions(-) create mode 100644 r-lib/pkgdown-alt-text/SKILL.md diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 4edc581..8814f47 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -52,7 +52,8 @@ "./r-lib/lifecycle", "./r-lib/r-package-development", "./r-lib/r-cli-app", - "./r-lib/mirai" + "./r-lib/mirai", + "./r-lib/pkgdown-alt-text" ] }, { diff --git a/README.md b/README.md index f882fac..becf91f 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ R package development skills for working with the r-lib ecosystem and modern R p - **[lifecycle](./r-lib/lifecycle/)** - Manage R package lifecycle according to tidyverse principles using the lifecycle package, covering deprecation workflows, function/argument renaming, superseding, and experimental stages - **[r-package-development](./r-lib/r-package-development/)** - R package development with devtools, testthat, and roxygen2, covering key commands, coding conventions, testing, documentation, and NEWS.md practices - **[mirai](./r-lib/mirai/)** - Async, parallel, and distributed computing in R using mirai, covering explicit dependency passing, daemon setup, parallel mapping with `mirai_map()`, Shiny integration, remote/HPC launchers, and migration from future/parallel +- **[pkgdown-alt-text](./r-lib/pkgdown/)** - Add accessible alt text to all images and plots in a pkgdown site, covering vignette code chunks (`fig.alt`), static markdown images, multi-plot chunks, and Quarto vignettes ### Shiny diff --git a/r-lib/README.md b/r-lib/README.md index 44e1252..34e50b6 100644 --- a/r-lib/README.md +++ b/r-lib/README.md @@ -62,12 +62,20 @@ Comprehensive guidance for async, parallel, and distributed computing in R using - [mirai package documentation](https://mirai.r-lib.org/) - [mirai GitHub repository](https://github.com/r-lib/mirai) +### `pkgdown-alt-text` + +Add accessible alt text to all images and plots in a pkgdown site. Use when auditing or improving accessibility across vignettes, articles, and README files in an R package. Covers finding missing alt text (using pkgdown's built-in warnings), writing effective descriptions using the three-part formula, adding `fig.alt` to Rmd/Qmd chunks (including multi-plot chunks), and adding alt text to static markdown images. + +**Organization**: Single SKILL.md with a step-by-step workflow: find → generate → add → verify. References the `quarto-alt-text` skill for alt text writing guidelines and chart-type templates (same principles apply). + +**Resources**: This skill synthesizes guidance from: +- [pkgdown: Accessibility](https://pkgdown.r-lib.org/articles/accessibility.html) + ## Potential Skills This category could include skills for: - Package development workflows (usethis, devtools) -- Documentation with roxygen2 and pkgdown - Package structure and organization - Dependencies and NAMESPACE management - R CMD check and CRAN submission diff --git a/r-lib/pkgdown-alt-text/SKILL.md b/r-lib/pkgdown-alt-text/SKILL.md new file mode 100644 index 0000000..35118af --- /dev/null +++ b/r-lib/pkgdown-alt-text/SKILL.md @@ -0,0 +1,207 @@ +--- +name: pkgdown-alt-text +description: > + Add accessible alt text to all images and plots in a pkgdown site. Use when + the user wants to add, improve, or audit alt text for figures in vignettes, + articles, or README files in an R package with a pkgdown site. Triggers for + requests about accessibility, fig.alt, figure descriptions, screen reader + support, or making a pkgdown site more accessible. +metadata: + author: Emil Hvitfeldt (@emilhvitfeldt) + version: "1.0" +license: MIT +--- + +# Add Alt Text to a pkgdown Site + +Generate accessible alt text for all images and plots across the pkgdown site. + +ARGUMENTS +- label: (optional) specific chunk label or image to target +- file: (optional) specific vignette or README file to process + +## Where images appear in a pkgdown site + +| Location | Image type | Can have alt text? | +|----------|------------|-------------------| +| `vignettes/*.Rmd` or `vignettes/*.qmd` | code-generated plots | Yes — `fig.alt` chunk option | +| `vignettes/*.Rmd` | static images via `knitr::include_graphics()` | Yes — `fig.alt` chunk option | +| `README.Rmd` / `README.md` | code-generated plots | Yes — `fig.alt` chunk option | +| `README.Rmd` / `README.md` | markdown images `![](path)` | Yes — fill in the bracket | +| `README.Rmd` / `README.md` | HTML `` tags | Yes — add `alt="..."` attribute | +| `R/*.R` `@examples` | code-generated plots | **No — pkgdown limitation** | + +There is currently no way to add alt text to plots generated in `@examples` +blocks. Focus effort on vignettes and README. + +## Step 1 — Find missing alt text + +### Build the site and read warnings + +The most reliable way: let pkgdown identify all missing alt text automatically. + +```r +# Build only articles (faster than full site) +Rscript -e "pkgdown::build_articles()" + +# Or build the full site +Rscript -e "pkgdown::build_site()" +``` + +pkgdown prints a warning for every code chunk that produces a plot but has no +`fig.alt`. Note down every file and chunk mentioned. + +### Find chunks missing fig.alt in vignettes + +```bash +# Find chunks that already have fig.alt (to see what's covered) +grep -rn "fig.alt\|fig-alt" vignettes/ README.Rmd + +# Find all knitr::include_graphics() calls (static images in chunks) +grep -rn "include_graphics" vignettes/ README.Rmd +``` + +### Find static images missing alt text + +```bash +# Markdown images with empty alt: ![](path) +grep -rn "!\[\](" vignettes/ README.md README.Rmd + +# All markdown images — review each for descriptive alt text +grep -rn "!\[" vignettes/ README.md README.Rmd + +# HTML tags — check each for a non-empty alt attribute +grep -rn "` tags at the top of +`README.Rmd`. Check that the `alt` attribute is present and descriptive: + +```html + + + + +Package hex logo: a blue hexagon with the package name. +``` + +## Step 2 — Audit quality of existing alt text + +When alt text already exists, leave it alone unless it has a concrete problem. +Only rewrite alt text that fails one of these checks: + +**Relative references** — alt text must be self-contained. Screen readers +don't know what "above" refers to. Fix phrases like: +- "A plot identical to the one above..." → describe the plot fully +- "Much like the first one..." → stand-alone description +- "The same data as shown above..." → name the data explicitly + +**Missing key information** — fix if the alt text omits: +- Chart type as the first words +- Axis labels and what they represent +- The key pattern or takeaway + +**Grammar and spelling errors** — alt text is read aloud by screen readers. +Fix typos and grammatically broken sentences. + +If existing alt text is accurate, complete, and self-contained, do not change +it even if you would have phrased it differently. + +## Step 3 — Generate alt text for each figure + +For each missing or weak figure, read ~50 lines of context around the chunk: +- The plotting code (what type of chart, axes, variables) +- Any data generation or transformation above the chunk +- The surrounding prose (explains the purpose and key insight) +- The `fig.cap` if present (alt text should complement, not duplicate it) + +Apply **Amy Cesal's formula** for data visualization alt text: +1. **Chart type** — first words identify the format +2. **Data description** — axes, variables, what is shown +3. **Key insight** — the pattern or takeaway (usually in surrounding prose) + +Use the source code to extract precise details: variable names, axis labels, +facet structure, color encodings, specific value ranges. This is the key +advantage over typical alt text scenarios. + +See the `quarto-alt-text` skill for detailed writing guidelines, chart-type +templates, length guidelines, and a quality checklist — the same principles +apply here. + +## Step 4 — Add fig.alt to Rmd chunks + +The `fig.alt` chunk option works for both code-generated plots and static +images loaded with `knitr::include_graphics()`. + +### Hashpipe syntax (preferred) + +```r +#| fig.alt: > +#| Scatter chart of bill length vs. bill depth for 344 penguins +#| across three species. Gentoo penguins form a distinct cluster +#| at higher bill depth. Adelie and Chinstrap overlap but separate +#| along the bill length axis, with Chinstrap skewing higher. +plot_code_here() +``` + +### Knitr chunk option syntax + +````markdown +```{r penguin-scatter, fig.alt="Scatter chart of bill length vs. bill depth..."} +plot_code_here() +``` +```` + +### Multiple plots in one chunk + +When a chunk produces multiple plots, `fig.alt` accepts a vector — one string +per plot, in order: + +```r +#| fig.alt: +#| - "Histogram of bill length. Right-skewed distribution with a peak at 45-50mm." +#| - "Histogram of bill depth. Bimodal distribution with peaks at 15mm and 18mm." +``` + +## Step 5 — Add alt text to static markdown images + +For `![](path)` images, fill in the bracket: + +```markdown + +![](man/figures/logo.png) + + +![A hexagonal logo with a blue background and white text reading 'pkgdown'.](man/figures/logo.png) +``` + +For purely decorative images (no informational content), an empty alt +explicitly signals to screen readers to skip the image — leave the bracket +empty intentionally and add a comment to make this clear: + +```markdown + +![](man/figures/decorative-banner.png) +``` + +## Step 6 — Verify + +```r +# Rebuild articles and confirm no more fig.alt warnings +Rscript -e "pkgdown::build_articles()" +``` + +No warnings about missing alt text means all vignette plots are covered. + +## Quarto vignettes (`.qmd`) + +For vignettes using Quarto format, use the Quarto-style `fig-alt` option: + +```r +#| fig-alt: > +#| Scatter chart of bill length vs. bill depth for 344 penguins +#| across three species. +``` + +Note the hyphen (`fig-alt`) vs the dot (`fig.alt`) used in `.Rmd` files. From 0f46f086a0267fb25e4f77a70c856b95587e01a0 Mon Sep 17 00:00:00 2001 From: Emil Hvitfeldt Date: Wed, 15 Apr 2026 08:16:43 -0700 Subject: [PATCH 2/4] fix link on readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index becf91f..a3c834e 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ R package development skills for working with the r-lib ecosystem and modern R p - **[lifecycle](./r-lib/lifecycle/)** - Manage R package lifecycle according to tidyverse principles using the lifecycle package, covering deprecation workflows, function/argument renaming, superseding, and experimental stages - **[r-package-development](./r-lib/r-package-development/)** - R package development with devtools, testthat, and roxygen2, covering key commands, coding conventions, testing, documentation, and NEWS.md practices - **[mirai](./r-lib/mirai/)** - Async, parallel, and distributed computing in R using mirai, covering explicit dependency passing, daemon setup, parallel mapping with `mirai_map()`, Shiny integration, remote/HPC launchers, and migration from future/parallel -- **[pkgdown-alt-text](./r-lib/pkgdown/)** - Add accessible alt text to all images and plots in a pkgdown site, covering vignette code chunks (`fig.alt`), static markdown images, multi-plot chunks, and Quarto vignettes +- **[pkgdown-alt-text](./r-lib/pkgdown-alt-text/)** - Add accessible alt text to all images and plots in a pkgdown site, covering vignette code chunks (`fig.alt`), static markdown images, multi-plot chunks, and Quarto vignettes ### Shiny From deebfc20f2caa65db72c8a6c97ee796a276b71a3 Mon Sep 17 00:00:00 2001 From: Emil Hvitfeldt Date: Wed, 15 Apr 2026 12:59:51 -0700 Subject: [PATCH 3/4] convert alt-text to use progressive disclosure --- .claude-plugin/marketplace.json | 4 +- {quarto/quarto-alt-text => alt-text}/SKILL.md | 122 +++++------ alt-text/references/pkgdown.md | 152 +++++++++++++ alt-text/references/quarto.md | 56 +++++ r-lib/pkgdown-alt-text/SKILL.md | 207 ------------------ 5 files changed, 264 insertions(+), 277 deletions(-) rename {quarto/quarto-alt-text => alt-text}/SKILL.md (57%) create mode 100644 alt-text/references/pkgdown.md create mode 100644 alt-text/references/quarto.md delete mode 100644 r-lib/pkgdown-alt-text/SKILL.md diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 8814f47..a239fca 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -53,7 +53,7 @@ "./r-lib/r-package-development", "./r-lib/r-cli-app", "./r-lib/mirai", - "./r-lib/pkgdown-alt-text" + "./alt-text" ] }, { @@ -75,7 +75,7 @@ "skills": [ "./brand-yml", "./quarto/quarto-authoring", - "./quarto/quarto-alt-text" + "./alt-text" ] } ] diff --git a/quarto/quarto-alt-text/SKILL.md b/alt-text/SKILL.md similarity index 57% rename from quarto/quarto-alt-text/SKILL.md rename to alt-text/SKILL.md index 35e0968..433c74a 100644 --- a/quarto/quarto-alt-text/SKILL.md +++ b/alt-text/SKILL.md @@ -1,29 +1,40 @@ --- -name: quarto-alt-text +name: alt-text description: > - Generate accessible alt text for data visualizations in Quarto documents. Use - when the user wants to add, improve, or review alt text for figures in .qmd - files. Triggers for requests about accessibility, figure descriptions, fig-alt, - screen reader support, or making Quarto documents more accessible. + Generate and improve accessible alt text for data visualizations and images + in R packages and Quarto documents. Use when the user wants to add, improve, + or audit alt text for figures in a pkgdown site or .qmd files. Activate for + requests that mention fig-alt, fig.alt, figure descriptions, or alt text in + the context of an R package or Quarto document. metadata: author: Emil Hvitfeldt (@emilhvitfeldt) version: "1.0" license: MIT --- -# Write Chart Alt Text +# Write Accessible Alt Text -Generate accessible alt text for data visualizations in this project. +Generate accessible alt text for data visualizations and images in this project. ARGUMENTS -- label: (optional) specific fig- label to generate alt text for -- file: (optional) specific .qmd file to process +- label: (optional) specific figure label or chunk to target +- file: (optional) specific file to process -## Instructions +## Detect project type -When invoked, analyze the figure(s) and generate alt text following these guidelines: +Before proceeding, identify the project context and read the relevant reference. +Check for a `_pkgdown.yml` file in the project root to detect a pkgdown site: -### Key Advantage: Source Code Access +```bash +ls _pkgdown.yml 2>/dev/null && echo "pkgdown" || echo "not pkgdown" +``` + +- **pkgdown site** (`_pkgdown.yml` present) → read `references/pkgdown.md` +- **Quarto documents** (no `_pkgdown.yml`, `.qmd` files present) → read `references/quarto.md` + +If the context is still ambiguous, ask the user which format they are working in. + +## Key advantage: source code access Unlike typical alt text scenarios where you only see an image, **we have access to the code that generates each chart**. Use this to extract precise details: @@ -47,59 +58,59 @@ Unlike typical alt text scenarios where you only see an image, **we have access - Chapter context tells you what the figure is meant to teach - This is often the best source for the "key insight" part of alt text -### Three-Part Structure (Amy Cesal's Formula) +## Three-part structure (Amy Cesal's formula) -1. **Chart type** - First words identify the format -2. **Data description** - Axes, variables, what's shown -3. **Key insight** - The pattern or takeaway (often found in surrounding text) +1. **Chart type** — first words identify the format +2. **Data description** — axes, variables, what is shown +3. **Key insight** — the pattern or takeaway (often found in surrounding text) -### Relationship to fig-cap +## Relationship to captions -Read the `fig-cap` first. The alt text should **complement, not duplicate** it: -- If caption states the insight, alt text can focus on describing the visual structure -- If caption is generic, alt text should include the key insight +Read the caption (`fig-cap`, `fig.cap`) first. Alt text should **complement, not duplicate** it: +- If the caption states the insight, alt text can focus on describing the visual structure +- If the caption is generic, alt text should include the key insight - Together they should give a complete understanding -### Content Rules +## Content rules **Include:** - Chart type as first words - Axis labels and what they represent -- Specific values/ranges when code reveals them (e.g., "peaks between 25-50") +- Specific values/ranges when code reveals them (e.g., "peaks between 25–50") - Number of panels/facets - What color/size encodes if used -- The key pattern that supports the chapter's point +- The key pattern that supports the surrounding point **Exclude:** -- "Image of..." or "Chart showing..." (screen readers announce this) +- "Image of…" or "Chart showing…" (screen readers announce this) - Decorative color descriptions (unless color encodes data) -- Information already in fig-cap +- Information already in the caption - Implementation details (package names, function internals) -### Length Guidelines +## Length guidelines -| Complexity | Sentences | When to use | -|------------|-----------|---------------------------------------------| -| Simple | 2-3 | Single geom, no facets, obvious pattern | -| Standard | 3-4 | Multiple geoms or color encoding | -| Complex | 4-5 | Faceted, multiple overlays, nuanced insight | +| Complexity | Sentences | When to use | +|------------|-----------|----------------------------------------------| +| Simple | 2–3 | Single geom, no facets, obvious pattern | +| Standard | 3–4 | Multiple geoms or color encoding | +| Complex | 4–5 | Faceted, multiple overlays, nuanced insight | -### Quality Checklist +## Quality checklist - [ ] Starts with chart type (Scatter chart, Histogram, Faceted bar chart, etc.) - [ ] Names the axis variables - [ ] Includes specific values/ranges from code when informative - [ ] States the key insight from surrounding prose -- [ ] Complements (not duplicates) the fig-cap +- [ ] Complements (not duplicates) the caption - [ ] Would make sense to someone who cannot see the image - [ ] Uses plain language (avoid jargon like "geom" or "aesthetic") -## Template Patterns +## Template patterns **Scatter chart:** ``` Scatter chart. [X var] along the x-axis, [Y var] along the y-axis. -[Shape: linear/curved/clustered]. [Specific pattern, e.g., "peaks when X is 25-50"]. +[Shape: linear/curved/clustered]. [Specific pattern, e.g., "peaks when X is 25–50"]. [Any overlaid fits or annotations]. ``` @@ -136,7 +147,7 @@ Faceted [chart type] with [N] panels, one per [faceting variable]. Correlation [matrix/heatmap] of [what variables]. [Arrangement]. [Overall pattern: mostly positive/negative/mixed]. [Notable clusters or strong/weak pairs]. -[If relevant: contrast with expected behavior, e.g., "unlike PCA, these are not orthogonal"]. +[If relevant: contrast with expected behavior]. ``` **Before/after comparison:** @@ -153,30 +164,6 @@ Correlation [matrix/heatmap] of [what variables]. [Arrangement]. [Which fits well vs. poorly and why]. ``` -## Workflow - -### Finding Figures - -To find all figure chunks in the project: -```bash -# List all figure labels with file and line number -grep -n "#| label: fig-" *.qmd - -# Find figures in a specific file -grep -n "#| label: fig-" numeric-splines.qmd - -# Find a specific figure -grep -rn "#| label: fig-splines-predictor-outcome" *.qmd -``` - -### For Each Figure - -1. **Locate** - Use grep to find file and line number -2. **Read context** - Read ~50 lines around the chunk (prose before + code + prose after) -3. **Extract details** - Note fig-cap, ggplot code, data generation, surrounding explanation -4. **Draft alt text** - Apply three-part structure (type → data → insight) -5. **Verify** - Check against quality checklist - ## Example **Code context:** @@ -190,15 +177,14 @@ plotting_data |> **Surrounding prose says:** "Normalization doesn't make data more normal" -**fig-cap:** "Normalization doesn't make data more normal. The green curve indicates the density of the unit normal distribution." +**Caption:** "Normalization doesn't make data more normal. The green curve indicates the density of the unit normal distribution." **Good alt text:** ``` -#| fig-alt: | -#| Faceted histogram with two panels stacked vertically. Top panel shows -#| original data with a bimodal distribution. Bottom panel shows the same -#| data after z-score normalization, retaining the bimodal shape. A green -#| normal distribution curve overlaid on the bottom panel clearly does not -#| match the data, demonstrating that normalization preserves distribution -#| shape rather than creating normality. +Faceted histogram with two panels stacked vertically. Top panel shows +original data with a bimodal distribution. Bottom panel shows the same +data after z-score normalization, retaining the bimodal shape. A green +normal distribution curve overlaid on the bottom panel clearly does not +match the data, demonstrating that normalization preserves distribution +shape rather than creating normality. ``` diff --git a/alt-text/references/pkgdown.md b/alt-text/references/pkgdown.md new file mode 100644 index 0000000..cf8fe85 --- /dev/null +++ b/alt-text/references/pkgdown.md @@ -0,0 +1,152 @@ +# Alt Text in pkgdown Sites + +This reference covers how to find images and add alt text across a pkgdown site. + +## Where images appear + +| Location | Image type | Can have alt text? | +|----------|------------|-------------------| +| `vignettes/*.Rmd` or `vignettes/*.qmd` | code-generated plots | Yes — `fig.alt` chunk option | +| `vignettes/*.Rmd` | static images via `knitr::include_graphics()` | Yes — `fig.alt` chunk option | +| `README.Rmd` / `README.md` | code-generated plots | Yes — `fig.alt` chunk option | +| `README.Rmd` / `README.md` | markdown images `![](path)` | Yes — fill in the bracket | +| `README.Rmd` / `README.md` | HTML `` tags | Yes — add `alt="..."` attribute | +| `R/*.R` `@examples` | code-generated plots | **No — pkgdown limitation** | + +There is currently no way to add alt text to plots generated in `@examples` blocks. +Focus effort on vignettes and README. + +## Step 1 — Find missing alt text + +### Find chunks missing fig.alt in vignettes + +```bash +# Find chunks that already have fig.alt (to see what's covered) +grep -rn "fig\.alt\|fig-alt" vignettes/ + +# Find all plot-producing chunks — each one needs a fig.alt +grep -rn "ggplot\|geom_\|autoplot\|include_graphics" vignettes/ +``` + +Compare the two lists to identify chunks with plots but no `fig.alt`. + +### Find static images missing alt text + +```bash +# Markdown images with empty alt: ![](path) +grep -rn "!\[\](" vignettes/ README.md README.Rmd + +# All markdown images — review each for descriptive alt text +grep -rn "!\[" vignettes/ README.md README.Rmd + +# HTML tags — check each for a non-empty alt attribute +grep -rn "` tags at the top of +`README.Rmd`. Check that the `alt` attribute is present and descriptive: + +```html + + + + +Package hex logo: a blue hexagon with the package name. +``` + +## Step 2 — Audit quality of existing alt text + +When alt text already exists, leave it alone unless it has a concrete problem. +Only rewrite alt text that fails one of these checks: + +**Relative references** — alt text must be self-contained. Fix phrases like: +- "A plot identical to the one above…" → describe the plot fully +- "The same data as shown above…" → name the data explicitly + +**Missing key information** — fix if alt text omits chart type, axis labels, or +the key pattern. + +**Grammar and spelling errors** — alt text is read aloud by screen readers. + +## Step 3 — Add fig.alt to Rmd chunks + +The `fig.alt` chunk option works for both code-generated plots and static +images loaded with `knitr::include_graphics()`. + +### Hashpipe syntax (preferred) + +```r +#| fig.alt: > +#| Scatter chart of bill length vs. bill depth for 344 penguins +#| across three species. Gentoo penguins form a distinct cluster +#| at higher bill depth. Adelie and Chinstrap overlap but separate +#| along the bill length axis, with Chinstrap skewing higher. +plot_code_here() +``` + +### Knitr chunk option syntax + +````markdown +```{r penguin-scatter, fig.alt="Scatter chart of bill length vs. bill depth..."} +plot_code_here() +``` +```` + +### Multiple plots in one chunk + +When a chunk produces multiple plots, `fig.alt` accepts a vector — one string +per plot, in order: + +```r +#| fig.alt: +#| - "Histogram of bill length. Right-skewed distribution with a peak at 45–50mm." +#| - "Histogram of bill depth. Bimodal distribution with peaks at 15mm and 18mm." +``` + +## Step 4 — Add alt text to static markdown images + +For `![](path)` images, fill in the bracket: + +```markdown + +![](man/figures/logo.png) + + +![A hexagonal logo with a blue background and white text reading 'pkgdown'.](man/figures/logo.png) +``` + +For purely decorative images, leave the bracket empty intentionally and add a +comment: + +```markdown + +![](man/figures/decorative-banner.png) +``` + +## Step 5 — Verify + +Because pkgdown does not warn about missing alt text in vignettes, verify by +re-running the same grep from Step 1 and confirming every plot-producing chunk +now has a `fig.alt`: + +```bash +# Should list every chunk with a plot +grep -rn "ggplot\|geom_\|autoplot\|include_graphics" vignettes/ + +# Should now match the same chunks +grep -rn "fig\.alt\|fig-alt" vignettes/ +``` + +For the home page, `build_site()` will warn if any README images are still +missing alt text. + +## Quarto vignettes (`.qmd`) + +For vignettes using Quarto format, use `fig-alt` (hyphen) instead of `fig.alt` (dot): + +```r +#| fig-alt: > +#| Scatter chart of bill length vs. bill depth for 344 penguins +#| across three species. +``` diff --git a/alt-text/references/quarto.md b/alt-text/references/quarto.md new file mode 100644 index 0000000..4ee83c0 --- /dev/null +++ b/alt-text/references/quarto.md @@ -0,0 +1,56 @@ +# Alt Text in Quarto Documents + +This reference covers how to find figures and add alt text in `.qmd` files. + +## Finding figures + +```bash +# List all figure labels with file and line number +grep -n "#| label: fig-" *.qmd + +# Find figures in a specific file +grep -n "#| label: fig-" my-document.qmd + +# Find a specific figure +grep -rn "#| label: fig-splines-predictor-outcome" *.qmd +``` + +## For each figure + +1. **Locate** — use grep to find file and line number +2. **Read context** — read ~50 lines around the chunk (prose before + code + prose after) +3. **Extract details** — note `fig-cap`, ggplot code, data generation, surrounding explanation +4. **Draft alt text** — apply the three-part structure from the main skill +5. **Verify** — check against the quality checklist + +## Adding fig-alt + +Use the hashpipe syntax inside the code chunk: + +```r +#| label: fig-penguin-scatter +#| fig-cap: "Bill length vs. bill depth for 344 penguins." +#| fig-alt: > +#| Scatter chart of bill length vs. bill depth for 344 penguins +#| across three species. Gentoo penguins form a distinct cluster +#| at higher bill depth. Adelie and Chinstrap overlap but separate +#| along the bill length axis, with Chinstrap skewing higher. +plot_code_here() +``` + +Note: use `fig-alt` (hyphen) in `.qmd` files. + +## Auditing existing alt text + +When alt text already exists, leave it alone unless it fails one of these checks: + +**Relative references** — alt text must be self-contained. Fix phrases like: +- "A plot identical to the one above…" → describe the plot fully +- "Much like the first one…" → stand-alone description + +**Missing key information** — fix if alt text omits: +- Chart type as the first words +- Axis labels and what they represent +- The key pattern or takeaway + +**Grammar and spelling errors** — alt text is read aloud by screen readers. diff --git a/r-lib/pkgdown-alt-text/SKILL.md b/r-lib/pkgdown-alt-text/SKILL.md deleted file mode 100644 index 35118af..0000000 --- a/r-lib/pkgdown-alt-text/SKILL.md +++ /dev/null @@ -1,207 +0,0 @@ ---- -name: pkgdown-alt-text -description: > - Add accessible alt text to all images and plots in a pkgdown site. Use when - the user wants to add, improve, or audit alt text for figures in vignettes, - articles, or README files in an R package with a pkgdown site. Triggers for - requests about accessibility, fig.alt, figure descriptions, screen reader - support, or making a pkgdown site more accessible. -metadata: - author: Emil Hvitfeldt (@emilhvitfeldt) - version: "1.0" -license: MIT ---- - -# Add Alt Text to a pkgdown Site - -Generate accessible alt text for all images and plots across the pkgdown site. - -ARGUMENTS -- label: (optional) specific chunk label or image to target -- file: (optional) specific vignette or README file to process - -## Where images appear in a pkgdown site - -| Location | Image type | Can have alt text? | -|----------|------------|-------------------| -| `vignettes/*.Rmd` or `vignettes/*.qmd` | code-generated plots | Yes — `fig.alt` chunk option | -| `vignettes/*.Rmd` | static images via `knitr::include_graphics()` | Yes — `fig.alt` chunk option | -| `README.Rmd` / `README.md` | code-generated plots | Yes — `fig.alt` chunk option | -| `README.Rmd` / `README.md` | markdown images `![](path)` | Yes — fill in the bracket | -| `README.Rmd` / `README.md` | HTML `` tags | Yes — add `alt="..."` attribute | -| `R/*.R` `@examples` | code-generated plots | **No — pkgdown limitation** | - -There is currently no way to add alt text to plots generated in `@examples` -blocks. Focus effort on vignettes and README. - -## Step 1 — Find missing alt text - -### Build the site and read warnings - -The most reliable way: let pkgdown identify all missing alt text automatically. - -```r -# Build only articles (faster than full site) -Rscript -e "pkgdown::build_articles()" - -# Or build the full site -Rscript -e "pkgdown::build_site()" -``` - -pkgdown prints a warning for every code chunk that produces a plot but has no -`fig.alt`. Note down every file and chunk mentioned. - -### Find chunks missing fig.alt in vignettes - -```bash -# Find chunks that already have fig.alt (to see what's covered) -grep -rn "fig.alt\|fig-alt" vignettes/ README.Rmd - -# Find all knitr::include_graphics() calls (static images in chunks) -grep -rn "include_graphics" vignettes/ README.Rmd -``` - -### Find static images missing alt text - -```bash -# Markdown images with empty alt: ![](path) -grep -rn "!\[\](" vignettes/ README.md README.Rmd - -# All markdown images — review each for descriptive alt text -grep -rn "!\[" vignettes/ README.md README.Rmd - -# HTML tags — check each for a non-empty alt attribute -grep -rn "` tags at the top of -`README.Rmd`. Check that the `alt` attribute is present and descriptive: - -```html - - - - -Package hex logo: a blue hexagon with the package name. -``` - -## Step 2 — Audit quality of existing alt text - -When alt text already exists, leave it alone unless it has a concrete problem. -Only rewrite alt text that fails one of these checks: - -**Relative references** — alt text must be self-contained. Screen readers -don't know what "above" refers to. Fix phrases like: -- "A plot identical to the one above..." → describe the plot fully -- "Much like the first one..." → stand-alone description -- "The same data as shown above..." → name the data explicitly - -**Missing key information** — fix if the alt text omits: -- Chart type as the first words -- Axis labels and what they represent -- The key pattern or takeaway - -**Grammar and spelling errors** — alt text is read aloud by screen readers. -Fix typos and grammatically broken sentences. - -If existing alt text is accurate, complete, and self-contained, do not change -it even if you would have phrased it differently. - -## Step 3 — Generate alt text for each figure - -For each missing or weak figure, read ~50 lines of context around the chunk: -- The plotting code (what type of chart, axes, variables) -- Any data generation or transformation above the chunk -- The surrounding prose (explains the purpose and key insight) -- The `fig.cap` if present (alt text should complement, not duplicate it) - -Apply **Amy Cesal's formula** for data visualization alt text: -1. **Chart type** — first words identify the format -2. **Data description** — axes, variables, what is shown -3. **Key insight** — the pattern or takeaway (usually in surrounding prose) - -Use the source code to extract precise details: variable names, axis labels, -facet structure, color encodings, specific value ranges. This is the key -advantage over typical alt text scenarios. - -See the `quarto-alt-text` skill for detailed writing guidelines, chart-type -templates, length guidelines, and a quality checklist — the same principles -apply here. - -## Step 4 — Add fig.alt to Rmd chunks - -The `fig.alt` chunk option works for both code-generated plots and static -images loaded with `knitr::include_graphics()`. - -### Hashpipe syntax (preferred) - -```r -#| fig.alt: > -#| Scatter chart of bill length vs. bill depth for 344 penguins -#| across three species. Gentoo penguins form a distinct cluster -#| at higher bill depth. Adelie and Chinstrap overlap but separate -#| along the bill length axis, with Chinstrap skewing higher. -plot_code_here() -``` - -### Knitr chunk option syntax - -````markdown -```{r penguin-scatter, fig.alt="Scatter chart of bill length vs. bill depth..."} -plot_code_here() -``` -```` - -### Multiple plots in one chunk - -When a chunk produces multiple plots, `fig.alt` accepts a vector — one string -per plot, in order: - -```r -#| fig.alt: -#| - "Histogram of bill length. Right-skewed distribution with a peak at 45-50mm." -#| - "Histogram of bill depth. Bimodal distribution with peaks at 15mm and 18mm." -``` - -## Step 5 — Add alt text to static markdown images - -For `![](path)` images, fill in the bracket: - -```markdown - -![](man/figures/logo.png) - - -![A hexagonal logo with a blue background and white text reading 'pkgdown'.](man/figures/logo.png) -``` - -For purely decorative images (no informational content), an empty alt -explicitly signals to screen readers to skip the image — leave the bracket -empty intentionally and add a comment to make this clear: - -```markdown - -![](man/figures/decorative-banner.png) -``` - -## Step 6 — Verify - -```r -# Rebuild articles and confirm no more fig.alt warnings -Rscript -e "pkgdown::build_articles()" -``` - -No warnings about missing alt text means all vignette plots are covered. - -## Quarto vignettes (`.qmd`) - -For vignettes using Quarto format, use the Quarto-style `fig-alt` option: - -```r -#| fig-alt: > -#| Scatter chart of bill length vs. bill depth for 344 penguins -#| across three species. -``` - -Note the hyphen (`fig-alt`) vs the dot (`fig.alt`) used in `.Rmd` files. From 83abc3861471100875fce39318d606dd14ad126e Mon Sep 17 00:00:00 2001 From: Emil Hvitfeldt Date: Wed, 15 Apr 2026 13:03:12 -0700 Subject: [PATCH 4/4] add stub skill for quarto-alt-text --- .claude-plugin/marketplace.json | 1 + quarto/quarto-alt-text/SKILL.md | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 quarto/quarto-alt-text/SKILL.md diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index a239fca..1bbc3e1 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -75,6 +75,7 @@ "skills": [ "./brand-yml", "./quarto/quarto-authoring", + "./quarto/quarto-alt-text", "./alt-text" ] } diff --git a/quarto/quarto-alt-text/SKILL.md b/quarto/quarto-alt-text/SKILL.md new file mode 100644 index 0000000..67cb135 --- /dev/null +++ b/quarto/quarto-alt-text/SKILL.md @@ -0,0 +1,20 @@ +--- +name: quarto-alt-text +description: > + Generate accessible alt text for data visualizations in Quarto documents. + Use when the user wants to add, improve, or review alt text for figures in + .qmd files. +metadata: + author: Emil Hvitfeldt (@emilhvitfeldt) + version: "2.0" +license: MIT +--- + +This skill has moved. Use the `alt-text` skill instead, which covers both +Quarto documents and pkgdown sites. + +If you have the `quarto` plugin installed, reinstall it to get the updated skill: + +``` +/plugin install https://github.com/posit-dev/skills .claude-plugin/marketplace.json#quarto +```