Skip to contents

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. One reactive changes, one attribute updates. No ui/server split. No fragile input IDs to wire together. Just component functions with reactive state and DOM in the same scope.

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 = bins,
          onInput = \(event) bins(as.integer(event$value))
        ),
        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 is the iridescent layer that forms inside a shell. This package is a thin rendering layer that forms on top of Shiny. An extra layer of 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.