External CSS in Shiny Dashboard - css

I'm trying to modify Shiny dashboard apperance by using CSS.
I've first used internal CSS as below and it works as expected.
library(shiny)
library(shinydashboard)
# Internal CSS - works fine
ui <- shinydashboard::dashboardPage(
shinydashboard::dashboardHeader(title = "MyDashboard"),
shinydashboard::dashboardSidebar(
sidebarMenu(
menuItem("Main", tabName = "Main", icon = icon("home"), startExpanded = TRUE,
menuSubItem("Tab1", tabName = "Tab1", icon = icon("chart-line")),
menuSubItem("Tab2", tabName = "Tab2", icon = icon("chart-line")),
menuSubItem("Tab3", tabName = "Tab3", icon = icon("dashboard"))
)
)
),
shinydashboard::dashboardBody(
tags$head(tags$style(HTML('
.skin-blue .main-header .logo {
background-color: #193807;
}
.skin-blue .main-header .navbar {
background-color: #193807;
}
.skin-blue .main-sidebar {
background-color: #193807;
}
'
))),
fluidPage(
)
)
)
server <- function(input, output) { }
shinyApp(ui, server)
Now I want to do the same by refering to an external CSS file. So I create a mystyle.css file inside www directory, which is located insise the folder, in which I have the file with dashboard app (so, if the app is in C:\Documents\Myapp, then the css file is in C:\Documents\Myapp\www).
The css file looks as follows:
.skin-blue .main-header .logo {
background-color: #193807;
}
.skin-blue .main-header .navbar {
background-color: #193807;
}
.skin-blue .main-sidebar {
background-color: #193807;
}
I refer to the css file with a tags$head and tags$link as shown below. But it's not working. What's wrong?
# External CSS - not working
ui <- shinydashboard::dashboardPage(
shinydashboard::dashboardHeader(title = "MyDashboard"),
shinydashboard::dashboardSidebar(
sidebarMenu(
menuItem("Main", tabName = "Main", icon = icon("home"), startExpanded = TRUE,
menuSubItem("Tab1", tabName = "Tab1", icon = icon("chart-line")),
menuSubItem("Tab2", tabName = "Tab2", icon = icon("chart-line")),
menuSubItem("Tab3", tabName = "Tab3", icon = icon("dashboard"))
)
)
),
shinydashboard::dashboardBody(
tags$head(tags$link(rel = "stylesheet", type="text/css", href="mystyle.css")),
fluidPage(
)
)
)
server <- function(input, output) { }
shinyApp(ui, server)

I know this is a very late reply to your question, however I feel I must answer as I too struggled linking my external CSS to my Shiny dashboard.
The method that worked for me was to use the function includeCSS("www/style.css") which I read about in this Shiny post.
Below is an example of how I used this function in my Shiny app.R UI. Note that the includeCSS() function is placed within the dashboardBody() section. I also use icons in my dashboard which does not prevent the CSS from linking for me.
ui <- dashboardPage(
dashboardHeader(title = "Text Analysis"),
dashboardSidebar(
sidebarMenu(
menuItem("Home",
tabName = "home",
icon = icon("home")
)
),
dashboardBody(
includeCSS("www/style.css"), # Link to style sheet
tabItems(
tabItem(tabName = "home",
homeUI("home")
),
)
)
)
Feel free to ignore this if you have not yet explored modules in Shiny apps yet...
My Shiny app uses modules, hence the homeUI() call in the tab item, and the CSS still renders on child and adjacent modules too. I am yet to explore whether CSS linked on child modules is rendered in parent modules. In the meantime, it is handy that the CSS is passed down for anyone wondering if they need to make an includeCSS() call in every module - you don't!

so what if you launch the app in external browser and the open the Developer Tool. Do you have the css file linked to the app successfully? something like below the screenshot:
weirdly, the first time I ran the app, the css file is empty but I tried one more time, it is ok now
After some more checking, the root casue for this might be:
below this warning is causing some issues for the browser to link the CSS file, so please use icon = icon("dashboard", verify_fa = FALSE) in the code to see if it works

Related

shinydashboard vs shinydashboardPlus - dashboardsidebar title differences

I have a Shiny app built with shinydashboard and I've just discovered shinydashboardPlus. One nice option is to have the sidebarMenu "minified", or when minimized it doesn't go away completely, but just displays the icons for each menuItem. However, with shinydashboardPlus, when minified, the title gets chopped off. With shinydashboard, the title stays intact, but the sidebar goes away completely.
Example code:
library(shiny)
library(shinydashboard)
#library(shinydashboardPlus)
# Basic dashboard page template
shinyApp(
ui = dashboardPage(
dashboardHeader(title = "Example"),
dashboardSidebar(#minified = TRUE,
sidebarMenu(
menuItem('Menu1', tabName = 'Menu1',
icon = icon('folder-open')),
menuItem('Menu2', tabName = 'Menu2',
icon = icon('code-branch'))
)
),
dashboardBody()
),
server = function(input, output) { }
)
Leaving the comment marks in place and running it uses shinydashboard, and gives this initially:
And when the hamburger is clicked to minimize the sidebar, the whole sidebar disappears:
If the comment marks are removed so that it runs using shinydashboardPlus, minimizing it gives this, where I have the icons in the sidebar, but the title is chopped:
Is there a way to get the shinydashboardPlus minification that shows just the icons, but doesn't chop off the title?
Here you go
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
# Basic dashboard page template
shinyApp(
ui = dashboardPage(
dashboardHeader(title = "Example"),
dashboardSidebar(#minified = TRUE,
sidebarMenu(
menuItem('Menu1', tabName = 'Menu1',
icon = icon('folder-open')),
menuItem('Menu2', tabName = 'Menu2',
icon = icon('code-branch'))
)
),
dashboardBody(
tags$style(
'
#media (min-width: 768px){
.sidebar-mini.sidebar-collapse .main-header .logo {
width: 230px;
}
.sidebar-mini.sidebar-collapse .main-header .navbar {
margin-left: 230px;
}
}
'
)
)
),
server = function(input, output) { }
)
change the width and margin-left numbers if you have extreme long titles.

