Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sidebar nav #100

Merged
merged 24 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
6c82dce
initial draft of contents links
jenisayshi Aug 29, 2024
9beec1f
add contents link dependency to make js work
jenisayshi Aug 30, 2024
e98ece0
draft sticky navbar and return to shiny ui
jenisayshi Aug 30, 2024
b044d37
make sidebar nav sticky
jenisayshi Sep 2, 2024
31c962f
fix example typo
jenisayshi Sep 2, 2024
44dae9e
add contents links documentation
jenisayshi Sep 3, 2024
3f15e2b
add onclick to contents link to scroll to top of window
jenisayshi Sep 3, 2024
4785ef6
contents links checks
jenisayshi Sep 3, 2024
1d05e22
fix footer
jenisayshi Sep 4, 2024
5c88bdd
delete custom pipe
jenisayshi Sep 4, 2024
943434c
add govuk-link to contents links and subcontents link classes?
jenisayshi Sep 4, 2024
5a1f7f1
merge subcontents_links into contents_links
jenisayshi Sep 4, 2024
7ef4a41
update tests
jenisayshi Sep 4, 2024
8996851
readd usethis::usepipe()
jenisayshi Sep 4, 2024
819adcc
update accordians typo
jenisayshi Sep 5, 2024
a8b4e7a
update contents links example
jenisayshi Sep 5, 2024
7768ed0
update documentation
jenisayshi Sep 5, 2024
1ba8e2d
fix scrolling to top of main
jenisayshi Sep 5, 2024
9ae0e87
update documentation
jenisayshi Sep 5, 2024
ecb8519
use the no visited state on contents links (also accidentally ran sty…
cjrace Sep 5, 2024
d521d7c
update documentation
jenisayshi Sep 6, 2024
f6c17a5
forgot to run devtools::document !
jenisayshi Sep 6, 2024
c7db974
update contents_links name to contents_link
jenisayshi Sep 6, 2024
6e67cd3
fix image in readme and clarify why the ids are needed
cjrace Sep 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ Imports:
shiny (>= 0.14),
htmltools,
shinyjs,
jsonlite
jsonlite,
magrittr,
stringr,
purrr
Suggests:
testthat
3 changes: 3 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# Generated by roxygen2: do not edit by hand

export("%>%")
export(accordion)
export(backlink_Input)
export(banner)
export(button_Input)
export(checkbox_Input)
export(contents_link)
export(cookieBanner)
export(date_Input)
export(details)
Expand Down Expand Up @@ -41,5 +43,6 @@ export(word_count)
importFrom(htmltools,attachDependencies)
importFrom(htmltools,findDependencies)
importFrom(htmltools,htmlDependency)
importFrom(magrittr,"%>%")
importFrom(shiny,addResourcePath)
importFrom(utils,packageVersion)
12 changes: 12 additions & 0 deletions R/attachDependency.R
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,18 @@ attachDependency <- function(tag, widget = NULL) {
)
}

else if (widget == "contents_link") {
dep <- list(
dep,
htmltools::htmlDependency(
name = "contents_link",
version = version,
src = c(href="shinyGovstyle/js"),
script = "contents_link.js"
)
)
}

}

