
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)See more examples:
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.
# install.packages("pak")
pak::pak("khusmann/irid")See the Getting Started vignette to get started.
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.
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.