Change navbar theme colour permanently in bs4Dash R shiny app

I am using bs4Dash (version >2.0) in a shiny app but I am unable to change the navbar color (change permanently irrespective of the dark/light theme) to yellow (#ffc107).
You can check the minimal example given in ?bs4Dash::skinSelector(). While the colour can be changed to yellow from 'Navbar themer' menu in the right control bar but I need to fix or default the header colour to yellow.
Here this is the minimal example given in skinselecter(). please use bs4dash version > 2.0 from github.
if (interactive()) {
library(shiny)
library(bs4Dash)
shinyApp(
ui = dashboardPage(
header = dashboardHeader(),
sidebar = dashboardSidebar(
sidebarMenu(
menuItem(
text = "Item 1"
),
menuItem(
text = "Item 2"
)
)
),
body = dashboardBody(),
controlbar = dashboardControlbar(skinSelector(), pinned = TRUE),
title = "Skin Selector"
),
server = function(input, output) { }
)
}
By including below css, i was able to solve this.
.navbar-gray-dark {
background-color: #ffc107;
}
.navbar-white {
background-color: #ffc107;
}

Shiny Dashboard- How to add text for Sidebar items

I was trying to add website information on my shiny dashboard and for the "About" section (See image) I want few lines to be displayed on the dashboard body when clicked on that tab. how could i possibly achieve it? I could successfully add href for the "contact" section.
Maybe I do not understand your question properly, but what about:
library(shiny)
library(shinydashboard)
header <- dashboardHeader()
sidebar <- dashboardSidebar(
sidebarMenu(
id = "tabs",
menuItem("About", icon = icon("info"), tabName = "about"),
menuItem("Contact", icon = icon("phone"), tabName = "contact")
)
)
)
body <- dashboardBody(
tabItems(
tabItem("about",
h1("About")),
tabItem("contact",
h1("Contact"))
)
)
shinyApp(
ui = dashboardPage(header, sidebar, body),
server = function(input, output) { }
)
When you click on About you get a new tab in the dashboardBody where you can display whatever you want.
Update
Based on your clarification you can use shinyjs to hide/show the relevant part:
library(shiny)
library(shinydashboard)
library(shinyjs)
header <- dashboardHeader()
sidebar <- dashboardSidebar(
sidebarMenu(
id = "tabs",
menuItem("About", icon = icon("info"), tabName = "about"),
menuItem("Contact", icon = icon("phone"), tabName = "contact")
)
)
)
body <- dashboardBody(
useShinyjs(),
fluidPage(
fluidRow(id = "mainContent",
column(12, h1("Main Content"))
),
hidden(fluidRow(id = "contact", h1("Contact Info")))
)
)
shinyApp(
ui = dashboardPage(header, sidebar, body),
server = function(input, output) {
observe({
if (input$tabs == "contact") {
hideElement("mainContent")
showElement("contact")
} else {
hideElement("contact")
showElement("mainContent")
}
})
}
)
When you now click on Contact the main part is hidden and the contact is shown. I have, however, the feeling that is a bit mis-using the idea of shinydashboard.
#thothal, it did not allow me to add as a comment coz of the length, hence posting my comment(below) as an answer.
I am sorry if I was unclear. However, your answer helped me partially. I have incorporated tabItems part in my dashboardBody section, as shown below:
dashboardBody(
fluidPage(
fluidRow(
column(12, div(dataTableOutput("dataTable")))
)
),
tabItems(
tabItem("About", h1("text to be displayed"))
)
)
but the "text to be displayed" shows up below the table.
What I want is, About section (when clicked) should display only the text and not the table. I understand this is just formatting of the code in dashboardBody section but I don't know how to do it.
Just to be more clear, my dashboard's section should display the datatable at all times and the about section when clicked should show up the text and not the datatable. I really hope this is clear. Thanks a ton for your help :)

daterangeinput without fluidpage in shiny dashboard

