-
Notifications
You must be signed in to change notification settings - Fork 65
feat: Add input_submit_textarea() input element
#1204
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
86 commits
Select commit
Hold shift + click to select a range
693b87c
feat(input_submit_button, input_submit_textarea): Add new input submi…
cpsievert 34cf8ee
`air format` (GitHub Actions)
cpsievert 75d73fb
Resave distributed files (GitHub Action)
cpsievert 3f98b68
Resave data (GitHub Action)
cpsievert 4f2ab2b
Update to latest Shiny
cpsievert 924d98d
Merge branch 'main' into feat/submit-input
cpsievert 1d69765
shiny remote no longer needed
cpsievert 27137d2
`usethis::use_tidy_description()` (GitHub Actions)
cpsievert dcf5a10
Resave distributed files (GitHub Action)
cpsievert 3da38ac
Resave data (GitHub Action)
cpsievert 7d88ff7
Update website deps (GitHub Action)
cpsievert 8afa5db
Merge branch 'main' into feat/submit-input
cpsievert 8ee990f
Bump shiny requirement
cpsievert 981dd96
Pass on adding input_submit_button() (at least for now)
cpsievert b6294cd
Make function signature more consistent with other inputs
cpsievert cc43168
Support HTML label updates
cpsievert d7036a1
Add autoresize logic
cpsievert 57a41f8
Fix shiny requirement
cpsievert aa5cb10
`usethis::use_tidy_description()` (GitHub Actions)
cpsievert 2a6995f
Resave data (GitHub Action)
cpsievert 168c332
Update website deps (GitHub Action)
cpsievert 9bfa28a
Avoid non-ASCII characters
cpsievert 9cd0726
CSS tweaks to better align with chat input styles
cpsievert f1c06ea
`usethis::use_tidy_description()` (GitHub Actions)
cpsievert 53eb8f8
`devtools::document()` (GitHub Actions)
cpsievert 4f4cc18
Update website deps (GitHub Action)
cpsievert ddf78a2
Doc improvements
cpsievert 141e27f
Strict equality check
cpsievert bf27042
Better scss file name
cpsievert 4c889ea
`usethis::use_tidy_description()` (GitHub Actions)
cpsievert da98f13
Update website deps (GitHub Action)
cpsievert e4443ff
Platform specific modifier in button label
cpsievert 7155c53
Get check passing
cpsievert bac1e68
`usethis::use_tidy_description()` (GitHub Actions)
cpsievert 0351b64
`yarn build` (GitHub Actions)
cpsievert 2511d40
Update website deps (GitHub Action)
cpsievert cfe0a04
Add to reference
cpsievert 6bdf0d2
`usethis::use_tidy_description()` (GitHub Actions)
cpsievert 7529734
Update website deps (GitHub Action)
cpsievert ef1e0f7
Update R/input-submit.R
cpsievert c46e452
Update inst/components/scss/input_submit_textarea.scss
cpsievert 18c9476
`usethis::use_tidy_description()` (GitHub Actions)
cpsievert b93ea6a
`devtools::document()` (GitHub Actions)
cpsievert cbec5c3
Resave distributed files (GitHub Action)
cpsievert 106f5c3
Update website deps (GitHub Action)
cpsievert 1e8a61a
Import label markup logic from shiny
cpsievert 86eec98
Simplify markup
cpsievert b47b227
`air format` (GitHub Actions)
cpsievert 703d6ee
`usethis::use_tidy_description()` (GitHub Actions)
cpsievert 6cedfb5
Update website deps (GitHub Action)
cpsievert 2dc98ef
Introduce a modifier key container; add explicit class to button
cpsievert e455d82
`usethis::use_tidy_description()` (GitHub Actions)
cpsievert 23242a2
Update website deps (GitHub Action)
cpsievert 61af9f9
Revert "Simplify markup"
cpsievert 5810cba
Change default to enter+modifier
cpsievert c66c6b6
`usethis::use_tidy_description()` (GitHub Actions)
cpsievert 8544f5f
Resave data (GitHub Action)
cpsievert a21777c
Update website deps (GitHub Action)
cpsievert cdf4d8d
Move the component identifier CSS class to top-level
cpsievert 331aaba
Update documentation
cpsievert ff02c93
Manually insert new lines for Alt+Enter; Query submit button everytim…
cpsievert e5a41e4
Improved styling/logic for submit key hint
cpsievert e9ef2eb
Allow children/attributes to be passed through ...; add rows argument…
cpsievert 674eb85
Better busy UI
cpsievert 138b83d
Rename top-level .bslib-submit-textarea to .bslib-input-submit-textarea
cpsievert 1640259
`usethis::use_tidy_description()` (GitHub Actions)
cpsievert 0013d15
Resave distributed files (GitHub Action)
cpsievert d1d1c0d
Resave data (GitHub Action)
cpsievert b7358fe
Update website deps (GitHub Action)
cpsievert 7ccf8e8
Add toolbar argument; require ... to be named; add gap between toolba…
cpsievert bff5c54
Focus textarea when (inner) container is clicked
cpsievert 71bca10
Delete unused code
cpsievert 012ac22
Merge branch 'main' into feat/submit-input
cpsievert f9692f8
`air format` (GitHub Actions)
cpsievert 29375f3
`usethis::use_tidy_description()` (GitHub Actions)
cpsievert 74479dc
Update website deps (GitHub Action)
cpsievert e3080a7
Address feedback
cpsievert e2553ea
chore: organize Rd content
cpsievert 104b788
fix: support trailing comma
cpsievert a340934
Add some basic snapshot tests
cpsievert f02252a
Apply suggestions from code review
cpsievert 693cf19
Merge branch 'main' into feat/submit-input
cpsievert f663f60
`air format` (GitHub Actions)
cpsievert 23cb0e5
`devtools::document()` (GitHub Actions)
cpsievert c35e47a
`yarn build` (GitHub Actions)
cpsievert 96ab310
Resave data (GitHub Action)
cpsievert File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,191 @@ | ||
| #' Create a textarea input control with explicit submission | ||
| #' | ||
| #' Creates a textarea input where users can enter multi-line text and submit | ||
| #' their input using a dedicated button or keyboard shortcut. This control is | ||
| #' ideal when you want to capture finalized input, rather than reacting to every | ||
| #' keystroke, making it useful for chat boxes, comments, or other scenarios | ||
| #' where users may compose and review their text before submitting. | ||
| #' | ||
| #' @section Server value: | ||
| #' The server receives a character string containing the user's text input. | ||
| #' | ||
| #' **Important:** The initial server value is always `""` (empty string), | ||
| #' regardless of any `value` parameter provided to `input_submit_textarea()`. | ||
| #' The server value updates only when the user explicitly submits the input by | ||
| #' either pressing the Enter key (possibly with a modifier key) or clicking the | ||
| #' submit button. | ||
| #' | ||
| #' @param id The input ID. | ||
| #' @param label The label to display above the input control. If `NULL`, no | ||
| #' label is displayed. | ||
| #' @param ... Additional attributes to apply to the underlying `<textarea>` | ||
| #' element (e.g., spellcheck, autocomplete, etc). | ||
| #' @param placeholder The placeholder text to display when the input is empty. | ||
| #' This can be used to provide a hint or example of the expected input. | ||
| #' @param value The initial input text. Note that, unlike [shiny::textAreaInput()], | ||
| #' this won't set a server-side value until the value is explicitly submitted. | ||
| #' @param width Any valid CSS unit (e.g., `width="100%"`). | ||
| #' @param rows The number of rows (i.e., height) of the textarea. This essentially | ||
| #' sets the minimum height -- the textarea can grow taller as the user | ||
| #' enters more text. | ||
| #' @param button A [htmltools::tags] element to use for the submit button. It's recommended | ||
| #' that this be a [input_task_button()] since it will automatically provide a | ||
| #' busy indicator (and disable) until the next flush occurs. Note also that if | ||
| #' the submit button launches a [shiny::ExtendedTask], this button can also be bound | ||
| #' to the task ([bind_task_button()]) and/or manually updated for more | ||
| #' accurate progress reporting ([update_task_button()]). | ||
| #' @param toolbar A list of optional UI elements (e.g., links, icons) to | ||
| #' display next to the submit button. | ||
| #' @param submit_key A character string indicating what keyboard event should | ||
| #' trigger the submit button. The default is `enter+modifier`, which requires | ||
| #' the user to hold down Ctrl (or Cmd on Mac) before pressing Enter to | ||
| #' submit. This helps prevent accidental submissions. To allow submission with | ||
| #' just the Enter key, use `enter`. In this case, the user can still insert | ||
| #' new lines using Shift+Enter or Alt+Enter. | ||
| #' | ||
| #' @return A textarea input control that can be added to a UI definition. | ||
| #' @seealso [update_submit_textarea()], [input_task_button()] | ||
| #' | ||
| #' @examplesIf rlang::is_interactive() | ||
| #' library(shiny) | ||
| #' library(bslib) | ||
| #' | ||
| #' ui <- page_fluid( | ||
| #' input_submit_textarea("text", placeholder = "Enter some input..."), | ||
| #' verbatimTextOutput("value") | ||
| #' ) | ||
| #' server <- function(input, output) { | ||
| #' output$value <- renderText({ | ||
| #' req(input$text) | ||
| #' Sys.sleep(2) | ||
| #' paste("You entered:", input$text) | ||
| #' }) | ||
| #' } | ||
| #' shinyApp(ui, server) | ||
| #' | ||
| #' @export | ||
| input_submit_textarea <- function( | ||
| id, | ||
| label = NULL, | ||
| ..., | ||
| placeholder = NULL, | ||
| value = "", | ||
| width = "min(680px, 100%)", | ||
| rows = 1, | ||
| button = NULL, | ||
| toolbar = NULL, | ||
| submit_key = c("enter+modifier", "enter") | ||
| ) { | ||
| rlang::check_installed("shiny", version = "1.11.1") | ||
| args <- rlang::list2(...) | ||
| if (any_unnamed(args)) { | ||
| abort(c( | ||
| "All `...` arguments must be named", | ||
| "i" = "Did you mean to pass UI elements to `toolbar`?" | ||
| )) | ||
| } | ||
|
|
||
| value <- shiny::restoreInput(id = id, default = value) | ||
| if (length(value) != 1 || !is.character(value)) { | ||
| abort("`value` must be a character string") | ||
| } | ||
|
|
||
| submit_key <- rlang::arg_match(submit_key) | ||
| needs_modifier <- isTRUE(submit_key == "enter+modifier") | ||
|
|
||
| if (is.null(button)) { | ||
| button <- input_task_button( | ||
cpsievert marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| id = paste0(id, "_submit"), | ||
| class = "btn-sm", | ||
| label = span(class = "bslib-submit-key", "\U23CE"), | ||
| icon = "Submit", | ||
| label_busy = div( | ||
| class = "spinner-border spinner-border-sm ms-2", | ||
| role = "status", | ||
| span(class = "visually-hidden", "Processing...") | ||
| ), | ||
| icon_busy = "Submit", | ||
| title = "Press Enter to Submit", | ||
| `aria-label` = "Press Enter to Submit" | ||
| ) | ||
| } | ||
|
|
||
| if (!is_button_tag(button)) { | ||
| abort("`button` must be a `tags$button()`") | ||
| } | ||
|
|
||
| button <- tagAppendAttributes(button, class = "bslib-submit-textarea-btn") | ||
cpsievert marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| div( | ||
| class = "bslib-input-submit-textarea shiny-input-container bslib-mb-spacing", | ||
| style = css( | ||
| # TODO: validateCssUnit() needs to handle more complex CSS | ||
| width = if (is.numeric(width)) paste0(width, "px") else width, | ||
| ), | ||
| shiny_input_label(id, label), | ||
| div( | ||
| class = "bslib-submit-textarea-container", | ||
| tags$textarea( | ||
| id = id, | ||
| class = "form-control", | ||
| style = css(width = if (!is.null(width)) "100%"), | ||
| placeholder = placeholder, | ||
| `data-needs-modifier` = if (needs_modifier) "", | ||
| rows = rows, | ||
| !!!args, | ||
| value | ||
| ), | ||
| tags$footer( | ||
| div(toolbar, class = "bslib-toolbar"), | ||
| button | ||
| ) | ||
| ) | ||
| ) | ||
| } | ||
|
|
||
| is_button_tag <- function(x) { | ||
| if (!inherits(x, "shiny.tag")) { | ||
| return(FALSE) | ||
| } | ||
|
|
||
| isTRUE(x$name == "button") || | ||
| isTRUE(x$attribs$type == "button") | ||
| } | ||
|
|
||
| #' @param value The value to set the user input to. | ||
| #' @param placeholder The placeholder text for the user input. | ||
| #' @param submit Whether to automatically submit the text for the user. Requires `value`. | ||
| #' @param focus Whether to move focus to the input element. Requires `value`. | ||
| #' @param session The `session` object; using the default is recommended. | ||
| #' | ||
| #' @rdname input_submit_textarea | ||
| #' @export | ||
| update_submit_textarea <- function( | ||
| id, | ||
| ..., | ||
| value = NULL, | ||
| placeholder = NULL, | ||
| label = NULL, | ||
| submit = FALSE, | ||
| focus = FALSE, | ||
| session = get_current_session() | ||
| ) { | ||
| rlang::check_dots_empty() | ||
|
|
||
| if (is.null(value) && (submit || focus)) { | ||
| stop( | ||
| "An input `value` must be provided when `submit` or `focus` are `TRUE`.", | ||
| call. = FALSE | ||
| ) | ||
| } | ||
|
|
||
| message <- dropNulls(list( | ||
| value = value, | ||
| placeholder = placeholder, | ||
| label = if (!is.null(label)) processDeps(label, session), | ||
| submit = submit, | ||
| focus = focus | ||
| )) | ||
|
|
||
| session$sendInputMessage(id, message) | ||
| } | ||
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.