From 201a592f8ead6b999080604cb3fe7d31d9677d3f Mon Sep 17 00:00:00 2001 From: Vincent Guyader Date: Fri, 24 Apr 2026 23:01:15 +0200 Subject: [PATCH 1/3] feat: implement W3.CSS alerts/notes/quotes/code/tags/round/margins/icons/progressbar Closes stub TODOs: alerts (#2), code (#5), icons (#12), margins (#15), notes (#17), progressbar (#19), quotes (#20), round (#21), tags (#26). All renderers return htmltools tags compatible with {shiny}. Simple class-returning helpers (w3_round, w3_margin) follow the existing w3_badge/w3_color style. --- DESCRIPTION | 2 +- NAMESPACE | 10 ++++ R/todo_w3css_alerts.R | 11 ----- R/todo_w3css_code.R | 11 ----- R/todo_w3css_icons.R | 11 ----- R/todo_w3css_margins.R | 11 ----- R/todo_w3css_notes.R | 11 ----- R/todo_w3css_progressbar.R | 11 ----- R/todo_w3css_quotes.R | 11 ----- R/todo_w3css_round.R | 11 ----- R/todo_w3css_tags.R | 11 ----- R/w3css_alerts.R | 24 ++++++++++ R/w3css_code.R | 27 +++++++++++ R/w3css_icons.R | 31 +++++++++++++ R/w3css_margins.R | 18 ++++++++ R/w3css_notes.R | 27 +++++++++++ R/w3css_progressbar.R | 27 +++++++++++ R/w3css_quotes.R | 22 +++++++++ R/w3css_round.R | 19 ++++++++ R/w3css_tags.R | 26 +++++++++++ man/w3_alert.Rd | 25 ++++++++++ man/w3_code.Rd | 27 +++++++++++ man/w3_icon.Rd | 31 +++++++++++++ man/w3_margin.Rd | 23 ++++++++++ man/w3_note.Rd | 24 ++++++++++ man/w3_progressbar.Rd | 26 +++++++++++ man/w3_quote.Rd | 23 ++++++++++ man/w3_round.Rd | 24 ++++++++++ man/w3_tag.Rd | 29 ++++++++++++ tests/testthat/test-todo-batch.R | 78 ++++++++++++++++++++++++++++++++ 30 files changed, 542 insertions(+), 100 deletions(-) delete mode 100644 R/todo_w3css_alerts.R delete mode 100644 R/todo_w3css_code.R delete mode 100644 R/todo_w3css_icons.R delete mode 100644 R/todo_w3css_margins.R delete mode 100644 R/todo_w3css_notes.R delete mode 100644 R/todo_w3css_progressbar.R delete mode 100644 R/todo_w3css_quotes.R delete mode 100644 R/todo_w3css_round.R delete mode 100644 R/todo_w3css_tags.R create mode 100644 R/w3css_alerts.R create mode 100644 R/w3css_code.R create mode 100644 R/w3css_icons.R create mode 100644 R/w3css_margins.R create mode 100644 R/w3css_notes.R create mode 100644 R/w3css_progressbar.R create mode 100644 R/w3css_quotes.R create mode 100644 R/w3css_round.R create mode 100644 R/w3css_tags.R create mode 100644 man/w3_alert.Rd create mode 100644 man/w3_code.Rd create mode 100644 man/w3_icon.Rd create mode 100644 man/w3_margin.Rd create mode 100644 man/w3_note.Rd create mode 100644 man/w3_progressbar.Rd create mode 100644 man/w3_quote.Rd create mode 100644 man/w3_round.Rd create mode 100644 man/w3_tag.Rd create mode 100644 tests/testthat/test-todo-batch.R diff --git a/DESCRIPTION b/DESCRIPTION index 7bc2f48..3b2c715 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -13,7 +13,7 @@ License: MIT + file LICENSE Encoding: UTF-8 LazyData: true Roxygen: list(markdown = TRUE) -RoxygenNote: 7.2.3 +RoxygenNote: 7.3.3 Depends: R (>= 2.10) Imports: diff --git a/NAMESPACE b/NAMESPACE index f801d1f..3aa4916 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,6 +1,7 @@ # Generated by roxygen2: do not edit by hand export(w3_actionButton) +export(w3_alert) export(w3_animate_bottom) export(w3_animate_fading) export(w3_animate_left) @@ -20,6 +21,8 @@ export(w3_bottombar) export(w3_center) export(w3_checkbox) export(w3_checkboxGroupInput) +export(w3_code) +export(w3_codespan) export(w3_col) export(w3_color) export(w3_container) @@ -30,24 +33,31 @@ export(w3_half) export(w3_hide_modal) export(w3_hover_border_color) export(w3_hover_color) +export(w3_icon) export(w3_left_align) export(w3_leftbar) export(w3_list) +export(w3_margin) export(w3_modal) +export(w3_note) export(w3_numericInput) export(w3_opacity) export(w3_padding) export(w3_page) export(w3_panel) export(w3_passwordInput) +export(w3_progressbar) export(w3_quarter) +export(w3_quote) export(w3_radioButton) export(w3_rest) export(w3_right_align) export(w3_rightbar) +export(w3_round) export(w3_selectInput) export(w3_show_modal) export(w3_spin) +export(w3_tag) export(w3_textInput) export(w3_text_color) export(w3_third) diff --git a/R/todo_w3css_alerts.R b/R/todo_w3css_alerts.R deleted file mode 100644 index 536bb31..0000000 --- a/R/todo_w3css_alerts.R +++ /dev/null @@ -1,11 +0,0 @@ -#' W3.CSS Alerts -#' -#' Implementation of W3.CSS Alerts, as described in -#' [https://www.w3schools.com/w3css/w3css_alerts.asp](https://www.w3schools.com/w3css/w3css_alerts.asp) -#' -#' @return -#' @export -#' -#' @examples -#' -#' TODO diff --git a/R/todo_w3css_code.R b/R/todo_w3css_code.R deleted file mode 100644 index 27bd737..0000000 --- a/R/todo_w3css_code.R +++ /dev/null @@ -1,11 +0,0 @@ -#' W3.CSS Code -#' -#' Implementation of W3.CSS Code, as described in -#' [https://www.w3schools.com/w3css/w3css_code.asp](https://www.w3schools.com/w3css/w3css_code.asp) -#' -#' @return -#' @export -#' -#' @examples -#' -#' TODO diff --git a/R/todo_w3css_icons.R b/R/todo_w3css_icons.R deleted file mode 100644 index 88efc92..0000000 --- a/R/todo_w3css_icons.R +++ /dev/null @@ -1,11 +0,0 @@ -#' W3.CSS Icons -#' -#' Implementation of W3.CSS Icons, as described in -#' [https://www.w3schools.com/w3css/w3css_icons.asp](https://www.w3schools.com/w3css/w3css_icons.asp) -#' -#' @return -#' @export -#' -#' @examples -#' -#' TODO diff --git a/R/todo_w3css_margins.R b/R/todo_w3css_margins.R deleted file mode 100644 index cf337c8..0000000 --- a/R/todo_w3css_margins.R +++ /dev/null @@ -1,11 +0,0 @@ -#' W3.CSS Margins -#' -#' Implementation of W3.CSS Margins, as described in -#' [https://www.w3schools.com/w3css/w3css_margins.asp](https://www.w3schools.com/w3css/w3css_margins.asp) -#' -#' @return -#' @export -#' -#' @examples -#' -#' TODO diff --git a/R/todo_w3css_notes.R b/R/todo_w3css_notes.R deleted file mode 100644 index dce69f5..0000000 --- a/R/todo_w3css_notes.R +++ /dev/null @@ -1,11 +0,0 @@ -#' W3.CSS Notes -#' -#' Implementation of W3.CSS Notes, as described in -#' [https://www.w3schools.com/w3css/w3css_notes.asp](https://www.w3schools.com/w3css/w3css_notes.asp) -#' -#' @return -#' @export -#' -#' @examples -#' -#' TODO diff --git a/R/todo_w3css_progressbar.R b/R/todo_w3css_progressbar.R deleted file mode 100644 index 3cf1937..0000000 --- a/R/todo_w3css_progressbar.R +++ /dev/null @@ -1,11 +0,0 @@ -#' W3.CSS Progress Bars -#' -#' Implementation of W3.CSS Progress Bars, as described in -#' [https://www.w3schools.com/w3css/w3css_progressbar.asp](https://www.w3schools.com/w3css/w3css_progressbar.asp) -#' -#' @return -#' @export -#' -#' @examples -#' -#' TODO diff --git a/R/todo_w3css_quotes.R b/R/todo_w3css_quotes.R deleted file mode 100644 index cc44a06..0000000 --- a/R/todo_w3css_quotes.R +++ /dev/null @@ -1,11 +0,0 @@ -#' W3.CSS Quotes -#' -#' Implementation of W3.CSS Quotes, as described in -#' [https://www.w3schools.com/w3css/w3css_quotes.asp](https://www.w3schools.com/w3css/w3css_quotes.asp) -#' -#' @return -#' @export -#' -#' @examples -#' -#' TODO diff --git a/R/todo_w3css_round.R b/R/todo_w3css_round.R deleted file mode 100644 index 97b7868..0000000 --- a/R/todo_w3css_round.R +++ /dev/null @@ -1,11 +0,0 @@ -#' W3.CSS Round Classes -#' -#' Implementation of W3.CSS Round Classes, as described in -#' [https://www.w3schools.com/w3css/w3css_round.asp](https://www.w3schools.com/w3css/w3css_round.asp) -#' -#' @return -#' @export -#' -#' @examples -#' -#' TODO diff --git a/R/todo_w3css_tags.R b/R/todo_w3css_tags.R deleted file mode 100644 index e5b5c52..0000000 --- a/R/todo_w3css_tags.R +++ /dev/null @@ -1,11 +0,0 @@ -#' W3.CSS Tags (Labels and Signs) -#' -#' Implementation of W3.CSS Tags (Labels and Signs), as described in -#' [https://www.w3schools.com/w3css/w3css_tags.asp](https://www.w3schools.com/w3css/w3css_tags.asp) -#' -#' @return -#' @export -#' -#' @examples -#' -#' TODO diff --git a/R/w3css_alerts.R b/R/w3css_alerts.R new file mode 100644 index 0000000..3362d06 --- /dev/null +++ b/R/w3css_alerts.R @@ -0,0 +1,24 @@ +#' W3.CSS Alerts +#' +#' Implementation of W3.CSS Alerts, as described in +#' [https://www.w3schools.com/w3css/w3css_alerts.asp](https://www.w3schools.com/w3css/w3css_alerts.asp) +#' +#' @param ... alert content. +#' @param level one of `"red"`, `"yellow"`, `"green"`, `"blue"` — controls +#' the background color class. Defaults to `"red"`. +#' +#' @return an htmltools tag. +#' @export +#' +#' @importFrom htmltools tags +#' +#' @examples +#' w3_alert("Danger!") +#' w3_alert("Heads up!", level = "yellow") +w3_alert <- function(..., level = c("red", "yellow", "green", "blue")) { + level <- match.arg(level) + tags$div( + class = paste("w3-panel", w3_color(level)), + tags$p(...) + ) +} diff --git a/R/w3css_code.R b/R/w3css_code.R new file mode 100644 index 0000000..8a140ac --- /dev/null +++ b/R/w3css_code.R @@ -0,0 +1,27 @@ +#' W3.CSS Code +#' +#' Implementation of W3.CSS Code, as described in +#' [https://www.w3schools.com/w3css/w3css_code.asp](https://www.w3schools.com/w3css/w3css_code.asp). +#' `w3_code()` renders a `
` block, `w3_codespan()`
+#' renders an inline `` span.
+#'
+#' @param ... code content.
+#'
+#' @return an htmltools tag.
+#' @export
+#'
+#' @importFrom htmltools tags
+#'
+#' @examples
+#' w3_code("x <- 1")
+w3_code <- function(...) {
+  tags$pre(class = "w3-code", ...)
+}
+
+#' @rdname w3_code
+#' @export
+#' @examples
+#' w3_codespan("foo")
+w3_codespan <- function(...) {
+  tags$code(class = "w3-codespan", ...)
+}
diff --git a/R/w3css_icons.R b/R/w3css_icons.R
new file mode 100644
index 0000000..d24c81e
--- /dev/null
+++ b/R/w3css_icons.R
@@ -0,0 +1,31 @@
+#' W3.CSS Icons
+#'
+#' Implementation of W3.CSS Icons, as described in
+#' [https://www.w3schools.com/w3css/w3css_icons.asp](https://www.w3schools.com/w3css/w3css_icons.asp).
+#' Renders an `` element; you must include the
+#' corresponding Font Awesome stylesheet in the page (see `shiny::icon()` for
+#' a matching loader).
+#'
+#' @param name icon name (without the `fa-` prefix), e.g. `"home"`,
+#'   `"cloud"`, `"search"`.
+#' @param library icon CSS prefix. `"fa"` (Font Awesome) by default;
+#'   `"w3"` uses the W3 icon set instead (`"w3-icon w3-..."`).
+#' @param ... extra attributes passed to the `` tag.
+#'
+#' @return an htmltools tag.
+#' @export
+#'
+#' @importFrom htmltools tags
+#'
+#' @examples
+#' w3_icon("home")
+#' w3_icon("cloud", library = "fa")
+w3_icon <- function(name, library = c("fa", "w3"), ...) {
+  library <- match.arg(library)
+  cls <- switch(
+    library,
+    fa = sprintf("fa fa-%s", name),
+    w3 = sprintf("w3-icon w3-%s", name)
+  )
+  tags$i(class = cls, ...)
+}
diff --git a/R/w3css_margins.R b/R/w3css_margins.R
new file mode 100644
index 0000000..af31bdc
--- /dev/null
+++ b/R/w3css_margins.R
@@ -0,0 +1,18 @@
+#' W3.CSS Margins
+#'
+#' Implementation of W3.CSS Margins, as described in
+#' [https://www.w3schools.com/w3css/w3css_margins.asp](https://www.w3schools.com/w3css/w3css_margins.asp).
+#'
+#' @param side one of `"all"` (default), `"top"`, `"right"`, `"bottom"`,
+#'   `"left"`. `"all"` returns the plain `w3-margin` class.
+#'
+#' @return the matching CSS class name.
+#' @export
+#'
+#' @examples
+#' w3_margin()
+#' w3_margin("top")
+w3_margin <- function(side = c("all", "top", "right", "bottom", "left")) {
+  side <- match.arg(side)
+  if (side == "all") "w3-margin" else sprintf("w3-margin-%s", side)
+}
diff --git a/R/w3css_notes.R b/R/w3css_notes.R
new file mode 100644
index 0000000..68a4c36
--- /dev/null
+++ b/R/w3css_notes.R
@@ -0,0 +1,27 @@
+#' W3.CSS Notes
+#'
+#' Implementation of W3.CSS Notes, as described in
+#' [https://www.w3schools.com/w3css/w3css_notes.asp](https://www.w3schools.com/w3css/w3css_notes.asp)
+#'
+#' @param ... note content.
+#' @param level one of `"yellow"`, `"red"`, `"blue"`, `"green"` — border
+#'   color. Defaults to `"yellow"`.
+#'
+#' @return an htmltools tag.
+#' @export
+#'
+#' @importFrom htmltools tags
+#'
+#' @examples
+#' w3_note("Important: read this first.")
+w3_note <- function(..., level = c("yellow", "red", "blue", "green")) {
+  level <- match.arg(level)
+  tags$div(
+    class = paste(
+      "w3-panel", "w3-leftbar",
+      sprintf("w3-border-%s", level),
+      sprintf("w3-pale-%s", level)
+    ),
+    tags$p(...)
+  )
+}
diff --git a/R/w3css_progressbar.R b/R/w3css_progressbar.R
new file mode 100644
index 0000000..2277ba5
--- /dev/null
+++ b/R/w3css_progressbar.R
@@ -0,0 +1,27 @@
+#' W3.CSS Progress Bars
+#'
+#' Implementation of W3.CSS Progress Bars, as described in
+#' [https://www.w3schools.com/w3css/w3css_progressbar.asp](https://www.w3schools.com/w3css/w3css_progressbar.asp)
+#'
+#' @param value numeric(1) in `[0, 100]`, current progress value.
+#' @param color W3 color name applied to the inner bar (default `"green"`).
+#' @param show_label logical, show the numeric value inside the bar.
+#'
+#' @return an htmltools tag.
+#' @export
+#'
+#' @importFrom htmltools tags
+#'
+#' @examples
+#' w3_progressbar(25)
+#' w3_progressbar(80, color = "blue", show_label = TRUE)
+w3_progressbar <- function(value, color = "green", show_label = FALSE) {
+  stopifnot(is.numeric(value), length(value) == 1L, !is.na(value))
+  value <- max(0, min(100, value))
+  inner <- tags$div(
+    class = paste("w3-container", w3_color(color)),
+    style = sprintf("width:%s%%", value),
+    if (show_label) sprintf("%s%%", value) else NULL
+  )
+  tags$div(class = "w3-light-grey", inner)
+}
diff --git a/R/w3css_quotes.R b/R/w3css_quotes.R
new file mode 100644
index 0000000..5c71c61
--- /dev/null
+++ b/R/w3css_quotes.R
@@ -0,0 +1,22 @@
+#' W3.CSS Quotes
+#'
+#' Implementation of W3.CSS Quotes, as described in
+#' [https://www.w3schools.com/w3css/w3css_quotes.asp](https://www.w3schools.com/w3css/w3css_quotes.asp)
+#'
+#' @param ... quote content.
+#' @param panel logical, wrap the blockquote in a styled panel. `TRUE` by default.
+#'
+#' @return an htmltools tag.
+#' @export
+#'
+#' @importFrom htmltools tags
+#'
+#' @examples
+#' w3_quote("Be yourself — everyone else is already taken.")
+w3_quote <- function(..., panel = TRUE) {
+  bq <- tags$blockquote(
+    class = if (panel) "w3-panel w3-leftbar w3-light-grey" else NULL,
+    ...
+  )
+  bq
+}
diff --git a/R/w3css_round.R b/R/w3css_round.R
new file mode 100644
index 0000000..767aa98
--- /dev/null
+++ b/R/w3css_round.R
@@ -0,0 +1,19 @@
+#' W3.CSS Rounded corners
+#'
+#' Implementation of W3.CSS Round, as described in
+#' [https://www.w3schools.com/w3css/w3css_round.asp](https://www.w3schools.com/w3css/w3css_round.asp).
+#'
+#' @param size corner size. One of `"default"`, `"small"`, `"medium"`,
+#'   `"large"`, `"xlarge"`, `"xxlarge"`.
+#'
+#' @return the matching CSS class name.
+#' @export
+#'
+#' @examples
+#' w3_round()
+#' w3_round("small")
+#' w3_round("xxlarge")
+w3_round <- function(size = c("default", "small", "medium", "large", "xlarge", "xxlarge")) {
+  size <- match.arg(size)
+  if (size == "default") "w3-round" else sprintf("w3-round-%s", size)
+}
diff --git a/R/w3css_tags.R b/R/w3css_tags.R
new file mode 100644
index 0000000..6289fdf
--- /dev/null
+++ b/R/w3css_tags.R
@@ -0,0 +1,26 @@
+#' W3.CSS Tags
+#'
+#' Implementation of W3.CSS Tags, as described in
+#' [https://www.w3schools.com/w3css/w3css_tags.asp](https://www.w3schools.com/w3css/w3css_tags.asp).
+#' Renders a `` element.
+#'
+#' @param ... label content.
+#' @param color optional W3 color name to apply via [w3_color()]
+#'   (e.g. `"red"`, `"teal"`). `NULL` by default.
+#' @param round optional corner rounding (one of `"small"`, `"medium"`,
+#'   `"large"`, `"xlarge"`, `"xxlarge"`). `NULL` for square corners.
+#'
+#' @return an htmltools tag.
+#' @export
+#'
+#' @importFrom htmltools tags
+#'
+#' @examples
+#' w3_tag("new")
+#' w3_tag("urgent", color = "red", round = "large")
+w3_tag <- function(..., color = NULL, round = NULL) {
+  classes <- "w3-tag"
+  if (!is.null(color)) classes <- paste(classes, w3_color(color))
+  if (!is.null(round)) classes <- paste(classes, w3_round(round))
+  tags$span(class = classes, ...)
+}
diff --git a/man/w3_alert.Rd b/man/w3_alert.Rd
new file mode 100644
index 0000000..30d8d36
--- /dev/null
+++ b/man/w3_alert.Rd
@@ -0,0 +1,25 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/w3css_alerts.R
+\name{w3_alert}
+\alias{w3_alert}
+\title{W3.CSS Alerts}
+\usage{
+w3_alert(..., level = c("red", "yellow", "green", "blue"))
+}
+\arguments{
+\item{...}{alert content.}
+
+\item{level}{one of \code{"red"}, \code{"yellow"}, \code{"green"}, \code{"blue"} — controls
+the background color class. Defaults to \code{"red"}.}
+}
+\value{
+an htmltools tag.
+}
+\description{
+Implementation of W3.CSS Alerts, as described in
+\url{https://www.w3schools.com/w3css/w3css_alerts.asp}
+}
+\examples{
+w3_alert("Danger!")
+w3_alert("Heads up!", level = "yellow")
+}
diff --git a/man/w3_code.Rd b/man/w3_code.Rd
new file mode 100644
index 0000000..7d8189e
--- /dev/null
+++ b/man/w3_code.Rd
@@ -0,0 +1,27 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/w3css_code.R
+\name{w3_code}
+\alias{w3_code}
+\alias{w3_codespan}
+\title{W3.CSS Code}
+\usage{
+w3_code(...)
+
+w3_codespan(...)
+}
+\arguments{
+\item{...}{code content.}
+}
+\value{
+an htmltools tag.
+}
+\description{
+Implementation of W3.CSS Code, as described in
+\url{https://www.w3schools.com/w3css/w3css_code.asp}.
+\code{w3_code()} renders a \verb{
} block, \code{w3_codespan()}
+renders an inline \verb{} span.
+}
+\examples{
+w3_code("x <- 1")
+w3_codespan("foo")
+}
diff --git a/man/w3_icon.Rd b/man/w3_icon.Rd
new file mode 100644
index 0000000..002629d
--- /dev/null
+++ b/man/w3_icon.Rd
@@ -0,0 +1,31 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/w3css_icons.R
+\name{w3_icon}
+\alias{w3_icon}
+\title{W3.CSS Icons}
+\usage{
+w3_icon(name, library = c("fa", "w3"), ...)
+}
+\arguments{
+\item{name}{icon name (without the \verb{fa-} prefix), e.g. \code{"home"},
+\code{"cloud"}, \code{"search"}.}
+
+\item{library}{icon CSS prefix. \code{"fa"} (Font Awesome) by default;
+\code{"w3"} uses the W3 icon set instead (\code{"w3-icon w3-..."}).}
+
+\item{...}{extra attributes passed to the \verb{} tag.}
+}
+\value{
+an htmltools tag.
+}
+\description{
+Implementation of W3.CSS Icons, as described in
+\url{https://www.w3schools.com/w3css/w3css_icons.asp}.
+Renders an \verb{} element; you must include the
+corresponding Font Awesome stylesheet in the page (see \code{shiny::icon()} for
+a matching loader).
+}
+\examples{
+w3_icon("home")
+w3_icon("cloud", library = "fa")
+}
diff --git a/man/w3_margin.Rd b/man/w3_margin.Rd
new file mode 100644
index 0000000..2bc59d4
--- /dev/null
+++ b/man/w3_margin.Rd
@@ -0,0 +1,23 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/w3css_margins.R
+\name{w3_margin}
+\alias{w3_margin}
+\title{W3.CSS Margins}
+\usage{
+w3_margin(side = c("all", "top", "right", "bottom", "left"))
+}
+\arguments{
+\item{side}{one of \code{"all"} (default), \code{"top"}, \code{"right"}, \code{"bottom"},
+\code{"left"}. \code{"all"} returns the plain \code{w3-margin} class.}
+}
+\value{
+the matching CSS class name.
+}
+\description{
+Implementation of W3.CSS Margins, as described in
+\url{https://www.w3schools.com/w3css/w3css_margins.asp}.
+}
+\examples{
+w3_margin()
+w3_margin("top")
+}
diff --git a/man/w3_note.Rd b/man/w3_note.Rd
new file mode 100644
index 0000000..211c639
--- /dev/null
+++ b/man/w3_note.Rd
@@ -0,0 +1,24 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/w3css_notes.R
+\name{w3_note}
+\alias{w3_note}
+\title{W3.CSS Notes}
+\usage{
+w3_note(..., level = c("yellow", "red", "blue", "green"))
+}
+\arguments{
+\item{...}{note content.}
+
+\item{level}{one of \code{"yellow"}, \code{"red"}, \code{"blue"}, \code{"green"} — border
+color. Defaults to \code{"yellow"}.}
+}
+\value{
+an htmltools tag.
+}
+\description{
+Implementation of W3.CSS Notes, as described in
+\url{https://www.w3schools.com/w3css/w3css_notes.asp}
+}
+\examples{
+w3_note("Important: read this first.")
+}
diff --git a/man/w3_progressbar.Rd b/man/w3_progressbar.Rd
new file mode 100644
index 0000000..308da02
--- /dev/null
+++ b/man/w3_progressbar.Rd
@@ -0,0 +1,26 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/w3css_progressbar.R
+\name{w3_progressbar}
+\alias{w3_progressbar}
+\title{W3.CSS Progress Bars}
+\usage{
+w3_progressbar(value, color = "green", show_label = FALSE)
+}
+\arguments{
+\item{value}{numeric(1) in \verb{[0, 100]}, current progress value.}
+
+\item{color}{W3 color name applied to the inner bar (default \code{"green"}).}
+
+\item{show_label}{logical, show the numeric value inside the bar.}
+}
+\value{
+an htmltools tag.
+}
+\description{
+Implementation of W3.CSS Progress Bars, as described in
+\url{https://www.w3schools.com/w3css/w3css_progressbar.asp}
+}
+\examples{
+w3_progressbar(25)
+w3_progressbar(80, color = "blue", show_label = TRUE)
+}
diff --git a/man/w3_quote.Rd b/man/w3_quote.Rd
new file mode 100644
index 0000000..a5fcc4e
--- /dev/null
+++ b/man/w3_quote.Rd
@@ -0,0 +1,23 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/w3css_quotes.R
+\name{w3_quote}
+\alias{w3_quote}
+\title{W3.CSS Quotes}
+\usage{
+w3_quote(..., panel = TRUE)
+}
+\arguments{
+\item{...}{quote content.}
+
+\item{panel}{logical, wrap the blockquote in a styled panel. \code{TRUE} by default.}
+}
+\value{
+an htmltools tag.
+}
+\description{
+Implementation of W3.CSS Quotes, as described in
+\url{https://www.w3schools.com/w3css/w3css_quotes.asp}
+}
+\examples{
+w3_quote("Be yourself — everyone else is already taken.")
+}
diff --git a/man/w3_round.Rd b/man/w3_round.Rd
new file mode 100644
index 0000000..9067f5d
--- /dev/null
+++ b/man/w3_round.Rd
@@ -0,0 +1,24 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/w3css_round.R
+\name{w3_round}
+\alias{w3_round}
+\title{W3.CSS Rounded corners}
+\usage{
+w3_round(size = c("default", "small", "medium", "large", "xlarge", "xxlarge"))
+}
+\arguments{
+\item{size}{corner size. One of \code{"default"}, \code{"small"}, \code{"medium"},
+\code{"large"}, \code{"xlarge"}, \code{"xxlarge"}.}
+}
+\value{
+the matching CSS class name.
+}
+\description{
+Implementation of W3.CSS Round, as described in
+\url{https://www.w3schools.com/w3css/w3css_round.asp}.
+}
+\examples{
+w3_round()
+w3_round("small")
+w3_round("xxlarge")
+}
diff --git a/man/w3_tag.Rd b/man/w3_tag.Rd
new file mode 100644
index 0000000..af0e0a8
--- /dev/null
+++ b/man/w3_tag.Rd
@@ -0,0 +1,29 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/w3css_tags.R
+\name{w3_tag}
+\alias{w3_tag}
+\title{W3.CSS Tags}
+\usage{
+w3_tag(..., color = NULL, round = NULL)
+}
+\arguments{
+\item{...}{label content.}
+
+\item{color}{optional W3 color name to apply via \code{\link[=w3_color]{w3_color()}}
+(e.g. \code{"red"}, \code{"teal"}). \code{NULL} by default.}
+
+\item{round}{optional corner rounding (one of \code{"small"}, \code{"medium"},
+\code{"large"}, \code{"xlarge"}, \code{"xxlarge"}). \code{NULL} for square corners.}
+}
+\value{
+an htmltools tag.
+}
+\description{
+Implementation of W3.CSS Tags, as described in
+\url{https://www.w3schools.com/w3css/w3css_tags.asp}.
+Renders a \verb{} element.
+}
+\examples{
+w3_tag("new")
+w3_tag("urgent", color = "red", round = "large")
+}
diff --git a/tests/testthat/test-todo-batch.R b/tests/testthat/test-todo-batch.R
new file mode 100644
index 0000000..1e86cbc
--- /dev/null
+++ b/tests/testthat/test-todo-batch.R
@@ -0,0 +1,78 @@
+test_that("w3_alert returns a styled panel div (#2)", {
+  out <- w3_alert("Beware", level = "red")
+  str <- as.character(out)
+  expect_true(grepl("w3-panel", str, fixed = TRUE))
+  expect_true(grepl("w3-red", str, fixed = TRUE))
+  expect_true(grepl("Beware", str, fixed = TRUE))
+})
+
+test_that("w3_note wraps content in a quote-styled div (#17)", {
+  out <- w3_note("important")
+  str <- as.character(out)
+  expect_true(grepl("w3-panel", str, fixed = TRUE))
+  expect_true(grepl("w3-leftbar", str, fixed = TRUE))
+  expect_true(grepl("important", str, fixed = TRUE))
+})
+
+test_that("w3_quote wraps content in a styled blockquote (#20)", {
+  out <- w3_quote("be yourself")
+  str <- as.character(out)
+  expect_true(grepl("blockquote", str, fixed = TRUE))
+  expect_true(grepl("be yourself", str, fixed = TRUE))
+})
+
+test_that("w3_codespan wraps inline code (#5)", {
+  out <- w3_codespan("x <- 1")
+  str <- as.character(out)
+  expect_true(grepl("w3-codespan", str, fixed = TRUE))
+  expect_true(grepl("x <- 1", str) || grepl("x <- 1", str, fixed = TRUE))
+})
+
+test_that("w3_code wraps a code block (#5)", {
+  out <- w3_code("x <- 1")
+  str <- as.character(out)
+  expect_true(grepl("
Date: Sat, 25 Apr 2026 09:16:24 +0200
Subject: [PATCH 2/3] fix(w3css): aria-valuenow on progressbar; broaden
 w3_alert palette

- Add role='progressbar' and aria-valuenow/min/max on w3_progressbar so
  screen readers announce the value (W3.CSS docs leave this to the
  caller; opting in here makes the helper accessible by default).
- Drop the four-level match.arg() on w3_alert(level = ...). The full
  W3 palette is supported by w3_color(), and clamping the alert helper
  to red/yellow/green/blue was an arbitrary subset.
---
 R/w3css_alerts.R                 | 10 ++++++----
 R/w3css_progressbar.R            | 15 +++++++++++++--
 man/w3_alert.Rd                  |  9 ++++++---
 man/w3_progressbar.Rd            |  7 ++++++-
 tests/testthat/test-todo-batch.R | 15 +++++++++++++++
 5 files changed, 46 insertions(+), 10 deletions(-)

diff --git a/R/w3css_alerts.R b/R/w3css_alerts.R
index 3362d06..eb4a7d0 100644
--- a/R/w3css_alerts.R
+++ b/R/w3css_alerts.R
@@ -4,8 +4,10 @@
 #' [https://www.w3schools.com/w3css/w3css_alerts.asp](https://www.w3schools.com/w3css/w3css_alerts.asp)
 #'
 #' @param ... alert content.
-#' @param level one of `"red"`, `"yellow"`, `"green"`, `"blue"` — controls
-#'   the background color class. Defaults to `"red"`.
+#' @param level any W3 color name accepted by [w3_color()] (e.g.
+#'   `"red"`, `"yellow"`, `"teal"`, `"deep-orange"`). Controls the
+#'   background color class. Defaults to `"red"`. Validation is delegated
+#'   to [w3_color()] so the full W3 palette is accepted.
 #'
 #' @return an htmltools tag.
 #' @export
@@ -15,8 +17,8 @@
 #' @examples
 #' w3_alert("Danger!")
 #' w3_alert("Heads up!", level = "yellow")
-w3_alert <- function(..., level = c("red", "yellow", "green", "blue")) {
-  level <- match.arg(level)
+#' w3_alert("Looks good!", level = "teal")
+w3_alert <- function(..., level = "red") {
   tags$div(
     class = paste("w3-panel", w3_color(level)),
     tags$p(...)
diff --git a/R/w3css_progressbar.R b/R/w3css_progressbar.R
index 2277ba5..90e757e 100644
--- a/R/w3css_progressbar.R
+++ b/R/w3css_progressbar.R
@@ -1,7 +1,11 @@
 #' W3.CSS Progress Bars
 #'
 #' Implementation of W3.CSS Progress Bars, as described in
-#' [https://www.w3schools.com/w3css/w3css_progressbar.asp](https://www.w3schools.com/w3css/w3css_progressbar.asp)
+#' [https://www.w3schools.com/w3css/w3css_progressbar.asp](https://www.w3schools.com/w3css/w3css_progressbar.asp).
+#'
+#' The outer wrapper carries the WAI-ARIA `role="progressbar"` and the
+#' `aria-valuenow / aria-valuemin / aria-valuemax` attributes so screen
+#' readers announce the progress correctly.
 #'
 #' @param value numeric(1) in `[0, 100]`, current progress value.
 #' @param color W3 color name applied to the inner bar (default `"green"`).
@@ -23,5 +27,12 @@ w3_progressbar <- function(value, color = "green", show_label = FALSE) {
     style = sprintf("width:%s%%", value),
     if (show_label) sprintf("%s%%", value) else NULL
   )
-  tags$div(class = "w3-light-grey", inner)
+  tags$div(
+    class = "w3-light-grey",
+    role = "progressbar",
+    `aria-valuenow` = as.character(value),
+    `aria-valuemin` = "0",
+    `aria-valuemax` = "100",
+    inner
+  )
 }
diff --git a/man/w3_alert.Rd b/man/w3_alert.Rd
index 30d8d36..8f3f4cf 100644
--- a/man/w3_alert.Rd
+++ b/man/w3_alert.Rd
@@ -4,13 +4,15 @@
 \alias{w3_alert}
 \title{W3.CSS Alerts}
 \usage{
-w3_alert(..., level = c("red", "yellow", "green", "blue"))
+w3_alert(..., level = "red")
 }
 \arguments{
 \item{...}{alert content.}
 
-\item{level}{one of \code{"red"}, \code{"yellow"}, \code{"green"}, \code{"blue"} — controls
-the background color class. Defaults to \code{"red"}.}
+\item{level}{any W3 color name accepted by \code{\link[=w3_color]{w3_color()}} (e.g.
+\code{"red"}, \code{"yellow"}, \code{"teal"}, \code{"deep-orange"}). Controls the
+background color class. Defaults to \code{"red"}. Validation is delegated
+to \code{\link[=w3_color]{w3_color()}} so the full W3 palette is accepted.}
 }
 \value{
 an htmltools tag.
@@ -22,4 +24,5 @@ Implementation of W3.CSS Alerts, as described in
 \examples{
 w3_alert("Danger!")
 w3_alert("Heads up!", level = "yellow")
+w3_alert("Looks good!", level = "teal")
 }
diff --git a/man/w3_progressbar.Rd b/man/w3_progressbar.Rd
index 308da02..b416ecb 100644
--- a/man/w3_progressbar.Rd
+++ b/man/w3_progressbar.Rd
@@ -18,7 +18,12 @@ an htmltools tag.
 }
 \description{
 Implementation of W3.CSS Progress Bars, as described in
-\url{https://www.w3schools.com/w3css/w3css_progressbar.asp}
+\url{https://www.w3schools.com/w3css/w3css_progressbar.asp}.
+}
+\details{
+The outer wrapper carries the WAI-ARIA \code{role="progressbar"} and the
+\code{aria-valuenow / aria-valuemin / aria-valuemax} attributes so screen
+readers announce the progress correctly.
 }
 \examples{
 w3_progressbar(25)
diff --git a/tests/testthat/test-todo-batch.R b/tests/testthat/test-todo-batch.R
index 1e86cbc..48a4e6f 100644
--- a/tests/testthat/test-todo-batch.R
+++ b/tests/testthat/test-todo-batch.R
@@ -72,6 +72,21 @@ test_that("w3_progressbar renders a width-styled inner div (#19)", {
   expect_true(grepl("width:42%", str, fixed = TRUE))
 })
 
+test_that("w3_progressbar exposes ARIA attributes for screen readers (#19)", {
+  str <- as.character(w3_progressbar(42))
+  expect_true(grepl("role=\"progressbar\"", str, fixed = TRUE))
+  expect_true(grepl("aria-valuenow=\"42\"", str, fixed = TRUE))
+  expect_true(grepl("aria-valuemin=\"0\"", str, fixed = TRUE))
+  expect_true(grepl("aria-valuemax=\"100\"", str, fixed = TRUE))
+})
+
+test_that("w3_alert accepts the full W3 palette (#2)", {
+  # Anything w3_color() accepts must work; level is no longer restricted.
+  out <- w3_alert("Heads up!", level = "teal")
+  expect_true(grepl("w3-teal", as.character(out), fixed = TRUE))
+  expect_error(w3_alert("nope", level = "definitely-not-a-color"))
+})
+
 test_that("w3_progressbar clamps values outside [0, 100]", {
   expect_true(grepl("width:100%", as.character(w3_progressbar(150)), fixed = TRUE))
   expect_true(grepl("width:0%",  as.character(w3_progressbar(-5)),  fixed = TRUE))

From 0a2df39c1bcf5ab3d7afc2eabbf5afe5401a76cf Mon Sep 17 00:00:00 2001
From: Vincent Guyader 
Date: Sat, 25 Apr 2026 19:21:01 +0200
Subject: [PATCH 3/3] ci: bump actions/checkout v3 -> v4

---
 .github/workflows/R-CMD-check.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml
index a3ac618..74d8c97 100644
--- a/.github/workflows/R-CMD-check.yaml
+++ b/.github/workflows/R-CMD-check.yaml
@@ -29,7 +29,7 @@ jobs:
       R_KEEP_PKG_SOURCE: yes
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
 
       - uses: r-lib/actions/setup-pandoc@v2