htmltools::attachDependencies(tag, dep, append = TRUE)
Expand Down
13 changes: 13 additions & 0 deletions R/clean_heading_text.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#' Clean heading text function
#' This internal function is used in subcontents_links and heading_text to create an automated link between the two
#' @param text string
#' @return a string
#' @keywords internal
clean_heading_text <- function(text){

text %>%
stringr::str_replace_all(" ", "_") %>%
stringr::str_to_lower() %>%
stringr::str_remove_all( "[^_[a-z]]")

}
285 changes: 285 additions & 0 deletions R/contents_links.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,285 @@
#' Subcontents links function
#' This function is used internally within contents_link to create links to headings within pages.
#' @param subcontents_text_list vector of link text for subcontents
#' @param subcontents_id_list vector of link ids for subcontents. pass NAs for automatic matching to id in shinygovstyle::heading_text
#' @return a ol html shiny object
#' @keywords internal
#' @examples
#' if (interactive()) {
#' ui <- shiny::fluidPage(
#' shinyGovstyle::header(
#' main_text = "Example",
#' secondary_text = "User Examples",
#' logo = "shinyGovstyle/images/moj_logo.png"
#' ),
#' shiny::column(
#' width = 3,
#' id = "nav",
#' shiny::tags$div(
#' shiny::tags$h2("Contents"),
#' subcontents_links(
#' c("radio_button_Input (inline)", "button_Input"),
#' c(NA, NA)
#' ),
#' subcontents_links(
#' c("date_Input", "button_Input"),
#' c(NA, "button_input_text_types")
#' )
#' )
#' )
#' )
#'
#' server <- function(input, output, session) {
#' }
#' shiny::shinyApp(ui = ui, server = server)
#' }
subcontents_links <- function(subcontents_text_list,
subcontents_id_list) {
if (!missing(subcontents_id_list)) {
# check if custom link_id_list is of equal length to links list
if (length(subcontents_text_list) != length(subcontents_id_list)) {
message(
"`subcontents_id_list` must be equal length to `subcontents_text_list`"
)
}
}

# create sidelink
create_sidelink <- function(link_text, link_id) {
# match id created in shinygovstyle::heading_text if custom id not specifcied
if (is.na(link_id)) {
link_id <- clean_heading_text(link_text)
}

shiny::tags$li(
"\u2014 ",
shiny::tags$a(class = "govuk-link--no-visited-state", link_text, href = stringr::str_c("\u0023", link_id))
)
}


# create <li></li> tags
list_tags <- purrr::map2(subcontents_text_list, subcontents_id_list, create_sidelink)


# return <ol> output
shiny::tags$ol(class = "govuk-subcontents", list_tags)
}