I have an issue while creating a shiny web app using semantic.dashboard library.
Below is the code for my app.
library(semantic.dashboard)
# Define UI
header <- dashboardHeader(
)
sidebar <- dashboardSidebar(
side = "left",
sidebarMenu(
menuItem(tabName = "overview", text = "Overview", icon = icon("home")),
menuItem(tabName = "analysis", text = "Analysis", icon = icon("chart bar"))
)
)
body <- dashboardBody(
dateRangeInput("datepicker", NULL, start = Sys.Date()-30, end = Sys.Date()-1)
)
tabItems(
tabItem(
tabName = "overview",
fluidRow(
)
),
tabItem(
tabName = "analysis",
fluidRow(
)
)
)
ui <- dashboardPage(
header,
sidebar,
body,
title = "My Dashboard",
theme = "lumen"
)
# Define server logic
server <- function(input, output, session) {
session$onSessionEnded(stopApp)
}
# Run the application
shinyApp(ui = ui, server = server)
The result is in the screenshot below:
The main problem is that the dates inside the daterangeinput widget are just like simple text inside textbox.
I can't click on them to change the dates.
Using fluidPage() would resolve the problem, but the whole web page isn't filled totally by the app (and for this app, responsiveness isn't really useful).
Below is the screenshot of the app when I use fluidPage(), you can see that there's so much space between the sidebar and the border, and beetween the sidebar and the body.
app with fluidPage()
I'd like to know if it's possible to use daterangeinput without using fluidPage() or, if not possible, know how to remove the padding between the border and the sidebar when using fluidPage.
Thanks in advance for your help.
Above example doesn't work because it uses bootstrap framework styles - contrary to shiny.semantic or semantic.dashboard packages.
Please check my PR to shiny.semantic package. I've implemented there simple date input with usage of semantic-ui components. You can also use it to create simple date range (added quick example in PR).

Rshiny - Disabling tabs / adding text to tabs

I have a problem with shiny tabs. I want to create a navigation page with two tabs. Right to them, I would like to insert some user's login details. There is no option "text" or other to insert a text in the navbarPage. But I created an additionnal tab instead:
library(shiny)
runApp(list(
ui = navbarPage(
title="My App",
tabPanel("tab1 title"),
tabPanel("tab2 title"),
tabPanel("User: Madzia")),
server = function(input, output) { }
))
It is OK like this, but I do not want the third tab to be "selectible": I want it to be disabled, so that we cannot click on it - the same as on "My App" text. Do you have any idea about how to handle this problem?
Thank you! Best, Madzia
You can achieve disabling a tab with a tiny bit of javascript. I have an example of how to hide a tab (not disable) in recent blog post, you can see the code for that here. I modified that code a bit for disabling instead.
This code is hacky because it was done in 2 minutes but will work for a basic use case
library(shiny)
library(shinyjs)
jscode <- '
shinyjs.init = function() {
$(".nav").on("click", ".disabled", function (e) {
e.preventDefault();
return false;
});
}
'
css <- '
.disabled {
background: #eee !important;
cursor: default !important;
color: black !important;
}
'
shinyApp(
ui = fluidPage(
useShinyjs(),
extendShinyjs(text = jscode, functions = "init"),
tags$style(css),
checkboxInput("foo", "Disable tab2", FALSE),
tabsetPanel(
id = "navbar",
tabPanel(title = "tab1",
value = "tab1",
h1("Tab 1")
),
tabPanel(title = "tab2",
value = "tab2",
h1("Tab 2")
),
tabPanel(title = "tab3",
value = "tab3",
h1("Tab 3")
)
)
),
server = function(input, output) {
observe({
toggleClass(condition = input$foo,
class = "disabled",
selector = "#navbar li a[data-value=tab2]")
})
}
)
Edit I didn't fully read the question when I posted my answer, I just saw that you wanted a way to disable a tab and that was my answer. Your specific usecase (creating a tab only to show the name of a user) is a bit strange, but I suppose this will still work...
I would like to keep my previous answer in existence because it may be useful for someone in the future who wants to know how to disable a tab.
But for this specific problem, disabling the tab is not the correct approach. It makes more sense to simply add text to the tab (as Valter pointed out in a comment). If you look at the documentation for bootstrap, it says you can add text into the navbar by adding an html element with class navbar-text. I experimented with the HTML a little bit to figure out exactly where this needs to be done, and created a little function that will wrap around navbarPage() to allow you to add text to it.
Here's an example:
library(shiny)
navbarPageWithText <- function(..., text) {
navbar <- navbarPage(...)
textEl <- tags$p(class = "navbar-text", text)
navbar[[3]][[1]]$children[[1]] <- htmltools::tagAppendChild(
navbar[[3]][[1]]$children[[1]], textEl)
navbar
}
ui <- navbarPageWithText(
"Test app",
tabPanel("tab1", "tab 1"),
tabPanel("tab2", "tab 2"),
text = "User: Dean"
)
server <- function(input, output, session) {
}
shinyApp(ui = ui, server = server)

Resources