shinyWidgets: the input controls Shiny does not ship
shinyWidgets : Extend widgets available in shiny
At a glance
- What is it?
- shinyWidgets is an R package that adds a set of ready-made input widgets to Shiny, covering toggles, button-styled radio groups, virtualised select menus, date pickers, string sliders, hierarchical tree selection and alert dialogs. Each one arrives with an update method so the server can change the value, and the JavaScript side is bundled with packer and webpack.
- Who is it for?
- Use shinyWidgets when a Shiny application needs an input control that the framework does not provide, because the package fills the specific gaps, a virtual select for a long choice list, a tree for hierarchical data and a slider that handles strings, rather than asking you to write and maintain a custom input binding.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 108 days ago.
- What is it written in?
- Mainly R, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the package adds and what it leaves alone
shinyWidgets exists to extend the widgets available in Shiny, and the README states the three things it enables in a single sentence: you can replace classical checkboxes with a switch button, add colours to radio buttons and checkbox groups, and use buttons as radio buttons or checkboxes. Around that core there is a set of controls for the cases where the standard inputs are the wrong shape rather than the wrong colour. A select menu for a long list of choices that would be unusable as a plain dropdown, a date picker with a time picker integrated, a slider that can hold strings rather than numbers, a tree for hierarchical selection, a text input that only fires on Enter or on a search button, and modal dialogs for feedback and confirmation. What the package does not do is restyle Shiny itself; it sits alongside the framework's own inputs and adds new ones.
Installation and the gallery
The package is on CRAN, so the standard install is one line in R.
install.packages("shinyWidgets")The development version comes from GitHub through the remotes package.
# install.packages("remotes")
remotes::install_github("dreamRs/shinyWidgets")A gallery application is included in the package itself, and you launch it from an R session.
shinyWidgets::shinyWidgetsGallery()There is also a live instance at shinyapps.dreamrs.fr/shinyWidgets. The gallery is the fastest way to understand what each widget does, since the package covers a wide range of input types and the README for each one is a screenshot and a short signature rather than a paragraph of prose. The package documentation is built with pkgdown, the site lives at dreamrs.github.io/shinyWidgets, and the repository carries the usual R package layout with R, man, tests, inst and data directories, plus a srcjs directory for the JavaScript sources and a data-raw directory.
Switches, checkboxes and buttons as radio groups
The checkbox family is where the package starts. A Bootstrap switch turns a checkbox into a toggle.
switchInput(inputId = "id", value = TRUE)A Material switch does the same with a different look and a status colour.
materialSwitch(inputId = "id", label = "Primary switch", status = "danger")Then there are the pretty variants, a checkbox, a switch and a toggle with different labels for the on and off states.
prettyToggle(
inputId = "id",
label_on = "Checked!",
label_off = "Unchecked..."
)The group widgets take a set of choices and render them as a row of buttons, so the radio and checkbox group become something that reads at a glance rather than a column of small circles. The same function serves both, and the comment in the README marks the alternative in the signature.
checkboxGroupButtons( # or radioGroupButtons
inputId = "id",
label = "Choice: ",
choices = c("A", "B", "C")
)The pretty group variant adds an outline mode, a plain mode, a status colour and an icon, so a group can be styled to match the rest of the application.
Select menus that survive a long list
The select widgets are where the package earns its keep, because a Shiny selectInput with a few hundred choices is unusable. The Bootstrap select picker is a multi-select with a large configuration surface.
pickerInput(
inputId = "id",
label = "Select:",
choices = month.name,
options = pickerOptions(
actionsBox = TRUE,
size = 10,
selectedTextFormat = "count > 3"
),
multiple = TRUE
)The actionsBox option gives the select-all and deselect-all buttons, size sets the height of the list, and selectedTextFormat controls how the summary text reads when many items are chosen. The virtual select widget is the other answer to the same problem, and it handles a hierarchy, grouping choices into named lists.
virtualSelectInput(
inputId = "id",
label = "Select:",
choices = list(
"Spring" = c("March", "April", "May"),
"Summer" = c("June", "July", "August"),
"Autumn" = c("September", "October", "November"),
"Winter" = c("December", "January", "February")
),
showValueAsTags = TRUE,
search = TRUE,
multiple = TRUE
)Grouped choices, tags for the selected values and a search box, with the list rendered virtually so only the visible portion exists in the DOM.
Dates, string sliders and the tree
The Air Datepicker covers dates, months or years and integrates a time picker, with a placeholder, a multiple selection limit and a clear button.
airDatepickerInput(
inputId = "id",
label = "Select:",
placeholder = "Placeholder",
multiple = 5,
clearButton = TRUE
)The sliders are the other place where the standard input is the wrong type. The string slider holds labels rather than numbers, which is what you want for a Likert question.
sliderTextInput(
inputId = "id",
label = "Choice:",
grid = TRUE,
force_edges = TRUE,
choices = c(
"Strongly disagree",
"Disagree",
"Neither agree nor disagree",
"Agree",
"Strongly agree"
)
)The noUiSlider is a range slider that can be coloured, carry more than two handles and sit vertically.
noUiSliderInput(
inputId = "id",
label = "Select:",
min = 0,
max = 600,
value = c(100, 220, 400),
tooltips = TRUE,
step = 1
)The tree widget selects values in a hierarchical structure, with a returnValue option and a closeDepth that controls how deep the tree stays expanded.
treeInput(
inputId = "ID2",
label = "Select cities:",
choices = create_tree(cities),
returnValue = "text",
closeDepth = 1
)That last one matters for the common case of a hierarchical geography: the choices come from a tree structure and the widget returns either the text or the value.
Alerts, confirmations and hiding inputs in a button
Beyond inputs there are components. Sweet Alert shows a feedback message using the sweetalert2 library, with sendSweetAlert for a message and confirmSweetAlert for a confirmation request, and the README points to the examples in the help pages rather than repeating them. The dropdown button hides a whole set of inputs inside a button, which is the standard pattern for an options panel that should not clutter the form.
dropdownButton(
tags$h3("List of Input"),
selectInput(inputId = 'xcol', label = 'X Variable', choices = names(iris)),
sliderInput(inputId = 'clusters', label = 'Cluster count', value = 3, min = 1, max = 9),
circle = TRUE,
status = "danger",
icon = icon("gear"), width = "300px",
tooltip = tooltipOptions(title = "Click to see inputs !")
)The search input is a text field that only triggers on Enter or on clicking the search button, with configurable placeholder, search and reset buttons and a width, which is the behaviour a user expects from a search box and the opposite of a live-filtering input.
The JavaScript half and how it is built
These are not pure R widgets. The package uses packer to manage its JavaScript assets, and the README points at the packer documentation for the details. You install the node modules with packer::npm_install(), you modify the input bindings in the srcjs/inputs directory, and then you run the packer build command. The repository root confirms the layout: a srcjs directory for the JavaScript sources, a package.json and package-lock.json for the node side, and webpack.common.js with webpack.dev.js and webpack.prod.js for the three webpack configurations. The devDependencies in the package manifest are the actual implementation, and the list is a good index of what each widget is built on: tree from widgetjs for the tree, air-datepicker for the date input, autonumeric for numeric inputs with formatting, dayjs for dates, multi.js and slim-select, virtual-select-plugin for the virtual select, nouislider for the sliders, quercus.js for the calendar, vanilla-calendar-pro, wnumb for the number input, and winbox for window-style interfaces. The package also ships AppVeyor and GitHub Actions workflows and an R-CMD-check workflow, which is the standard R package hygiene.
The update method is the part that makes them usable
The README mentions it in one line and it is the most important design point: each widget has an update method to change the value of an input from the server. Shiny's own inputs have had this for a long time, and a widget without it is a dead end in an interactive application, because the server cannot respond to a change in the data by changing what the user sees. With an update method, a widget can be reset when a filter changes, filled with new choices when a dataset is subset, or locked while an operation runs. The consequence is that a widget is a drop-in for the input it replaces rather than a special case in your reactive code. It also means the widgets behave consistently with the rest of the framework's reactive model, which is what makes them usable in a form that has a mixture of standard and package inputs.
Editorial conclusion
Use shinyWidgets when a Shiny application needs an input control that the framework does not provide, because the package fills the specific gaps, a virtual select for a long choice list, a tree for hierarchical data and a slider that handles strings, rather than asking you to write and maintain a custom input binding. Do not reach for it to restyle inputs that Shiny already handles well, since it adds a dependency and a JavaScript layer for controls you did not need to change. Verify first that the widget you want exists in the current release, since the package's version and its CRAN presence track a moving target, that your Shiny version and bootstrap theme agree with the widget you pick, since the Bootstrap and Material switches are different implementations, and that you can build the JavaScript assets with packer and node before you package, since the widgets are client-side code that has to be compiled.
Frequently asked questions
How do I install shinyWidgets?
Install the CRAN version with install.packages("shinyWidgets"), or the development version with remotes::install_github("dreamRs/shinyWidgets") after installing the remotes package. A gallery application is included and launches with shinyWidgets::shinyWidgetsGallery().
Which widgets does shinyWidgets provide?
Bootstrap and Material switches, pretty checkboxes, switches and toggles, checkbox groups and radio buttons rendered as buttons, a Bootstrap select picker, a virtual select that supports long and grouped choice lists, an Air Datepicker with an integrated time picker, a string slider, a noUiSlider range slider, a hierarchical tree input, a search input, sweetalert2 alerts and confirmations, and a dropdown button that hides inputs.
Can a shinyWidgets input be changed from the server?
Yes. Each widget has an update method to change the value of an input from the server, so the widgets behave like the standard Shiny inputs in a reactive application.
Do I need node to work with shinyWidgets?
To build the JavaScript assets you do. The package uses packer to manage them, with packer::npm_install() to install the node modules and a packer build command after editing the bindings in srcjs/inputs. The webpack configuration files are in the repository root.
What licence is shinyWidgets released under?
The licence field on the repository says GPL-3.0, with a LICENSE.md file at the root, and the latest release is v0.9.1 published on 2026-03-10.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/dreamrs-shinywidgets)