diff --git a/NAMESPACE b/NAMESPACE index e48d07c..fa57e3b 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -41,7 +41,9 @@ importFrom(billboarder,billboarderOutput) importFrom(billboarder,renderBillboarder) importFrom(htmltools,HTML) importFrom(htmltools,doRenderTags) +importFrom(htmltools,htmlDependency) importFrom(htmltools,singleton) +importFrom(htmltools,tagAppendAttributes) importFrom(htmltools,tagList) importFrom(htmltools,tags) importFrom(openssl,aes_cbc_decrypt) diff --git a/R/fab_button.R b/R/fab_button.R index 38cf6eb..b2a67f2 100644 --- a/R/fab_button.R +++ b/R/fab_button.R @@ -1,95 +1,112 @@ #' @title Create a FAB button #' -#' @description Create a fixed button in bottom right corner with additional button(s) in it +#' @description Create a fixed button in page corner with additional button(s) in it #' -#' @param ... HTML tags 'a' or 'button' or \code{actionButton} (with \code{NULL} labels). +#' @param ... \code{actionButton}s to be used as floating buttons. +#' @param position Position for the button. +#' @param animation Animation when displaying floating buttons. +#' @param toggle Display floating buttons when main button is clicked or hovered. #' @param inputId Id for the FAB button (act like an \code{actionButton}). -#' @param icon An \code{icon} for the main button. -#' @param status Bootstra^p status to apply to the main button. +#' @param label Label for main button. #' #' @export #' #' @importFrom shiny icon -#' @importFrom htmltools tagList singleton tags -#' -#' @examples -#' if (interactive()) { -#' library(shiny) -#' library(shinymanager) -#' -#' ui <- fluidPage( -#' -#' tags$h1("FAB button"), -#' -#' tags$p("FAB button:"), -#' verbatimTextOutput(outputId = "res_fab"), -#' -#' tags$p("Logout button:"), -#' verbatimTextOutput(outputId = "res_logout"), -#' -#' tags$p("Info button:"), -#' verbatimTextOutput(outputId = "res_info"), -#' -#' fab_button( -#' actionButton( -#' inputId = "logout", -#' label = NULL, -#' tooltip = "Logout", -#' icon = icon("sign-out") -#' ), -#' actionButton( -#' inputId = "info", -#' label = NULL, -#' tooltip = "Information", -#' icon = icon("info") -#' ), -#' inputId = "fab" -#' ) -#' -#' ) -#' -#' server <- function(input, output, session) { -#' -#' output$res_fab <- renderPrint({ -#' input$fab -#' }) -#' -#' output$res_logout <- renderPrint({ -#' input$logout -#' }) -#' -#' output$res_info <- renderPrint({ -#' input$info -#' }) -#' -#' } -#' -#' shinyApp(ui, server) -#' } -fab_button <- function(..., inputId = NULL, icon = NULL, status = "default") { - if (is.null(icon)) - icon <- icon("plus fa-lg") +#' @importFrom htmltools tagList tags tagAppendAttributes +#' +#' @example examples/fab_button.R +fab_button <- function(..., + position = c("bottom-right", "top-right", "bottom-left", "top-left"), + animation = c("slidein", "slidein-spring", "fountain", "zoomin"), + toggle = c("hover", "click"), + inputId = NULL, + label = NULL) { args <- list(...) - for (i in seq_along(args)) { - if (!is.null(args[[i]]$attribs$class)) { - args[[i]]$attribs$class <- paste(args[[i]]$attribs$class, "buttons-fab") - } else { - args[[i]]$attribs$class <- "buttons-fab" - } + if (!is.null(args$status)) { + warning("fab_button: status argument is deprecated.", call. = FALSE) + args$status <- NULL + } + if (!is.null(args$icon)) { + warning("fab_button: icon argument is deprecated.", call. = FALSE) + args$icon <- NULL } + toggle <- match.arg(toggle) + animation <- match.arg(animation) + position <- match.arg(position) + position <- switch( + position, + "bottom-right" = "br", + "top-right" = "tr", + "bottom-left" = "bl", + "top-left" = "tl" + ) tagList( - htmltools::singleton( - tags$head( - tags$link(rel = "stylesheet", type = "text/css", href = "shinymanager/fab-button.css") + tags$ul( + class = paste("mfb-component", position, sep = "--"), + class = paste("mfb", animation, sep = "-"), + `data-mfb-toggle` = toggle, + tags$li( + class = "mfb-component__wrap", + tags$a( + id = inputId, + `data-mfb-label` = label, + class = "mfb-component__button--main action-button", + icon("plus", class = "mfb-component__main-icon--resting"), + icon("close", class = "mfb-component__main-icon--active") + ), + tags$ul( + class = "mfb-component__list", + lapply( + X = args, + FUN = function(x) { + if (inherits(x, "list")) { + id <- x$inputId + label <- x$label + tagIcon <- x$icon + } else if (inherits(x, "shiny.tag")) { + id <- x$attribs$id + label <- x$children[[1]][[2]] + tagIcon <- x$children[[1]][[1]] + } else { + stop("Arguments in `...` must be lists or actionButtons") + } + if (!is.null(tagIcon) && inherits(tagIcon, "shiny.tag")) { + tagIcon <- htmltools::tagAppendAttributes( + tagIcon, + class = "mfb-component__child-icon" + ) + } + tags$li( + tags$a( + `data-mfb-label` = label, + id = id, + class = "mfb-component__button--child action-button", + tagIcon + ) + ) + } + ) + ) ) ), - tags$nav( - class = "container-fab", args, - tags$button( - class = paste0("btn btn-", status, " buttons-fab btn-fab-main action-button"), - id = inputId, icon - ) - ) + html_dependency_fab() ) } + + +#' @importFrom htmltools htmlDependency +html_dependency_fab <- function() { + htmlDependency( + name = "fab-button", + version = "0.3.7", + src = c( + href = "shinymanager/fab-button", + file = "assets/fab-button" + ), + package = "shinymanager", + stylesheet = "fab-button.min.css", + all_files = FALSE + ) +} + diff --git a/R/secure-app.R b/R/secure-app.R index 00aa801..b4f902b 100644 --- a/R/secure-app.R +++ b/R/secure-app.R @@ -11,6 +11,7 @@ #' you can use themes provided by \code{shinythemes}. #' It will affect the authentication panel and the admin page. #' @param language Language to use for labels, supported values are : "en", "fr", "pt-BR". +#' @param fab_position Position for the FAB button, see \code{\link{fab_button}} for options. #' #' @note A special input value will be accessible server-side with \code{input$shinymanager_where} #' to know in which step user is : authentication, application, admin or password. @@ -25,12 +26,18 @@ #' @name secure-app #' #' @example examples/secure_app.R -secure_app <- function(ui, ..., enable_admin = FALSE, head_auth = NULL, theme = NULL, language = "en") { +secure_app <- function(ui, + ..., + enable_admin = FALSE, + head_auth = NULL, + theme = NULL, + language = "en", + fab_position = "bottom-right") { if (!language %in% c("en", "fr", "pt-BR")) { warning("Only supported language for the now are: en, fr, pt-BR", call. = FALSE) language <- "en" } - + lan <- use_language(language) ui <- force(ui) enable_admin <- force(enable_admin) @@ -38,7 +45,7 @@ secure_app <- function(ui, ..., enable_admin = FALSE, head_auth = NULL, theme = if (is.null(theme)) { theme <- "shinymanager/css/readable.min.css" } - + function(request) { query <- parseQueryString(request$QUERY_STRING) token <- query$token @@ -69,19 +76,18 @@ secure_app <- function(ui, ..., enable_admin = FALSE, head_auth = NULL, theme = header = tagList( tags$style(".navbar-header {margin-left: 16.66% !important;}"), fab_button( + position = fab_position, actionButton( inputId = ".shinymanager_logout", - label = NULL, - tooltip = lan$get("Logout"), + label = lan$get("Logout"), icon = icon("sign-out") ), actionButton( inputId = ".shinymanager_app", - label = NULL, - tooltip = lan$get("Go to application"), + label = lan$get("Go to application"), icon = icon("share") ) - ), + ), shinymanager_where("admin") ), tabPanel( @@ -99,16 +105,15 @@ secure_app <- function(ui, ..., enable_admin = FALSE, head_auth = NULL, theme = } else { if (isTRUE(enable_admin) && .tok$is_admin(token) && !is.null(.tok$get_sqlite_path())) { menu <- fab_button( + position = fab_position, actionButton( inputId = ".shinymanager_logout", - label = NULL, - tooltip = lan$get("Logout"), + label = lan$get("Logout"), icon = icon("sign-out") ), actionButton( inputId = ".shinymanager_admin", - label = NULL, - tooltip = lan$get("Administrator mode"), + label = lan$get("Administrator mode"), icon = icon("cogs") ) ) @@ -117,10 +122,10 @@ secure_app <- function(ui, ..., enable_admin = FALSE, head_auth = NULL, theme = warning("Admin mode is only available when using a SQLite database!", call. = FALSE) } menu <- fab_button( + position = fab_position, actionButton( inputId = ".shinymanager_logout", - label = NULL, - tooltip = lan$get("Logout"), + label = lan$get("Logout"), icon = icon("sign-out") ) ) @@ -167,42 +172,42 @@ secure_app <- function(ui, ..., enable_admin = FALSE, head_auth = NULL, theme = #' @param max_users \code{integer}. If not NULL, maximum of users in sql credentials. #' @param fileEncoding character string: Encoding of logs downloaded file. See \code{\link{write.table}} #' @param session Shiny session. -#' -#' @details -#' -#' If database credentials, you can configure inputs with \code{inputs_list} for editing users information -#' from the admin console. \code{start}, \code{expire}, \code{admin} and \code{password} are not configurable. +#' +#' @details +#' +#' If database credentials, you can configure inputs with \code{inputs_list} for editing users information +#' from the admin console. \code{start}, \code{expire}, \code{admin} and \code{password} are not configurable. #' The others columns are rendering by defaut using a \code{textInput}. You can modify this using \code{inputs_list}. #' \code{inputs_list} must be a named list. Each name must be a column name, and then we must have the function -#' shiny to call \code{fun} and the arguments \code{args} like this : +#' shiny to call \code{fun} and the arguments \code{args} like this : #' \code{ #' list(group = list( -#' fun = "selectInput", +#' fun = "selectInput", #' args = list( -#' choices = c("all", "restricted"), -#' multiple = TRUE, +#' choices = c("all", "restricted"), +#' multiple = TRUE, #' selected = c("all", "restricted") #' ) #' ) #' ) #' } -#' +#' #' @export #' #' @importFrom shiny callModule getQueryString parseQueryString #' updateQueryString observe getDefaultReactiveDomain isolate invalidateLater #' #' @rdname secure-app -secure_server <- function(check_credentials, - timeout = 15, +secure_server <- function(check_credentials, + timeout = 15, inputs_list = NULL, max_users = NULL, fileEncoding = "", session = shiny::getDefaultReactiveDomain()) { - + isolate(resetQueryString(session = session)) token_start <- isolate(getToken(session = session)) - + lan <- reactiveVal(use_language()) observe({ lang <- getLanguage(session = session) @@ -210,34 +215,34 @@ secure_server <- function(check_credentials, lan(use_language(lang)) } }) - + callModule( module = auth_server, id = "auth", check_credentials = check_credentials, - use_token = TRUE, + use_token = TRUE, lan = lan ) - + callModule( module = pwd_server, id = "password", user = reactiveValues(user = .tok$get(token_start)$user), update_pwd = update_pwd, - use_token = TRUE, + use_token = TRUE, lan = lan ) - + .tok$set_timeout(timeout) - + path_sqlite <- .tok$get_sqlite_path() if (!is.null(path_sqlite)) { callModule( module = admin, id = "admin", sqlite_path = path_sqlite, - passphrase = .tok$get_passphrase(), - inputs_list = inputs_list, + passphrase = .tok$get_passphrase(), + inputs_list = inputs_list, max_users = max_users, lan = lan ) @@ -245,14 +250,14 @@ secure_server <- function(check_credentials, module = logs, id = "logs", sqlite_path = path_sqlite, - passphrase = .tok$get_passphrase(), - fileEncoding = fileEncoding, + passphrase = .tok$get_passphrase(), + fileEncoding = fileEncoding, lan = lan ) } - + user_info_rv <- reactiveValues() - + observe({ token <- getToken(session = session) if (!is.null(token)) { @@ -272,21 +277,21 @@ secure_server <- function(check_credentials, } } }) - + observeEvent(session$input$.shinymanager_admin, { token <- getToken(session = session) updateQueryString(queryString = sprintf("?token=%s&admin=true&language=%s", token, lan()$get_language()), session = session, mode = "replace") .tok$reset_count(token) session$reload() }, ignoreInit = TRUE) - + observeEvent(session$input$.shinymanager_app, { token <- getToken(session = session) updateQueryString(queryString = sprintf("?token=%s&language=%s", token, lan()$get_language()), session = session, mode = "replace") .tok$reset_count(token) session$reload() }, ignoreInit = TRUE) - + observeEvent(session$input$.shinymanager_logout, { token <- getToken(session = session) logout_logs(token) @@ -294,11 +299,11 @@ secure_server <- function(check_credentials, clearQueryString(session = session) session$reload() }, ignoreInit = TRUE) - - - + + + if (timeout > 0) { - + observeEvent(session$input$.shinymanager_timeout, { token <- getToken(session = session) if (!is.null(token)) { @@ -310,7 +315,7 @@ secure_server <- function(check_credentials, } } }) - + observe({ invalidateLater(30000, session) token <- getToken(session = session) @@ -323,9 +328,9 @@ secure_server <- function(check_credentials, } } }) - + } - + return(user_info_rv) } diff --git a/examples/fab_button.R b/examples/fab_button.R new file mode 100644 index 0000000..ddf81a2 --- /dev/null +++ b/examples/fab_button.R @@ -0,0 +1,51 @@ +library(shiny) +library(shinymanager) + +ui <- fluidPage( + + tags$h1("FAB button"), + + tags$p("FAB button:"), + verbatimTextOutput(outputId = "res_fab"), + + tags$p("Logout button:"), + verbatimTextOutput(outputId = "res_logout"), + + tags$p("Info button:"), + verbatimTextOutput(outputId = "res_info"), + + fab_button( + actionButton( + inputId = "logout", + label = "Logout", + icon = icon("sign-out") + ), + actionButton( + inputId = "info", + label = "Information", + icon = icon("info") + ), + inputId = "fab" + ) + +) + +server <- function(input, output, session) { + + output$res_fab <- renderPrint({ + input$fab + }) + + output$res_logout <- renderPrint({ + input$logout + }) + + output$res_info <- renderPrint({ + input$info + }) + +} + +if (interactive()) { + shinyApp(ui, server) +} diff --git a/inst/assets/fab-button.css b/inst/assets/fab-button.css deleted file mode 100644 index afad8ee..0000000 --- a/inst/assets/fab-button.css +++ /dev/null @@ -1,119 +0,0 @@ - - -/* http://codepen.io/koenigsegg1/pen/pjeJvb */ - - - -.container-fab { - bottom: 0; - position: fixed; - margin: 1em; - right: 0; - z-index: 99999; -} - -.buttons-fab { - border-radius: 50%; - display: block; - width: 48px; - height: 48px; - margin: 20px auto 0; - position: relative; - -webkit-transition: all .1s ease-out; - transition: all .1s ease-out; -} - -.buttons-fab:active, -.buttons-fab:focus, -.buttons-fab:hover { - box-shadow: 0 0 4px rgba(0,0,0,.14), - 0 4px 8px rgba(0,0,0,.28); - -webkit-transform: rotate(45deg); - -moz-transform: rotate(45deg); - -ms-transform: rotate(45deg); - -o-transform: rotate(45deg); - transform: rotate(45deg); -} - -.buttons-fab:not(:last-child) { - width: 40px; - height: 40px; - margin: 20px auto 0; - opacity: 0; - -webkit-transform: translateY(50px); - -ms-transform: translateY(50px); - transform: translateY(50px); -} - -.container-fab:hover -.buttons-fab:not(:last-child) { - opacity: 1; - -webkit-transform: none; - -ms-transform: none; - transform: none; - margin: 15px auto 0; -} - -/* Unessential styling for sliding up buttons-fab at differnt speeds */ - -/* -.buttons-fab:nth-last-child(1) { - -webkit-transition-delay: 25ms; - transition-delay: 25ms; - background-image: url('http://cbwconline.com/IMG/Share.svg'); - background-size: contain; -} -*/ - -/* -.buttons-fab:not(:last-child):nth-last-child(2) { - -webkit-transition-delay: 50ms; - transition-delay: 20ms; - background-image: url('http://cbwconline.com/IMG/Facebook-Flat.png'); - background-size: contain; -} -*/ - -/* -.buttons-fab:not(:last-child):nth-last-child(3) { - -webkit-transition-delay: 75ms; - transition-delay: 40ms; - background-image: url('http://cbwconline.com/IMG/Twitter-Flat.png'); - background-size: contain; -} -*/ - -/* -.buttons-fab:not(:last-child):nth-last-child(4) { - -webkit-transition-delay: 100ms; - transition-delay: 60ms; - background-image: url('http://cbwconline.com/IMG/Google%20Plus.svg'); - background-size: contain; -} -*/ - -/* Show tooltip content on hover */ - -[tooltip]:before { - bottom: 25%; - font-family: arial; - font-weight: 600; - border-radius: 2px; - background: #585858; - color: #fff; - content: attr(tooltip); - font-size: 12px; - visibility: hidden; - opacity: 0; - padding: 5px 7px; - margin-right: 12px; - position: absolute; - right: 100%; - white-space: nowrap; -} - -[tooltip]:hover:before, -[tooltip]:hover:after { - visibility: visible; - opacity: 1; -} diff --git a/inst/assets/fab-button/_/_fountain.scss b/inst/assets/fab-button/_/_fountain.scss new file mode 100644 index 0000000..856b97e --- /dev/null +++ b/inst/assets/fab-button/_/_fountain.scss @@ -0,0 +1,77 @@ +@mixin effects-fountain{ + +/** + * FOUNTAIN + * When hovering the main button the child buttons + * jump into view from outside the viewport + */ + + .mfb-component--tl.mfb-fountain, + .mfb-component--tr.mfb-fountain{ + .mfb-component__list{ + li{ + -webkit-transform: scale(0); + transform: scale(0); + } + @for $i from 1 through $number-of-child-buttons { + $distance: -1 * $button-space * $i; + li:nth-child( #{$i} ) { + -webkit-transform: translateY($distance) scale(0); + transform: translateY($distance) scale(0); + transition: all $slide-speed; + // this is the delay at which the buttons start disappearing + transition-delay: ( $number-of-child-buttons - $i ) * 0.05s; + } + } + } + &[data-mfb-toggle="hover"]:hover, + &[data-mfb-state="open"]{ + .mfb-component__list{ + @for $i from 1 through $number-of-child-buttons { + $distance: $button-space * $i; + li:nth-child( #{$i} ) { + -webkit-transform: translateY($distance) scale(1); + transform: translateY($distance) scale(1); + // this is the delay at which the buttons appear + transition-delay: $i * 0.05s; + } + } + } + } + } + + .mfb-component--bl.mfb-fountain, + .mfb-component--br.mfb-fountain{ + .mfb-component__list{ + li{ + -webkit-transform: scale(0); + transform: scale(0); + } + @for $i from 1 through $number-of-child-buttons { + $distance: $button-space * $i; + li:nth-child( #{$i} ) { + -webkit-transform: translateY($distance) scale(0); + transform: translateY($distance) scale(0); + transition: all $slide-speed; + // this is the delay at which the buttons start disappearing + transition-delay: ( $number-of-child-buttons - $i ) * 0.05s; + } + } + } + &[data-mfb-toggle="hover"]:hover, + &[data-mfb-state="open"]{ + .mfb-component__list{ + @for $i from 1 through $number-of-child-buttons { + $distance: -1 * $button-space * $i; + li:nth-child( #{$i} ) { + -webkit-transform: translateY($distance) scale(1); + transform: translateY($distance) scale(1); + // this is the delay at which the buttons appear + transition-delay: $i * 0.05s; + } + } + } + } + } + +} diff --git a/inst/assets/fab-button/_/_slidein-spring.scss b/inst/assets/fab-button/_/_slidein-spring.scss new file mode 100644 index 0000000..7a08d72 --- /dev/null +++ b/inst/assets/fab-button/_/_slidein-spring.scss @@ -0,0 +1,67 @@ +@mixin effects-slidein-spring{ + +/** + * SLIDE IN SPRING + * Same as slide-in but with a springy animation. + * + */ + + .mfb-component--tl.mfb-slidein-spring, + .mfb-component--tr.mfb-slidein-spring{ + .mfb-component__list li{ + opacity: 0; + transition: all $slide-speed; + transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55); + } + @for $i from 1 through $number-of-child-buttons { + .mfb-component__list li:nth-child( #{$i} ) { + transition-delay: #{$i * 0.05}s; + } + } + &[data-mfb-toggle="hover"]:hover, + &[data-mfb-state="open"]{ + .mfb-component__list{ + li{ + opacity: 1; + } + @for $i from 1 through $number-of-child-buttons { + $distance: $button-space * $i; + li:nth-child( #{$i} ) { + transition-delay: #{$i * 0.05}s; + -webkit-transform: translateY( $distance ); + transform: translateY( $distance ); } + } + } + } + } + + .mfb-component--bl.mfb-slidein-spring, + .mfb-component--br.mfb-slidein-spring{ + .mfb-component__list li{ + opacity: 0; + transition: all $slide-speed; + transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55); + } + @for $i from 1 through $number-of-child-buttons { + .mfb-component__list li:nth-child( #{$i} ) { + transition-delay: #{$i * 0.05}s; + } + } + &[data-mfb-toggle="hover"]:hover, + &[data-mfb-state="open"]{ + .mfb-component__list{ + li{ + opacity: 1; + } + @for $i from 1 through $number-of-child-buttons { + $distance: -1 * $button-space * $i; + li:nth-child( #{$i} ) { + transition-delay: #{$i * 0.05}s; + -webkit-transform: translateY( $distance ); + transform: translateY( $distance ); } + } + } + } + } + +} diff --git a/inst/assets/fab-button/_/_slidein.scss b/inst/assets/fab-button/_/_slidein.scss new file mode 100644 index 0000000..879405d --- /dev/null +++ b/inst/assets/fab-button/_/_slidein.scss @@ -0,0 +1,53 @@ +@mixin effects-slidein{ + +/** + * SLIDE IN + FADE + * When hovering the main button, the child buttons slide out from beneath + * the main button while transitioning from transparent to opaque. + * + */ + + .mfb-component--tl.mfb-slidein, + .mfb-component--tr.mfb-slidein{ + .mfb-component__list li{ + opacity: 0; + transition: all $slide-speed; + } + &[data-mfb-toggle="hover"]:hover, + &[data-mfb-state="open"]{ + .mfb-component__list{ + li{ + opacity: 1; + } + @for $i from 1 through $number-of-child-buttons { + $distance: $button-space * $i; + li:nth-child( #{$i} ) { + -webkit-transform: translateY( $distance ); + transform: translateY( $distance ); } + } + } + } + } + + .mfb-component--bl.mfb-slidein, + .mfb-component--br.mfb-slidein{ + .mfb-component__list li{ + opacity: 0; + transition: all $slide-speed; + } + &[data-mfb-toggle="hover"]:hover, + &[data-mfb-state="open"]{ + .mfb-component__list{ + li{ + opacity: 1; + } + @for $i from 1 through $number-of-child-buttons { + $distance: -1 * $button-space * $i; + li:nth-child( #{$i} ) { -webkit-transform: translateY( $distance ); + transform: translateY( $distance ); } + } + } + } + } + +} diff --git a/inst/assets/fab-button/_/_zoomin.scss b/inst/assets/fab-button/_/_zoomin.scss new file mode 100644 index 0000000..60202c0 --- /dev/null +++ b/inst/assets/fab-button/_/_zoomin.scss @@ -0,0 +1,78 @@ +@mixin effects-zoomin{ + +/** + * ZOOM-IN + * When hovering the main button, the child buttons grow + * from zero to normal size. + * + */ + + .mfb-component--tl.mfb-zoomin, + .mfb-component--tr.mfb-zoomin{ + .mfb-component__list{ + li{ + -webkit-transform: scale(0); + transform: scale(0); + } + @for $i from 1 through $number-of-child-buttons { + $distance: $button-space * $i; + li:nth-child( #{$i} ) { + -webkit-transform: translateY($distance) scale(0); + transform: translateY($distance) scale(0); + transition: all $slide-speed; + // this is the delay at which the buttons *disappear* + transition-delay: ( $number-of-child-buttons - $i ) * 0.05s; + } + } + } + &[data-mfb-toggle="hover"]:hover, + &[data-mfb-state="open"]{ + .mfb-component__list{ + @for $i from 1 through $number-of-child-buttons { + $distance: $button-space * $i; + li:nth-child( #{$i} ) { + -webkit-transform: translateY($distance) scale(1); + transform: translateY($distance) scale(1); + // this is the delay at which the buttons *appear* + transition-delay: $i * 0.05s; + } + } + } + } + } + + .mfb-component--bl.mfb-zoomin, + .mfb-component--br.mfb-zoomin{ + .mfb-component__list{ + li{ + -webkit-transform: scale(0); + transform: scale(0); + } + @for $i from 1 through $number-of-child-buttons { + $distance: -1 * $button-space * $i; + li:nth-child( #{$i} ) { + -webkit-transform: translateY($distance) scale(0); + transform: translateY($distance) scale(0); + transition: all $slide-speed; + // this is the delay at which the buttons start disappearing + transition-delay: ( $number-of-child-buttons - $i ) * 0.05s; + } + } + } + &[data-mfb-toggle="hover"]:hover, + &[data-mfb-state="open"]{ + .mfb-component__list{ + @for $i from 1 through $number-of-child-buttons { + $distance: -1 * $button-space * $i; + li:nth-child( #{$i} ) { + -webkit-transform: translateY($distance) scale(1); + transform: translateY($distance) scale(1); + // this is the delay at which the buttons appear + transition-delay: $i * 0.05s; + } + } + } + } + } + +} diff --git a/inst/assets/fab-button/fab-button-scss.R b/inst/assets/fab-button/fab-button-scss.R new file mode 100644 index 0000000..bc41685 --- /dev/null +++ b/inst/assets/fab-button/fab-button-scss.R @@ -0,0 +1,24 @@ + +# Compile CSS for FAB button ---------------------------------------------- + +# From https://github.com/nobitagit/material-floating-button + +library(sass) + +sass( + input = list( + "main-color" = "#FFF", + "button-text-color" = "#2E2E2E", + "label-text-color" = "#F1F1F1", + "main-button-size" = "48px", + "child_button_size" = "40px", + "border-distance" = "15px", + "button-space" = "60px", + "number-of-child-buttons" = "4", + sass_file( + input = "inst/assets/fab-button/mfb.scss" + ) + ), + output = "inst/assets/fab-button/fab-button.min.css", + options = sass_options(output_style = "compressed") +) diff --git a/inst/assets/fab-button/fab-button.min.css b/inst/assets/fab-button/fab-button.min.css new file mode 100644 index 0000000..c50a30e --- /dev/null +++ b/inst/assets/fab-button/fab-button.min.css @@ -0,0 +1 @@ +.mfb-component--br,.mfb-component--bl,.mfb-component--tr,.mfb-component--tl{box-sizing:border-box;margin:15px;position:fixed;white-space:nowrap;z-index:30;padding-left:0;list-style:none}.mfb-component--br *,.mfb-component--bl *,.mfb-component--tr *,.mfb-component--tl *,.mfb-component--br *:before,.mfb-component--bl *:before,.mfb-component--tr *:before,.mfb-component--tl *:before,.mfb-component--br *:after,.mfb-component--bl *:after,.mfb-component--tr *:after,.mfb-component--tl *:after{box-sizing:inherit}.mfb-component--tl{left:0;top:0}.mfb-component--tr{right:0;top:0}.mfb-component--bl{left:0;bottom:0}.mfb-component--br{right:0;bottom:0}.mfb-component__button--child,.mfb-component__button--main{background-color:#fff;display:inline-block;position:relative;border:none;border-radius:50%;box-shadow:0 0 4px rgba(0,0,0,0.14),0 4px 8px rgba(0,0,0,0.28);cursor:pointer;outline:none;padding:0;position:relative;-webkit-user-drag:none;color:#2E2E2E}.mfb-component__list{list-style:none;margin:0;padding:0}.mfb-component__list>li{display:block;position:absolute;top:0;right:5px;padding:14px 0;margin:-14px 0}.mfb-component__icon,.mfb-component__child-icon,.mfb-component__main-icon--active,.mfb-component__main-icon--resting{position:absolute;font-size:18px;text-align:center;line-height:48px;width:100%}.mfb-component__wrap{padding:15px;margin:-15px}[data-mfb-toggle="hover"]:hover .mfb-component__icon,[data-mfb-toggle="hover"]:hover .mfb-component__child-icon,[data-mfb-toggle="hover"]:hover .mfb-component__main-icon--active,[data-mfb-toggle="hover"]:hover .mfb-component__main-icon--resting,[data-mfb-state="open"] .mfb-component__icon,[data-mfb-state="open"] .mfb-component__child-icon,[data-mfb-state="open"] .mfb-component__main-icon--active,[data-mfb-state="open"] .mfb-component__main-icon--resting{-webkit-transform:scale(1) rotate(0deg);transform:scale(1) rotate(0deg)}.mfb-component__button--main{height:48px;width:48px;z-index:20}.mfb-component__button--child{height:40px;width:40px}.mfb-component__main-icon--active,.mfb-component__main-icon--resting{-webkit-transform:scale(1) rotate(360deg);transform:scale(1) rotate(360deg);-webkit-transition:-webkit-transform 150ms cubic-bezier(0.4, 0, 1, 1);transition:transform 150ms cubic-bezier(0.4, 0, 1, 1)}.mfb-component__child-icon,.mfb-component__child-icon{line-height:40px;font-size:12.85714px}.mfb-component__main-icon--active{opacity:0}[data-mfb-toggle="hover"]:hover .mfb-component__main-icon,[data-mfb-state="open"] .mfb-component__main-icon{-webkit-transform:scale(1) rotate(0deg);transform:scale(1) rotate(0deg)}[data-mfb-toggle="hover"]:hover .mfb-component__main-icon--resting,[data-mfb-state="open"] .mfb-component__main-icon--resting{opacity:0;position:absolute !important}[data-mfb-toggle="hover"]:hover .mfb-component__main-icon--active,[data-mfb-state="open"] .mfb-component__main-icon--active{opacity:1}.mfb-component--tl.mfb-slidein .mfb-component__list li,.mfb-component--tr.mfb-slidein .mfb-component__list li{opacity:0;transition:all .5s}.mfb-component--tl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li,.mfb-component--tl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li,.mfb-component--tr.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li,.mfb-component--tr.mfb-slidein[data-mfb-state="open"] .mfb-component__list li{opacity:1}.mfb-component--tl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 1 ),.mfb-component--tl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child( 1 ),.mfb-component--tr.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 1 ),.mfb-component--tr.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child( 1 ){-webkit-transform:translateY(60px);transform:translateY(60px)}.mfb-component--tl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 2 ),.mfb-component--tl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child( 2 ),.mfb-component--tr.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 2 ),.mfb-component--tr.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child( 2 ){-webkit-transform:translateY(120px);transform:translateY(120px)}.mfb-component--tl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 3 ),.mfb-component--tl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child( 3 ),.mfb-component--tr.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 3 ),.mfb-component--tr.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child( 3 ){-webkit-transform:translateY(180px);transform:translateY(180px)}.mfb-component--tl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 4 ),.mfb-component--tl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child( 4 ),.mfb-component--tr.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 4 ),.mfb-component--tr.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child( 4 ){-webkit-transform:translateY(240px);transform:translateY(240px)}.mfb-component--bl.mfb-slidein .mfb-component__list li,.mfb-component--br.mfb-slidein .mfb-component__list li{opacity:0;transition:all .5s}.mfb-component--bl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li,.mfb-component--bl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li,.mfb-component--br.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li,.mfb-component--br.mfb-slidein[data-mfb-state="open"] .mfb-component__list li{opacity:1}.mfb-component--bl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 1 ),.mfb-component--bl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child( 1 ),.mfb-component--br.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 1 ),.mfb-component--br.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child( 1 ){-webkit-transform:translateY(-60px);transform:translateY(-60px)}.mfb-component--bl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 2 ),.mfb-component--bl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child( 2 ),.mfb-component--br.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 2 ),.mfb-component--br.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child( 2 ){-webkit-transform:translateY(-120px);transform:translateY(-120px)}.mfb-component--bl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 3 ),.mfb-component--bl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child( 3 ),.mfb-component--br.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 3 ),.mfb-component--br.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child( 3 ){-webkit-transform:translateY(-180px);transform:translateY(-180px)}.mfb-component--bl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 4 ),.mfb-component--bl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child( 4 ),.mfb-component--br.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 4 ),.mfb-component--br.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child( 4 ){-webkit-transform:translateY(-240px);transform:translateY(-240px)}.mfb-component--tl.mfb-slidein-spring .mfb-component__list li,.mfb-component--tr.mfb-slidein-spring .mfb-component__list li{opacity:0;transition:all .5s;transition-timing-function:cubic-bezier(0.68, -0.55, 0.265, 1.55)}.mfb-component--tl.mfb-slidein-spring .mfb-component__list li:nth-child( 1 ),.mfb-component--tr.mfb-slidein-spring .mfb-component__list li:nth-child( 1 ){transition-delay:.05s}.mfb-component--tl.mfb-slidein-spring .mfb-component__list li:nth-child( 2 ),.mfb-component--tr.mfb-slidein-spring .mfb-component__list li:nth-child( 2 ){transition-delay:.1s}.mfb-component--tl.mfb-slidein-spring .mfb-component__list li:nth-child( 3 ),.mfb-component--tr.mfb-slidein-spring .mfb-component__list li:nth-child( 3 ){transition-delay:.15s}.mfb-component--tl.mfb-slidein-spring .mfb-component__list li:nth-child( 4 ),.mfb-component--tr.mfb-slidein-spring .mfb-component__list li:nth-child( 4 ){transition-delay:.2s}.mfb-component--tl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li,.mfb-component--tl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li,.mfb-component--tr.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li,.mfb-component--tr.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li{opacity:1}.mfb-component--tl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 1 ),.mfb-component--tl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child( 1 ),.mfb-component--tr.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 1 ),.mfb-component--tr.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child( 1 ){transition-delay:.05s;-webkit-transform:translateY(60px);transform:translateY(60px)}.mfb-component--tl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 2 ),.mfb-component--tl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child( 2 ),.mfb-component--tr.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 2 ),.mfb-component--tr.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child( 2 ){transition-delay:.1s;-webkit-transform:translateY(120px);transform:translateY(120px)}.mfb-component--tl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 3 ),.mfb-component--tl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child( 3 ),.mfb-component--tr.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 3 ),.mfb-component--tr.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child( 3 ){transition-delay:.15s;-webkit-transform:translateY(180px);transform:translateY(180px)}.mfb-component--tl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 4 ),.mfb-component--tl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child( 4 ),.mfb-component--tr.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 4 ),.mfb-component--tr.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child( 4 ){transition-delay:.2s;-webkit-transform:translateY(240px);transform:translateY(240px)}.mfb-component--bl.mfb-slidein-spring .mfb-component__list li,.mfb-component--br.mfb-slidein-spring .mfb-component__list li{opacity:0;transition:all .5s;transition-timing-function:cubic-bezier(0.68, -0.55, 0.265, 1.55)}.mfb-component--bl.mfb-slidein-spring .mfb-component__list li:nth-child( 1 ),.mfb-component--br.mfb-slidein-spring .mfb-component__list li:nth-child( 1 ){transition-delay:.05s}.mfb-component--bl.mfb-slidein-spring .mfb-component__list li:nth-child( 2 ),.mfb-component--br.mfb-slidein-spring .mfb-component__list li:nth-child( 2 ){transition-delay:.1s}.mfb-component--bl.mfb-slidein-spring .mfb-component__list li:nth-child( 3 ),.mfb-component--br.mfb-slidein-spring .mfb-component__list li:nth-child( 3 ){transition-delay:.15s}.mfb-component--bl.mfb-slidein-spring .mfb-component__list li:nth-child( 4 ),.mfb-component--br.mfb-slidein-spring .mfb-component__list li:nth-child( 4 ){transition-delay:.2s}.mfb-component--bl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li,.mfb-component--bl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li,.mfb-component--br.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li,.mfb-component--br.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li{opacity:1}.mfb-component--bl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 1 ),.mfb-component--bl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child( 1 ),.mfb-component--br.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 1 ),.mfb-component--br.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child( 1 ){transition-delay:.05s;-webkit-transform:translateY(-60px);transform:translateY(-60px)}.mfb-component--bl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 2 ),.mfb-component--bl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child( 2 ),.mfb-component--br.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 2 ),.mfb-component--br.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child( 2 ){transition-delay:.1s;-webkit-transform:translateY(-120px);transform:translateY(-120px)}.mfb-component--bl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 3 ),.mfb-component--bl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child( 3 ),.mfb-component--br.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 3 ),.mfb-component--br.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child( 3 ){transition-delay:.15s;-webkit-transform:translateY(-180px);transform:translateY(-180px)}.mfb-component--bl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 4 ),.mfb-component--bl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child( 4 ),.mfb-component--br.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 4 ),.mfb-component--br.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child( 4 ){transition-delay:.2s;-webkit-transform:translateY(-240px);transform:translateY(-240px)}.mfb-component--tl.mfb-zoomin .mfb-component__list li,.mfb-component--tr.mfb-zoomin .mfb-component__list li{-webkit-transform:scale(0);transform:scale(0)}.mfb-component--tl.mfb-zoomin .mfb-component__list li:nth-child( 1 ),.mfb-component--tr.mfb-zoomin .mfb-component__list li:nth-child( 1 ){-webkit-transform:translateY(60px) scale(0);transform:translateY(60px) scale(0);transition:all .5s;transition-delay:.15s}.mfb-component--tl.mfb-zoomin .mfb-component__list li:nth-child( 2 ),.mfb-component--tr.mfb-zoomin .mfb-component__list li:nth-child( 2 ){-webkit-transform:translateY(120px) scale(0);transform:translateY(120px) scale(0);transition:all .5s;transition-delay:.1s}.mfb-component--tl.mfb-zoomin .mfb-component__list li:nth-child( 3 ),.mfb-component--tr.mfb-zoomin .mfb-component__list li:nth-child( 3 ){-webkit-transform:translateY(180px) scale(0);transform:translateY(180px) scale(0);transition:all .5s;transition-delay:.05s}.mfb-component--tl.mfb-zoomin .mfb-component__list li:nth-child( 4 ),.mfb-component--tr.mfb-zoomin .mfb-component__list li:nth-child( 4 ){-webkit-transform:translateY(240px) scale(0);transform:translateY(240px) scale(0);transition:all .5s;transition-delay:0s}.mfb-component--tl.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 1 ),.mfb-component--tl.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child( 1 ),.mfb-component--tr.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 1 ),.mfb-component--tr.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child( 1 ){-webkit-transform:translateY(60px) scale(1);transform:translateY(60px) scale(1);transition-delay:.05s}.mfb-component--tl.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 2 ),.mfb-component--tl.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child( 2 ),.mfb-component--tr.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 2 ),.mfb-component--tr.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child( 2 ){-webkit-transform:translateY(120px) scale(1);transform:translateY(120px) scale(1);transition-delay:.1s}.mfb-component--tl.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 3 ),.mfb-component--tl.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child( 3 ),.mfb-component--tr.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 3 ),.mfb-component--tr.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child( 3 ){-webkit-transform:translateY(180px) scale(1);transform:translateY(180px) scale(1);transition-delay:.15s}.mfb-component--tl.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 4 ),.mfb-component--tl.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child( 4 ),.mfb-component--tr.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 4 ),.mfb-component--tr.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child( 4 ){-webkit-transform:translateY(240px) scale(1);transform:translateY(240px) scale(1);transition-delay:.2s}.mfb-component--bl.mfb-zoomin .mfb-component__list li,.mfb-component--br.mfb-zoomin .mfb-component__list li{-webkit-transform:scale(0);transform:scale(0)}.mfb-component--bl.mfb-zoomin .mfb-component__list li:nth-child( 1 ),.mfb-component--br.mfb-zoomin .mfb-component__list li:nth-child( 1 ){-webkit-transform:translateY(-60px) scale(0);transform:translateY(-60px) scale(0);transition:all .5s;transition-delay:.15s}.mfb-component--bl.mfb-zoomin .mfb-component__list li:nth-child( 2 ),.mfb-component--br.mfb-zoomin .mfb-component__list li:nth-child( 2 ){-webkit-transform:translateY(-120px) scale(0);transform:translateY(-120px) scale(0);transition:all .5s;transition-delay:.1s}.mfb-component--bl.mfb-zoomin .mfb-component__list li:nth-child( 3 ),.mfb-component--br.mfb-zoomin .mfb-component__list li:nth-child( 3 ){-webkit-transform:translateY(-180px) scale(0);transform:translateY(-180px) scale(0);transition:all .5s;transition-delay:.05s}.mfb-component--bl.mfb-zoomin .mfb-component__list li:nth-child( 4 ),.mfb-component--br.mfb-zoomin .mfb-component__list li:nth-child( 4 ){-webkit-transform:translateY(-240px) scale(0);transform:translateY(-240px) scale(0);transition:all .5s;transition-delay:0s}.mfb-component--bl.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 1 ),.mfb-component--bl.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child( 1 ),.mfb-component--br.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 1 ),.mfb-component--br.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child( 1 ){-webkit-transform:translateY(-60px) scale(1);transform:translateY(-60px) scale(1);transition-delay:.05s}.mfb-component--bl.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 2 ),.mfb-component--bl.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child( 2 ),.mfb-component--br.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 2 ),.mfb-component--br.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child( 2 ){-webkit-transform:translateY(-120px) scale(1);transform:translateY(-120px) scale(1);transition-delay:.1s}.mfb-component--bl.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 3 ),.mfb-component--bl.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child( 3 ),.mfb-component--br.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 3 ),.mfb-component--br.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child( 3 ){-webkit-transform:translateY(-180px) scale(1);transform:translateY(-180px) scale(1);transition-delay:.15s}.mfb-component--bl.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 4 ),.mfb-component--bl.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child( 4 ),.mfb-component--br.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 4 ),.mfb-component--br.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child( 4 ){-webkit-transform:translateY(-240px) scale(1);transform:translateY(-240px) scale(1);transition-delay:.2s}.mfb-component--tl.mfb-fountain .mfb-component__list li,.mfb-component--tr.mfb-fountain .mfb-component__list li{-webkit-transform:scale(0);transform:scale(0)}.mfb-component--tl.mfb-fountain .mfb-component__list li:nth-child( 1 ),.mfb-component--tr.mfb-fountain .mfb-component__list li:nth-child( 1 ){-webkit-transform:translateY(-60px) scale(0);transform:translateY(-60px) scale(0);transition:all .5s;transition-delay:.15s}.mfb-component--tl.mfb-fountain .mfb-component__list li:nth-child( 2 ),.mfb-component--tr.mfb-fountain .mfb-component__list li:nth-child( 2 ){-webkit-transform:translateY(-120px) scale(0);transform:translateY(-120px) scale(0);transition:all .5s;transition-delay:.1s}.mfb-component--tl.mfb-fountain .mfb-component__list li:nth-child( 3 ),.mfb-component--tr.mfb-fountain .mfb-component__list li:nth-child( 3 ){-webkit-transform:translateY(-180px) scale(0);transform:translateY(-180px) scale(0);transition:all .5s;transition-delay:.05s}.mfb-component--tl.mfb-fountain .mfb-component__list li:nth-child( 4 ),.mfb-component--tr.mfb-fountain .mfb-component__list li:nth-child( 4 ){-webkit-transform:translateY(-240px) scale(0);transform:translateY(-240px) scale(0);transition:all .5s;transition-delay:0s}.mfb-component--tl.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 1 ),.mfb-component--tl.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child( 1 ),.mfb-component--tr.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 1 ),.mfb-component--tr.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child( 1 ){-webkit-transform:translateY(60px) scale(1);transform:translateY(60px) scale(1);transition-delay:.05s}.mfb-component--tl.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 2 ),.mfb-component--tl.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child( 2 ),.mfb-component--tr.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 2 ),.mfb-component--tr.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child( 2 ){-webkit-transform:translateY(120px) scale(1);transform:translateY(120px) scale(1);transition-delay:.1s}.mfb-component--tl.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 3 ),.mfb-component--tl.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child( 3 ),.mfb-component--tr.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 3 ),.mfb-component--tr.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child( 3 ){-webkit-transform:translateY(180px) scale(1);transform:translateY(180px) scale(1);transition-delay:.15s}.mfb-component--tl.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 4 ),.mfb-component--tl.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child( 4 ),.mfb-component--tr.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 4 ),.mfb-component--tr.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child( 4 ){-webkit-transform:translateY(240px) scale(1);transform:translateY(240px) scale(1);transition-delay:.2s}.mfb-component--bl.mfb-fountain .mfb-component__list li,.mfb-component--br.mfb-fountain .mfb-component__list li{-webkit-transform:scale(0);transform:scale(0)}.mfb-component--bl.mfb-fountain .mfb-component__list li:nth-child( 1 ),.mfb-component--br.mfb-fountain .mfb-component__list li:nth-child( 1 ){-webkit-transform:translateY(60px) scale(0);transform:translateY(60px) scale(0);transition:all .5s;transition-delay:.15s}.mfb-component--bl.mfb-fountain .mfb-component__list li:nth-child( 2 ),.mfb-component--br.mfb-fountain .mfb-component__list li:nth-child( 2 ){-webkit-transform:translateY(120px) scale(0);transform:translateY(120px) scale(0);transition:all .5s;transition-delay:.1s}.mfb-component--bl.mfb-fountain .mfb-component__list li:nth-child( 3 ),.mfb-component--br.mfb-fountain .mfb-component__list li:nth-child( 3 ){-webkit-transform:translateY(180px) scale(0);transform:translateY(180px) scale(0);transition:all .5s;transition-delay:.05s}.mfb-component--bl.mfb-fountain .mfb-component__list li:nth-child( 4 ),.mfb-component--br.mfb-fountain .mfb-component__list li:nth-child( 4 ){-webkit-transform:translateY(240px) scale(0);transform:translateY(240px) scale(0);transition:all .5s;transition-delay:0s}.mfb-component--bl.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 1 ),.mfb-component--bl.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child( 1 ),.mfb-component--br.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 1 ),.mfb-component--br.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child( 1 ){-webkit-transform:translateY(-60px) scale(1);transform:translateY(-60px) scale(1);transition-delay:.05s}.mfb-component--bl.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 2 ),.mfb-component--bl.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child( 2 ),.mfb-component--br.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 2 ),.mfb-component--br.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child( 2 ){-webkit-transform:translateY(-120px) scale(1);transform:translateY(-120px) scale(1);transition-delay:.1s}.mfb-component--bl.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 3 ),.mfb-component--bl.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child( 3 ),.mfb-component--br.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 3 ),.mfb-component--br.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child( 3 ){-webkit-transform:translateY(-180px) scale(1);transform:translateY(-180px) scale(1);transition-delay:.15s}.mfb-component--bl.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 4 ),.mfb-component--bl.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child( 4 ),.mfb-component--br.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child( 4 ),.mfb-component--br.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child( 4 ){-webkit-transform:translateY(-240px) scale(1);transform:translateY(-240px) scale(1);transition-delay:.2s}[data-mfb-label]:after{content:attr(data-mfb-label);opacity:0;transition:all .5s;background:rgba(0,0,0,0.4);padding:4px 10px;border-radius:3px;color:#F1F1F1;font-size:14px;font-weight:normal;pointer-events:none;line-height:normal;position:absolute;top:50%;margin-top:-11px;transition:all .5s}[data-mfb-toggle="hover"] [data-mfb-label]:hover:after,[data-mfb-state="open"] [data-mfb-label]:after{content:attr(data-mfb-label);opacity:1;transition:all .3s}.mfb-component--br [data-mfb-label]:after,.mfb-component--tr [data-mfb-label]:after{content:attr(data-mfb-label);right:70px}.mfb-component--br .mfb-component__list [data-mfb-label]:after,.mfb-component--tr .mfb-component__list [data-mfb-label]:after{content:attr(data-mfb-label);right:66px}.mfb-component--tl [data-mfb-label]:after,.mfb-component--bl [data-mfb-label]:after{content:attr(data-mfb-label);left:70px}.mfb-component--tl .mfb-component__list [data-mfb-label]:after,.mfb-component--bl .mfb-component__list [data-mfb-label]:after{content:attr(data-mfb-label);left:66px} diff --git a/inst/assets/fab-button/mfb.scss b/inst/assets/fab-button/mfb.scss new file mode 100644 index 0000000..5fce068 --- /dev/null +++ b/inst/assets/fab-button/mfb.scss @@ -0,0 +1,411 @@ +/** + * CONTENTS + * + * #Introduction........Naming conventions used throughout the code. + * + * #SETTINGS + * Variables............Globally-available variables and config. + * + * #TOOLS + * Mixins...............Useful mixins. + * + * #GENERIC + * Demo styles..........Styles for demo only (consider removing these). + * + * #BASE + * Raw styles...........The very basic component wrapper. + * Modifiers............The basic styles dependant on component placement. + * Debuggers............The basic styles dependant on component placement. + * + * #BUTTONS + * Base..................Wrapping and constraining every button. + * Modifiers.............Styles that depends on state and settings. + * Animations............Main animations of the component. + * Debuggers.............Styles for development. + * + * #LABELS + * Base..................Wrapping and constraining every label. + * Modifiers.............Styles that depends on state and settings. + * Debuggers.............Styles for development. + * + * #DEVELOPMENT + * In development........These styles are in development and not yet finalised + * Debuggers.............Helper styles and flags for development. + */ + +/*------------------------------------*\ + #Introduction +\*------------------------------------*/ +/** + * The code AND the comments use naming conventions to refer to each part of + * the UI put in place by this component. If you see that somewhere they are + * not followed please consider a Pull Request. The naming conventions are: + * + * "Component" : the widget itself as a whole. This is the last time it will be + * called anything different than "component". So, stay away from + * "widget", "button" or anything else when referring to the + * Component in general. + * + * "Main Button" : the button that is always in view. Hovering or clicking on it + * will reveal the child buttons. + * + * "Child buttons" : if you've read the previous point you know what they are. + * Did you read the previous point? :) + * + * "Label(s)" : the tooltip that fades in when hovering over a button. + +/*------------------------------------*\ + #SETTINGS | Variables +\*------------------------------------*/ + +/** + * These variables are the default styles that serve as fallback and can be + * easily customised at compile time. + * Consider overriding them in your own style sheets rather than editing them + * here. Refer to the docs for more info. + */ + +/* COLORS ----------------------------*/ + +// the main/primary color +$main-color: #E40A5D !default; +// button colors +$button-text-color: #f1f1f1 !default; +$button-box-shadow: 0 0 4px rgba(0,0,0,.14),0 4px 8px rgba(0,0,0,.28) !default; +// labels colors +$label-text-color: rgba(255, 255, 255, 0.8) !default; +// labels background +$label-background-color: rgba(0,0,0, .4); +/* EFFECTS ---------------------------*/ + +// which effects must be made available in the css +$effects-zoomin: true !default; +$effects-slidein: true !default; +$effects-fountain: true !default; + +/* SPEEDS ----------------------------*/ + +// the speed of the inflation of each button after hovering on the main button +$delay-staggering-inflate: 0.1s !default; +// when hovering on the main button the child buttons slide into view +$slide-speed: .5s !default; +// the labels disappear at this speed on mouse out +$label-hover-off: .5s !default; +// the labels appear at this speed on mouse over +$label-hover-on: .3s !default; + +/* SIZES -----------------------------*/ + +// main button diameter +$main-button-size: 56px !default; +// main button diameter +$child_button_size: 56px !default; +// the distance of the main button from the closest corners of the screen +$border-distance: 25px !default; +// font-size for the icons +$icons-font-size: 18px !default; +// font-size for labels +$labels-font-size: 14px !default; +// font-weight for labels +$labels-font-weight: normal !default; +// top & bottom padding for the labels +$labels-padding-vertical: 4px !default; +// left & right padding for the labels +$labels-padding-horizontal: 10px !default; + +/* SPACING ---------------------------*/ + +// space between buttons +$button-space: 70px !default; +// space between button and label +$button-label-space: 70px !default; + +/* OTHER VARIABLES -------------------*/ + +// how many child buttons does the component have +$number-of-child-buttons: 4 !default; + +/*------------------------------------*\ + #BASE | Raw styles +\*------------------------------------*/ + +/** + * The very core styling of the button. + * These styles are shared by every instance of the button. + * Styles placed here should NOT care about placement in the screen, + * options chosen by the user or state of the button. + */ + +%mfb-component{ + box-sizing: border-box; // A better box-sizing + margin: $border-distance; + position: fixed; + white-space: nowrap; + z-index: 30; + // this padding is really needed only if the element is an