Skip to content
Back to skills

2260 Inputs 0e8fceb4

ASecurity

bslib provides specialized input widgets that enhance standard Shiny inputs with modern features.

  • 9 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 11, 2026
developmentjavascripttypescriptpythonrustjavabashsqlreactdockergit

Works with

  • cli

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 2260-inputs_0e8fceb4 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 2260 Inputs 0e8fceb4?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 2260 Inputs 0e8fceb4
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-2260-inputs-0e8fceb4/badge)](https://www.skillsdirectory.com/skills/tools-only-2260-inputs-0e8fceb4)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# Special Inputs in bslib

bslib provides specialized input widgets that enhance standard Shiny inputs with modern features.

## Table of Contents

- [input_switch()](#input_switch)
- [input_dark_mode()](#input_dark_mode)
- [input_task_button()](#input_task_button)
- [input_code_editor()](#input_code_editor)
- [input_submit_textarea()](#input_submit_textarea)
- [Choosing the Right Input](#choosing-the-right-input)

## input_switch()

A modern toggle switch, alternative to `checkboxInput()` for on/off states with immediate effect.

```r
input_switch("enable_feature", "Enable advanced features")
input_switch("notifications", "Enable notifications", value = TRUE)
```

Use `input_switch()` freely in sidebars, card bodies, or toolbars wherever a boolean toggle fits. Update from the server with `update_switch("id", value = FALSE)` or flip the current state with `toggle_switch("id")`.

## input_dark_mode()

Toggle between Bootstrap 5.3 light/dark color modes. Automatically switches the `data-bs-theme` attribute on the page.

```r
input_dark_mode(id = "mode")                # Follow OS preference
input_dark_mode(id = "mode", mode = "dark") # Start in dark mode
```

**Placing in a navbar:** wrap in `nav_item()` and use `nav_spacer()` before it to push it to the right edge:

```r
page_navbar(
  title = "My App",
  nav_panel("Dashboard", ...),
  nav_spacer(),
  nav_item(input_dark_mode(id = "mode"))
)
```

**Hidden mode (OS-aware without a toggle button):** use `style = css(display = "none")` to activate Bootstrap's color mode system without rendering a UI control. The app follows the user's OS `prefers-color-scheme` by default and can still be controlled from the server:

```r
nav_item(input_dark_mode(id = "mode", style = css(display = "none")))
```

Omit `id` if you don't need the server to read or change the mode.

**Server access:** `input$mode` returns `"light"` or `"dark"`.

**Programmatic toggle:** `toggle_dark_mode()`, `toggle_dark_mode("light")`, `toggle_dark_mode("dark")`.

For full custom theme switching (different color palettes beyond light/dark), combine with `session$setCurrentTheme()`. See the **shiny-bslib-theming** skill for details.

## input_task_button()

Action button for long-running operations with built-in loading state. Auto-disables while running.

```r
# UI
input_task_button("run_analysis", "Run Analysis")

# Server
observeEvent(input$run_analysis, {
  result <- expensive_computation()
  output$result <- renderText(result)
})
```

### With ExtendedTask

For truly long-running tasks, combine with `ExtendedTask` and `bind_task_button()`:

```r
library(future)
plan(multisession)

server <- function(input, output, session) {
  long_task <- ExtendedTask$new(function() {
    future({ Sys.sleep(10); "Task complete!" }, seed = TRUE)
  }) |> bind_task_button("run")

  observeEvent(input$run, { long_task$invoke() })
  output$result <- renderText({ long_task$result() })
}
```

**`bind_task_button(target_task, button_id)`** keeps the button in "busy" state while the task runs. Does NOT auto-trigger on click — you still need `observeEvent()`.

**Update button:** `update_task_button("run", label = "Done", icon = bsicons::bs_icon("check"))`

## input_code_editor()

Lightweight code editor with syntax highlighting, powered by [prism-code-editor](https://prism-code-editor.netlify.app/). Auto-switches themes with dark mode. Try `shiny::runExample("code-editor", package = "bslib")`.

**Value updates reach the server** when the user moves focus away or presses `Ctrl/Cmd+Enter` (not on every keystroke).

```r
input_code_editor(
  id = "code",
  language = "r",
  value = "# Enter R code here\n"
)
```

**Languages:** `"r"`, `"python"`, `"julia"`, `"sql"`, `"javascript"`, `"typescript"`, `"html"`, `"css"`, `"scss"`, `"sass"`, `"json"`, `"markdown"`, `"yaml"`, `"xml"`, `"toml"`, `"ini"`, `"bash"`, `"docker"`, `"latex"`, `"cpp"`, `"rust"`, `"diff"`, `"plain"`.

### Configuration

| Parameter | Default | Description |
|---|---|---|
| `height` | `"auto"` | CSS height |
| `theme_light` | `"github-light"` | Light mode theme |
| `theme_dark` | `"github-dark"` | Dark mode theme |
| `read_only` | `FALSE` | Disable editing |
| `line_numbers` | `TRUE` | Show line numbers |
| `word_wrap` | | Enable word wrapping |
| `tab_size` | `2` | Tab width |
| `indentation` | `"space"` | `"space"` or `"tab"` |
| `fill` | `TRUE` | Fill container |

**Available themes:** `"atom-one-dark"`, `"dracula"`, `"github-dark-dimmed"`, `"github-dark"`, `"github-light"`, `"night-owl-light"`, `"night-owl"`, `"prism-okaidia"`, `"prism-solarized-light"`, `"prism-tomorrow"`, `"prism-twilight"`, `"prism"`, `"vs-code-dark"`, `"vs-code-light"`.

**Keyboard shortcuts:** `Ctrl/Cmd+Enter` (submit), `Ctrl/Cmd+Z` (undo), `Tab`/`Shift+Tab` (indent/dedent).

**Dynamic language switching:**
```r
observeEvent(input$language, {
  update_code_editor("code", language = input$language)
})
```

## input_submit_textarea()

Textarea with explicit submission — prevents reactive updates on every keystroke. Auto-grows as user types. Ideal for chat boxes, comments, or inputs where users compose before submitting.

**Important:** Initial server value is always `""`. Updates only on explicit submit.

```r
input_submit_textarea(
  id = "user_input",
  label = "Enter text:",
  placeholder = "Type here...",
  rows = 4
)
```

### Submission Behavior

- **Default (`submit_key = "enter+modifier"`):** `Ctrl/Cmd+Enter` to submit
- **Enter-only:** `submit_key = "enter"` — submit with Enter, Shift+Enter for new lines

### Custom Button and Toolbar

The `button` parameter accepts any HTML element. `input_task_button()` recommended for built-in busy state:

```r
input_submit_textarea(
  id = "query",
  placeholder = "Ask a question...",
  button = input_task_button("submit", "Send", icon = bsicons::bs_icon("send")),
  toolbar = list(
    actionLink("attach", bsicons::bs_icon("paperclip"))
  )
)
```

### Update

`update_submit_textarea()` accepts `value` to change the text, `submit = TRUE` to trigger submission programmatically, and `focus = TRUE` to move keyboard focus to the textarea.

### Chat Interface Pattern

```r
# UI
card(
  card_header("Chat"),
  card_body(uiOutput("chat_messages"), fillable = FALSE, fill = TRUE),
  card_footer(
    input_submit_textarea("chat_input", placeholder = "Type a message...", submit_key = "enter")
  )
)

# Server
observeEvent(input$chat_input, {
  req(nchar(input$chat_input) > 0)
  add_message(input$chat_input)
  update_submit_textarea("chat_input", value = "")
})
```

## Choosing the Right Input

| Need | Use | Instead of |
|---|---|---|
| On/off toggle, immediate effect | `input_switch()` | `checkboxInput()` |
| Selection/agreement, form submit | `checkboxInput()` | `input_switch()` |
| Long operation (>2s), prevent duplicates | `input_task_button()` | `actionButton()` |
| Quick action, custom loading | `actionButton()` | `input_task_button()` |
| Code with syntax highlighting | `input_code_editor()` | `textAreaInput()` |
| Expensive downstream, compose then submit | `input_submit_textarea()` | `textAreaInput()` |
| Live preview, cheap updates | `textAreaInput()` | `input_submit_textarea()` |
| Light/dark mode toggle | `input_dark_mode()` | Custom toggle |

### Feedback for Task Buttons

Show completion feedback after long operations:
```r
observeEvent(input$process, {
  result <- process_data()
  show_toast(toast("Processing complete", header = "Done", type = "success"))
})
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.