appsilon / shiny.fluent Goto Github PK
View Code? Open in Web Editor NEWMicrosoft's Fluent UI for Shiny apps
Home Page: https://appsilon.github.io/shiny.fluent
Microsoft's Fluent UI for Shiny apps
Home Page: https://appsilon.github.io/shiny.fluent
Remove Fluent source map as it's not functional at the moment and it's taking too makes the package size > 5MB causing it to fail R CMD CHECK
It is relatively easy to render a CommandBar
with some buttons, but it's quite hard to actually connect them to Shiny, i.e. get click events. A natural idea is to use CommandBarButton.shinyInput
components, but it's not that simple. We should improve the example and/or think of some helpers / interface improvements to better support this use case.
In addition to just adding the component (#47), we might want to add some helper functions. It would would be great to have a Shiny app working like Fluent UI Theme Designer, which could be launched with themeDesigner() and used to export a config ready to be consumed by shiny.fluent.
Referring to the Shimmer()
progress indicator: https://developer.microsoft.com/en-us/fluentui#/controls/web/shimmer
section "Shimmered DetailsList simulating loading data asynchronously"
<ShimmeredDetailsList
setKey="items"
items={items || []}
columns={shimmerColumns}
selectionMode={SelectionMode.none}
onRenderItemColumn={onRenderItemColumn}
enableShimmer={!items}
ariaLabelForShimmer="Content is being fetched"
ariaLabelForGrid="Item details"
listProps={shimmeredDetailsListProps}
/>
how can i make the 'download' button in the command bar actually download something?
For Fluent UI icons to work, initializeIcons()
must be called before any components are rendered. Currently we call it here without providing any arguments - this way a default CDN is used. As a result, the icons won't work without access to that CDN, e.g. offline or behind a firewall.
I see two ways to overcome it:
The issue tracker is not for questions. If you have a question or provide general feedback, we'd love to hear it and help! Please go to https://github.com/Appsilon/shiny.fluent/discussions and write it there.
Like the title said, limiting the height is what I want. This is how I attempted.
Dropdown.shinyInput(NS(id, "metro"), placeHolder = "Select a metro", multiSelect = TRUE, dropdownItemsWrapper = list(
maxHeight = "320px", overflowY = "auto"), options = metro_options)
Tried to implement the valueBox
and infoBox
under current fluidPage
, but they behaved very weirdly.
if (interactive()) {
library(shiny)
library(semantic.dashboard)
library(shiny.fluent)
ui <- fluidPage(
dashboardHeader(title = "Dynamic boxes"),
dashboardSidebar(),
dashboardBody(
fluidRow(
box(width = 2, actionButton("count", "Count")),
infoBoxOutput("ibox"),
valueBoxOutput("vbox")
)
)
)
server <- function(input, output) {
output$ibox <- renderInfoBox({
infoBox(
"Title",
input$count,
icon = icon("credit-card")
)
})
output$vbox <- renderValueBox({
valueBox(
"Title",
input$count,
icon = icon("credit-card")
)
})
}
shinyApp(ui, server)
}
CI breaks due to not being able to install shiny.react
Push to repository
CI successfully passing
In shiny.fluent JS test
workflow Install dependencies
step fails with error:
Run remotes::install_github("Appsilon/shiny.react")
Using bundled GitHub PAT. Please add your own PAT to the env varGITHUB_PAT
Error: Error: Failed to install 'unknown package' from GitHub:
cannot open URL 'https://api.github.com/repos/Appsilon/shiny.react/contents/DESCRIPTION?ref=HEAD'
Execution halted
Error: Process completed with exit code 1.
Example will not run on latest versions of shiny.fluent/shiny.react
Add a minimal example that shows the issue (we recommend using the https://reprex.tidyverse.org/ package).
shiny.fluent::runExample("demo")
shiny.fluent::runExample("dashboard")
# Error in router$ui : object of type 'closure' is not subsettable
Example runs.
Example does not run.
Place for any additional details that you would like to include.
Such a wrapper could provide an easy access to selected rows in a similar way to how DT does it. See discussion for a partial solution.
Ensure that R CMD check --as-cran
passes without any errors, warnings or notes. Update CI to fail on notes (currently it only fails on errors).
Depends on Appsilon/shiny.react#17. All .shinyInput
wrappers should be debounced/throttled to mimic their counterparts in vanilla Shiny. It seems that Shiny uses either no rate limiting (e.g. buttons, checkboxes, dropdowns) or a debounce of 250 ms (e.g. text fields, sliders).
Workaround for PrimaryButton() as a download button
Great package, very impressive.
While walking through the tutorials I noticed that there was a missing code chunk in the st-sales-reps-dashboard article at the bottom for the router-server
code chunk:
To fix the issue, I adjusted the code in inst/examples/tutorial/dashboard_layout.R line 299/300, replacing
server <- function(input, output, session) {
# ---- server-router ----
router$server(input, output, session)
# ---- server-rest ----
filtered_deals <- reactive({
with
server <- function(input, output, session) {
# ---- router-server ----
router$server(input, output, session)
# ---- server-rest ----
filtered_deals <- reactive({
Notice that I replaced # ---- server-router ----
with # ---- router-server ----
and removed the spacing for the section heading so that the vignette, st-sales-reps-dashboard.Rmd can now pickup the proper code chunk (see line 216).
Now the vignette renders properly and displays the router-server
code chunk accordingly.
To demonstrate I re-deployed the gh-pages in my fork and you can see the result here: https://jimbrig.github.io/shiny.fluent/articles/st-sales-reps-dashboard.html.
Thanks again for the great package!
preferably with an example showing;
Currently the documentation only shows example for 1 selection at a time.
You guys are the best!
Thanks,
Matt
Add support for a shiny.fluent
component that allows users to upload a file; similar to shiny::fileInput()
.
Firstly, thanks to the developers for creating shiny.fluent
. While I've been unable to use the library to its fullest just yet, I'm excited to begin developing with it once I've overcome some hurdles I've outlined below. I hope these comments can be viewed as constructive criticism on improving the tutorial, rather than a complaint!
I have spent some time this week going through the shiny.fluent
tutorial. I'm a reasonably experienced R developer but found it difficult to follow. I think this is because there's lots of 'replace' and 'now let's just add' parts of the tutorial which do not explicitly say what users are supposed to replace or where new code chunks should be added. In addition, the lack of cumulative code blocks makes it very difficult to determine whether the user's script it on parity with the tutorial.
For example in Tutorial 1 we need to add some data to the app. However, users aren't told where to add the code to process the data. For experienced R/Shiny developers, it's reasonably straightforward to work out that this should perhaps live outside the ui
and server
elements, but this is not mentioned in the text. It would be possible to also wrap the data loading into a reactive within server
, leading to confusion on the best place to locate this code. To the best of my knowledge, the tutorial does not link to the accompanying tutorials files so it's left to the user to attempt to work out what's supposed to go where, which is made difficult without clear instruction. Similarly, the tutorial does not explicitly say where the app's filters should live (again outside of ui
and server
but this is not explicitly defined; a reasonable alternative place to locate the filter code could be within ui
). While most users of shiny.fluent
are no doubt reasonably competent Shiny developers, I still think the tutorial would benefit greatly from being clearer for all skill levels.
I think an easy way to fix this particular issue would be to show cumulative code chunks in the tutorial, rather than just showing the new piece of code without saying where it needs to go in the script file.
Finally, in the tutorial code directory there is a script called dashboard_layout.R
. In there there are multiple ui
and server
elements (e.g. for server here and here). Again, I was not able to find an explanation in the tutorial text as to why two server instances are defined. Is it one for each page in the dashboard? Or is this a mistake in the code?
If I pull out dashboard_layout.R
into a new Shiny project--copying the www
folder in the process so I have the CSS and logo--I cannot get the page to render correctly in Chrome (see screenshot below). At present, I can't figure out why. I suspect it's because of multiple ui
and server
elements, but I can't be sure just yet. Is anyone able to confirm whether dashboard_layout.R
is fully reproducible? Or does the end user need to make some tweaks to this script in order to get the page to render correctly?
there doesn't appear to be anyway that clicking the button can cause a reactive or observed event. Are these shiny.fluent command icons just for looks? are they actually usable?
could you provide an example please?
Thanks!
Matt
[email protected]
as maintainer email.Slider.shinyInput
with ranged = TRUE
only returns the upper value selected. Instead, it should return a vector of two values (lower, upper) when ranged = TRUE
.
You can use the raw React interface to access both lower and upper value:
library(shiny)
library(shiny.fluent)
shinyApp(
ui = Slider(onChange = setInput("slider", 2), ranged = TRUE),
server = function(input, output) {
observe(dput(input$slider))
}
)
Add a short problem description here.
shiny.fluent
Enable source maps
or similar option is enabled in the browsershiny-fluent.js
in Sources tabA non-minified script is shown
A minified script is shown
When value = NULL
is passed to Calendar.shinyInput
or DatePicker.shinyInput
, they use the current date in the browser, but start with a NULL
value when accessed in Shiny (input$
). In contrast, e.g. shiny::dateInput()
uses current day if given value = NULL
.
When using Dropdown()
or updateDropdown()
with multiSelect = TRUE
, users are unable to select/click items.
updateDropdown(session = session, input_id = "equipment",
label = "Select Desired Equipment", placeholder = "Select an option...",
options = y, styles = list(root = list(width = "10vw"),
dropdownItemsWrapper = list(`max-height` = "400px", overflow = "auto")),
multiSelect = TRUE, disabled = FALSE)
I found the following error message when I try to run components example to view the html code it produces, eg CommandBar
& FontIcon
Error in writeImpl(text) :
Text to be written must be a length-one character vector
In addition: Warning message:
In if (!is.na(attribValue)) { :
the condition has length > 1 and only the first element will be used
library(shiny)
library(shiny.fluent)
# CommandBar code in "demo" example
CommandBar(
items = list(
CommandBarItem("New", "Add", subitems = list(
CommandBarItem("Email message", "Mail", key = "emailMessage", href = "mailto:[email protected]"),
CommandBarItem("Calendar event", "Calendar", key = "calendarEvent")
)),
CommandBarItem("Upload sales plan", "Upload"),
CommandBarItem("Share analysis", "Share"),
CommandBarItem("Download report", "Download")
),
farItems = list(
CommandBarItem("Grid view", "Tiles", iconOnly = TRUE),
CommandBarItem("Info", "Info", iconOnly = TRUE)
),
style = list(width = "100%"))
#> Warning in if (!is.na(attribValue)) {: the condition has length > 1 and only the
#> first element will be used
#> Error in writeImpl(text): Text to be written must be a length-one character vector
# FontIcon code in function example
style <- list(fontSize = 50, margin = 10)
tags$div(
FontIcon(iconName = "CompassNW", style = style),
FontIcon(iconName = "Dictionary", style = style),
FontIcon(iconName = "TrainSolid", style = style)
)
#> Warning in if (!is.na(attribValue)) {: the condition has length > 1 and only the
#> first element will be used
#> Error in writeImpl(text): Text to be written must be a length-one character vector
Created on 2021-04-14 by the reprex package (v2.0.0)
It should print the html code it produces in the app
An unexpected error...
I think the root cause of this issue is in htmltools WSTextWriter, should be closed after that issue solved. Just leave a record here, in case anyone encounter same problem
As great as shiny.fluent is, it does not have dynamic response at the moment.
This is the app on a large screen.
The same app on a smaller screen.
The navbar width, font-sizes etc. are the same in both screens.
As far as I understand, it is not dynamic to screen sizes yet.
Will this feature be added in the near future to make the excellent fluent app dynamic to all screen sizes, including mobile screens?
We need functions like updatePrimaryButton.shinyInput()
for all shiny.fluent buttons. This is dependent on Appsilon/shiny.react#12.
I am trying to reproduce 02_basic_app.R
located here. However, dates are not displaying in the correct format, meaning that the date filters do not work.
Screenshot of dates incorrectly rendered on latest version of Chrome:
I'm running the following package versions on R v4.0.5:
shiny 1.7.1
shiny.fluent 0.2.1
shiny.router 0.2.2
EDIT - Here's my full sessionInfo()
R version 4.0.5 (2021-03-31)
Platform: x86_64-apple-darwin13.4.0 (64-bit)
Running under: macOS 12.0.1
Matrix products: default
LAPACK: /opt/homebrew/Caskroom/miniconda/base/envs/renv/lib/libopenblasp-r0.3.18.dylib
locale:
[1] en_GB.UTF-8/en_GB.UTF-8/en_GB.UTF-8/C/en_GB.UTF-8/en_GB.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] shiny.router_0.2.2 shiny.fluent_0.2.1 shiny_1.7.1 sass_0.4.0 plotly_4.10.0 leaflet_2.0.4.1 glue_1.5.0
[8] ggplot2_3.3.5 dplyr_1.0.7
loaded via a namespace (and not attached):
[1] tidyselect_1.1.1 bslib_0.3.1 purrr_0.3.4 colorspace_2.0-2 vctrs_0.3.8
[6] generics_0.1.1 leaflet.providers_1.9.0 htmltools_0.5.2 viridisLite_0.4.0 yaml_2.2.1
[11] utf8_1.2.2 rlang_0.4.12 later_1.3.0 pillar_1.6.4 jquerylib_0.1.4
[16] withr_2.4.2 DBI_1.1.1 lifecycle_1.0.1 munsell_0.5.0 gtable_0.3.0
[21] htmlwidgets_1.5.4 labeling_0.4.2 fastmap_1.1.0 httpuv_1.6.3 crosstalk_1.2.0
[26] fansi_0.5.0 shiny.react_0.2.3 Rcpp_1.0.7 xtable_1.8-4 promises_1.2.0.1
[31] scales_1.1.1 cachem_1.0.6 jsonlite_1.7.2 mime_0.12 digest_0.6.28
[36] grid_4.0.5 cli_3.1.0 tools_4.0.5 magrittr_2.0.1 logger_0.2.2
[41] lazyeval_0.2.2 tibble_3.1.6 crayon_1.4.2 tidyr_1.1.4 pkgconfig_2.0.3
[46] ellipsis_0.3.2 data.table_1.14.2 rstudioapi_0.13 assertthat_0.2.1 httr_1.4.2
[51] R6_2.5.1 compiler_4.0.5
I try to formatting detailslist in Shiny Fluent. For example, except first column I want to make columns right alligment. Also, I try to add comma separator for thousands and % as prefix for first column.
Any idea?
updateNormalPeoplePicker.shinyInput()
does not work like other update*()
functions.
Browser returns javascript errror
react-dom.production.min.js:56 Uncaught TypeError: o.options.filter is not a function
at onEmptyInputFocus (inputs.jsx:55)
at t.onEmptyInputFocus (BasePicker.tsx:443)
at t.n._userTriggeredSuggestions (BasePicker.tsx:983)
at n.onInputFocus (BasePicker.tsx:549)
at Object.vi (react-dom.production.min.js:202)
at ui (react-dom.production.min.js:32)
at xi (react-dom.production.min.js:32)
at zg (react-dom.production.min.js:55)
at rg (react-dom.production.min.js:56)
at react-dom.production.min.js:66
updateNormalPeoplePicker.shinyInput(
inputId = ns("users"),
options = tibble::tribble(
~key, ~imageInitials, ~text, ~secondaryText,
"KP", "KP", "KYLE POWER", "KYLE"
)
)
Unable to update or alter component elements, specifically to remove previously selected items.
Our showcase dashboard (directory, deployed) lists all available components along with usage examples in R. Unfortunately the examples are not loaded from the files in the inst/examples
directory, but from the inst/examples/dashboard/examples.R
file which needs to be manually kept in sync. It is a big maintenance burden.
The same problem is nicely solved in appsilon.blueprint: the showcase there actually reads the example files. We need to do something similar in shiny.fluent.
Please split the implementation into two (or more) PRs:
inst/examples
into the format needed (assuming we'll follow the appsilon.blueprint approach - consult with reviewer if you have a different idea).inst/examples/dashboard
to actually load the example files.inst/examples
, so that a change to e.g. Button.R
is reflected in the dashboard without additional changes.Referring to Microsoft FluentUI documentation: https://developer.microsoft.com/en-us/fluentui#/controls/web/datepicker
Currently, DatePicker.shinyInput()
defaults to a value of current date if not specified. I am not able to use the placeholder
argument to fill with text. Always defaults to current date of system.
I would like the DatePicker to have null
value with text string "Select a date..."
Take the following app:
library(shiny)
library(shiny.fluent)
library(tibble)
options1 <- tibble(key = c(1, 2), text = c("A", "B"))
options2 <- tibble(key = c(3, 4), text = c("C", "D"))
ui <- fluentPage(
PrimaryButton.shinyInput("button1", "Update Dropdown1"),
Dropdown.shinyInput("dropdown1", value = 1, options = options1),
PrimaryButton.shinyInput("button2", "Update Dropdown2"),
uiOutput("dropdown2")
)
server <- function(input, output, session) {
dropdown2 <- reactiveVal(
Dropdown.shinyInput("dropdown2", value = 1, options = options1)
)
observeEvent(input$button1, {
updateDropdown.shinyInput(session, "dropdown1", value = 3, options = options2)
})
observeEvent(input$button2, {
dropdown2(Dropdown.shinyInput("dropdown2", value = 3, options = options2))
})
output$dropdown2 <- renderUI({
dropdown2()
})
}
shinyApp(ui, server)
Using "Update Dropdown1" button crashes the dropdown with a RangeError: Invalid array length
exception in the JS console. Replacing the tibbles with lists like so:
options1 <- list(
list(key = 1, text = "A"),
list(key = 2, text = "B")
)
options2 <- list(
list(key = 3, text = "C"),
list(key = 4, text = "D")
)
Fixes the problem.
The props should work the same way regardless of whether they were passed to a component directly or via an update function. In this case, tibble works in the first case, but not in the second one. We want consistency: either both cases fail (in a way that's easy to debug for the user), or both cases work (preferable).
The components are very similar in visual appearance, but their values are accessed differently in the server - perhaps we should unify it?
The best approach will be probably to add support for "nested" components to shiny.react. Another possibility would be to inject such components into the top level with a changed name (like StackItem
), but that's likely to be less maintainable long term. See discussion for more info.
In header (commandBar) and sidebar (iconButtons), there are several icons/iconButtons that don't do anything
Add a task or place them in the corresponding example pages.
Fluent UI defines several enums which are used as props for various components. Using them in shiny.fluent requires checking the documentation to find the desired numeric value. It would be helpful to include enum definitions in the package - for example the SelectionMode
enum can have an equivalent in form of an R list list(multiple = 2, none = 0, single = 1)
.
How do we ensure this is up to date? A script which auto-generates R code?
Message from Hadley:
Your package, shiny.fluent, lists the tidyverse in either Depends,
Imports, or Suggests in the DESCRIPTION file. This is a bad idea because,
in short, the tidyverse is a set of packages designed for interactive data
analysis, and it includes a very large number (>80) of direct and indirect
dependencies, most of which your package probably doesn't use.Instead of depending on the entire tidyverse, please import from, suggest,
or depend on the packages in the tidyverse that you actually use. This
will make your package faster to install and will head off potential
problems down the road.
Replace the dependency on tidyverse
in DESCRIPTION
with the specific packages we need. Update all references to tidyverse
in our code and examples (e.g. library(tidyverse)
, tidyverse::
).
It is possible to use multiSelect = TRUE
with the bare React Dropdown
component, but it is rather difficult. We should add support for multiSelect = TRUE
to the Dropdown.shinyInput
convenience wrapper - currently it doesn't work. First reported in #29.
Update our Open Source Analytics app to include shiny.react & shiny.fluent.
Perhaps we want to not only track GitHub stars, but also usage?
Integrate shiny.i18n
with sales dashboard demo
Run shiny.fluent::runExample("006_leaflet_and_dt_in_react")
and check the JS console in the browser. Leaflet throws errors, which is a problem if we want to merge this app into the E2E tests app. It might be helpful to check if Leaflet was throwing errors with shiny.react 0.1.0 too (prior to core rewrite) and compare the differences.
Thanks for this awesome package!
However, when I use the function DatePicker.shinyInput()
to input date, i found the output not always equals to what I input. I then learned the reference of DatePicker.shinyInput()
,ran the example it provided,but still got the incorrect output.
Eg: I pick "2022-10-28", but get "2022-10-27".
library(shiny.fluent)
if (interactive()) {
shinyApp(
ui = div(
DatePicker.shinyInput("date", value = "2020-06-25T22:00:00.000Z"),
textOutput("dateValue"),
h3("If `value` is missing, default to system date"),
DatePicker.shinyInput("date2"),
textOutput("dateDefault"),
h3("If `value` is NULL, return NULL"),
DatePicker.shinyInput("date3", value = NULL, placeholder = "I am placeholder!"),
textOutput("dateNull")
),
server = function(input, output) {
output$dateValue <- renderText({
sprintf("Value: %s", input$date)
})
output$dateDefault <- renderText({
sprintf("Value: %s", input$date2)
})
output$dateNull <- renderText({
sprintf("Value: %s", deparse(input$date3))
})
}
)
}
There is a POC of ThemeProvider
usage on branch kamil.theme-provider
. An example of how to use the component should be added as well.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.