Is there a way to make it so that if a user reaches the end of the "line" on a textInput field that it continues on the next line and increases the height of the textbox so that they can see the entirety of what they have typed? Right now, the text continues on the same line making what was typed first no longer visible. Increasing the height of the textbox would also work given that if they reached the end of textbox, then a scroll bar appeared allowing them to go back to the top of what was typed.
library('shiny')
ui<-fluidPage(
fluidRow(
textInput(inputId = "response1", label = "Type your Response Below")
))
server<-function(input,output,session)
{}
shinyApp(ui=ui, server=server)
Briefly, my proposition is to use an HTML tag textarea and then to give it the css style of shiny widgets.
In the example below I had first created a new div in which I put the HTML tag textarea with id=response2 and a label. Then I added the the css style of the textInput from and applied it to the textarea tag using tags head and style.
Full example:
library(shiny)
ui <- fluidPage(
# Default style of normal textInput applied to the textarea (HTML tag)
tags$head(
tags$style("textarea {
width:300px;
height:34px;
display: block;
padding: 6px 12px;
font-size: 14px;
line-height: 1.42857143;
color: #555;
background-color: #fff;
background-image: none;
border: 1px solid #ccc;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
}
textarea:focus {
border-color: #66afe9;
outline: 0;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6)
}"
)
),
h3("Normal text input"),
textInput(inputId = "response1", label = "Type your Response Below"),
h3("Styled textarea"),
withTags(
div(
h5(b("Type your Response Below")),
textarea(id = "response2")
)
),
br(),
h3("Text from the styled textarea"),
textOutput("out")
)
server<-function(input, output, session) {
output$out <- renderText({
input$response2
})
}
shinyApp(ui = ui, server = server)
Edit:
Another way of doing the same thing with a smaller amount of the code would be to add the css class of shiny inputs form-control shiny-bound-input to the textarea tag and change the width and the height using style attribute.
library(shiny)
ui <- fluidPage(
h3("Normal text input"),
textInput(inputId = "response1", label = "Type your Response Below"),
h3("Styled textarea"),
withTags(
div(
h5(b("Type your Response Below")),
textarea(id = "response2",
class = "form-control shiny-bound-input",
style = "width: 300px; height: 34px")
)
),
br(),
h3("Text from the styled textarea"),
textOutput("out")
)
server<-function(input, output, session) {
output$out <- renderText({
input$response2
})
}
shinyApp(ui = ui, server = server)
Another way to achieve this is to use textAreaInput instead of textInput, which takes the parameter rows.
This parameter, according to the textAreaInput documentation, takes "The value of the visible character rows of the input".
As such, it can be used like so:
library('shiny')
ui<-fluidPage(
fluidRow(
textAreaInput(inputId = "response1", label = "Type your Response Below", rows=4)
))
server<-function(input,output,session)
{}
shinyApp(ui=ui, server=server)
PS: textAreaInput has its own update-value function: updateTextAreaInput (just in case you are using the textInput's equivalent of updateTextInput)
Related
I'm making a user interface in Shiny and am trying to make a bunch of stylized buttons.
I suceeded in having them be the color I want, and the last thing I want is for the button to darken on hover, like the default buttons do.
I've made the following function for these buttons:
dateButton <- function(id, label) {
actionButton(inputId = id, label = label, style = "color: white;
background-color: darkblue;
border-radius:15%;
border-color: white;
.hover {
box-shadow: inset 0 0 100px 100px rgba(255, 255, 255, 0.1);
}")
}
I'm sure the problem is .hover, I can't find how to format these list-like attributes. Any resources would also be appreciated.
Repr:
library(shiny)
dateButton <- function(id, label) {
actionButton(inputId = id, label = label, style = "color: white;
background-color: darkblue;
border-radius:15%;
border-color: white;
.hover {
box-shadow: inset 0 0 100px 100px rgba(255, 255, 255, 0.1);;}")
ui <- fluidPage(
dateButton("my_button", "B1"),
actionButton("default_button", "B2")
)
server <- function(input, output, session) {
}
shinyApp(ui, server)
}
When ran, B2 does what I want on hover, while B1 doesn't.
It doesn't seem possible to add the :hover pseudo-class selector to an object's inline style attribute. Instead it would work most smoothly to either insert as a <head><style>... section or link to an external style sheet (more examples here). First of these options as shown below:
library(shiny)
dateButton <- function(id, label) {
actionButton(
inputId = id,
label = label
)
}
ui <- fluidPage(
tags$head(tags$style(HTML("
#my_button {
background-color: darkblue;
color: white;
border-radius:15%;
border-color: white;
}
#my_button:hover {
box-shadow: inset 0 0 100px 100px rgba(255, 255, 255, 0.1);
font-weight: bold
}
"))),
dateButton("my_button", "B1"),
actionButton("default_button", "B2"))
server <- function(input, output, session) {
}
shinyApp(ui, server)
Edit - making a class to be shared across buttons
If you want to apply this to more buttons, add a class attribute in your constructor function call, and use css accordingly:
library(shiny)
dateButton <- function(id, label) {
actionButton(
inputId = id,
class = "hover-button",
label = label
)
}
ui <- fluidPage(
tags$head(tags$style(HTML("
.hover-button {
background-color: darkblue;
color: white;
border-radius:15%;
border-color: white;
}
.hover-button:hover {
box-shadow: inset 0 0 100px 100px rgba(255, 255, 255, 0.1);
font-weight: bold
}
"))),
dateButton("my_button", "B1"),
actionButton("default_button", "B2"))
server <- function(input, output, session) {
}
shinyApp(ui, server)
I would like to simply add a hovering window over an icon after a simple line of text.
I have found the shinyBS package, which seems to make this possible but it is linked to shiny outputs.
Having something like the code below in the "ui" of the shiny app makes the buttons work but they are linked to the radioButtons in this case.
CVI <- c("Hello1", "Hello2", "Hello3")
CNI <- c("Peter1", "Peter2", "Peter3")
radioButtons(inputId = "Attribute", label="Attribute", choiceValues = CVI,
choiceNames = list(
tagList(
tags$span(CNI[1]), #DoS
tags$span(icon("info-circle"), id = "1_info", style = "color: gray;")
),
tagList(
tags$span(CNI[2]), #DoO
tags$span(icon("info-circle"), id = "2_info", style = "color: gray;")
),
tagList(
tags$span(CNI[3]), #Ratio
tags$span(icon("info-circle"), id = "3_info", style = "color: gray;")
))
),# radiobuttons end
Popover buttons
bsPopover(id="1_info", title=NULL, content="Test1", trigger="hover", placement="right", options=list(container="body")),
bsPopover(id="2_info", title=NULL, content="Test2", trigger="hover", placement="right", options=list(container="body")),
bsPopover(id="3_info", title=NULL, content="Test3", trigger="hover", placement="right", options=list(container="body"))
How can I achieve something similar but without the radioButtons, simply like the word "Example" and then an icon where I hover and get a popup with some information (see picture).
I would create it somewhat like this:
Example_Text <- "Example_text" # This is what comes in the popup
"Example", span(icon("info-circle"), id = "Example_Popup", style = "color: gray;")
The native HTML tooltips are not customizable. Bootstrap tooltips are.
library(shiny)
library(bslib)
css <- '
.tooltip {
pointer-events: none;
}
.tooltip > .tooltip-inner {
pointer-events: none;
background-color: #73AD21;
color: #FFFFFF;
border: 1px solid green;
padding: 10px;
font-size: 25px;
font-style: italic;
text-align: justify;
margin-left: 0;
max-width: 1000px;
}
.tooltip > .arrow::before {
border-right-color: #73AD21;
}
'
js <- "
$(function () {
$('[data-toggle=tooltip]').tooltip()
})
"
shinyApp(
server = function(input,output,session){},
ui = fluidPage(
theme = bs_theme(version = 4),
tags$head(
tags$style(HTML(css)),
tags$script(HTML(js))
),
br(),
span(
"Example",
span(
`data-toggle` = "tooltip", `data-placement` = "right",
title = "A tooltip",
icon("info-circle")
)
)
)
)
This can be done with div(title=, style=, ...).
shinyApp(
server = function(input,output,session){},
ui = fluidPage(
span(
"Example",
div(style = "display:inline-block;",
title = "A tooltip",
icon("info-circle")))
)
)
Pause your mouse over the icon and you'll see A tooltip. It isn't styled like the directional callout you have in your page, perhaps it's sufficient.
I want to have a glow to the refresh button when I change the pickerinput.
I have been able to get the glow but the problem is that this is glowing from the start. I don't want this to glow from the start and Yes! it is necessary to have a default selected value.
I hope this is clear enough. I'm sorry if I didn't adhere to the guidelines. I'm still learning.
Thank you in advance!
library("shiny")
library(shinyWidgets)
library(shinyjs)
#Created Ui having picker input, action button and Css for it
ui <- tagList(shinyjs::useShinyjs(),
fluidPage(
tags$h2("Select / Deselect all"),
actionButton("button_1", "Refresh Plot",style= "animation: none;"),
pickerInput(
inputId = "p1",
label = "Select all option",
choices = rownames(mtcars),
multiple = TRUE,
options = list(`actions-box` = TRUE), selected = rownames(mtcars)[1]
)),
tags$head(tags$style(HTML('#keyframes glowing {
0% { background-color: #4a257a !important; box-shadow: 0 0 5px #0795ab; }
50% { background-color: #6632ad !important; box-shadow: 0 0 20px #43b0d1; }
100% { background-color: #4a257a !important; box-shadow: 0 0 5px #0795ab; }
}
'))))
server <- function(input, output) {
observe({
runjs(paste0('$("#button_1").css("animation","glowing 5000ms infinite")'))
delay(5000, runjs(paste0('$("#button_1").css("animation","none")')))
print(input$p1)
})
}
shinyApp(ui, server)
Change observe({...}) to observeEvent(input$p1, {...}, ignoreInit = TRUE)
I have 2 textInput and 2 selectInput functions. One on the dark background on my sidebar and the other on the white (inside the bsModal). My question is: is there a way to style them in different ways? Ideally, I would like to keep the ones on the sidebar the way I styled, and for the ones inside bsModal at least change font color and a border color.
Code:
## Shiny
library(shiny)
library(shinydashboard)
library(shinyBS)
ui <- dashboardPage(
## Header ----
dashboardHeader(
disable = TRUE
),
## Sidebar ----
dashboardSidebar(
sidebarMenu(
div(style = "border-left-color: #1e282c; padding: 10px",
menuItem(text = div(HTML("<left>Search</left>")),
tabName = "search",
icon = icon("search", "fa-2x"))
)
)
),
## Body ----
dashboardBody(
## when header is disabled need to compensate for the missing 50px
## to avoid empty space on the bottom
tags$script('window.onload = function() {
function fixBodyHeight() {
var el = $(document.getElementsByClassName("content-wrapper")[0]);
var h = el.height();
el.css("min-height", h + 50 + "px");
};
window.addEventListener("resize", fixBodyHeight);
fixBodyHeight();
};'),
tags$style(HTML(
"
.well{
background-color: #222C3C;
color: #FFFFFF;
}
.form-control {
background-color: transparent;
border: 0px;
border-bottom: 1px solid #ffffff;
color: #ffffff;
}
.selectize-input{
background: transparent;
}
.selectize-input.items.not-full.has-options {
border: 0px;
border-bottom: 1px solid #ffffff;
border-radius: 0;
}
.selectize-dropdown, .selectize-input, .selectize-input input{
color: #FFFFFF;
}
.selectize-control.multi .selectize-input > div{
background: rgb(9, 231, 178, 0.3);
color: #ffffff;
}
.selectize-dropdown-content {
background: #1B2431;
color: #ffffff;
border-radius: 4px;
}
.selectize-input.full{
background-color: transparent;
color: #FFFFFF;
border: 0px;
border-bottom: 1px solid #ffffff;
border-radius: 0;
}
.selectize-input, .selectize-control.single, .selectize-input.input-active{
background: transparent !important;
}
"
)),
# includeCSS("www/style.css"),
tabItems(
tabItem(
tabName = "search",
sidebarLayout(
sidebarPanel(
tabsetPanel(
tabPanel(div("Search task"),
textInput("searchTextIn", HTML("<i class='fa fa-search'></i> KEYWORDS"), value = ""),
selectizeInput("productFilter", HTML("<i class='fa fa-share-alt gly-rotate-135'></i> PRODUCT OR COMPONENT"),
choices = c("A", "AAA", "B", "BBBBBB", "C", "CCCCCC"),
multiple = TRUE,
selected = c("A", "AAA")),
actionLink("saveToGroup", HTML("<u> Save to group </u>"), style = "color: #d3d3d3cf"),
width = 3)
)),
mainPanel(
bsModal("saveToGroupPopup", "Save to group", "saveToGroup",
div(selectizeInput("saveToGroupSelection",
"Add this search to a search group:",
choices = c("Category A", "Category B", "Category C",
"Batman"),
selected = NULL,
multiple = TRUE,
options = list(maxItems = 1))),
textInput("saveToGroupNew", label = NULL, value = "",
placeholder = "Create new…")
)
)
)
)
)
)
)
server <- function(input, output) {}
shinyApp(ui = ui, server = server)
you can use glamor to style your inputs differently. Basically glamor allows you to write css using javascript like conditions. just pass a boolean variable along with the class and on the basis of that variable choose the style of text field for example
const descDiv = **isDark** => css({
color: isDark ? color.white : colors.gray,
marginBottom: isDark? '0rem' :'1rem',
letterSpacing:isDark ? '0px' :'-0.6px', //if isDark true 0px else -0.6px
width:isDark? '10rem' :'13.5rem'
});
One solution that worked for me is for the textInput is actually quite easy, all I needed to do is in my css:
textInput(id, "")
tags$style(HTML("
#id.form-control{color:gray;}
"))
For the selectize input is a bit more confusing:
selectizeInput(id, ....)
tags$style(HTML("
#id + div>.selectize-input.items.not-full.has-options{border-bottom: 1px solid #F2F2F2;}
#id + div>.selectize-dropdown, #id+ div>.selectize-input, #id+ div>.selectize-input input{ color: gray;}
#id + div> div> .item {color: gray;}
"))
I am developing a R Shiny Application that use the shinyWidgets library. I use 2 times the radioGroupButtons widget. I would like to make it green the first time, and red the second time, using CSS. (In reality I want to make more customisation).
Here is a basic code, applying CSS to every buttons. How can I apply 2 CSS classes?
Thank you very very much for your help !
library("shinyWidgets")
library(shiny)
# Useless server
server <- function(input, output) {
output$distPlot <- renderPlot({
hist(rnorm(input$button1), col = 'skyblue', border = 'white')
})
}
# Ui
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
# A CSS for every .btn button
tags$style(HTML("
.btn {
color: #2ecc71;
border: 2px #2ecc71 solid;
}
.btn:hover {
color: #fff;
background-color: #2ecc71;
}
.btn-default.active, .btn-default:active, .open > .dropdown-toggle.btn-default {
color: #fff;
background-color: #2ecc71;
border-color: #2ecc71;
}
")),
# first radio button, it is green!
radioGroupButtons("button1", label = "It's green !!", choices=c("choice1"=50, "Choice2"=100, "Choice3"=150), selected=100),
# second radio button, I wish it is red!
radioGroupButtons("button2", label = "I wish I was red :( ...", choices=c("choice1"=1, "Choice2"=2), selected=1)
),
mainPanel(plotOutput("distPlot"))
)
)
shinyApp(ui = ui, server = server)
So you want to add some specific classes to your radioGroupButtons. Well, ShinyWidgets doesn't let you, so why not create your own radioButtons widget function.
(Well, this function will be almost entirely copied from radioGroupButtons)
Hint: Type radioGroupButton into the R Console to view the source code.
And lets tweak that function, such that it accepts a class argument, which will be applied to the html element. Then, you can easily access the different radioGroupButton-classes with your CSS.
Working code below:
library("shinyWidgets")
library(shiny)
# Defining the new Widget.
customRadioGroupButtons <- function (inputId, label = NULL, choices, selected = NULL, status = "default", size = "normal", direction = "horizontal", justified = FALSE, individual = FALSE, checkIcon = list(), class=NULL) {
choices <- shinyWidgets:::choicesWithNames(choices)
if (!is.null(selected) && length(selected) > 1)
stop("selected must be length 1")
if (is.null(selected))
selected <- choices[1]
size <- match.arg(arg = size, choices = c("xs", "sm", "normal",
"lg"))
direction <- match.arg(arg = direction, choices = c("horizontal",
"vertical"))
status <- match.arg(arg = status, choices = c("default",
"primary", "success", "info", "warning", "danger"))
divClass <- if (individual)
""
else "btn-group"
if (!individual & direction == "vertical") {
divClass <- paste0(divClass, "-vertical")
}
if (justified) {
divClass <- paste(divClass, "btn-group-justified")
}
if (size != "normal") {
divClass <- paste0(divClass, " btn-group-", size)
}
# Below here, the paste call is the only difference to the original function.
radioGroupButtonsTag <- tagList(tags$div(id = inputId, class = paste("radioGroupButtons", class),
if (!is.null(label))
tags$label(class = "control-label", `for` = inputId, label),
if (!is.null(label))
br(), style = "margin-top: 3px; margin-bottom: 3px; ", style = if (justified) "width: 100%;",
tags$div(class = divClass, role = "group",
`aria-label` = "...", `data-toggle` = "buttons",
class = "btn-group-container-sw", shinyWidgets:::generateRGB(inputId, choices, selected, status, size, checkIcon))))
shinyWidgets:::attachShinyWidgetsDep(radioGroupButtonsTag)
}
# Useless server
server <- function(input, output) {
output$distPlot <- renderPlot({
hist(rnorm(input$button1), col = 'skyblue', border = 'white')
})
}
# Ui
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
# Note: Consider making a function if you use this more often.
tags$style(HTML("
.radioGroupButtons.green .btn {
color: #2ecc71;
border: 2px #2ecc71 solid;
}
.radioGroupButtons.green .btn:hover {
color: #fff;
background-color: #2ecc71;
}
.radioGroupButtons.green .btn-default.active, .radioGroupButtons.green .btn-default:active, .radioGroupButtons.green .open > .dropdown-toggle.btn-default {
color: #fff;
background-color: #2ecc71;
border-color: #2ecc71;
}
.radioGroupButtons.red .btn {
color: #EE102B;
border: 2px #EE102B solid;
}
.radioGroupButtons.red .btn:hover {
color: #fff;
background-color: #EE102B;
}
.radioGroupButtons.red .btn-default.active, .radioGroupButtons.green .btn-default:active, .radioGroupButtons.green .open > .dropdown-toggle.btn-default {
color: #fff;
background-color: #EE102B;
border-color: #EE102B;
}
")),
# first radio button, it is green!
customRadioGroupButtons("button1", class="green", label = "It's green !!", choices=c("choice1"=50, "Choice2"=100, "Choice3"=150), selected=100),
# second radio button, I wish it is red!
customRadioGroupButtons("button2", class="red", label = "I wish I was red :( ...", choices=c("choice1"=1, "Choice2"=2), selected=1)
),
mainPanel(plotOutput("distPlot"))
)
)
shinyApp(ui = ui, server = server)
You can add a Bootstrap status then overwrite the class, for example if you add status = "danger", buttons will have class btn-danger :
I can remove the limitation to valid Bootstrap status in the function, it could be useful for such styling (fill an issue here so i remenber).
library("shinyWidgets")
library("shiny")
# Useless server
server <- function(input, output) {
output$distPlot <- renderPlot({
hist(rnorm(input$button1), col = 'skyblue', border = 'white')
})
}
# Ui
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
# A CSS for every .btn button
tags$style(HTML("
.btn-success.btn {
color: #2ecc71;
background-color: #fff;
border: 2px #2ecc71 solid;
}
.btn-success.btn:hover {
color: #fff;
background-color: #2ecc71;
}
.btn-success.active {
color: #fff;
background-color: #2ecc71;
border-color: #2ecc71;
}
.btn-danger.btn {
color: #EE102B;
background-color: #fff;
border: 2px #EE102B solid;
}
.btn-danger.btn:hover {
color: #fff;
background-color: #EE102B;
}
.btn-danger.active {
color: #fff;
background-color: #EE102B;
border-color: #EE102B;
}
")),
# first radio button, it is green!
radioGroupButtons("button1", label = "It's green !!", status = "success", choices=c("choice1"=50, "Choice2"=100, "Choice3"=150), selected=100),
# second radio button, I wish it is red!
radioGroupButtons("button2", label = "I wish I was red :( ...", status = "danger", choices=c("choice1"=1, "Choice2"=2), selected=1)
),
mainPanel(plotOutput("distPlot"))
)
)
shinyApp(ui = ui, server = server)