#' Contents link function
#'
#' This function creates an action link to nav between tabs and optionally link to subcontents headers.
#' @param link_text vector of link text for contents
#' @param input_id contents button id
#' @param subcontents_text_list vector of link text for subcontents
#' @param subcontents_id_list vector of link ids for subcontents. if missing automatically matches to id in shinygovstyle::heading_text
#' @return an action button html shiny object
#' @export
#' @examples
#' if (interactive()) {
#' ui <- shiny::fluidPage(
#' title="ShinyGovstyle",
#' cookieBanner("Run Example"),
#' header("MOJ", "ShinyGovstyle Example",
#' logo="shinyGovstyle/images/moj_logo-1.png", logo_width = 66),
#' banner(
#' "banner",
#' "Beta",
#' 'This is a new service \u002D your <a class="govuk-link" href="#">
#' feedback</a> will help us to improve it.'),
#'
#' #Need this to make the error and word count work
#' shinyjs::useShinyjs(),
#'
#' #Add a message to show users how to see this code
#' shiny::tags$br(),
#' shiny::markdown(
#' "Run ```View(run_example)``` in console to see the code for this app"),
#'
#'
jenisayshi marked this conversation as resolved.
Show resolved Hide resolved
#' gov_row(
#' # Nav columns
#' shiny::column(
#'
#' width = 3,
#' id = "nav", # DO NOT REMOVE ID
#'
#' # Contents box
#' shiny::tags$div(
#' id = "govuk-contents-box", #DO NOT REMOVE ID
#' class = "govuk-contents-box", #DO NOT REMOVE CLASS
#'
#' shiny::tags$h2("Contents"),
#'
#' # Text types tab
#' contents_link(
#' "Text Types",
#' "text_types_button",
#' subcontents_text_list = c("date_Input",
#' "text_Input",
#' "text_area_Input",
#' "button_Input"),
#' subcontents_id_list = c(NA, NA, NA, "button_input_text_types")
#' ),
#'
#' # Tables tabs and accordions tab
#' contents_link(
#' "Tables, tabs and accordions",
#' "tables_tabs_and_accordions_button",
#' subcontents_text_list = c("govTable", "govTabs", "accordions", "button_Input"),
#' subcontents_id_list = c(NA, NA, NA, "button_input_tables_tabs_accordions")
#' ),
#'
#'
#' contents_link(
#' "Cookies",
#' "cookies_button"),
#'
#' )
#' ),
#'
#'
#' shiny::column( width = 9,
#'
#' id = "main_col", # DO NOT REMOVE ID
#'
#' #Set up a nav panel so everything not on single page
#' shiny::tabsetPanel(
#' type = "hidden",
#' id = "tab-container", # DO NOT REMOVE ID
#'
#' shiny::tabPanel(
#' "Text Types",
#' value = "text_types",
#' gov_layout(
#' size = "two-thirds",
#' backlink_Input("back1"),
#' heading_text("Page 2", size = "l"),
#' label_hint("label2", "These are some examples of the types of user
#' text inputs that you can use"),
#' heading_text("date_Input", size = "s"),
#' date_Input(
#' inputId = "date1",
#' label = "What is your date of birth?",
#' hint_label = "For example, 31 3 1980"),
#' heading_text("text_Input", size = "s"),
#' text_Input(inputId = "txt1", label = "Event name"),
#' heading_text("text_area_Input", size = "s"),
#' text_area_Input(
#' inputId = "text_area1",
#' label = "Can you provide more detail?",
#' hint_label = "Do not include personal or financial information,
#' like your National Insurance number or credit card details."),
#' text_area_Input(
#' inputId = "text_area2",
#' label = "How are you today?",
#' hint_label = "Leave blank to trigger error",
#' error = T,
#' error_message = "Please do not leave blank",
#' word_limit = 300),
#' heading_text(
#' "button_Input", size = "s",
#' id = "button_input_text_types"),
#' button_Input("btn2", "Go to next page"),
#' button_Input("btn3", "Check for errors", type = "warning")
#' )
#' ),
#'
#' shiny::tabPanel(
#' "Tables, tabs and accordions",
#' value = "tables_tabs_and_accordions",
#' gov_layout(
#' size = "two-thirds",
#' backlink_Input("back2"),
#' heading_text("Page 3", size = "l"),
#' label_hint("label3", "These are some examples of using tabs and
#' tables"),
#' heading_text("govTable", size = "s"),
#' heading_text("govTabs", size = "s"),
#' heading_text("accordions", size = "s"),
#' shinyGovstyle:: accordion(
#' "acc1",
#' c("Writing well for the web",
#' "Writing well for specialists",
#' "Know your audience",
#' "How people read"
#' ),
#' c("This is the content for Writing well for the web.",
#' "This is the content for Writing well for specialists.",
#' "This is the content for Know your audience.",
#' "This is the content for How people read."
#' )),
#'
#' heading_text(
#' "button_Input", size = "s",
#' id = "button_input_tables_tabs_accordions"),
#' button_Input("btn4", "Go to next page"),
#' )
#' ),
#'
#'
#' #####################Create cookie panel################################
#' shiny::tabPanel(
#' "Cookies",
#' value = "panel-cookies",
#' gov_layout(
#' size = "two-thirds",
#' heading_text("Cookie page", size = "l"),
#' label_hint("label-cookies", "This an example cookie page that could be
#' expanded")
#' )
#' )))
#'
#'
#' ), #end of gov row
#'
#' footer(TRUE)
#'
#'
#' ) #end of fluid page
#'
#' server <- function(input, output, session) {
#'
#'
#' # Tab nav
#' shiny::observeEvent(input$back2, {
#' shiny::updateTabsetPanel(session, "tab-container", selected = "text_types")
#' })
#'
#' shiny::observeEvent(input$tables_tabs_and_accordions_button, {
#' shiny::updateTabsetPanel(session, "tab-container", selected = "tables_tabs_and_accordions")
#' })
#'
#' shiny::observeEvent(input$cookies_button, {
#' shiny::updateTabsetPanel(session, "tab-container", selected = "panel-cookies")
#' })
#'
#' }
#'
#' shiny::shinyApp(ui = ui, server = server)
#' }
contents_link <- function(link_text,
input_id,
subcontents_text_list,
subcontents_id_list) {
if (missing(subcontents_id_list) & !missing(subcontents_text_list)) {
subcontents_id_list <- rep(NA, length(subcontents_text_list))
}

contents_div <- shiny::tags$div(
class = "govuk-contents",
shiny::actionLink(
class = "govuk-contents__link govuk-link--no-visited-state",
inputId = input_id,
label = link_text
),

# add subcontents links if required
if (!missing(subcontents_text_list)) {
subcontents_links(subcontents_text_list, subcontents_id_list)
}
)

attachDependency(contents_div, "contents_link")
}
11 changes: 9 additions & 2 deletions R/heading_text.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#' This function create a heading text
#' @param text_input Text to display
#' @param size Text size using xl, l, m, s. Defaults to xl.
#' @param id Custom header id
#' @return a heading text html shiny object
#' @keywords heading
#' @export
Expand All @@ -23,8 +24,14 @@
#' shinyApp(ui = ui, server = server)
#' }

heading_text <- function(text_input, size = "xl"){
heading_text <- function(text_input, size = "xl", id){

if(missing(id)){
id <- clean_heading_text(text_input)
}

govHeading <- shiny::tags$h1(shiny::HTML(text_input),
class=paste0("govuk-heading-", size))
class=paste0("govuk-heading-", size),
id = id)
attachDependency(govHeading)
}
Loading