How to add back button in the top corner of the left page with Shiny?

am trying to add back button to top-corner of the left page, with a triangular form.

Here is a reproducible example of the Shiny app:

library(shiny)


ui <- fluidPage(
  tags$head(
    tags$style(HTML("
      body {
        display: flex;
        flex-direction: column;
        justify-content: flex-start;
        align-items: center;
        height: 100vh;
        margin: 5px 0;
        background-color: navy; /* Set background color for the body */
        position: relative; /* Add position relative for the logo */
      }
      .input-container {
        width: 100%;
        text-align: center;
        background-color: navy; /* Set background color for the input container */
        padding: 20px; /* Add padding for better visibility */
      }
      .input-container input[type='text'],
      .input-container input[type='number'],
      .input-container .btn {
        width: 100%;
        padding: 15px;
        margin: 5px 0;
        box-sizing: border-box;
        font-size: 18px;
        text-align: center;
        color: navy; /* Text color navy */
      }
      .input-container .btn {
        margin-top: 20px;
        color: white;
      }
      /* Style for Your Details text */
      .details-container {
        text-align: center;
      }
      .details-text {
        color: white;
        font-size: 24px;
        margin-bottom: 15px;
        text-align: center;
        display: inline-block;
      }
      .logo {
        position: absolute;
        bottom: 10px;
        left: 50%;
        transform: translateX(-50%);
        width: 300px; /* Adjust the width of the logo */
        height: auto; /* Maintain aspect ratio */
        display: none; /* Initially hide the logo */
      }
    "))
  ),
  titlePanel(" "),
  uiOutput("page")
)

server <- function(input, output, session) {
  output$page <- renderUI({
    if (is.null(input$currentPage)) {
      tagList(
        div(class = "input-container",
            actionButton("startButton", "START", style = "font-size: 50px;") #  style = "font-size: 24px;"
        ),
        tags$img(src = "www/free_english_logo.png", class = "logo", width = "400px") # Adjust the width of the logo
      )
    } else if (input$currentPage == "page2") {
      tagList(
        div(class = "input-container",
            tags$p(class = "details-text", "Your Details:"),
            textInput("name", label = NULL, placeholder = "Name", style = "background-color: lightblue; color: navy;"),
            textInput("nationality", label = NULL, placeholder = "Nationality", style = "background-color: lightyellow; color: navy;"),
            textInput("age", label = NULL, value = "", placeholder = "Age", style = "background-color: lightgreen; color: navy;"),
            textInput("email", label = NULL, placeholder = "Email", style = "background-color: lightgray; color: navy;"),
            actionButton("nextButton", "NEXT") #  style = "font-size: 24px;"
        ),
        tags$img(src = "www/free_english_logo.png", class = "logo", width = "400px") # Adjust the width of the logo
      )
    } else if (input$currentPage == "page3") {
      tagList(
        div(class = "input-container",
            tags$p(class = "details-text", "Teaching level:"),
            actionButton("basicButton", "Basic"),
            actionButton("intermediateButton", "Intermediate"),
            actionButton("intermediatePlusButton", "Intermediate +"),
            actionButton("notSureButton", "Not sure"),
            actionButton("nextButtonPage3", "NEXT") #  style = "font-size: 24px;"
        ),
        tags$img(src ="www/free_english_logo.png", class = "logo", width = "400px") # Adjust the width of the logo
      )
    }
  })
  
  observeEvent(input$startButton, {
    output$page <- renderUI({
      tagList(
        div(class = "input-container",
            tags$p(class = "details-text", "Your Details:"),
            textInput("name", label = NULL, placeholder = "Name"),
            textInput("nationality", label = NULL, placeholder = "Nationality"),
            textInput("age", label = NULL, value = "", placeholder = "Age"),
            textInput("email", label = NULL, placeholder = "Email"),
            actionButton("nextButton", "NEXT") #  style = "font-size: 24px;"
        ),
        tags$img(src = "www/free_english_logo.png", class = "logo", width = "400px") # Adjust the width of the logo
      )
    })
  })
  
  observeEvent(input$nextButton, {
    name <- input$name
    nationality <- input$nationality
    age <- input$age
    email <- input$email
    
    output$page <- renderUI({
      tagList(
        div(class = "input-container",
            tags$p(class = "details-text", "Teaching level:"),
            actionButton("basicButton", "Basic", style = "background-color: lightblue; color: navy;"),
            actionButton("intermediateButton", "Intermediate", style = "background-color: lightyellow; color: navy;"),
            actionButton("intermediatePlusButton", "Intermediate +", style = "background-color: lightgreen; color: navy;"),
            actionButton("notSureButton", "Not sure", style = "background-color: lightgray; color: navy;"),
            actionButton("nextButtonPage3", "NEXT") #  style = "font-size: 24px;"
        ),
        tags$img(src = "www/free_english_logo.png", class = "logo", width = "400px") # Adjust the width of the logo
      )
    })
  })
}

shinyApp(ui, server)

And this is an example of the the "Back" button I need on each page , but starting with the second page , all the way to the other pages.

Is there a way to fix this?

You have two seperate issues

  1. how to get your button styled in your preferred way
  2. how to organise your code and switch forward and back between pages
  1. here is some css you can use
    .backButton {
  width: 200px;
  height: 200px;
  background-color: white;
    clip-path: polygon(50% 0%, 100% 50%, 50% 50%, 0% 50%);
  position:absolute;
  top:-40px;
  left:-40px;
   color: blue;
  text-align: center;
  padding-bottom: 40px;
  transform: rotate(-45deg);
}

and add it as a class to a button like the following on the page in your ui on which it is to show

 actionButton("mybackbutton",label = "Back",class="backButton")

this will register click events on input$mybackbutton as normal.

How to structure the code is a challenge seemingly.
I dont like and would rarely put renderUI's nested within observes ( though I have been in a few rate situations where that was the best solution).

A simply possibly better approach for a multi page app might be to place every page as its own independent UI with a name.
and some page control is referred to to see if the page should be drawn or not. i.e. a check within the renderUI code, not around it.

I think you must have contemplated this as you had input$currentPage yet there was no sign of an currentPage control. you could probably implement it as a simple reactiveVal() containing a string name for the current page. then the buttons on each page that point forward or back can just change the name within the reactiveVal, invalidating their old pages and causes the relevant page to draw.

@nirgrahamuk Thank you for answering. I have it now as a button exactly where I want it yet it does not go back when I press on it. Is this because again where I place it?

Also, with regards to multiple files of ui, etc. Actually I work with golem framework and have modules for each page . But want to make it reproducible.

Hopefully there is a way out for BACK button to function.