Component-Based 'Shiny' UI with Fine-Grained Reactivity

A component-based reactive UI framework for 'Shiny' that binds reactive values directly to DOM attributes, enabling fine-grained updates without re-rendering or 'update*Input' callbacks.


irid

CRANstatus Lifecycle:experimental R-CMD-check Codecov testcoverage

Component-based UI for Shiny with fine-grained reactivity.

If you’ve ever fought updateSliderInput, wrestled freezeReactiveValue, or watched renderUI destroy your DOM on every change, irid is for you.

irid lets you bind a reactiveVal directly to any DOM attribute — change the reactive, and that one attribute updates without re-rendering the whole component. There’s no ui/server split: your component is an ordinary R function holding both state and markup.

library(irid)
library(bslib)

OldFaithful <- function() {
  bins <- reactiveVal(30L)

  page_fluid(
    card(
      card_body(
        tags$label(\() paste0("Number of bins: ", bins())),
        tags$input(
          type = "range", min = "1", max = "50",
          value = reactiveProxy(get = bins, set = \(v) bins(as.integer(v)))
        ),
        PlotOutput(\() {
          x <- faithful$waiting
          b <- seq(min(x), max(x), length.out = bins() + 1)
          hist(
            x, breaks = b,
            xlab = "Waiting time to next eruption (in mins)",
            main = "Histogram of waiting times"
          )
        })
      )
    )
  )
}

iridApp(OldFaithful)

Try it live

See more examples:

100% backward compatible

You don’t have to go all-in. Drop irid components into an existing Shiny app to handle complex interactivity with iridOutput/renderIrid:

ui <- fluidPage(
  iridOutput("oldFaithful"),
  tableOutput("summary")
)

server <- function(input, output, session) {
  output$oldFaithful <- renderIrid(OldFaithful())  # irid component
  output$summary <- renderTable(summary(faithful))   # classic Shiny
}

shinyApp(ui, server)

Old Shiny inputs and irid components coexist in the same server scope. Migrate one renderUI at a time, or switch to iridApp when you’re ready.

See also: Shiny Interop example.

Installation

# install.packages("pak")
pak::pak("khusmann/irid")

Learn more

See the Getting Started vignette to get started.

Why irid?

irid comes from iridescent — like the rainbow shimmer inside a shell, formed by its layered structure. A component layer for Shiny — extra shiny, for Shiny.

Inspiration

irid brings ideas from modern JavaScript component frameworks to Shiny — especially Solid.js, which pioneered fine-grained reactivity where each change updates only the specific DOM node it’s bound to. Shiny’s reactive engine (reactiveVal, reactive, observe) was already close to this model; irid closes the gap by connecting it directly to the DOM the way Solid does. React’s component model and controlled input patterns were also an influence.

Reference manual

It appears you don't have a PDF plugin for this browser. You can click here to download the reference manual.

install.packages("irid")

0.3.0 by Kyle Husmann, 3 months ago


https://irid.kylehusmann.com, https://github.com/khusmann/irid


Report a bug at https://github.com/khusmann/irid/issues


Browse source code at https://github.com/cran/irid


Authors: Kyle Husmann [aut, cre]


Documentation:   PDF Manual  


MIT + file LICENSE license


Imports cli, htmltools, rlang, shiny

Suggests bslib, callr, chromote, DT, ggplot2, httpuv, jsonlite, knitr, pkgload, plotly, purrr, rmarkdown, testthat, tibble, vctrs, withr


See at CRAN